summaryrefslogtreecommitdiffstats
path: root/lib/kwmf
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
commit8362bf63dea22bbf6736609b0f49c152f975eb63 (patch)
tree0eea3928e39e50fae91d4e68b21b1e6cbae25604 /lib/kwmf
downloadkoffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz
koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'lib/kwmf')
-rw-r--r--lib/kwmf/Makefile.am19
-rw-r--r--lib/kwmf/kowmfpaint.cc297
-rw-r--r--lib/kwmf/kowmfpaint.h127
-rw-r--r--lib/kwmf/kowmfread.cc101
-rw-r--r--lib/kwmf/kowmfread.h154
-rw-r--r--lib/kwmf/kowmfreadprivate.cc1251
-rw-r--r--lib/kwmf/kowmfreadprivate.h362
-rw-r--r--lib/kwmf/kowmfstack.cc38
-rw-r--r--lib/kwmf/kowmfstack.h74
-rw-r--r--lib/kwmf/kowmfstruct.h147
-rw-r--r--lib/kwmf/kowmfwrite.cc456
-rw-r--r--lib/kwmf/kowmfwrite.h142
-rw-r--r--lib/kwmf/kwmf.cc964
-rw-r--r--lib/kwmf/kwmf.h220
-rw-r--r--lib/kwmf/metafuncs.h90
-rw-r--r--lib/kwmf/qwmf.cc1258
-rw-r--r--lib/kwmf/qwmf.h231
-rw-r--r--lib/kwmf/wmfstruct.h107
18 files changed, 6038 insertions, 0 deletions
diff --git a/lib/kwmf/Makefile.am b/lib/kwmf/Makefile.am
new file mode 100644
index 00000000..b257f435
--- /dev/null
+++ b/lib/kwmf/Makefile.am
@@ -0,0 +1,19 @@
+####### General stuff
+
+INCLUDES= $(KOFFICECORE_INCLUDES) -I$(srcdir) $(all_includes)
+libkwmf_la_LDFLAGS = $(all_libraries) -version-info 3:0:0 -no-undefined
+# We use kdecore for kdDebug :)
+libkwmf_la_LIBADD = $(LIB_KDECORE)
+
+####### Files
+
+lib_LTLIBRARIES = libkwmf.la libkowmf.la
+
+libkwmf_la_SOURCES = kwmf.cc qwmf.cc
+
+#include_HEADERS = kowmfread.h kowmfwrite.h kowmfpaint.h
+noinst_HEADERS = kwmf.h qwmf.h metafuncs.h wmfstruct.h kowmfreadprivate.h kowmfstack.h kowmfstruct.h
+
+libkowmf_la_SOURCES = kowmfreadprivate.cc kowmfstack.cc kowmfread.cc kowmfwrite.cc kowmfpaint.cc
+libkowmf_la_LDFLAGS = $(all_libraries) -version-info 2:0:0 -no-undefined
+libkowmf_la_LIBADD = $(LIB_KDECORE)
diff --git a/lib/kwmf/kowmfpaint.cc b/lib/kwmf/kowmfpaint.cc
new file mode 100644
index 00000000..7ce8ee8b
--- /dev/null
+++ b/lib/kwmf/kowmfpaint.cc
@@ -0,0 +1,297 @@
+/* This file is part of the KDE libraries
+ * Copyright (c) 2003 thierry lorthiois ([email protected])
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <kdebug.h>
+
+#include "kowmfpaint.h"
+
+KoWmfPaint::KoWmfPaint() : KoWmfRead() {
+ mTarget = 0;
+}
+
+
+bool KoWmfPaint::play( QPaintDevice& target, bool relativeCoord )
+{
+ if ( mPainter.isActive() ) return false;
+ mTarget = &target;
+ mRelativeCoord = relativeCoord;
+
+ // Play the wmf file
+ return KoWmfRead::play( );
+}
+
+
+//-----------------------------------------------------------------------------
+// Virtual Painter
+
+bool KoWmfPaint::begin() {
+ bool ret = mPainter.begin( mTarget );
+
+ if ( ret ) {
+ if ( mRelativeCoord ) {
+ mInternalWorldMatrix.reset();
+ }
+ else {
+ // some wmf files doesn't call setwindowOrg and setWindowExt, so it's better to do :
+ QRect rec = boundingRect();
+ mPainter.setWindow( rec.left(), rec.top(), rec.width(), rec.height() );
+ }
+ }
+ return ret;
+}
+
+
+bool KoWmfPaint::end() {
+ if ( mRelativeCoord ) {
+ QRect rec = boundingRect();
+
+ // Draw 2 invisible points
+ // because QPicture::setBoundingRect() doesn't give expected result (QT3.1.2)
+ // setBoundingRect( boundingRect() );
+// mPainter.setPen( Qt::NoPen );
+// mPainter.drawPoint( rec.left(), rec.top() );
+// mPainter.drawPoint( rec.right(), rec.bottom() );
+ }
+ return mPainter.end();
+}
+
+
+void KoWmfPaint::save() {
+ mPainter.save();
+}
+
+
+void KoWmfPaint::restore() {
+ mPainter.restore();
+}
+
+
+void KoWmfPaint::setFont( const QFont &font ) {
+ mPainter.setFont( font );
+}
+
+
+void KoWmfPaint::setPen( const QPen &pen ) {
+ QPen p = pen;
+ int width = pen.width();
+
+ if ( mTarget->isExtDev() ) {
+ width = 0;
+ }
+ else {
+ // WMF spec : width of pen in logical coordinate
+ // => width of pen proportional with device context width
+ QRect devRec = mPainter.xForm( mPainter.window() );
+ QRect rec = mPainter.window();
+ if ( rec.width() != 0 )
+ width = ( width * devRec.width() ) / rec.width() ;
+ else
+ width = 0;
+ }
+
+ p.setWidth( width );
+ mPainter.setPen( p );
+}
+
+
+const QPen &KoWmfPaint::pen() const {
+ return mPainter.pen();
+}
+
+
+void KoWmfPaint::setBrush( const QBrush &brush ) {
+ mPainter.setBrush( brush );
+}
+
+
+void KoWmfPaint::setBackgroundColor( const QColor &c ) {
+ mPainter.setBackgroundColor( c );
+}
+
+
+void KoWmfPaint::setBackgroundMode( Qt::BGMode mode ) {
+ mPainter.setBackgroundMode( mode );
+}
+
+
+void KoWmfPaint::setRasterOp( Qt::RasterOp op ) {
+ mPainter.setRasterOp( op );
+}
+
+
+// ---------------------------------------------------------------------
+// To change those functions it's better to have
+// a large set of WMF files. WMF special case includes :
+// - without call to setWindowOrg and setWindowExt
+// - change the origin or the scale in the middle of the drawing
+// - negative width or height
+// and relative/absolute coordinate
+void KoWmfPaint::setWindowOrg( int left, int top ) {
+ if ( mRelativeCoord ) {
+ double dx = mInternalWorldMatrix.dx();
+ double dy = mInternalWorldMatrix.dy();
+
+ // translation : Don't use setWindow()
+ mInternalWorldMatrix.translate( -dx, -dy );
+ mPainter.translate( -dx, -dy );
+ mInternalWorldMatrix.translate( -left, -top );
+ mPainter.translate( -left, -top );
+ }
+ else {
+ QRect rec = mPainter.window();
+ mPainter.setWindow( left, top, rec.width(), rec.height() );
+ }
+}
+
+
+void KoWmfPaint::setWindowExt( int w, int h ) {
+ if ( mRelativeCoord ) {
+ QRect r = mPainter.window();
+ double dx = mInternalWorldMatrix.dx();
+ double dy = mInternalWorldMatrix.dy();
+ double sx = mInternalWorldMatrix.m11();
+ double sy = mInternalWorldMatrix.m22();
+
+ // scale : don't use setWindow()
+ mInternalWorldMatrix.translate( -dx, -dy );
+ mPainter.translate( -dx, -dy );
+ mInternalWorldMatrix.scale( 1/sx, 1/sy );
+ mPainter.scale( 1/sx, 1/sy );
+
+ sx = (double)r.width() / (double)w;
+ sy = (double)r.height() / (double)h;
+
+ mInternalWorldMatrix.scale( sx, sy );
+ mPainter.scale( sx, sy );
+ mInternalWorldMatrix.translate( dx, dy );
+ mPainter.translate( dx, dy );
+ }
+ else {
+ QRect rec = mPainter.window();
+ mPainter.setWindow( rec.left(), rec.top(), w, h );
+ }
+}
+
+
+void KoWmfPaint::setWorldMatrix( const QWMatrix &wm, bool combine ) {
+ mPainter.setWorldMatrix( wm, combine );
+}
+
+
+void KoWmfPaint::setClipRegion( const QRegion &rec ) {
+ mPainter.setClipRegion( rec, QPainter::CoordPainter );
+}
+
+
+QRegion KoWmfPaint::clipRegion() {
+ return mPainter.clipRegion( QPainter::CoordPainter );
+}
+
+
+void KoWmfPaint::moveTo( int x, int y ) {
+ mPainter.moveTo( x, y );
+}
+
+
+void KoWmfPaint::lineTo( int x, int y ) {
+ mPainter.lineTo( x, y );
+}
+
+
+void KoWmfPaint::drawRect( int x, int y, int w, int h ) {
+ mPainter.drawRect( x, y, w, h );
+}
+
+
+void KoWmfPaint::drawRoundRect( int x, int y, int w, int h, int roudw, int roudh ) {
+ mPainter.drawRoundRect( x, y, w, h, roudw, roudh );
+}
+
+
+void KoWmfPaint::drawEllipse( int x, int y, int w, int h ) {
+ mPainter.drawEllipse( x, y, w, h );
+}
+
+
+void KoWmfPaint::drawArc( int x, int y, int w, int h, int a, int alen ) {
+ mPainter.drawArc( x, y, w, h, a, alen );
+}
+
+
+void KoWmfPaint::drawPie( int x, int y, int w, int h, int a, int alen ) {
+ mPainter.drawPie( x, y, w, h, a, alen );
+}
+
+
+void KoWmfPaint::drawChord( int x, int y, int w, int h, int a, int alen ) {
+ mPainter.drawChord( x, y, w, h, a, alen );
+}
+
+
+void KoWmfPaint::drawPolyline( const QPointArray &pa ) {
+ mPainter.drawPolyline( pa );
+}
+
+
+void KoWmfPaint::drawPolygon( const QPointArray &pa, bool winding ) {
+ mPainter.drawPolygon( pa, winding );
+}
+
+
+void KoWmfPaint::drawPolyPolygon( QPtrList<QPointArray>& listPa, bool winding ) {
+ QPointArray *pa;
+
+ mPainter.save();
+ QBrush brush = mPainter.brush();
+
+ // define clipping region
+ QRegion region;
+ for ( pa = listPa.first() ; pa ; pa = listPa.next() ) {
+ region = region.eor( *pa );
+ }
+ mPainter.setClipRegion( region, QPainter::CoordPainter );
+
+ // fill polygons
+ if ( brush != Qt::NoBrush ) {
+ mPainter.fillRect( region.boundingRect(), brush );
+ }
+
+ // draw polygon's border
+ mPainter.setClipping( false );
+ if ( mPainter.pen().style() != Qt::NoPen ) {
+ mPainter.setBrush( Qt::NoBrush );
+ for ( pa = listPa.first() ; pa ; pa = listPa.next() ) {
+ mPainter.drawPolygon( *pa, winding );
+ }
+ }
+
+ // restore previous state
+ mPainter.restore();
+}
+
+
+void KoWmfPaint::drawImage( int x, int y, const QImage &img, int sx, int sy, int sw, int sh ) {
+ mPainter.drawImage( x, y, img, sx, sy, sw, sh );
+}
+
+
+void KoWmfPaint::drawText( int x, int y, int w, int h, int flags, const QString& s, double ) {
+ mPainter.drawText( x, y, w, h, flags, s );
+}
+
+
diff --git a/lib/kwmf/kowmfpaint.h b/lib/kwmf/kowmfpaint.h
new file mode 100644
index 00000000..b229f2ff
--- /dev/null
+++ b/lib/kwmf/kowmfpaint.h
@@ -0,0 +1,127 @@
+/* This file is part of the KDE libraries
+ * Copyright (c) 2003 thierry lorthiois ([email protected])
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+#ifndef _KOWMFPAINT_H_
+#define _KOWMFPAINT_H_
+
+#include <qpainter.h>
+
+#include "kowmfread.h"
+#include <../kofficecore/koffice_export.h>
+/**
+ * KoWmfPaint inherits the abstract class KoWmfRead
+ * and redirects WMF actions onto a QPaintDevice.
+ * Uses relative or absolute coordinate.
+ *
+ * how to use:
+ * <pre>
+ * QPixmap pix( 100, 100 );
+ * KoWmfPaint wmf;
+ * if ( wmf.load( "/home/test.wmf" ) ) {
+ * wmf.play( pix );
+ * }
+ * paint.drawPixmap( 0, 0, pix );
+ * </pre>
+ *
+ */
+
+class KOWMF_EXPORT KoWmfPaint : public KoWmfRead
+{
+public:
+ KoWmfPaint();
+ ~KoWmfPaint() { }
+
+ /**
+ * play WMF file on a QPaintDevice. Return true on success.
+ * Use absolute or relative coordinate :
+ * absolute coord. reset the world transfomation Matrix (by default)
+ * relative coord. use the existing world transfomation Matrix
+ */
+ bool play( QPaintDevice& target, bool relativeCoord=false );
+
+
+private:
+ // -------------------------------------------------------------------------
+ // A virtual QPainter
+ bool begin();
+ bool end();
+ void save();
+ void restore();
+
+ // Drawing tools
+ void setFont( const QFont& font );
+ // the pen : the width of the pen is in logical coordinate
+ void setPen( const QPen& pen );
+ const QPen& pen() const;
+ void setBrush( const QBrush& brush );
+
+ // Drawing attributes/modes
+ void setBackgroundColor( const QColor& c );
+ void setBackgroundMode( Qt::BGMode mode );
+ void setRasterOp( Qt::RasterOp op );
+
+ /**
+ * Change logical Coordinate
+ * some wmf files call those functions several times in the middle of a drawing
+ * others wmf files doesn't call setWindow* at all
+ * negative width and height are possible
+ */
+ void setWindowOrg( int left, int top );
+ void setWindowExt( int width, int height );
+
+ // Clipping
+ // the 'CoordinateMode' is ommitted : always CoordPainter in wmf
+ // setClipRegion() is often used with save() and restore() => implement all or none
+ void setClipRegion( const QRegion &rec );
+ QRegion clipRegion();
+
+ // Graphics drawing functions
+ void moveTo( int x, int y );
+ void lineTo( int x, int y );
+ void drawRect( int x, int y, int w, int h );
+ void drawRoundRect( int x, int y, int w, int h, int = 25, int = 25 );
+ void drawEllipse( int x, int y, int w, int h );
+ void drawArc( int x, int y, int w, int h, int a, int alen );
+ void drawPie( int x, int y, int w, int h, int a, int alen );
+ void drawChord( int x, int y, int w, int h, int a, int alen );
+ void drawPolyline( const QPointArray& pa );
+ void drawPolygon( const QPointArray& pa, bool winding=FALSE );
+ /**
+ * drawPolyPolygon draw the XOR of a list of polygons
+ * listPa : list of polygons
+ */
+ void drawPolyPolygon( QPtrList<QPointArray>& listPa, bool winding=FALSE );
+ void drawImage( int x, int y, const QImage &, int sx = 0, int sy = 0, int sw = -1, int sh = -1 );
+
+ // Text drawing functions
+ // rotation = the degrees of rotation in counterclockwise
+ // not yet implemented in KWinMetaFile
+ void drawText( int x, int y, int w, int h, int flags, const QString &s, double rotation );
+
+ // matrix transformation : only used in some bitmap manipulation
+ void setWorldMatrix( const QWMatrix &, bool combine=FALSE );
+
+private:
+ QPainter mPainter;
+ QPaintDevice *mTarget;
+ bool mRelativeCoord;
+ // memorisation of WMF matrix transformation (in relative coordinate)
+ QWMatrix mInternalWorldMatrix;
+
+};
+
+#endif
diff --git a/lib/kwmf/kowmfread.cc b/lib/kwmf/kowmfread.cc
new file mode 100644
index 00000000..a4df0023
--- /dev/null
+++ b/lib/kwmf/kowmfread.cc
@@ -0,0 +1,101 @@
+/* This file is part of the KDE libraries
+ * Copyright (c) 2003 thierry lorthiois ([email protected])
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <qfile.h>
+#include <kdebug.h>
+
+#include "kowmfread.h"
+#include "kowmfreadprivate.h"
+
+KoWmfRead::KoWmfRead() {
+ mKwmf = new KoWmfReadPrivate();
+}
+
+KoWmfRead::~KoWmfRead() {
+ delete mKwmf;
+}
+
+
+bool KoWmfRead::load( const QString& filename )
+{
+ QFile file( filename );
+
+ if ( !file.open( IO_ReadOnly ) )
+ {
+ kdDebug() << "KoWmfRead : Cannot open file " << QFile::encodeName(filename) << endl;
+ return false;
+ }
+
+ bool ret = mKwmf->load( file.readAll() );
+ file.close();
+
+ return ret;
+}
+
+
+bool KoWmfRead::load( const QByteArray& array )
+{
+ return mKwmf->load( array );
+}
+
+
+bool KoWmfRead::play( )
+{
+ return mKwmf->play( this );
+}
+
+
+bool KoWmfRead::isValid( void ) const {
+ return mKwmf->mValid;
+}
+
+
+bool KoWmfRead::isStandard( void ) const {
+ return mKwmf->mStandard;
+}
+
+
+bool KoWmfRead::isPlaceable( void ) const {
+ return mKwmf->mPlaceable;
+}
+
+
+bool KoWmfRead::isEnhanced( void ) const {
+ return mKwmf->mEnhanced;
+}
+
+
+QRect KoWmfRead::boundingRect( void ) const {
+ return mKwmf->mBBox;
+}
+
+
+int KoWmfRead::defaultDpi( void ) const {
+ if ( mKwmf->mPlaceable ) {
+ return mKwmf->mDpi;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+void KoWmfRead::setDebug( int nbrFunc ) {
+ mKwmf->mNbrFunc = nbrFunc;
+}
+
diff --git a/lib/kwmf/kowmfread.h b/lib/kwmf/kowmfread.h
new file mode 100644
index 00000000..becfc74f
--- /dev/null
+++ b/lib/kwmf/kowmfread.h
@@ -0,0 +1,154 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 2003 thierry lorthiois ([email protected])
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+#ifndef _KOWMFREAD_H_
+#define _KOWMFREAD_H_
+
+#include <qpen.h>
+#include <qbrush.h>
+#include <qfont.h>
+#include <qcolor.h>
+#include <qrect.h>
+#include <qregion.h>
+#include <qimage.h>
+#include <qwmatrix.h>
+#include <qstring.h>
+#include <qptrlist.h>
+#include <qpointarray.h>
+
+#include <../kofficecore/koffice_export.h>
+class KoWmfReadPrivate;
+
+/**
+ * KoWmfRead allows the redirection of the actions stored in a WMF file.
+ * Most of the virtuals functions are compatible with QPainter format.
+ *
+ * How to use :
+ * inherit this class and define abstract functions
+ * then create an object and call @ref load() and @ref play()
+ *
+ */
+
+class KOWMF_EXPORT KoWmfRead
+{
+public:
+ KoWmfRead();
+ virtual ~KoWmfRead();
+
+ /**
+ * Load WMF file. Returns true on success.
+ */
+ virtual bool load( const QString& fileName );
+ virtual bool load( const QByteArray& array );
+
+ /**
+ * play the WMF file => call virtuals functions
+ */
+ virtual bool play( );
+
+ /**
+ * Returns true if the metafile is standard / placeable / enhanced / valid
+ */
+ bool isStandard( void ) const;
+ bool isPlaceable( void ) const;
+ bool isEnhanced( void ) const;
+ bool isValid( void ) const;
+
+ /**
+ * Returns the bounding rectangle
+ * Standard Meta File : return the bounding box from setWindowOrg and setWindowExt (slow)
+ * Placeable Meta File : return the bounding box from header
+ * always in logical coordinate
+ */
+ virtual QRect boundingRect( void ) const;
+
+ /**
+ * Returns the default DotPerInch for placeable meta file,
+ * return 0 for Standard meta file
+ */
+ int defaultDpi( void ) const;
+
+ /**
+ * Activate debug mode.
+ * nbFunc : number of functions to draw
+ * nbFunc!=0 switch to debug mode with trace
+ */
+ void setDebug( int nbFunc );
+
+ // -------------------------------------------------------------------------
+ // A virtual QPainter : inherit those virtuals functions
+ // for a good documentation : check QPainter documentation
+ virtual bool begin() = 0;
+ virtual bool end() = 0;
+ virtual void save() = 0;
+ virtual void restore() = 0;
+
+ // Drawing tools
+ virtual void setFont( const QFont & ) = 0;
+ // the pen : the width of the pen is in logical coordinate
+ virtual void setPen( const QPen &p ) = 0;
+ virtual const QPen &pen() const = 0;
+ virtual void setBrush( const QBrush & ) = 0;
+
+ // Drawing attributes/modes
+ virtual void setBackgroundColor( const QColor & ) = 0;
+ virtual void setBackgroundMode( Qt::BGMode ) = 0;
+ virtual void setRasterOp( Qt::RasterOp ) = 0;
+
+ // Change logical Coordinate
+ // some wmf files call those functions several times in the middle of a drawing
+ // others doesn't call setWindow* at all
+ virtual void setWindowOrg( int left, int top ) = 0;
+ virtual void setWindowExt( int width, int height ) = 0;
+
+ // Clipping
+ // the 'CoordinateMode' parameter is ommitted : always CoordPainter in wmf
+ // setClipRegion() is often used with save() and restore() => implement all or none
+ virtual void setClipRegion( const QRegion & ) = 0;
+ virtual QRegion clipRegion() = 0;
+
+ // Graphics drawing functions
+ virtual void moveTo( int x, int y ) = 0;
+ virtual void lineTo( int x, int y ) = 0;
+ virtual void drawRect( int x, int y, int w, int h ) = 0;
+ virtual void drawRoundRect( int x, int y, int w, int h, int = 25, int = 25 ) = 0;
+ virtual void drawEllipse( int x, int y, int w, int h ) = 0;
+ virtual void drawArc( int x, int y, int w, int h, int a, int alen ) = 0;
+ virtual void drawPie( int x, int y, int w, int h, int a, int alen ) = 0;
+ virtual void drawChord( int x, int y, int w, int h, int a, int alen ) = 0;
+ virtual void drawPolyline( const QPointArray &pa ) = 0;
+ virtual void drawPolygon( const QPointArray &pa, bool winding=FALSE ) = 0;
+ // drawPolyPolygon draw the XOR of a list of polygons
+ // listPa : list of polygons
+ virtual void drawPolyPolygon( QPtrList<QPointArray>& listPa, bool winding=FALSE ) = 0;
+ virtual void drawImage( int x, int y, const QImage &, int sx = 0, int sy = 0, int sw = -1, int sh = -1 ) = 0;
+
+ // Text drawing functions
+ // rotation = the degrees of rotation in counterclockwise
+ // not yet implemented in KWinMetaFile
+ virtual void drawText( int x, int y, int w, int h, int flags, const QString &s, double rotation ) = 0;
+
+ // matrix transformation : only used for bitmap manipulation
+ virtual void setWorldMatrix( const QWMatrix &, bool combine=FALSE ) = 0;
+
+private:
+ KoWmfReadPrivate *mKwmf;
+
+};
+
+#endif
+
diff --git a/lib/kwmf/kowmfreadprivate.cc b/lib/kwmf/kowmfreadprivate.cc
new file mode 100644
index 00000000..7a8c5efa
--- /dev/null
+++ b/lib/kwmf/kowmfreadprivate.cc
@@ -0,0 +1,1251 @@
+/* This file is part of the KDE libraries
+ * Copyright (c) 1998 Stefan Taferner
+ * 2001/2003 thierry lorthiois ([email protected])
+ * With the help of WMF documentation by Caolan Mc Namara
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <math.h>
+#include <qfileinfo.h>
+#include <qimage.h>
+#include <qwmatrix.h>
+#include <qptrlist.h>
+#include <qpointarray.h>
+#include <qdatastream.h>
+#include <kdebug.h>
+
+#include "kowmfreadprivate.h"
+#include "kowmfread.h"
+
+
+KoWmfReadPrivate::KoWmfReadPrivate()
+{
+ mNbrFunc = 0;
+ mValid = false;
+ mStandard = false;
+ mPlaceable = false;
+ mEnhanced = false;
+ mBuffer = 0;
+ mObjHandleTab = 0;
+}
+
+
+KoWmfReadPrivate::~KoWmfReadPrivate()
+{
+ if ( mObjHandleTab != 0 ) {
+ for ( int i=0 ; i < mNbrObject ; i++ ) {
+ if ( mObjHandleTab[i] != 0 )
+ delete mObjHandleTab[i];
+ }
+ delete[] mObjHandleTab;
+ }
+ if ( mBuffer != 0 ) {
+ mBuffer->close();
+ delete mBuffer;
+ }
+}
+
+
+bool KoWmfReadPrivate::load( const QByteArray& array )
+{
+ // delete previous buffer
+ if ( mBuffer != 0 ) {
+ mBuffer->close();
+ delete mBuffer;
+ }
+
+ // load into buffer
+ mBuffer = new QBuffer( array );
+ mBuffer->open( IO_ReadOnly );
+
+ // read and check the header
+ WmfEnhMetaHeader eheader;
+ WmfMetaHeader header;
+ WmfPlaceableHeader pheader;
+ unsigned short checksum;
+ int filePos;
+
+ QDataStream st( mBuffer );
+ st.setByteOrder( QDataStream::LittleEndian );
+ mStackOverflow = mWinding = false;
+ mTextAlign = mTextRotation = 0;
+ mTextColor = Qt::black;
+ mValid = false;
+ mStandard = false;
+ mPlaceable = false;
+ mEnhanced = false;
+
+ //----- Read placeable metafile header
+ st >> pheader.key;
+ if ( pheader.key==( Q_UINT32 )APMHEADER_KEY ) {
+ mPlaceable = true;
+ st >> pheader.handle;
+ st >> pheader.left;
+ st >> pheader.top;
+ st >> pheader.right;
+ st >> pheader.bottom;
+ st >> pheader.inch;
+ st >> pheader.reserved;
+ st >> pheader.checksum;
+ checksum = calcCheckSum( &pheader );
+ if ( pheader.checksum!=checksum ) {
+ return false;
+ }
+ st >> header.fileType;
+ st >> header.headerSize;
+ st >> header.version;
+ st >> header.fileSize;
+ st >> header.numOfObjects;
+ st >> header.maxRecordSize;
+ st >> header.numOfParameters;
+ mNbrObject = header.numOfObjects;
+ mBBox.setLeft( pheader.left );
+ mBBox.setTop( pheader.top );
+ mBBox.setRight( pheader.right );
+ mBBox.setBottom( pheader.bottom );
+ mDpi = pheader.inch;
+ }
+ else {
+ mBuffer->at( 0 );
+ //----- Read as enhanced metafile header
+ filePos = mBuffer->at();
+ st >> eheader.recordType;
+ st >> eheader.recordSize;
+ st >> eheader.boundsLeft;
+ st >> eheader.boundsTop;
+ st >> eheader.boundsRight;
+ st >> eheader.boundsBottom;
+ st >> eheader.frameLeft;
+ st >> eheader.frameTop;
+ st >> eheader.frameRight;
+ st >> eheader.frameBottom;
+ st >> eheader.signature;
+ if ( eheader.signature==ENHMETA_SIGNATURE ) {
+ mEnhanced = true;
+ st >> eheader.version;
+ st >> eheader.size;
+ st >> eheader.numOfRecords;
+ st >> eheader.numHandles;
+ st >> eheader.reserved;
+ st >> eheader.sizeOfDescription;
+ st >> eheader.offsetOfDescription;
+ st >> eheader.numPaletteEntries;
+ st >> eheader.widthDevicePixels;
+ st >> eheader.heightDevicePixels;
+ st >> eheader.widthDeviceMM;
+ st >> eheader.heightDeviceMM;
+ }
+ else {
+ //----- Read as standard metafile header
+ mStandard = true;
+ mBuffer->at( filePos );
+ st >> header.fileType;
+ st >> header.headerSize;
+ st >> header.version;
+ st >> header.fileSize;
+ st >> header.numOfObjects;
+ st >> header.maxRecordSize;
+ st >> header.numOfParameters;
+ mNbrObject = header.numOfObjects;
+ }
+ }
+ mOffsetFirstRecord = mBuffer->at();
+
+ //----- Test header validity
+ if ( ((header.headerSize == 9) && (header.numOfParameters == 0)) || (mPlaceable) ) {
+ // valid wmf file
+ mValid = true;
+ }
+ else {
+ kdDebug() << "KoWmfReadPrivate : incorrect file format !" << endl;
+ }
+
+ // check bounding rectangle for standard meta file
+ if ( (mValid) && (mStandard) ) {
+ Q_UINT16 numFunction = 1;
+ Q_UINT32 size;
+ bool firstOrg=true, firstExt=true;
+
+ // search functions setWindowOrg and setWindowExt
+ while ( numFunction ) {
+ filePos = mBuffer->at();
+ st >> size >> numFunction;
+
+ if ( size == 0 ) {
+ kdDebug() << "KoWmfReadPrivate : incorrect file!" << endl;
+ mValid = 0;
+ break;
+ }
+
+ numFunction &= 0xFF;
+ if ( numFunction == 11 ) {
+ Q_INT16 top, left;
+
+ st >> top >> left;
+ if ( firstOrg ) {
+ firstOrg = false;
+ mBBox.setLeft( left );
+ mBBox.setTop( top );
+ }
+ else {
+ if ( left < mBBox.left() ) mBBox.setLeft( left );
+ if ( top < mBBox.top() ) mBBox.setTop( top );
+ }
+ }
+ if ( numFunction == 12 ) {
+ Q_INT16 width, height;
+
+ st >> height >> width;
+ if ( width < 0 ) width = -width;
+ if ( height < 0 ) height = -height;
+ if ( firstExt ) {
+ firstExt = false;
+ mBBox.setWidth( width );
+ mBBox.setHeight( height );
+ }
+ else {
+ if ( width > mBBox.width() ) mBBox.setWidth( width );
+ if ( height > mBBox.height() ) mBBox.setHeight( height );
+ }
+ }
+ mBuffer->at( filePos + (size<<1) );
+ // ## shouldn't we break from the loop as soon as we found what we were looking for?
+ }
+ }
+
+ return (mValid);
+}
+
+
+bool KoWmfReadPrivate::play( KoWmfRead* readWmf )
+{
+ if ( !(mValid) ) {
+ kdDebug() << "KoWmfReadPrivate::play : invalid WMF file" << endl;
+ return false;
+ }
+
+ if ( mNbrFunc ) {
+ if ( (mStandard) ) {
+ kdDebug() << "Standard : " << mBBox.left() << " " << mBBox.top() << " " << mBBox.width() << " " << mBBox.height() << endl;
+ }
+ else {
+ kdDebug() << "DPI : " << mDpi << " : " << mBBox.left() << " " << mBBox.top() << " " << mBBox.width() << " " << mBBox.height() << endl;
+ kdDebug() << "inch : " << mBBox.width()/mDpi << " " << mBBox.height()/mDpi << endl;
+ kdDebug() << "mm : " << mBBox.width()*25.4/mDpi << " " << mBBox.height()*25.4/mDpi << endl;
+ }
+ kdDebug() << mValid << " " << mStandard << " " << mPlaceable << endl;
+ }
+
+ // stack of handle
+ mObjHandleTab = new KoWmfHandle* [ mNbrObject ];
+ for ( int i=0; i < mNbrObject ; i++ ) {
+ mObjHandleTab[ i ] = 0;
+ }
+
+ Q_UINT16 numFunction;
+ Q_UINT32 size;
+ int bufferOffset, j;
+
+ // buffer with functions
+ QDataStream st( mBuffer );
+ st.setByteOrder( QDataStream::LittleEndian );
+
+ mReadWmf = readWmf;
+ mWindow = mBBox;
+ if ( mReadWmf->begin() ) {
+ // play wmf functions
+ mBuffer->at( mOffsetFirstRecord );
+ numFunction = j = 1;
+ mWinding = false;
+
+ while ( ( numFunction ) && ( !mStackOverflow ) ) {
+ bufferOffset = mBuffer->at();
+ st >> size >> numFunction;
+
+ /**
+ * mapping between n� function and index of table 'metaFuncTab'
+ * lower 8 digits of the function => entry in the table
+ */
+ numFunction &= 0xFF;
+ if ( numFunction > 0x5F ) {
+ numFunction -= 0x90;
+ }
+ if ( (numFunction > 111) || (koWmfFunc[ numFunction ].method == 0) ) {
+ // function outside WMF specification
+ kdDebug() << "KoWmfReadPrivate::paint : BROKEN WMF file" << endl;
+ mValid = false;
+ break;
+ }
+
+ if ( mNbrFunc ) {
+ // debug mode
+ if ( (j+12) > mNbrFunc ) {
+ // output last 12 functions
+ int offBuff = mBuffer->at();
+ Q_UINT16 param;
+
+ kdDebug() << j << " : " << numFunction << " : ";
+ for ( Q_UINT16 i=0 ; i < (size-3) ; i++ ) {
+ st >> param;
+ kdDebug() << param << " ";
+ }
+ kdDebug() << endl;
+ mBuffer->at( offBuff );
+ }
+ if ( j >= mNbrFunc ) {
+ break;
+ }
+ j++;
+ }
+
+ // execute the function
+ (this->*koWmfFunc[ numFunction ].method)( size, st );
+
+ mBuffer->at( bufferOffset + (size<<1) );
+ }
+
+ mReadWmf->end();
+ }
+
+ for ( int i=0 ; i < mNbrObject ; i++ ) {
+ if ( mObjHandleTab[ i ] != 0 )
+ delete mObjHandleTab[ i ];
+ }
+ delete[] mObjHandleTab;
+ mObjHandleTab = 0;
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Metafile painter methods
+
+void KoWmfReadPrivate::setWindowOrg( Q_UINT32, QDataStream& stream )
+{
+ Q_INT16 top, left;
+
+ stream >> top >> left;
+ mReadWmf->setWindowOrg( left, top );
+ mWindow.setLeft( left );
+ mWindow.setTop( top );
+// kdDebug() << "Org : (" << left << ", " << top << ") " << endl;
+}
+
+/* TODO : deeper look in negative width and height
+*/
+
+void KoWmfReadPrivate::setWindowExt( Q_UINT32, QDataStream& stream )
+{
+ Q_INT16 width, height;
+
+ // negative value allowed for width and height
+ stream >> height >> width;
+ mReadWmf->setWindowExt( width, height );
+ mWindow.setWidth( width );
+ mWindow.setHeight( height );
+// kdDebug() << "Ext : (" << width << ", " << height << ") "<< endl;
+}
+
+
+void KoWmfReadPrivate::OffsetWindowOrg( Q_UINT32, QDataStream &stream )
+{
+ Q_INT16 offTop, offLeft;
+
+ stream >> offTop >> offLeft;
+ mReadWmf->setWindowOrg( mWindow.left() + offLeft, mWindow.top() + offTop );
+ mWindow.setLeft( mWindow.left() + offLeft );
+ mWindow.setTop( mWindow.top() + offTop );
+}
+
+
+void KoWmfReadPrivate::ScaleWindowExt( Q_UINT32, QDataStream &stream )
+{
+ Q_INT16 width, height;
+ Q_INT16 heightDenom, heightNum, widthDenom, widthNum;
+
+ stream >> heightDenom >> heightNum >> widthDenom >> widthNum;
+
+ if ( ( widthDenom != 0 ) && ( heightDenom != 0 ) ) {
+ width = (mWindow.width() * widthNum) / widthDenom;
+ height = (mWindow.height() * heightNum) / heightDenom;
+ mReadWmf->setWindowExt( width, height );
+ mWindow.setWidth( width );
+ mWindow.setHeight( height );
+ }
+// kdDebug() << "KoWmfReadPrivate::ScaleWindowExt : " << widthDenom << " " << heightDenom << endl;
+}
+
+
+//-----------------------------------------------------------------------------
+// Drawing
+
+void KoWmfReadPrivate::lineTo( Q_UINT32, QDataStream& stream )
+{
+ Q_INT16 top, left;
+
+ stream >> top >> left;
+ mReadWmf->lineTo( left, top );
+}
+
+
+void KoWmfReadPrivate::moveTo( Q_UINT32, QDataStream& stream )
+{
+ Q_INT16 top, left;
+
+ stream >> top >> left;
+ mReadWmf->moveTo( left, top );
+}
+
+
+void KoWmfReadPrivate::ellipse( Q_UINT32, QDataStream& stream )
+{
+ Q_INT16 top, left, right, bottom;
+
+ stream >> bottom >> right >> top >> left;
+ mReadWmf->drawEllipse( left, top, right-left, bottom-top );
+}
+
+
+void KoWmfReadPrivate::polygon( Q_UINT32, QDataStream& stream )
+{
+ Q_UINT16 num;
+
+ stream >> num;
+
+ QPointArray pa( num );
+
+ pointArray( stream, pa );
+ mReadWmf->drawPolygon( pa, mWinding );
+}
+
+
+void KoWmfReadPrivate::polyPolygon( Q_UINT32, QDataStream& stream )
+{
+ Q_UINT16 numberPoly;
+ Q_UINT16 sizePoly;
+ QPtrList<QPointArray> listPa;
+
+ stream >> numberPoly;
+
+ listPa.setAutoDelete( true );
+ for ( int i=0 ; i < numberPoly ; i++ ) {
+ stream >> sizePoly;
+ listPa.append( new QPointArray( sizePoly ) );
+ }
+
+ // list of point array
+ QPointArray *pa;
+ for ( pa = listPa.first() ; pa ; pa = listPa.next() ) {
+ pointArray( stream, *pa );
+ }
+
+ // draw polygon's
+ mReadWmf->drawPolyPolygon( listPa, mWinding );
+ listPa.clear();
+}
+
+
+void KoWmfReadPrivate::polyline( Q_UINT32, QDataStream& stream )
+{
+ Q_UINT16 num;
+
+ stream >> num;
+ QPointArray pa( num );
+
+ pointArray( stream, pa );
+ mReadWmf->drawPolyline( pa );
+}
+
+
+void KoWmfReadPrivate::rectangle( Q_UINT32, QDataStream& stream )
+{
+ Q_INT16 top, left, right, bottom;
+
+ stream >> bottom >> right >> top >> left;
+ mReadWmf->drawRect( left, top, right-left, bottom-top );
+}
+
+
+void KoWmfReadPrivate::roundRect( Q_UINT32, QDataStream& stream )
+{
+ int xRnd = 0, yRnd = 0;
+ Q_UINT16 widthCorner, heightCorner;
+ Q_INT16 top, left, right, bottom;
+
+ stream >> heightCorner >> widthCorner;
+ stream >> bottom >> right >> top >> left;
+
+ // convert (widthCorner, heightCorner) in percentage
+ if ( (right - left) != 0 )
+ xRnd = (widthCorner * 100) / (right - left);
+ if ( (bottom - top) != 0 )
+ yRnd = (heightCorner * 100) / (bottom - top);
+
+ mReadWmf->drawRoundRect( left, top, right-left, bottom-top, xRnd, yRnd );
+}
+
+
+void KoWmfReadPrivate::arc( Q_UINT32, QDataStream& stream )
+{
+ int xCenter, yCenter, angleStart, aLength;
+ Q_INT16 topEnd, leftEnd, topStart, leftStart;
+ Q_INT16 top, left, right, bottom;
+
+ stream >> topEnd >> leftEnd >> topStart >> leftStart;
+ stream >> bottom >> right >> top >> left;
+
+ xCenter = left + ((right-left) / 2);
+ yCenter = top + ((bottom-top) / 2);
+ xyToAngle ( leftStart-xCenter, yCenter-topStart, leftEnd-xCenter, yCenter-topEnd, angleStart, aLength );
+
+ mReadWmf->drawArc( left, top, right-left, bottom-top, angleStart, aLength);
+}
+
+
+void KoWmfReadPrivate::chord( Q_UINT32, QDataStream& stream )
+{
+ int xCenter, yCenter, angleStart, aLength;
+ Q_INT16 topEnd, leftEnd, topStart, leftStart;
+ Q_INT16 top, left, right, bottom;
+
+ stream >> topEnd >> leftEnd >> topStart >> leftStart;
+ stream >> bottom >> right >> top >> left;
+
+ xCenter = left + ((right-left) / 2);
+ yCenter = top + ((bottom-top) / 2);
+ xyToAngle ( leftStart-xCenter, yCenter-topStart, leftEnd-xCenter, yCenter-topEnd, angleStart, aLength );
+
+ mReadWmf->drawChord( left, top, right-left, bottom-top, angleStart, aLength);
+}
+
+
+void KoWmfReadPrivate::pie( Q_UINT32, QDataStream& stream )
+{
+ int xCenter, yCenter, angleStart, aLength;
+ Q_INT16 topEnd, leftEnd, topStart, leftStart;
+ Q_INT16 top, left, right, bottom;
+
+ stream >> topEnd >> leftEnd >> topStart >> leftStart;
+ stream >> bottom >> right >> top >> left;
+
+ xCenter = left + ((right-left) / 2);
+ yCenter = top + ((bottom-top) / 2);
+ xyToAngle ( leftStart-xCenter, yCenter-topStart, leftEnd-xCenter, yCenter-topEnd, angleStart, aLength );
+
+ mReadWmf->drawPie( left, top, right-left, bottom-top, angleStart, aLength);
+}
+
+
+void KoWmfReadPrivate::setPolyFillMode( Q_UINT32, QDataStream& stream )
+{
+ Q_UINT16 winding;
+
+ stream >> winding;
+ mWinding = (winding != 0);
+}
+
+
+void KoWmfReadPrivate::setBkColor( Q_UINT32, QDataStream& stream )
+{
+ Q_UINT32 color;
+
+ stream >> color;
+ mReadWmf->setBackgroundColor( qtColor( color ) );
+}
+
+
+void KoWmfReadPrivate::setBkMode( Q_UINT32, QDataStream& stream )
+{
+ Q_UINT16 bkMode;
+
+ stream >> bkMode;
+ if ( bkMode == 1 )
+ mReadWmf->setBackgroundMode( Qt::TransparentMode );
+ else
+ mReadWmf->setBackgroundMode( Qt::OpaqueMode );
+}
+
+
+void KoWmfReadPrivate::setPixel( Q_UINT32, QDataStream& stream )
+{
+ Q_INT16 top, left;
+ Q_UINT32 color;
+
+ stream >> color >> top >> left;
+
+ QPen oldPen = mReadWmf->pen();
+ QPen pen = oldPen;
+ pen.setColor( qtColor( color ) );
+ mReadWmf->setPen( pen );
+ mReadWmf->moveTo( left, top );
+ mReadWmf->lineTo( left, top );
+ mReadWmf->setPen( oldPen );
+}
+
+
+void KoWmfReadPrivate::setRop( Q_UINT32, QDataStream& stream )
+{
+ Q_UINT16 rop;
+
+ stream >> rop;
+ mReadWmf->setRasterOp( winToQtRaster( rop ) );
+}
+
+
+void KoWmfReadPrivate::saveDC( Q_UINT32, QDataStream& )
+{
+ mReadWmf->save();
+}
+
+
+void KoWmfReadPrivate::restoreDC( Q_UINT32, QDataStream& stream )
+{
+ Q_INT16 num;
+
+ stream >> num;
+ for ( int i=0; i > num ; i-- )
+ mReadWmf->restore();
+}
+
+
+void KoWmfReadPrivate::intersectClipRect( Q_UINT32, QDataStream& stream )
+{
+ Q_INT16 top, left, right, bottom;
+
+ stream >> bottom >> right >> top >> left;
+
+ QRegion region = mReadWmf->clipRegion();
+ QRegion newRegion( left, top, right-left, bottom-top );
+ if ( region.isEmpty() ) {
+ region = newRegion;
+ }
+ else {
+ region = region.intersect( newRegion );
+ }
+
+ mReadWmf->setClipRegion( region );
+}
+
+
+void KoWmfReadPrivate::excludeClipRect( Q_UINT32, QDataStream& stream )
+{
+ Q_INT16 top, left, right, bottom;
+
+ stream >> bottom >> right >> top >> left;
+
+ QRegion region = mReadWmf->clipRegion();
+ QRegion newRegion( left, top, right-left, bottom-top );
+ if ( region.isEmpty() ) {
+ region = newRegion;
+ }
+ else {
+ region = region.subtract( newRegion );
+ }
+
+ mReadWmf->setClipRegion( region );
+}
+
+
+//-----------------------------------------------------------------------------
+// Text
+
+void KoWmfReadPrivate::setTextColor( Q_UINT32, QDataStream& stream )
+{
+ Q_UINT32 color;
+
+ stream >> color;
+ mTextColor = qtColor( color );
+}
+
+
+void KoWmfReadPrivate::setTextAlign( Q_UINT32, QDataStream& stream )
+{
+ stream >> mTextAlign;
+}
+
+
+void KoWmfReadPrivate::textOut( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "textOut : unimplemented " << endl;
+ }
+}
+
+
+void KoWmfReadPrivate::extTextOut( Q_UINT32 , QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "extTextOut : unimplemented " << endl;
+ }
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Bitmap
+
+void KoWmfReadPrivate::SetStretchBltMode( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "SetStretchBltMode : unimplemented " << endl;
+ }
+}
+
+
+void KoWmfReadPrivate::dibBitBlt( Q_UINT32 size, QDataStream& stream )
+{
+ Q_UINT32 raster;
+ Q_INT16 topSrc, leftSrc, widthSrc, heightSrc;
+ Q_INT16 topDst, leftDst;
+
+ stream >> raster;
+ stream >> topSrc >> leftSrc >> heightSrc >> widthSrc;
+ stream >> topDst >> leftDst;
+
+ if ( size > 11 ) { // DIB image
+ QImage bmpSrc;
+
+ if ( dibToBmp( bmpSrc, stream, (size - 11) * 2 ) ) {
+ mReadWmf->setRasterOp( winToQtRaster( raster ) );
+
+ mReadWmf->save();
+ if ( widthSrc < 0 ) {
+ // negative width => horizontal flip
+ QWMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
+ mReadWmf->setWorldMatrix( m, true );
+ }
+ if ( heightSrc < 0 ) {
+ // negative height => vertical flip
+ QWMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
+ mReadWmf->setWorldMatrix( m, true );
+ }
+ mReadWmf->drawImage( leftDst, topDst, bmpSrc, leftSrc, topSrc, widthSrc, heightSrc );
+ mReadWmf->restore();
+ }
+ }
+ else {
+ kdDebug() << "KoWmfReadPrivate::dibBitBlt without image not implemented " << endl;
+ }
+}
+
+
+void KoWmfReadPrivate::dibStretchBlt( Q_UINT32 size, QDataStream& stream )
+{
+ Q_UINT32 raster;
+ Q_INT16 topSrc, leftSrc, widthSrc, heightSrc;
+ Q_INT16 topDst, leftDst, widthDst, heightDst;
+ QImage bmpSrc;
+
+ stream >> raster;
+ stream >> heightSrc >> widthSrc >> topSrc >> leftSrc;
+ stream >> heightDst >> widthDst >> topDst >> leftDst;
+
+ if ( dibToBmp( bmpSrc, stream, (size - 13) * 2 ) ) {
+ mReadWmf->setRasterOp( winToQtRaster( raster ) );
+
+ mReadWmf->save();
+ if ( widthDst < 0 ) {
+ // negative width => horizontal flip
+ QWMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
+ mReadWmf->setWorldMatrix( m, true );
+ }
+ if ( heightDst < 0 ) {
+ // negative height => vertical flip
+ QWMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
+ mReadWmf->setWorldMatrix( m, true );
+ }
+ bmpSrc = bmpSrc.copy( leftSrc, topSrc, widthSrc, heightSrc );
+ // TODO: scale the bitmap : QImage::scale(widthDst, heightDst)
+ // is actually too slow
+
+ mReadWmf->drawImage( leftDst, topDst, bmpSrc );
+ mReadWmf->restore();
+ }
+}
+
+
+void KoWmfReadPrivate::stretchDib( Q_UINT32 size, QDataStream& stream )
+{
+ Q_UINT32 raster;
+ Q_INT16 arg, topSrc, leftSrc, widthSrc, heightSrc;
+ Q_INT16 topDst, leftDst, widthDst, heightDst;
+ QImage bmpSrc;
+
+ stream >> raster >> arg;
+ stream >> heightSrc >> widthSrc >> topSrc >> leftSrc;
+ stream >> heightDst >> widthDst >> topDst >> leftDst;
+
+ if ( dibToBmp( bmpSrc, stream, (size - 14) * 2 ) ) {
+ mReadWmf->setRasterOp( winToQtRaster( raster ) );
+
+ mReadWmf->save();
+ if ( widthDst < 0 ) {
+ // negative width => horizontal flip
+ QWMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
+ mReadWmf->setWorldMatrix( m, true );
+ }
+ if ( heightDst < 0 ) {
+ // negative height => vertical flip
+ QWMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
+ mReadWmf->setWorldMatrix( m, true );
+ }
+ bmpSrc = bmpSrc.copy( leftSrc, topSrc, widthSrc, heightSrc );
+ // TODO: scale the bitmap ( QImage::scale(param[ 8 ], param[ 7 ]) is actually too slow )
+
+ mReadWmf->drawImage( leftDst, topDst, bmpSrc );
+ mReadWmf->restore();
+ }
+}
+
+
+void KoWmfReadPrivate::dibCreatePatternBrush( Q_UINT32 size, QDataStream& stream )
+{
+ KoWmfPatternBrushHandle* handle = new KoWmfPatternBrushHandle;
+
+ if ( addHandle( handle ) ) {
+ Q_UINT32 arg;
+ QImage bmpSrc;
+
+ stream >> arg;
+ if ( dibToBmp( bmpSrc, stream, (size - 5) * 2 ) ) {
+ handle->image = bmpSrc;
+ handle->brush.setPixmap( handle->image );
+ }
+ else {
+ kdDebug() << "KoWmfReadPrivate::dibCreatePatternBrush : incorrect DIB image" << endl;
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Object handle
+
+void KoWmfReadPrivate::selectObject( Q_UINT32, QDataStream& stream )
+{
+ Q_UINT16 idx;
+
+ stream >> idx;
+ if ( (idx < mNbrObject) && (mObjHandleTab[ idx ] != 0) )
+ mObjHandleTab[ idx ]->apply( mReadWmf );
+ else
+ kdDebug() << "KoWmfReadPrivate::selectObject : selection of an empty object" << endl;
+}
+
+
+void KoWmfReadPrivate::deleteObject( Q_UINT32, QDataStream& stream )
+{
+ Q_UINT16 idx;
+
+ stream >> idx;
+ deleteHandle( idx );
+}
+
+
+void KoWmfReadPrivate::createEmptyObject()
+{
+ // allocation of an empty object (to keep object counting in sync)
+ KoWmfPenHandle* handle = new KoWmfPenHandle;
+
+ addHandle( handle );
+}
+
+
+void KoWmfReadPrivate::createBrushIndirect( Q_UINT32, QDataStream& stream )
+{
+ Qt::BrushStyle style;
+ Q_UINT16 sty, arg2;
+ Q_UINT32 color;
+ KoWmfBrushHandle* handle = new KoWmfBrushHandle;
+
+ if ( addHandle( handle ) ) {
+ stream >> sty >> color >> arg2;
+
+ if ( sty == 2 ) {
+ if ( arg2 < 6 )
+ style = koWmfHatchedStyleBrush[ arg2 ];
+ else
+ {
+ kdDebug() << "KoWmfReadPrivate::createBrushIndirect: invalid hatched brush " << arg2 << endl;
+ style = Qt::SolidPattern;
+ }
+ }
+ else {
+ if ( sty < 9 )
+ style = koWmfStyleBrush[ sty ];
+ else {
+ kdDebug() << "KoWmfReadPrivate::createBrushIndirect: invalid brush " << sty << endl;
+ style = Qt::SolidPattern;
+ }
+ }
+ handle->brush.setStyle( style );
+ handle->brush.setColor( qtColor( color ) );
+ }
+}
+
+
+void KoWmfReadPrivate::createPenIndirect( Q_UINT32, QDataStream& stream )
+{
+ // TODO: userStyle and alternateStyle
+ Qt::PenStyle penStyle;
+ Q_UINT32 color;
+ Q_UINT16 style, width, arg;
+
+ KoWmfPenHandle* handle = new KoWmfPenHandle;
+
+ if ( addHandle( handle ) ) {
+ stream >> style >> width >> arg >> color;
+
+ if ( style < 7 )
+ penStyle=koWmfStylePen[ style ];
+ else {
+ kdDebug() << "KoWmfReadPrivate::createPenIndirect: invalid pen " << style << endl;
+ penStyle = Qt::SolidLine;
+ }
+
+ handle->pen.setStyle( penStyle );
+ handle->pen.setColor( qtColor( color ) );
+ handle->pen.setCapStyle( Qt::RoundCap );
+ handle->pen.setWidth( width );
+ }
+}
+
+
+void KoWmfReadPrivate::createFontIndirect( Q_UINT32 size, QDataStream& stream )
+{
+ Q_INT16 pointSize, rotation;
+ Q_UINT16 weight, property, fixedPitch, arg;
+
+ KoWmfFontHandle* handle = new KoWmfFontHandle;
+
+ if ( addHandle( handle ) ) {
+ stream >> pointSize >> arg;
+ stream >> rotation >> arg;
+ stream >> weight >> property >> arg >> arg;
+ stream >> fixedPitch;
+
+ // text rotation (in 1/10 degree)
+ // TODO: memorisation of rotation in object Font
+ mTextRotation = -rotation / 10;
+ handle->font.setFixedPitch( ((fixedPitch & 0x01) == 0) );
+ // TODO: investigation why some test case need -2
+ // size of font in logical point
+ handle->font.setPointSize( QABS(pointSize) - 2 );
+ handle->font.setWeight( (weight >> 3) );
+ handle->font.setItalic( (property & 0x01) );
+ handle->font.setUnderline( (property & 0x100) );
+
+ // font name
+ int maxChar = (size-12) * 2;
+ char* nameFont = new char[maxChar];
+ stream.readRawBytes( nameFont, maxChar );
+ handle->font.setFamily( nameFont );
+ delete[] nameFont;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Misc functions
+
+void KoWmfReadPrivate::end( Q_UINT32, QDataStream& )
+{
+}
+
+Q_UINT16 KoWmfReadPrivate::calcCheckSum( WmfPlaceableHeader* apmfh )
+{
+ Q_UINT16* lpWord;
+ Q_UINT16 wResult, i;
+
+ // Start with the first word
+ wResult = *( lpWord = ( Q_UINT16* )( apmfh ) );
+ // XOR in each of the other 9 words
+ for( i=1; i<=9; i++ )
+ {
+ wResult ^= lpWord[ i ];
+ }
+ return wResult;
+}
+
+
+void KoWmfReadPrivate::notyet( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::region( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "region : unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::palette( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "palette : unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::escape( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "escape : unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::setRelAbs( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "setRelAbs : unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::setMapMode( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "setMapMode : unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::extFloodFill( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "extFloodFill : unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::startDoc( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "startDoc : unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::startPage( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "startPage : unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::endDoc( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "endDoc : unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::endPage( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "endPage : unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::resetDC( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "resetDC : unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::bitBlt( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "bitBlt : unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::setDibToDev( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "setDibToDev : unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::createBrush( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "createBrush : unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::createPatternBrush( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "createPatternBrush : unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::createBitmap( Q_UINT32, QDataStream& )
+{
+ if ( mNbrFunc ) {
+ kdDebug() << "createBitmap : unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::createBitmapIndirect( Q_UINT32, QDataStream& )
+{
+ createEmptyObject();
+ if ( mNbrFunc ) {
+ kdDebug() << "createBitmapIndirect : unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::createPalette( Q_UINT32, QDataStream& )
+{
+ createEmptyObject();
+ if ( mNbrFunc ) {
+ kdDebug() << "createPalette : unimplemented " << endl;
+ }
+}
+
+void KoWmfReadPrivate::createRegion( Q_UINT32, QDataStream& )
+{
+ createEmptyObject();
+ if ( mNbrFunc ) {
+ kdDebug() << "createRegion : unimplemented " << endl;
+ }
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Utilities and conversion Wmf -> Qt
+
+bool KoWmfReadPrivate::addHandle( KoWmfHandle* handle )
+{
+ int idx;
+
+ for ( idx=0; idx < mNbrObject ; idx++ ) {
+ if ( mObjHandleTab[ idx ] == 0 ) break;
+ }
+
+ if ( idx < mNbrObject ) {
+ mObjHandleTab[ idx ] = handle;
+ return true;
+ }
+ else {
+ delete handle;
+ mStackOverflow = true;
+ kdDebug() << "KoWmfReadPrivate::addHandle : stack overflow = broken file !" << endl;
+ return false;
+ }
+}
+
+
+void KoWmfReadPrivate::deleteHandle( int idx )
+{
+ if ( (idx < mNbrObject) && (mObjHandleTab[idx] != 0) ) {
+ delete mObjHandleTab[ idx ];
+ mObjHandleTab[ idx ] = 0;
+ }
+ else {
+ kdDebug() << "KoWmfReadPrivate::deletehandle() : bad index number" << endl;
+ }
+}
+
+
+void KoWmfReadPrivate::pointArray( QDataStream& stream, QPointArray& pa )
+{
+ Q_INT16 left, top;
+ int i, max;
+
+ for ( i=0, max=pa.size() ; i < max ; i++ ) {
+ stream >> left >> top;
+ pa.setPoint( i, left, top );
+ }
+}
+
+
+void KoWmfReadPrivate::xyToAngle( int xStart, int yStart, int xEnd, int yEnd, int& angleStart, int& angleLength )
+{
+ double 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;
+}
+
+
+Qt::RasterOp KoWmfReadPrivate::winToQtRaster( Q_UINT16 param ) const
+{
+ if ( param < 17 )
+ return koWmfOpTab16[ param ];
+ else
+ return Qt::CopyROP;
+}
+
+
+Qt::RasterOp KoWmfReadPrivate::winToQtRaster( Q_UINT32 param ) const
+{
+ /* TODO: Ternary raster operations
+ 0x00C000CA dest = (source AND pattern)
+ 0x00F00021 dest = pattern
+ 0x00FB0A09 dest = DPSnoo
+ 0x005A0049 dest = pattern XOR dest */
+ int i;
+
+ for ( i=0 ; i < 15 ; i++ ) {
+ if ( koWmfOpTab32[ i ].winRasterOp == param ) break;
+ }
+
+ if ( i < 15 )
+ return koWmfOpTab32[ i ].qtRasterOp;
+ else
+ return Qt::CopyROP;
+}
+
+
+bool KoWmfReadPrivate::dibToBmp( QImage& bmp, QDataStream& stream, Q_UINT32 size )
+{
+ typedef struct _BMPFILEHEADER {
+ Q_UINT16 bmType;
+ Q_UINT32 bmSize;
+ Q_UINT16 bmReserved1;
+ Q_UINT16 bmReserved2;
+ Q_UINT32 bmOffBits;
+ } BMPFILEHEADER;
+
+ int sizeBmp = size + 14;
+
+ QByteArray pattern( sizeBmp ); // BMP header and DIB data
+ pattern.fill(0);
+ stream.readRawBytes( &pattern[ 14 ], size );
+
+ // add BMP header
+ BMPFILEHEADER* bmpHeader;
+ bmpHeader = (BMPFILEHEADER*)(pattern.data());
+ bmpHeader->bmType = 0x4D42;
+ bmpHeader->bmSize = sizeBmp;
+
+// if ( !bmp.loadFromData( (const uchar*)bmpHeader, pattern.size(), "BMP" ) ) {
+ if ( !bmp.loadFromData( pattern, "BMP" ) ) {
+ kdDebug() << "KoWmfReadPrivate::dibToBmp: invalid bitmap " << endl;
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
diff --git a/lib/kwmf/kowmfreadprivate.h b/lib/kwmf/kowmfreadprivate.h
new file mode 100644
index 00000000..4dda478b
--- /dev/null
+++ b/lib/kwmf/kowmfreadprivate.h
@@ -0,0 +1,362 @@
+/* This file is part of the KDE libraries
+ * Copyright (c) 1998 Stefan Taferner
+ * 2001/2003 thierry lorthiois ([email protected])
+ * With the help of WMF documentation by Caolan Mc Namara
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+#ifndef _KOWMFREADPRIVATE_H_
+#define _KOWMFREADPRIVATE_H_
+
+#include <qpen.h>
+#include <qcolor.h>
+#include <qfont.h>
+#include <qrect.h>
+#include <qregion.h>
+#include <qbuffer.h>
+#include <qstring.h>
+
+#include "kowmfstruct.h"
+#include "kowmfstack.h"
+
+class KoWmfRead;
+
+/**
+ * KoWmfReadPrivate allows to read WMF files
+ *
+ */
+
+class KoWmfReadPrivate
+{
+public:
+ KoWmfReadPrivate();
+ virtual ~KoWmfReadPrivate();
+
+ /**
+ * Load WMF file. Returns true on success.
+ */
+ bool load( const QByteArray& array );
+
+ /**
+ * Plays a metafile in @p readKwmf and returns true on success.
+ * To draw on a device you have to inherit the class ReadKwmf
+ */
+ bool play( KoWmfRead* readKwmf );
+
+
+ /* Metafile painter methods */
+
+ /// set window origin
+ void setWindowOrg( Q_UINT32 size, QDataStream& stream );
+ /// set window extents
+ void setWindowExt( Q_UINT32 size, QDataStream& stream );
+ /// scale window extents
+ void ScaleWindowExt( Q_UINT32, QDataStream& stream );
+ /// offset in window origin
+ void OffsetWindowOrg( Q_UINT32, QDataStream& stream );
+
+ /****************** Drawing *******************/
+ /// draw line to coord
+ void lineTo( Q_UINT32 size, QDataStream& stream );
+ /// move pen to coord
+ void moveTo( Q_UINT32 size, QDataStream& stream );
+ /// draw ellipse
+ void ellipse( Q_UINT32 size, QDataStream& stream );
+ /// draw polygon
+ void polygon( Q_UINT32 size, QDataStream& stream );
+ /// draw a list of polygons
+ void polyPolygon( Q_UINT32 size, QDataStream& stream );
+ /// draw series of lines
+ void polyline( Q_UINT32 size, QDataStream& stream );
+ /// draw a rectangle
+ void rectangle( Q_UINT32 size, QDataStream& stream );
+ /// draw round rectangle
+ void roundRect( Q_UINT32 size, QDataStream& stream );
+ /// draw arc
+ void arc( Q_UINT32 size, QDataStream& stream );
+ /// draw chord
+ void chord( Q_UINT32 size, QDataStream& stream );
+ /// draw pie
+ void pie( Q_UINT32 size, QDataStream& stream );
+ /// set polygon fill mode
+ void setPolyFillMode( Q_UINT32 size, QDataStream& stream );
+ /// set background pen color
+ void setBkColor( Q_UINT32 size, QDataStream& stream );
+ /// set background pen mode
+ void setBkMode( Q_UINT32 size, QDataStream& stream );
+ /// set a pixel
+ void setPixel( Q_UINT32 size, QDataStream& stream );
+ /// set raster operation mode
+ void setRop( Q_UINT32 size, QDataStream& stream );
+ /// save device context */
+ void saveDC( Q_UINT32 size, QDataStream& stream );
+ /// restore device context
+ void restoreDC( Q_UINT32 size, QDataStream& stream );
+ /// clipping region is the intersection of this region and the original region
+ void intersectClipRect( Q_UINT32 size, QDataStream& stream );
+ /// delete a clipping rectangle of the original region
+ void excludeClipRect( Q_UINT32 size, QDataStream& stream );
+
+ /****************** Text *******************/
+ /// set text color
+ void setTextColor( Q_UINT32 size, QDataStream& stream );
+ /// set text alignment
+ void setTextAlign( Q_UINT32 size, QDataStream& stream );
+ /// draw text
+ void textOut( Q_UINT32 size, QDataStream& stream );
+ void extTextOut( Q_UINT32 size, QDataStream& stream );
+
+ /****************** Bitmap *******************/
+ void SetStretchBltMode( Q_UINT32, QDataStream& stream );
+ /// copies a DIB into a dest location
+ void dibBitBlt( Q_UINT32 size, QDataStream& stream );
+ /// stretches a DIB into a dest location
+ void dibStretchBlt( Q_UINT32 size, QDataStream& stream );
+ void stretchDib( Q_UINT32 size, QDataStream& stream );
+ /// create a pattern brush
+ void dibCreatePatternBrush( Q_UINT32 size, QDataStream& stream );
+
+ /****************** Object handle *******************/
+ /// activate object handle
+ void selectObject( Q_UINT32 size, QDataStream& stream );
+ /// free object handle
+ void deleteObject( Q_UINT32 size, QDataStream& stream );
+ /// create an empty object in the object list
+ void createEmptyObject();
+ /// create a logical brush
+ void createBrushIndirect( Q_UINT32 size, QDataStream& stream );
+ /// create a logical pen
+ void createPenIndirect( Q_UINT32 size, QDataStream& stream );
+ /// create a logical font
+ void createFontIndirect( Q_UINT32 size, QDataStream& stream );
+
+ /****************** misc *******************/
+ /// end of meta file
+ void end( Q_UINT32, QDataStream& stream );
+
+ /** Calculate header checksum */
+ static Q_UINT16 calcCheckSum( WmfPlaceableHeader* );
+
+ // function unimplemented
+ void notyet( Q_UINT32, QDataStream& stream );
+ void region( Q_UINT32, QDataStream& stream );
+ void palette( Q_UINT32, QDataStream& stream );
+ void escape( Q_UINT32, QDataStream& stream );
+ void setRelAbs( Q_UINT32, QDataStream& stream );
+ void setMapMode( Q_UINT32, QDataStream& stream );
+ void extFloodFill( Q_UINT32, QDataStream& stream );
+ void startDoc( Q_UINT32, QDataStream& stream );
+ void startPage( Q_UINT32, QDataStream& stream );
+ void endDoc( Q_UINT32, QDataStream& stream );
+ void endPage( Q_UINT32, QDataStream& stream );
+ void resetDC( Q_UINT32, QDataStream& stream );
+ void bitBlt( Q_UINT32, QDataStream& stream );
+ void setDibToDev( Q_UINT32, QDataStream& stream );
+ void createBrush( Q_UINT32, QDataStream& stream );
+ void createPatternBrush( Q_UINT32, QDataStream& stream );
+ void createBitmap( Q_UINT32, QDataStream& stream );
+ void createBitmapIndirect( Q_UINT32, QDataStream& stream );
+ void createPalette( Q_UINT32, QDataStream& stream );
+ void createRegion( Q_UINT32, QDataStream& stream );
+
+private:
+ //-----------------------------------------------------------------------------
+ // Utilities and conversion Wmf -> Qt
+
+ /** Handle win-object-handles */
+ bool addHandle( KoWmfHandle* );
+ void deleteHandle( int );
+
+ /** Convert QINT16 points into QPointArray */
+ void pointArray( QDataStream& stream, QPointArray& pa );
+
+ /** Convertion between windows color and QColor */
+ QColor qtColor( Q_UINT32 color ) const
+ { return QColor( color & 0xFF, (color>>8) & 0xFF, (color>>16) & 0xFF ); }
+
+ /** Convert (x1,y1) and (x2, y2) positions in angle and angleLength */
+ void xyToAngle( int xStart, int yStart, int xEnd, int yEnd, int& angle, int& aLength );
+
+ /** Convert windows rasterOp in QT rasterOp */
+ Qt::RasterOp winToQtRaster( Q_UINT16 param ) const;
+ Qt::RasterOp winToQtRaster( Q_UINT32 param ) const;
+
+ /** Converts DIB to BMP */
+ bool dibToBmp( QImage& bmp, QDataStream& stream, Q_UINT32 size);
+
+
+public:
+ // state of the WMF
+ bool mValid;
+ bool mStandard;
+ bool mPlaceable;
+ bool mEnhanced;
+
+ /// bounding rectangle
+ QRect mBBox; // placeable file : this is the header
+ // standard file : this is the value in setWindowOrg and setWindowExt
+ /// number of points per inch for the default size
+ int mDpi;
+
+ /// number of functions to draw (==0 for all)
+ int mNbrFunc;
+
+private:
+ // the output
+ KoWmfRead *mReadWmf;
+
+ // current coordinate != mBBox
+ QRect mWindow;
+ // current state of the drawing
+ QColor mTextColor;
+ Q_UINT16 mTextAlign;
+ int mTextRotation;
+ bool mWinding;
+
+ // memory allocation for WMF file
+ QBuffer* mBuffer;
+ int mOffsetFirstRecord;
+
+ // stack of object handle
+ KoWmfHandle** mObjHandleTab;
+ // number of object on the stack
+ int mNbrObject;
+ bool mStackOverflow;
+};
+
+/**
+ * static data
+ */
+ static const struct KoWmfFunc {
+ void ( KoWmfReadPrivate::*method )( Q_UINT32, QDataStream& );
+ } koWmfFunc[] = {
+ { &KoWmfReadPrivate::end }, // 0
+ { &KoWmfReadPrivate::setBkColor }, // 1
+ { &KoWmfReadPrivate::setBkMode }, // 2
+ { &KoWmfReadPrivate::setMapMode }, // 3
+ { &KoWmfReadPrivate::setRop }, // 4
+ { &KoWmfReadPrivate::setRelAbs }, // 5
+ { &KoWmfReadPrivate::setPolyFillMode }, // 6
+ { &KoWmfReadPrivate::SetStretchBltMode }, // 7
+ { &KoWmfReadPrivate::notyet }, // 8
+ { &KoWmfReadPrivate::setTextColor }, // 9
+ { &KoWmfReadPrivate::ScaleWindowExt }, // 10
+ { &KoWmfReadPrivate::setWindowOrg }, // 11
+ { &KoWmfReadPrivate::setWindowExt }, // 12
+ { &KoWmfReadPrivate::notyet }, // 13
+ { &KoWmfReadPrivate::notyet }, // 14
+ { &KoWmfReadPrivate::OffsetWindowOrg }, // 15
+ { &KoWmfReadPrivate::notyet }, // 16
+ { &KoWmfReadPrivate::notyet }, // 17
+ { &KoWmfReadPrivate::notyet }, // 18
+ { &KoWmfReadPrivate::lineTo }, // 19
+ { &KoWmfReadPrivate::moveTo }, // 20
+ { &KoWmfReadPrivate::excludeClipRect }, // 21
+ { &KoWmfReadPrivate::intersectClipRect }, // 22
+ { &KoWmfReadPrivate::arc }, // 23
+ { &KoWmfReadPrivate::ellipse }, // 24
+ { &KoWmfReadPrivate::notyet }, // 25
+ { &KoWmfReadPrivate::pie }, // 26
+ { &KoWmfReadPrivate::rectangle }, // 27
+ { &KoWmfReadPrivate::roundRect }, // 28
+ { &KoWmfReadPrivate::notyet }, // 29
+ { &KoWmfReadPrivate::saveDC }, // 30
+ { &KoWmfReadPrivate::setPixel }, // 31
+ { &KoWmfReadPrivate::notyet }, // 32
+ { &KoWmfReadPrivate::textOut }, // 33
+ { &KoWmfReadPrivate::bitBlt }, // 34
+ { &KoWmfReadPrivate::notyet }, // 35
+ { &KoWmfReadPrivate::polygon }, // 36
+ { &KoWmfReadPrivate::polyline }, // 37
+ { &KoWmfReadPrivate::escape }, // 38
+ { &KoWmfReadPrivate::restoreDC }, // 39
+ { &KoWmfReadPrivate::region }, // 40
+ { &KoWmfReadPrivate::region }, // 41
+ { &KoWmfReadPrivate::region }, // 42
+ { &KoWmfReadPrivate::region }, // 43
+ { &KoWmfReadPrivate::region }, // 44
+ { &KoWmfReadPrivate::selectObject }, // 45
+ { &KoWmfReadPrivate::setTextAlign }, // 46
+ { 0 }, // 47
+ { &KoWmfReadPrivate::chord }, // 48
+ { &KoWmfReadPrivate::notyet }, // 49
+ { &KoWmfReadPrivate::extTextOut }, // 50
+ { &KoWmfReadPrivate::setDibToDev }, // 51
+ { &KoWmfReadPrivate::palette }, // 52
+ { &KoWmfReadPrivate::palette }, // 53
+ { &KoWmfReadPrivate::palette }, // 54
+ { &KoWmfReadPrivate::palette }, // 55
+ { &KoWmfReadPrivate::polyPolygon }, // 56
+ { &KoWmfReadPrivate::palette }, // 57
+ { 0 }, // 58
+ { 0 }, // 59
+ { 0 }, // 60
+ { 0 }, // 61
+ { 0 }, // 62
+ { 0 }, // 63
+ { &KoWmfReadPrivate::dibBitBlt }, // 64
+ { &KoWmfReadPrivate::dibStretchBlt }, // 65
+ { &KoWmfReadPrivate::dibCreatePatternBrush }, // 66
+ { &KoWmfReadPrivate::stretchDib }, // 67
+ { 0 }, // 68
+ { 0 }, // 69
+ { 0 }, // 70
+ { 0 }, // 71
+ { &KoWmfReadPrivate::extFloodFill }, // 72
+ { 0 }, // 73
+ { 0 }, // 74
+ { 0 }, // 75
+ { &KoWmfReadPrivate::resetDC }, // 76
+ { &KoWmfReadPrivate::startDoc }, // 77
+ { 0 }, // 78
+ { &KoWmfReadPrivate::startPage }, // 79
+ { &KoWmfReadPrivate::endPage }, // 80
+ { 0 }, // 81
+ { 0 }, // 82
+ { 0 }, // 83
+ { 0 }, // 84
+ { 0 }, // 85
+ { 0 }, // 86
+ { 0 }, // 87
+ { 0 }, // 88
+ { 0 }, // 89
+ { 0 }, // 90
+ { 0 }, // 91
+ { 0 }, // 92
+ { 0 }, // 93
+ { &KoWmfReadPrivate::endDoc }, // 94
+ { 0 }, // 95
+ // 0x5F last function until 0xF0
+ { &KoWmfReadPrivate::deleteObject }, // 96
+ { 0 }, // 97
+ { 0 }, // 98
+ { 0 }, // 99
+ { 0 }, // 100
+ { 0 }, // 101
+ { 0 }, // 102
+ { &KoWmfReadPrivate::createPalette }, // 103
+ { &KoWmfReadPrivate::createBrush }, // 104
+ { &KoWmfReadPrivate::createPatternBrush }, // 105
+ { &KoWmfReadPrivate::createPenIndirect }, // 106
+ { &KoWmfReadPrivate::createFontIndirect }, // 107
+ { &KoWmfReadPrivate::createBrushIndirect }, //108
+ { &KoWmfReadPrivate::createBitmapIndirect }, //109
+ { &KoWmfReadPrivate::createBitmap }, // 110
+ { &KoWmfReadPrivate::createRegion } // 111
+ };
+
+
+#endif
+
diff --git a/lib/kwmf/kowmfstack.cc b/lib/kwmf/kowmfstack.cc
new file mode 100644
index 00000000..80896690
--- /dev/null
+++ b/lib/kwmf/kowmfstack.cc
@@ -0,0 +1,38 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 1998 Stefan Taferner
+ 2001/2003 thierry lorthiois ([email protected])
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "kowmfstack.h"
+#include "kowmfread.h"
+
+void KoWmfBrushHandle::apply( KoWmfRead *p ) {
+ p->setBrush( brush );
+}
+
+void KoWmfPenHandle::apply( KoWmfRead *p ) {
+ p->setPen( pen );
+}
+
+void KoWmfPatternBrushHandle::apply( KoWmfRead *p ) {
+ p->setBrush( brush );
+}
+
+void KoWmfFontHandle::apply( KoWmfRead *p ) {
+ p->setFont( font );
+}
+
diff --git a/lib/kwmf/kowmfstack.h b/lib/kwmf/kowmfstack.h
new file mode 100644
index 00000000..0dcb5a8d
--- /dev/null
+++ b/lib/kwmf/kowmfstack.h
@@ -0,0 +1,74 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 1998 Stefan Taferner
+ 2001/2003 thierry lorthiois ([email protected])
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+#ifndef _KOWMFSTACK_H_
+#define _KOWMFSTACK_H_
+
+#include <qpen.h>
+#include <qcolor.h>
+#include <qfont.h>
+#include <qbrush.h>
+#include <qpixmap.h>
+
+class KoWmfRead;
+
+/**
+ * WMF file allows manipulation on a stack of object.
+ * It's possile to create, delete or select an object.
+ */
+class KoWmfHandle
+{
+public:
+ virtual void apply( KoWmfRead * ) = 0;
+};
+
+class KoWmfBrushHandle: public KoWmfHandle
+{
+public:
+ virtual ~KoWmfBrushHandle() {};
+ virtual void apply( KoWmfRead * );
+ QBrush brush;
+};
+
+class KoWmfPenHandle: public KoWmfHandle
+{
+public:
+ virtual ~KoWmfPenHandle() {};
+ virtual void apply( KoWmfRead * );
+ QPen pen;
+};
+
+class KoWmfPatternBrushHandle: public KoWmfHandle
+{
+public:
+ virtual ~KoWmfPatternBrushHandle() {};
+ virtual void apply( KoWmfRead * );
+ QBrush brush;
+ QPixmap image;
+};
+
+class KoWmfFontHandle: public KoWmfHandle
+{
+public:
+ virtual ~KoWmfFontHandle() {};
+ virtual void apply( KoWmfRead * );
+ QFont font;
+ int rotation;
+};
+
+#endif
diff --git a/lib/kwmf/kowmfstruct.h b/lib/kwmf/kowmfstruct.h
new file mode 100644
index 00000000..2837fa71
--- /dev/null
+++ b/lib/kwmf/kowmfstruct.h
@@ -0,0 +1,147 @@
+/* This library is distributed under the conditions of the GNU LGPL.
+ * WMF Metafile Structures
+ * Author: 2002/2003 thierry lorthiois
+ */
+#ifndef _KOWMFSTRUCT_H_
+#define _KOWMFSTRUCT_H_
+
+#include <qglobal.h>
+#include <qnamespace.h>
+
+#define APMHEADER_KEY 0x9AC6CDD7
+#define ENHMETA_SIGNATURE 0x464D4520
+
+struct WmfMetaHeader
+{
+ Q_UINT16 fileType; // Type of metafile (0=memory, 1=disk)
+ Q_UINT16 headerSize; // always 9
+ Q_UINT16 version;
+ Q_UINT32 fileSize; // Total size of the metafile in WORDs
+ Q_UINT16 numOfObjects; // Maximum Number of objects in the stack
+ Q_UINT32 maxRecordSize; // The size of largest record in WORDs
+ Q_UINT16 numOfParameters; // not used (always 0)
+};
+
+
+struct WmfPlaceableHeader
+{
+ Q_UINT32 key; // Magic number (always 9AC6CDD7h)
+ Q_UINT16 handle; // Metafile HANDLE number (always 0)
+ Q_INT16 left; // Left coordinate in metafile units
+ Q_INT16 top;
+ Q_INT16 right;
+ Q_INT16 bottom;
+ Q_UINT16 inch; // Number of metafile units per inch
+ Q_UINT32 reserved;
+ Q_UINT16 checksum; // Checksum value for previous 10 WORDs
+};
+
+
+struct WmfEnhMetaHeader
+{
+ Q_UINT32 recordType; // Record type (is always 00000001h)
+ Q_UINT32 recordSize; // Record size in bytes. This may be greater
+ // than the sizeof( ENHMETAHEADER ).
+ Q_INT32 boundsLeft; // Inclusive-inclusive bounds in device units
+ Q_INT32 boundsTop;
+ Q_INT32 boundsRight;
+ Q_INT32 boundsBottom;
+ Q_INT32 frameLeft; // Inclusive-inclusive Picture Frame
+ Q_INT32 frameTop;
+ Q_INT32 frameRight;
+ Q_INT32 frameBottom;
+ Q_UINT32 signature; // Signature. Must be ENHMETA_SIGNATURE.
+ Q_UINT32 version; // Version number
+ Q_UINT32 size; // Size of the metafile in bytes
+ Q_UINT32 numOfRecords; // Number of records in the metafile
+ Q_UINT16 numHandles; // Number of handles in the handle table
+ // Handle index zero is reserved.
+ Q_UINT16 reserved; // always 0
+ Q_UINT32 sizeOfDescription; // Number of chars in the unicode description string
+ // This is 0 if there is no description string
+ Q_UINT32 offsetOfDescription; // Offset to the metafile description record.
+ // This is 0 if there is no description string
+ Q_UINT32 numPaletteEntries; // Number of color palette entries
+ Q_INT32 widthDevicePixels; // Size of the reference device in pixels
+ Q_INT32 heightDevicePixels;
+ Q_INT32 widthDeviceMM; // Size of the reference device in millimeters
+ Q_INT32 heightDeviceMM;
+};
+
+
+struct WmfMetaRecord
+{
+ Q_UINT32 size; // Total size of the record in WORDs
+ Q_UINT16 function; // Record function number
+ Q_UINT16 param[ 1 ]; // Q_UINT16 array of parameters
+};
+
+
+struct WmfEnhMetaRecord
+{
+ Q_UINT32 function; // Record function number
+ Q_UINT32 size; // Record size in bytes
+ Q_UINT32 param[ 1 ]; // Q_UINT32 array of parameters
+};
+
+// Static data
+ static const struct OpTab
+ {
+ Q_UINT32 winRasterOp;
+ Qt::RasterOp qtRasterOp;
+ } koWmfOpTab32[] =
+ {
+ { 0x00CC0020, Qt::CopyROP },
+ { 0x00EE0086, Qt::OrROP },
+ { 0x008800C6, Qt::AndROP },
+ { 0x00660046, Qt::XorROP },
+ { 0x00440328, Qt::AndNotROP },
+ { 0x00330008, Qt::NotCopyROP },
+ { 0x001100A6, Qt::NandROP },
+ { 0x00C000CA, Qt::CopyROP },
+ { 0x00BB0226, Qt::NotOrROP },
+ { 0x00F00021, Qt::CopyROP },
+ { 0x00FB0A09, Qt::CopyROP },
+ { 0x005A0049, Qt::CopyROP },
+ { 0x00550009, Qt::NotROP },
+ { 0x00000042, Qt::ClearROP },
+ { 0x00FF0062, Qt::SetROP }
+ };
+
+ static const Qt::RasterOp koWmfOpTab16[] =
+ {
+ Qt::CopyROP,
+ Qt::ClearROP, Qt::NandROP, Qt::NotAndROP, Qt::NotCopyROP,
+ Qt::AndNotROP, Qt::NotROP, Qt::XorROP, Qt::NorROP,
+ Qt::AndROP, Qt::NotXorROP, Qt::NopROP, Qt::NotOrROP,
+ Qt::CopyROP, Qt::OrNotROP, Qt::OrROP, Qt::SetROP
+ };
+
+ static const Qt::BrushStyle koWmfHatchedStyleBrush[] =
+ {
+ Qt::HorPattern,
+ Qt::VerPattern,
+ Qt::FDiagPattern,
+ Qt::BDiagPattern,
+ Qt::CrossPattern,
+ Qt::DiagCrossPattern
+ };
+
+ static const Qt::BrushStyle koWmfStyleBrush[] =
+ { 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 */
+ };
+
+ static const Qt::PenStyle koWmfStylePen[] =
+ { Qt::SolidLine, Qt::DashLine, Qt::DotLine, Qt::DashDotLine, Qt::DashDotDotLine,
+ Qt::NoPen, Qt::SolidLine };
+
+#endif
+
diff --git a/lib/kwmf/kowmfwrite.cc b/lib/kwmf/kowmfwrite.cc
new file mode 100644
index 00000000..1c553391
--- /dev/null
+++ b/lib/kwmf/kowmfwrite.cc
@@ -0,0 +1,456 @@
+/* This file is part of the KDE libraries
+ * Copyright (c) 2003 thierry lorthiois ([email protected])
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <math.h>
+#include <qfile.h>
+#include <qdatastream.h>
+
+#include <kdebug.h>
+
+#include "kowmfstruct.h"
+#include "kowmfreadprivate.h"
+#include "kowmfwrite.h"
+
+/**
+ * Private data
+ */
+class KoWmfWritePrivate
+{
+public:
+ QRect mBBox; // bounding rectangle
+ int mDpi; // number of point per inch for the default size
+ int mMaxRecordSize;
+
+ // memory allocation for WMF file
+ QFile mFileOut;
+ QDataStream mSt;
+};
+
+
+
+KoWmfWrite::KoWmfWrite( const QString& fileName ) {
+ d = new KoWmfWritePrivate;
+
+ d->mDpi = 1024;
+ d->mMaxRecordSize = 0;
+ d->mFileOut.setName( fileName );
+}
+
+KoWmfWrite::~KoWmfWrite() {
+ delete d;
+}
+
+
+void KoWmfWrite::setDefaultDpi( int dpi ) {
+ d->mDpi = dpi;
+}
+
+
+//-----------------------------------------------------------------------------
+// Virtual Painter => create the WMF
+
+bool KoWmfWrite::begin() {
+
+ if ( !d->mFileOut.open( IO_WriteOnly ) )
+ {
+ kdDebug() << "Cannot open file " << QFile::encodeName(d->mFileOut.name()) << endl;
+ return false;
+ }
+ d->mSt.setDevice( &d->mFileOut );
+ d->mSt.setByteOrder( QDataStream::LittleEndian );
+
+ // reserved placeable and standard header
+ for ( int i=0 ; i < 10 ; i++ ) {
+ d->mSt << (Q_UINT32)0;
+ }
+
+ // initialize the stack of objects
+ // Pen
+ d->mSt << (Q_UINT32)8 << (Q_UINT16)0x02FA;
+ d->mSt << (Q_UINT16)5 << (Q_UINT16)0 << (Q_UINT16)0 << (Q_UINT32)0;
+ // Brush
+ d->mSt << (Q_UINT32)7 << (Q_UINT16)0x02FC;
+ d->mSt << (Q_UINT16)1 << (Q_UINT32)0 << (Q_UINT16)0;
+ for ( int i=0 ; i < 4 ; i++ ) {
+ d->mSt << (Q_UINT32)8 << (Q_UINT16)0x02FA << (Q_UINT16)0 << (Q_UINT32)0 << (Q_UINT32)0;
+ }
+ d->mMaxRecordSize = 8;
+
+ return true;
+}
+
+
+bool KoWmfWrite::end() {
+ WmfPlaceableHeader pheader = { 0x9AC6CDD7, 0, 0, 0, 0, 0, 0, 0, 0 };
+ Q_UINT16 checksum;
+
+ // End of the wmf file
+ d->mSt << (Q_UINT32)3 << (Q_UINT16)0;
+
+ // adjust header
+ pheader.left = d->mBBox.left();
+ pheader.top = d->mBBox.top();
+ pheader.right = d->mBBox.right();
+ pheader.bottom = d->mBBox.bottom();
+ pheader.inch = d->mDpi;
+ checksum = KoWmfReadPrivate::calcCheckSum( &pheader );
+
+ // write headers
+ d->mFileOut.at( 0 );
+ d->mSt << (Q_UINT32)0x9AC6CDD7 << (Q_UINT16)0;
+ d->mSt << (Q_INT16)d->mBBox.left() << (Q_INT16)d->mBBox.top() << (Q_INT16)d->mBBox.right() << (Q_INT16)d->mBBox.bottom();
+ d->mSt << (Q_UINT16)d->mDpi << (Q_UINT32)0 << checksum;
+ d->mSt << (Q_UINT16)1 << (Q_UINT16)9 << (Q_UINT16)0x300 << (Q_UINT32)(d->mFileOut.size()/2);
+ d->mSt << (Q_UINT16)6 << (Q_UINT32)d->mMaxRecordSize << (Q_UINT16)0;
+
+ d->mFileOut.close();
+
+ return true;
+}
+
+
+void KoWmfWrite::save() {
+ d->mSt << (Q_UINT32)3 << (Q_UINT16)0x001E;
+}
+
+
+void KoWmfWrite::restore() {
+ d->mSt << (Q_UINT32)4 << (Q_UINT16)0x0127 << (Q_UINT16)1;
+}
+
+
+void KoWmfWrite::setPen( const QPen &pen ) {
+ int style;
+ int max = sizeof(koWmfStylePen) / sizeof(Qt::SolidLine);
+
+ // we can't delete an object currently selected
+ // select another object
+ d->mSt << (Q_UINT32)4 << (Q_UINT16)0x012D << (Q_UINT16)0;
+ // delete object
+ d->mSt << (Q_UINT32)4 << (Q_UINT16)0x01f0 << (Q_UINT16)2;
+
+ for ( style=0 ; style < max ; style++ ) {
+ if ( koWmfStylePen[ style ] == pen.style() ) break;
+ }
+ if ( style == max ) {
+ // SolidLine
+ style = 0;
+ }
+ d->mSt << (Q_UINT32)8 << (Q_UINT16)0x02FA;
+ d->mSt << (Q_UINT16)style << (Q_UINT16)pen.width() << (Q_UINT16)0 << (Q_UINT32)winColor( pen.color() );
+
+ // select object
+ d->mSt << (Q_UINT32)4 << (Q_UINT16)0x012D << (Q_UINT16)2;
+}
+
+
+void KoWmfWrite::setBrush( const QBrush &brush ) {
+ int style;
+ int max = sizeof(koWmfStyleBrush) / sizeof(Qt::NoBrush);
+
+ // we can't delete an object currently selected
+ // select another object
+ d->mSt << (Q_UINT32)4 << (Q_UINT16)0x012D << (Q_UINT16)1;
+ // delete object
+ d->mSt << (Q_UINT32)4 << (Q_UINT16)0x01f0 << (Q_UINT16)3;
+
+ for ( style=0 ; style < max ; style++ ) {
+ if ( koWmfStyleBrush[ style ] == brush.style() ) break;
+ }
+ if ( style == max ) {
+ // SolidPattern
+ style = 0;
+ }
+ d->mSt << (Q_UINT32)7 << (Q_UINT16)0x02FC;
+ d->mSt << (Q_UINT16)style << (Q_UINT32)winColor( brush.color() ) << (Q_UINT16)0;
+
+ // select object
+ d->mSt << (Q_UINT32)4 << (Q_UINT16)0x012D << (Q_UINT16)3;
+}
+
+
+void KoWmfWrite::setFont( const QFont & ) {
+}
+
+
+void KoWmfWrite::setBackgroundColor( const QColor &c ) {
+ d->mSt << (Q_UINT32)5 << (Q_UINT16)0x0201 << (Q_UINT32)winColor( c );
+}
+
+
+void KoWmfWrite::setBackgroundMode( Qt::BGMode mode ) {
+ d->mSt << (Q_UINT32)4 << (Q_UINT16)0x0102;
+ if ( mode == Qt::TransparentMode )
+ d->mSt << (Q_UINT16)1;
+ else
+ d->mSt << (Q_UINT16)0;
+}
+
+
+void KoWmfWrite::setRasterOp( Qt::RasterOp op ) {
+ d->mSt << (Q_UINT32)5 << (Q_UINT16)0x0104 << (Q_UINT32)qtRasterToWin32( op );
+}
+
+
+void KoWmfWrite::setWindow( int left, int top, int width, int height ) {
+ d->mBBox.setRect( left, top, width, height );
+
+ // windowOrg
+ d->mSt << (Q_UINT32)5 << (Q_UINT16)0x020B << (Q_UINT16)top << (Q_UINT16)left;
+
+ // windowExt
+ d->mSt << (Q_UINT32)5 << (Q_UINT16)0x020C << (Q_UINT16)height << (Q_UINT16)width;
+}
+
+
+void KoWmfWrite::setClipRegion( const QRegion & ) {
+
+}
+
+
+void KoWmfWrite::clipping( bool enable ) {
+ if ( !enable ) {
+ // clipping region == bounding rectangle
+ setClipRegion( d->mBBox );
+ }
+}
+
+
+void KoWmfWrite::moveTo( int left, int top ) {
+ d->mSt << (Q_UINT32)5 << (Q_UINT16)0x0214 << (Q_UINT16)top << (Q_UINT16)left;
+}
+
+
+void KoWmfWrite::lineTo( int left, int top ) {
+ d->mSt << (Q_UINT32)5 << (Q_UINT16)0x0213 << (Q_UINT16)top << (Q_UINT16)left;
+}
+
+
+void KoWmfWrite::drawRect( int left, int top, int width, int height ) {
+ QRect rec( left, top, width, height );
+
+ d->mSt << (Q_UINT32)7 << (Q_UINT16)0x041B;
+ d->mSt << (Q_UINT16)rec.bottom() << (Q_UINT16)rec.right() << (Q_UINT16)rec.top() << (Q_UINT16)rec.left();
+}
+
+
+void KoWmfWrite::drawRoundRect( int left, int top, int width, int height , int roudw, int roudh ) {
+ int widthCorner, heightCorner;
+ QRect rec( left, top, width, height );
+
+ // convert percentage (roundw, roudh) in (widthCorner, heightCorner)
+ widthCorner = ( roudw * width ) / 100;
+ heightCorner = ( roudh * height ) / 100;
+
+ d->mSt << (Q_UINT32)9 << (Q_UINT16)0x061C << (Q_UINT16)heightCorner << (Q_UINT16)widthCorner;
+ d->mSt << (Q_UINT16)rec.bottom() << (Q_UINT16)rec.right() << (Q_UINT16)rec.top() << (Q_UINT16)rec.left();
+
+ d->mMaxRecordSize = QMAX( d->mMaxRecordSize, 9 );
+}
+
+
+void KoWmfWrite::drawEllipse( int left, int top, int width, int height ) {
+ QRect rec( left, top, width, height );
+
+ d->mSt << (Q_UINT32)7 << (Q_UINT16)0x0418;
+ d->mSt << (Q_UINT16)rec.bottom() << (Q_UINT16)rec.right() << (Q_UINT16)rec.top() << (Q_UINT16)rec.left();
+}
+
+
+void KoWmfWrite::drawArc( int left, int top, int width, int height , int a, int alen ) {
+ int xCenter, yCenter;
+ int offXStart, offYStart, offXEnd, offYEnd;
+
+ angleToxy( offXStart, offYStart, offXEnd, offYEnd, a, alen );
+ xCenter = left + (width / 2);
+ yCenter = top + (height / 2);
+
+ d->mSt << (Q_UINT32)11 << (Q_UINT16)0x0817;
+ d->mSt << (Q_UINT16)(yCenter + offYEnd) << (Q_UINT16)(xCenter + offXEnd);
+ d->mSt << (Q_UINT16)(yCenter + offYStart) << (Q_UINT16)(xCenter + offXStart);
+ d->mSt << (Q_UINT16)(top + height) << (Q_UINT16)(left + width);
+ d->mSt << (Q_UINT16)top << (Q_UINT16)left;
+
+ d->mMaxRecordSize = QMAX( d->mMaxRecordSize, 11 );
+}
+
+
+void KoWmfWrite::drawPie( int left, int top, int width, int height , int a, int alen ) {
+ int xCenter, yCenter;
+ int offXStart, offYStart, offXEnd, offYEnd;
+
+ angleToxy( offXStart, offYStart, offXEnd, offYEnd, a, alen );
+ xCenter = left + (width / 2);
+ yCenter = top + (height / 2);
+
+ d->mSt << (Q_UINT32)11 << (Q_UINT16)0x081A;
+ d->mSt << (Q_UINT16)(yCenter + offYEnd) << (Q_UINT16)(xCenter + offXEnd);
+ d->mSt << (Q_UINT16)(yCenter + offYStart) << (Q_UINT16)(xCenter + offXStart);
+ d->mSt << (Q_UINT16)(top + height) << (Q_UINT16)(left + width);
+ d->mSt << (Q_UINT16)top << (Q_UINT16)left;
+
+ d->mMaxRecordSize = QMAX( d->mMaxRecordSize, 11 );
+}
+
+
+void KoWmfWrite::drawChord( int left, int top, int width, int height , int a, int alen ) {
+ int xCenter, yCenter;
+ int offXStart, offYStart, offXEnd, offYEnd;
+
+ angleToxy( offXStart, offYStart, offXEnd, offYEnd, a, alen );
+ xCenter = left + (width / 2);
+ yCenter = top + (height / 2);
+
+ d->mSt << (Q_UINT32)11 << (Q_UINT16)0x0830;
+ d->mSt << (Q_UINT16)(yCenter + offYEnd) << (Q_UINT16)(xCenter + offXEnd);
+ d->mSt << (Q_UINT16)(yCenter + offYStart) << (Q_UINT16)(xCenter + offXStart);
+ d->mSt << (Q_UINT16)(top + height) << (Q_UINT16)(left + width);
+ d->mSt << (Q_UINT16)top << (Q_UINT16)left;
+
+ d->mMaxRecordSize = QMAX( d->mMaxRecordSize, 11 );
+}
+
+
+void KoWmfWrite::drawPolyline( const QPointArray &pa ) {
+ int size = 4 + (pa.size() * 2);
+
+ d->mSt << (Q_UINT32)size << (Q_UINT16)0x0325 << (Q_UINT16)pa.size();
+ pointArray( pa );
+
+ d->mMaxRecordSize = QMAX( d->mMaxRecordSize, size );
+}
+
+
+void KoWmfWrite::drawPolygon( const QPointArray &pa, bool ) {
+ int size = 4 + (pa.size() * 2);
+
+ d->mSt << (Q_UINT32)size << (Q_UINT16)0x0324 << (Q_UINT16)pa.size();
+ pointArray( pa );
+
+ d->mMaxRecordSize = QMAX( d->mMaxRecordSize, size );
+}
+
+
+void KoWmfWrite::drawPolyPolygon( QPtrList<QPointArray>& listPa, bool ) {
+
+ QPointArray *pa;
+ int sizeArrayPoly = 0;
+
+ for ( pa = listPa.first() ; pa ; pa = listPa.next() ) {
+ sizeArrayPoly += (pa->size() * 2);
+ }
+ int size = 4 + listPa.count() + sizeArrayPoly;
+ d->mSt << (Q_UINT32)size << (Q_UINT16)0x0538 << (Q_UINT16)listPa.count();
+
+ // number of point for each Polygon
+ for ( pa = listPa.first() ; pa ; pa = listPa.next() ) {
+ d->mSt << (Q_UINT16)pa->size();
+ }
+
+ // list of points
+ for ( pa = listPa.first() ; pa ; pa = listPa.next() ) {
+ pointArray( *pa );
+ }
+
+ d->mMaxRecordSize = QMAX( d->mMaxRecordSize, size );
+
+}
+
+
+void KoWmfWrite::drawImage( int , int , const QImage &, int , int , int , int ) {
+/*
+ QImage img;
+
+ img = image;
+ img.setFormat( "BMP" );
+
+ QIODevice io = img.ioDevice();
+ io.at( 14 ); // skip the BMP header
+ d->mSt << io.readAll();
+*/
+}
+
+
+void KoWmfWrite::drawText( int , int , int , int , int , const QString& , double ) {
+// d->mSt << (Q_UINT32)3 << (Q_UINT16)0x0A32;
+}
+
+//-----------------------------------------------------------------------------
+// Utilities and conversion Qt --> Wmf
+
+void KoWmfWrite::pointArray( const QPointArray &pa ) {
+ int left, top, i, max;
+
+ for ( i=0, max=pa.size() ; i < max ; i++ ) {
+ pa.point( i, &left, &top );
+ d->mSt << (Q_INT16)left << (Q_INT16)top;
+ }
+}
+
+
+Q_UINT32 KoWmfWrite::winColor( QColor color ) {
+ Q_UINT32 c;
+
+ c = (color.red() & 0xFF);
+ c += ( (color.green() & 0xFF) << 8 );
+ c += ( (color.blue() & 0xFF) << 16 );
+
+ return c;
+}
+
+
+void KoWmfWrite::angleToxy( int &xStart, int &yStart, int &xEnd, int &yEnd, int a, int alen ) {
+ double angleStart, angleLength;
+
+ angleStart = ((double)a * 3.14166) / 2880;
+ angleLength = ((double)alen * 3.14166) / 2880;
+
+ xStart = (int)(cos(angleStart) * 50);
+ yStart = -(int)(sin(angleStart) * 50);
+ xEnd = (int)(cos(angleLength) * 50);
+ yEnd = -(int)(sin(angleLength) * 50);
+}
+
+
+Q_UINT16 KoWmfWrite::qtRasterToWin16( Qt::RasterOp op ) const {
+ int i;
+
+ for ( i=0 ; i < 17 ; i++ ) {
+ if ( koWmfOpTab16[ i ] == op ) break;
+ }
+
+ if ( i < 17 )
+ return (Q_UINT16)i;
+ else
+ return (Q_UINT16)0;
+}
+
+
+Q_UINT32 KoWmfWrite::qtRasterToWin32( Qt::RasterOp op ) const {
+ int i;
+
+ for ( i=0 ; i < 15 ; i++ ) {
+ if ( koWmfOpTab32[ i ].qtRasterOp == op ) break;
+ }
+
+ if ( i < 15 )
+ return koWmfOpTab32[ i ].winRasterOp;
+ else
+ return koWmfOpTab32[ 0 ].winRasterOp;
+}
+
diff --git a/lib/kwmf/kowmfwrite.h b/lib/kwmf/kowmfwrite.h
new file mode 100644
index 00000000..1063ef76
--- /dev/null
+++ b/lib/kwmf/kowmfwrite.h
@@ -0,0 +1,142 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 2003 thierry lorthiois ([email protected])
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+#ifndef _KOWMFWRITE_H_
+#define _KOWMFWRITE_H_
+
+#include <qpen.h>
+#include <qbrush.h>
+#include <qcolor.h>
+#include <qfont.h>
+#include <qrect.h>
+#include <qbuffer.h>
+#include <qregion.h>
+#include <qstring.h>
+#include <qwmatrix.h>
+#include <qimage.h>
+#include <qptrlist.h>
+#include <qpointarray.h>
+#include <koffice_export.h>
+class KoWmfWritePrivate;
+
+/**
+ * KoWmfWrite allows to create a windows placeable meta file (WMF).
+ * Most of the functions are compatible with QPainter format.
+ *
+ * sample of utilization:
+ * <pre>
+ * KoWmfWrite wmf("/home/test.wmf");
+ * wmf.begin();
+ * wmf.setWindow(0, 0, 200, 200);
+ * wmf.drawRect(10, 20, 50, 120);
+ * wmf.end();
+ * </pre>
+ */
+class KOWMF_EXPORT KoWmfWrite
+{
+public:
+ KoWmfWrite( const QString& fileName );
+ virtual ~KoWmfWrite();
+
+
+ // -------------------------------------------------------------------------
+ // virtual Painter
+ // for a good documentation : check QPainter documentation
+ /**
+ * Open the file. Returns true on success.
+ */
+ bool begin();
+ /**
+ * Close the file. Returns true on success.
+ */
+ bool end();
+ void save();
+ void restore();
+
+ /**
+ * Placeable WMF's use logical coordinates and have a default DPI.
+ * This function set the dot per inch ratio.
+ * If not specified the dpi is 1024.
+ */
+ void setDefaultDpi( int dpi );
+
+ // Drawing tools
+ void setFont( const QFont& f );
+ // the width of the pen is in logical coordinate
+ void setPen( const QPen& p );
+ void setBrush( const QBrush& b );
+
+ // Drawing attributes/modes
+ void setBackgroundColor( const QColor& r );
+ void setBackgroundMode( Qt::BGMode );
+ void setRasterOp( Qt::RasterOp );
+
+ // Change logical Coordinate
+ void setWindow( int left, int top , int width, int height );
+
+ // Clipping
+ // the 'CoordinateMode' parameter is ommitted : always CoordPainter in wmf
+ // not yet implemented
+ void setClipRegion( const QRegion& r );
+ void clipping( bool enable );
+
+ // Graphics drawing functions
+ void moveTo( int left, int top );
+ void lineTo( int left, int top );
+ void drawRect( int left, int top, int width, int height );
+ void drawRoundRect( int left, int top, int width, int height, int = 25, int = 25 );
+ void drawEllipse( int left, int top, int width, int height );
+ void drawArc( int left, int top, int width, int height, int a, int alen );
+ void drawPie( int left, int top, int width, int height, int a, int alen );
+ void drawChord( int left, int top, int width, int height, int a, int alen );
+ void drawPolyline( const QPointArray& pa );
+ void drawPolygon( const QPointArray& pa, bool winding=FALSE );
+ // drawPolyPolygon draw the XOR of a list of polygons
+ // listPa : list of polygons
+ void drawPolyPolygon( QPtrList<QPointArray>& listPa, bool winding=FALSE );
+ void drawImage( int left, int top, const QImage &, int sx = 0, int sy = 0, int sw = -1, int sh = -1 );
+
+ // Text drawing functions
+ // rotation = the degrees of rotation in counterclockwise
+ // not yet implemented
+ void drawText( int x, int y, int w, int h, int flags, const QString &s, double rotation );
+
+private:
+ //-----------------------------------------------------------------------------
+ // Utilities and conversion Qt --> Wmf
+
+ /** Convert QPointArray into Q_INT16 position (result in mSt) */
+ void pointArray( const QPointArray& pa );
+
+ /** Convertion between windows color and QColor */
+ Q_UINT32 winColor( QColor color );
+
+ /** Convert angle a and alen in coordinate (xStart,yStart) and (xEnd, yEnd) */
+ void angleToxy( int& xStart, int& yStart, int& xEnd, int& yEnd, int a, int alen );
+
+ /** Convert windows rasterOp in QT rasterOp */
+ Q_UINT16 qtRasterToWin16( Qt::RasterOp op ) const;
+ Q_UINT32 qtRasterToWin32( Qt::RasterOp op ) const;
+
+
+private:
+ KoWmfWritePrivate *d;
+
+};
+
+#endif
+
diff --git a/lib/kwmf/kwmf.cc b/lib/kwmf/kwmf.cc
new file mode 100644
index 00000000..989b3e29
--- /dev/null
+++ b/lib/kwmf/kwmf.cc
@@ -0,0 +1,964 @@
+/*
+ Copyright (C) 2000, S.R.Haque <[email protected]>.
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+DESCRIPTION
+
+ This is based on code originally written by Stefan Taferner
+ ([email protected]) and also borrows from libwmf (by Martin Vermeer and
+ Caolan McNamara).
+*/
+
+#include <kdebug.h>
+#include <math.h>
+#include <qfile.h>
+#include <qpointarray.h>
+#include <kwmf.h>
+#include <qrect.h>
+
+#define PI (3.14159265358979323846)
+
+const int KWmf::s_area = 30504;
+const int KWmf::s_maxHandles = 64;
+
+KWmf::KWmf(
+ unsigned dpi)
+{
+ m_dpi = dpi;
+ m_objectHandles = new WinObjHandle*[s_maxHandles];
+}
+
+KWmf::~KWmf()
+{
+ delete[] m_objectHandles;
+}
+
+//
+//
+//
+
+void KWmf::brushSet(
+ unsigned colour,
+ unsigned style)
+{
+ m_dc.m_brushColour = colour;
+ m_dc.m_brushStyle = style;
+}
+
+//-----------------------------------------------------------------------------
+unsigned KWmf::getColour(
+ S32 colour)
+{
+ unsigned red, green, blue;
+
+ red = colour & 255;
+ green = (colour >> 8) & 255;
+ blue = (colour >> 16) & 255;
+ return (red << 16) + (green << 8) + blue;
+}
+
+void KWmf::genericArc(
+ QString type,
+ QDataStream &operands)
+{
+ QPoint topLeft;
+ QPoint bottomRight;
+ QPoint start;
+ QPoint end;
+
+ topLeft = normalisePoint(operands);
+ bottomRight = normalisePoint(operands);
+ start = normalisePoint(operands);
+ end = normalisePoint(operands);
+
+ // WMF defines arcs with the major and minor axes of an ellipse, and two points.
+ // From each point draw a line to the center of the ellipse: the intercepts define
+ // the ends of the arc.
+
+ QRect ellipse(topLeft, bottomRight);
+ QPoint centre = ellipse.center();
+ double startAngle = atan2((double)(centre.y() - start.y()), (double)(centre.x() - start.x()));
+ double stopAngle = atan2((double)(centre.y() - end.y()), (double)(centre.x() - end.x()));
+
+ startAngle = 180 * startAngle / PI;
+ stopAngle = 180 * stopAngle / PI;
+
+ gotEllipse(m_dc, type, centre, ellipse.size() / 2,
+ static_cast<unsigned int>(startAngle),
+ static_cast<unsigned int>(stopAngle));
+}
+
+int KWmf::handleIndex(void) const
+{
+ int i;
+
+ for (i = 0; i < s_maxHandles; i++)
+ {
+ if (!m_objectHandles[i])
+ return i;
+ }
+ kdError(s_area) << "handle table full !" << endl;
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+KWmf::WinObjPenHandle *KWmf::handleCreatePen(void)
+{
+ WinObjPenHandle *handle = new WinObjPenHandle;
+ int idx = handleIndex();
+
+ if (idx >= 0)
+ m_objectHandles[idx] = handle;
+ return handle;
+}
+
+//-----------------------------------------------------------------------------
+KWmf::WinObjBrushHandle *KWmf::handleCreateBrush(void)
+{
+ WinObjBrushHandle *handle = new WinObjBrushHandle;
+ int idx = handleIndex();
+
+ if (idx >= 0)
+ m_objectHandles[idx] = handle;
+ return handle;
+}
+
+//-----------------------------------------------------------------------------
+void KWmf::handleDelete(int idx)
+{
+ if (idx >= 0 && idx < s_maxHandles && m_objectHandles[idx])
+ {
+ delete m_objectHandles[idx];
+ m_objectHandles[idx] = NULL;
+ }
+}
+
+//
+//
+//
+
+void KWmf::invokeHandler(
+ S16 opcode,
+ U32 words,
+ QDataStream &operands)
+{
+ typedef void (KWmf::*method)(U32 words, QDataStream &operands);
+
+ typedef struct
+ {
+ const char *name;
+ unsigned short opcode;
+ method handler;
+ } opcodeEntry;
+
+ static const opcodeEntry funcTab[] =
+ {
+ { "ANIMATEPALETTE", 0x0436, 0 },
+ { "ARC", 0x0817, &KWmf::opArc },
+ { "BITBLT", 0x0922, 0 },
+ { "CHORD", 0x0830, 0 },
+ { "CREATEBRUSHINDIRECT", 0x02FC, &KWmf::opBrushCreateIndirect },
+ { "CREATEFONTINDIRECT", 0x02FB, 0 },
+ { "CREATEPALETTE", 0x00F7, 0 },
+ { "CREATEPATTERNBRUSH", 0x01F9, 0 },
+ { "CREATEPENINDIRECT", 0x02FA, &KWmf::opPenCreateIndirect },
+ { "CREATEREGION", 0x06FF, 0 },
+ { "DELETEOBJECT", 0x01F0, &KWmf::opObjectDelete },
+ { "DIBBITBLT", 0x0940, 0 },
+ { "DIBCREATEPATTERNBRUSH",0x0142, 0 },
+ { "DIBSTRETCHBLT", 0x0b41, 0 },
+ { "ELLIPSE", 0x0418, &KWmf::opEllipse },
+ { "ESCAPE", 0x0626, &KWmf::opNoop },
+ { "EXCLUDECLIPRECT", 0x0415, 0 },
+ { "EXTFLOODFILL", 0x0548, 0 },
+ { "EXTTEXTOUT", 0x0a32, 0 },
+ { "FILLREGION", 0x0228, 0 },
+ { "FLOODFILL", 0x0419, 0 },
+ { "FRAMEREGION", 0x0429, 0 },
+ { "INTERSECTCLIPRECT", 0x0416, 0 },
+ { "INVERTREGION", 0x012A, 0 },
+ { "LINETO", 0x0213, &KWmf::opLineTo },
+ { "MOVETO", 0x0214, &KWmf::opMoveTo },
+ { "OFFSETCLIPRGN", 0x0220, 0 },
+ { "OFFSETVIEWPORTORG", 0x0211, 0 },
+ { "OFFSETWINDOWORG", 0x020F, 0 },
+ { "PAINTREGION", 0x012B, 0 },
+ { "PATBLT", 0x061D, 0 },
+ { "PIE", 0x081A, &KWmf::opPie },
+ { "POLYGON", 0x0324, &KWmf::opPolygon },
+ { "POLYLINE", 0x0325, &KWmf::opPolyline },
+ { "POLYPOLYGON", 0x0538, 0 },
+ { "REALIZEPALETTE", 0x0035, 0 },
+ { "RECTANGLE", 0x041B, &KWmf::opRectangle },
+ { "RESIZEPALETTE", 0x0139, 0 },
+ { "RESTOREDC", 0x0127, &KWmf::opRestoreDc },
+ { "ROUNDRECT", 0x061C, 0 },
+ { "SAVEDC", 0x001E, &KWmf::opSaveDc },
+ { "SCALEVIEWPORTEXT", 0x0412, 0 },
+ { "SCALEWINDOWEXT", 0x0410, 0 },
+ { "SELECTCLIPREGION", 0x012C, 0 },
+ { "SELECTOBJECT", 0x012D, &KWmf::opObjectSelect },
+ { "SELECTPALETTE", 0x0234, 0 },
+ { "SETBKCOLOR", 0x0201, 0 },
+ { "SETBKMODE", 0x0102, 0 },
+ { "SETDIBTODEV", 0x0d33, 0 },
+ { "SETMAPMODE", 0x0103, 0 },
+ { "SETMAPPERFLAGS", 0x0231, 0 },
+ { "SETPALENTRIES", 0x0037, 0 },
+ { "SETPIXEL", 0x041F, 0 },
+ { "SETPOLYFILLMODE", 0x0106, &KWmf::opPolygonSetFillMode },
+ { "SETRELABS", 0x0105, 0 },
+ { "SETROP2", 0x0104, 0 },
+ { "SETSTRETCHBLTMODE", 0x0107, 0 },
+ { "SETTEXTALIGN", 0x012E, 0 },
+ { "SETTEXTCHAREXTRA", 0x0108, 0 },
+ { "SETTEXTCOLOR", 0x0209, 0 },
+ { "SETTEXTJUSTIFICATION", 0x020A, 0 },
+ { "SETVIEWPORTEXT", 0x020E, 0 },
+ { "SETVIEWPORTORG", 0x020D, 0 },
+ { "SETWINDOWEXT", 0x020C, &KWmf::opWindowSetExt },
+ { "SETWINDOWORG", 0x020B, &KWmf::opWindowSetOrg },
+ { "STRETCHBLT", 0x0B23, 0 },
+ { "STRETCHDIB", 0x0f43, 0 },
+ { "TEXTOUT", 0x0521, 0 },
+ { NULL, 0, 0 }
+ };
+ unsigned i;
+ method result;
+
+ // Scan lookup table for operation.
+
+ for (i = 0; funcTab[i].name; i++)
+ {
+ if (funcTab[i].opcode == opcode)
+ {
+ break;
+ }
+ }
+
+ // Invoke handler.
+
+ result = funcTab[i].handler;
+ if (!result)
+ {
+ if (funcTab[i].name)
+ kdError(s_area) << "invokeHandler: unsupported opcode: " <<
+ funcTab[i].name <<
+ " operands: " << words << endl;
+ else
+ kdError(s_area) << "invokeHandler: unsupported opcode: 0x" <<
+ QString::number(opcode, 16) <<
+ " operands: " << words << endl;
+
+ // Skip data we cannot use.
+
+ for (i = 0; i < words; i++)
+ {
+ S16 discard;
+
+ operands >> discard;
+ }
+ }
+ else
+ {
+ kdDebug(s_area) << "invokeHandler: opcode: " << funcTab[i].name <<
+ " operands: " << words << endl;
+
+ // We don't invoke the handler directly on the incoming operands, but
+ // via a temporary datastream. This adds overhead, but eliminates the
+ // need for the individual handlers to read *exactly* the right amount
+ // of data (thus speeding development, and possibly adding some
+ // future-proofing).
+
+ if (words)
+ {
+ QByteArray *record = new QByteArray(words * 2);
+ QDataStream *body;
+
+ operands.readRawBytes(record->data(), words * 2);
+ body = new QDataStream(*record, IO_ReadOnly);
+ body->setByteOrder(QDataStream::LittleEndian);
+ (this->*result)(words, *body);
+ delete body;
+ delete record;
+ }
+ else
+ {
+ QDataStream *body = new QDataStream();
+
+ (this->*result)(words, *body);
+ delete body;
+ }
+ }
+}
+
+QPoint KWmf::normalisePoint(
+ QDataStream &operands)
+{
+ S16 x;
+ S16 y;
+
+ operands >> x >> y;
+ return QPoint((x - m_windowOrgX) * m_windowFlipX / m_dpi, (y - m_windowOrgY) * m_windowFlipY / m_dpi);
+}
+
+QSize KWmf::normaliseSize(
+ QDataStream &operands)
+{
+ S16 width;
+ S16 height;
+
+ operands >> width >> height;
+ return QSize(width / m_dpi, height / m_dpi);
+}
+
+bool KWmf::parse(
+ const QString &file)
+{
+ QFile in(file);
+ if (!in.open(IO_ReadOnly))
+ {
+ kdError(s_area) << "Unable to open input file!" << endl;
+ in.close();
+ return false;
+ }
+ QDataStream stream(&in);
+ bool result = parse(stream, in.size());
+ in.close();
+ return result;
+}
+
+bool KWmf::parse(
+ QDataStream &stream,
+ unsigned size)
+{
+ int startedAt;
+ bool isPlaceable;
+ bool isEnhanced;
+
+ startedAt = stream.device()->at();
+ stream.setByteOrder(QDataStream::LittleEndian); // Great, I love Qt !
+
+ for (int i = 0; i < s_maxHandles; i++)
+ m_objectHandles[i] = NULL;
+
+ typedef struct _RECT
+ {
+ S16 left;
+ S16 top;
+ S16 right;
+ S16 bottom;
+ } RECT;
+
+ typedef struct _RECTL
+ {
+ S32 left;
+ S32 top;
+ S32 right;
+ S32 bottom;
+ } RECTL;
+
+ typedef struct _SIZE
+ {
+ S16 width;
+ S16 height;
+ } SIZE;
+
+ typedef struct _SIZEL
+ {
+ S32 width;
+ S32 height;
+ } SIZEL;
+
+ struct WmfEnhMetaHeader
+ {
+ S32 iType; // Record type EMR_HEADER
+ S32 nSize; // Record size in bytes. This may be greater
+ // than the sizeof(ENHMETAHEADER).
+ RECTL rclBounds; // Inclusive-inclusive bounds in device units
+ RECTL rclFrame; // Inclusive-inclusive Picture Frame of metafile
+ // in .01 mm units
+ S32 dSignature; // Signature. Must be ENHMETA_SIGNATURE.
+ S32 nVersion; // Version number
+ S32 nBytes; // Size of the metafile in bytes
+ S32 nRecords; // Number of records in the metafile
+ S16 nHandles; // Number of handles in the handle table
+ // Handle index zero is reserved.
+ S16 sReserved; // Reserved. Must be zero.
+ S32 nDescription; // Number of chars in the unicode description string
+ // This is 0 if there is no description string
+ S32 offDescription; // Offset to the metafile description record.
+ // This is 0 if there is no description string
+ S32 nPalEntries; // Number of entries in the metafile palette.
+ SIZEL szlDevice; // Size of the reference device in pels
+ SIZEL szlMillimeters; // Size of the reference device in millimeters
+ };
+ #define ENHMETA_SIGNATURE 0x464D4520
+
+ struct WmfMetaHeader
+ {
+ S16 mtType;
+ S16 mtHeaderSize;
+ S16 mtVersion;
+ S32 mtSize;
+ S16 mtNoObjects;
+ S32 mtMaxRecord;
+ S16 mtNoParameters;
+ };
+
+ struct WmfPlaceableHeader
+ {
+ S32 key;
+ S16 hmf;
+ RECT bbox;
+ S16 inch;
+ S32 reserved;
+ S16 checksum;
+ };
+ #define APMHEADER_KEY 0x9AC6CDD7L
+
+ WmfPlaceableHeader pheader;
+ WmfEnhMetaHeader eheader;
+ WmfMetaHeader header;
+ S16 checksum;
+ int fileAt;
+
+ //----- Read placeable metafile header
+
+ stream >> pheader.key;
+ isPlaceable = (pheader.key == (S32)APMHEADER_KEY);
+ if (isPlaceable)
+ {
+ stream >> pheader.hmf;
+ stream >> pheader.bbox.left;
+ stream >> pheader.bbox.top;
+ stream >> pheader.bbox.right;
+ stream >> pheader.bbox.bottom;
+ stream >> pheader.inch;
+ stream >> pheader.reserved;
+ stream >> pheader.checksum;
+ checksum = 0;
+ S16 *ptr = (S16 *)&pheader;
+
+ // XOR in each of the S16s.
+
+ for (unsigned i = 0; i < sizeof(WmfPlaceableHeader)/sizeof(S16); i++)
+ {
+ checksum ^= ptr[i];
+ }
+ if (pheader.checksum != checksum)
+ isPlaceable = false;
+ m_dpi = (unsigned)((double)pheader.inch / m_dpi);
+ m_windowOrgX = pheader.bbox.left;
+ m_windowOrgY = pheader.bbox.top;
+ if (pheader.bbox.right > pheader.bbox.left)
+ m_windowFlipX = 1;
+ else
+ m_windowFlipX = -1;
+ if (pheader.bbox.bottom > pheader.bbox.top)
+ m_windowFlipY = 1;
+ else
+ m_windowFlipY = -1;
+ }
+ else
+ {
+ stream.device()->at(startedAt);
+ m_dpi = (unsigned)((double)576 / m_dpi);
+ m_windowOrgX = 0;
+ m_windowOrgY = 0;
+ m_windowFlipX = 1;
+ m_windowFlipY = 1;
+ }
+
+ //----- Read as enhanced metafile header
+
+ fileAt = stream.device()->at();
+ stream >> eheader.iType;
+ stream >> eheader.nSize;
+ stream >> eheader.rclBounds.left;
+ stream >> eheader.rclBounds.top;
+ stream >> eheader.rclBounds.right;
+ stream >> eheader.rclBounds.bottom;
+ stream >> eheader.rclFrame.left;
+ stream >> eheader.rclFrame.top;
+ stream >> eheader.rclFrame.right;
+ stream >> eheader.rclFrame.bottom;
+ stream >> eheader.dSignature;
+ isEnhanced = (eheader.dSignature == ENHMETA_SIGNATURE);
+ if (isEnhanced) // is it really enhanced ?
+ {
+ stream >> eheader.nVersion;
+ stream >> eheader.nBytes;
+ stream >> eheader.nRecords;
+ stream >> eheader.nHandles;
+ stream >> eheader.sReserved;
+ stream >> eheader.nDescription;
+ stream >> eheader.offDescription;
+ stream >> eheader.nPalEntries;
+ stream >> eheader.szlDevice.width;
+ stream >> eheader.szlDevice.height;
+ stream >> eheader.szlMillimeters.width;
+ stream >> eheader.szlMillimeters.height;
+
+ kdError(s_area) << "WMF Extended Header NOT YET IMPLEMENTED, SORRY." << endl;
+ /*
+ if (mSingleStep)
+ {
+ debug(" iType=%d", eheader.iType);
+ debug(" nSize=%d", eheader.nSize);
+ debug(" rclBounds=(%ld;%ld;%ld;%ld)",
+ eheader.rclBounds.left, eheader.rclBounds.top,
+ eheader.rclBounds.right, eheader.rclBounds.bottom);
+ debug(" rclFrame=(%ld;%ld;%ld;%ld)",
+ eheader.rclFrame.left, eheader.rclFrame.top,
+ eheader.rclFrame.right, eheader.rclFrame.bottom);
+ debug(" dSignature=%d", eheader.dSignature);
+ debug(" nVersion=%d", eheader.nVersion);
+ debug(" nBytes=%d", eheader.nBytes);
+ }
+ debug("NOT YET IMPLEMENTED, SORRY.");
+ */
+ return false;
+ }
+ else // no, not enhanced
+ {
+ // debug("WMF Header");
+ //----- Read as standard metafile header
+ stream.device()->at(fileAt);
+ stream >> header.mtType;
+ stream >> header.mtHeaderSize;
+ stream >> header.mtVersion;
+ stream >> header.mtSize;
+ stream >> header.mtNoObjects;
+ stream >> header.mtMaxRecord;
+ stream >> header.mtNoParameters;
+ /*
+ if (mSingleStep)
+ {
+ debug(" mtType=%u", header.mtType);
+ debug(" mtHeaderSize=%u", header.mtHeaderSize);
+ debug(" mtVersion=%u", header.mtVersion);
+ debug(" mtSize=%ld", header.mtSize);
+ }
+ */
+ }
+
+ walk((size - (stream.device()->at() - startedAt)) / 2, stream);
+ return true;
+}
+
+void KWmf::opArc(
+ U32 /*words*/,
+ QDataStream &operands)
+{
+ genericArc("arc", operands);
+}
+
+void KWmf::opBrushCreateIndirect(
+ U32 /*words*/,
+ QDataStream &operands)
+{
+ 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;
+ WinObjBrushHandle *handle = handleCreateBrush();
+ S16 arg;
+ S32 colour;
+ S16 discard;
+
+ operands >> arg >> colour;
+ handle->m_colour = getColour(colour);
+ if (arg == 2)
+ {
+ operands >> arg;
+ if (arg >= 0 && arg < 6)
+ {
+ style = hatchedStyleTab[arg];
+ }
+ else
+ {
+ kdError(s_area) << "createBrushIndirect: invalid hatched brush " << arg << endl;
+ style = Qt::SolidPattern;
+ }
+ }
+ else
+ if (arg >= 0 && arg < 9)
+ {
+ style = styleTab[arg];
+ operands >> discard;
+ }
+ else
+ {
+ kdError(s_area) << "createBrushIndirect: invalid brush " << arg << endl;
+ style = Qt::SolidPattern;
+ operands >> discard;
+ }
+ handle->m_style = style;
+}
+
+void KWmf::opEllipse(
+ U32 /*words*/,
+ QDataStream &operands)
+{
+ QPoint topLeft;
+ QPoint bottomRight;
+
+ topLeft = normalisePoint(operands);
+ bottomRight = normalisePoint(operands);
+
+ QRect ellipse(topLeft, bottomRight);
+
+ gotEllipse(m_dc, "full", ellipse.center(), ellipse.size() / 2, 0, 0);
+}
+
+void KWmf::opLineTo(
+ U32 /*words*/,
+ QDataStream &operands)
+{
+ QPoint lineTo;
+
+ lineTo = normalisePoint(operands);
+ QPointArray points(2);
+ points.setPoint(0, m_lineFrom);
+ points.setPoint(1, lineTo);
+ gotPolyline(m_dc, points);
+
+ // Remember this point for next time.
+
+ m_lineFrom = lineTo;
+}
+
+void KWmf::opMoveTo(
+ U32 /*words*/,
+ QDataStream &operands)
+{
+ m_lineFrom = normalisePoint(operands);
+}
+
+void KWmf::opNoop(
+ U32 words,
+ QDataStream &operands)
+{
+ skip(words, operands);
+}
+
+//-----------------------------------------------------------------------------
+void KWmf::opObjectDelete(
+ U32 /*words*/,
+ QDataStream &operands)
+{
+ S16 idx;
+
+ operands >> idx;
+ handleDelete(idx);
+}
+
+//-----------------------------------------------------------------------------
+void KWmf::opObjectSelect(
+ U32 /*words*/,
+ QDataStream &operands)
+{
+ S16 idx;
+
+ operands >> idx;
+ if (idx >= 0 && idx < s_maxHandles && m_objectHandles[idx])
+ m_objectHandles[idx]->apply(*this);
+}
+
+//
+//
+//
+
+void KWmf::opPenCreateIndirect(
+ U32 /*words*/,
+ QDataStream &operands)
+{
+ static Qt::PenStyle styleTab[] =
+ {
+ Qt::SolidLine,
+ Qt::DashLine,
+ Qt::DotLine,
+ Qt::DashDotLine,
+ Qt::DashDotDotLine,
+ Qt::NoPen,
+ Qt::SolidLine, // PS_INSIDEFRAME
+ Qt::SolidLine, // PS_USERSTYLE
+ Qt::SolidLine // PS_ALTERNATE
+ };
+ WinObjPenHandle *handle = handleCreatePen();
+ S16 arg;
+ S32 colour;
+
+ operands >> arg;
+ if (arg >= 0 && arg < 8)
+ {
+ handle->m_style = styleTab[arg];
+ }
+ else
+ {
+ kdError(s_area) << "createPenIndirect: invalid pen " << arg << endl;
+ handle->m_style = Qt::SolidLine;
+ }
+ operands >> arg;
+ handle->m_width = arg;
+ operands >> arg >> colour;
+ handle->m_colour = getColour(colour);
+}
+
+void KWmf::opPie(
+ U32 /*words*/,
+ QDataStream &operands)
+{
+ genericArc("pie", operands);
+}
+
+void KWmf::opPolygonSetFillMode(
+ U32 /*words*/,
+ QDataStream &operands)
+{
+ S16 tmp;
+
+ operands >> tmp;
+ m_dc.m_winding = tmp != 0;
+}
+
+void KWmf::opPolygon(
+ U32 /*words*/,
+ QDataStream &operands)
+{
+ S16 tmp;
+
+ operands >> tmp;
+ QPointArray points(tmp);
+
+ for (int i = 0; i < tmp; i++)
+ {
+ points.setPoint(i, normalisePoint(operands));
+ }
+ gotPolygon(m_dc, points);
+}
+
+void KWmf::opPolyline(
+ U32 /*words*/,
+ QDataStream &operands)
+{
+ S16 tmp;
+
+ operands >> tmp;
+ QPointArray points(tmp);
+
+ for (int i = 0; i < tmp; i++)
+ {
+ points.setPoint(i, normalisePoint(operands));
+ }
+ gotPolyline(m_dc, points);
+}
+
+void KWmf::opRectangle(
+ U32 /*words*/,
+ QDataStream &operands)
+{
+ QPoint topLeft;
+ QSize size;
+
+ topLeft = normalisePoint(operands);
+ size = normaliseSize(operands);
+ QRect rect(topLeft, size);
+ QPointArray points(4);
+
+ points.setPoint(0, topLeft);
+ points.setPoint(1, rect.topRight());
+ points.setPoint(2, rect.bottomRight());
+ points.setPoint(3, rect.bottomLeft());
+ gotRectangle(m_dc, points);
+}
+
+void KWmf::opRestoreDc(
+ U32 /*words*/,
+ QDataStream &operands)
+{
+ S16 pop;
+ S16 i;
+
+ operands >> pop;
+ for (i = 0; i < pop; i++)
+ {
+ m_dc = m_savedDcs.pop();
+ }
+}
+
+void KWmf::opSaveDc(
+ U32 /*words*/,
+ QDataStream &/*operands*/)
+{
+ m_savedDcs.push(m_dc);
+
+ // TBD: reinitialise m_dc.
+}
+
+void KWmf::opWindowSetOrg(
+ U32 /*words*/,
+ QDataStream &operands)
+{
+ S16 top;
+ S16 left;
+
+ operands >> top >> left;
+ m_windowOrgX = left;
+ m_windowOrgY = top;
+}
+
+void KWmf::opWindowSetExt(
+ U32 /*words*/,
+ QDataStream &operands)
+{
+ S16 height;
+ S16 width;
+
+ operands >> height >> width;
+ if (width > 0)
+ m_windowFlipX = 1;
+ else
+ m_windowFlipX = -1;
+ if (height > 0)
+ m_windowFlipY = 1;
+ else
+ m_windowFlipY = -1;
+}
+
+void KWmf::penSet(
+ unsigned colour,
+ unsigned style,
+ unsigned width)
+{
+ m_dc.m_penColour = colour;
+ m_dc.m_penStyle = style;
+ m_dc.m_penWidth = width;
+}
+
+void KWmf::skip(
+ U32 words,
+ QDataStream &operands)
+{
+ if ((int)words < 0)
+ {
+ kdError(s_area) << "skip: " << (int)words << endl;
+ return;
+ }
+ if (words)
+ {
+ U32 i;
+ S16 discard;
+
+ kdDebug(s_area) << "skip: " << words << endl;
+ for (i = 0; i < words; i++)
+ {
+ operands >> discard;
+ }
+ }
+}
+
+void KWmf::walk(
+ U32 words,
+ QDataStream &operands)
+{
+ // Read bits:
+ //
+ // struct WmfMetaRecord
+ // {
+ // S32 rdSize; // Record size (in words) of the function
+ // S16 rdFunction; // Record function number
+ // S16 rdParm[1]; // WORD array of parameters
+ // };
+ //
+ // struct WmfEnhMetaRecord
+ // {
+ // S32 iType; // Record type EMR_xxx
+ // S32 nSize; // Record size in bytes
+ // S32 dParm[1]; // DWORD array of parameters
+ // };
+
+ S32 wordCount;
+ S16 opcode;
+ U32 length = 0;
+
+ while (length < words)
+ {
+ operands >> wordCount;
+ operands >> opcode;
+
+ // If we get some duff data, protect ourselves.
+ if (length + wordCount > words)
+ {
+ wordCount = words - length;
+ }
+ length += wordCount;
+ if (opcode == 0)
+ {
+ // This appears to be an EOF marker.
+ break;
+ }
+
+ // Package the arguments...
+
+ invokeHandler(opcode, wordCount - 3, operands);
+ }
+
+ // Eat unexpected data that the caller may expect us to consume.
+ skip(words - length, operands);
+}
+
+KWmf::DrawContext::DrawContext()
+{
+ // TBD: initalise with proper values.
+ m_brushColour = 0x808080;
+ m_brushStyle = 1;
+ m_penColour = 0x808080;
+ m_penStyle = 1;
+ m_penWidth = 1;
+}
+
+void KWmf::WinObjBrushHandle::apply(
+ KWmf &p)
+{
+ p.brushSet(m_colour, m_style);
+}
+
+void KWmf::WinObjPenHandle::apply(
+ KWmf &p)
+{
+ p.penSet(m_colour, m_style, m_width);
+}
diff --git a/lib/kwmf/kwmf.h b/lib/kwmf/kwmf.h
new file mode 100644
index 00000000..4f1b050a
--- /dev/null
+++ b/lib/kwmf/kwmf.h
@@ -0,0 +1,220 @@
+/*
+ Copyright (C) 2000, S.R.Haque <[email protected]>.
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ aS32 with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+DESCRIPTION
+
+ This is a generic parser for Windows MetaFiles (WMFs). The output is
+ a series of callbacks (a.k.a. virtual functions) which the caller can
+ override as required.
+
+ This is based on code originally written by Stefan Taferner
+*/
+
+#ifndef KWMF_H
+#define KWMF_H
+
+#include <qvaluestack.h>
+#include <koffice_export.h>
+class QDataStream;
+class QPointArray;
+
+class KOWMF_EXPORT KWmf
+{
+public:
+
+ // Construction.
+
+ KWmf(
+ unsigned dpi);
+ virtual ~KWmf();
+
+ // Called to parse the given file.
+
+ bool parse(
+ const QString &file);
+ bool parse(
+ QDataStream &stream,
+ unsigned size);
+
+ class KOWMF_EXPORT DrawContext
+ {
+ public:
+ DrawContext();
+ bool m_winding;
+ unsigned m_brushColour;
+ unsigned m_brushStyle;
+ unsigned m_penColour;
+ unsigned m_penStyle;
+ unsigned m_penWidth;
+ };
+
+ // Should be protected...
+
+ void brushSet(
+ unsigned colour,
+ unsigned style);
+ void penSet(
+ unsigned colour,
+ unsigned style,
+ unsigned width);
+
+protected:
+ // Override to get results of parsing.
+
+ virtual void gotEllipse(
+ const DrawContext &dc,
+ QString type,
+ QPoint topLeft,
+ QSize halfAxes,
+ unsigned startAngle,
+ unsigned stopAngle) = 0;
+ virtual void gotPolygon(
+ const DrawContext &dc,
+ const QPointArray &points) = 0;
+ virtual void gotPolyline(
+ const DrawContext &dc,
+ const QPointArray &points) = 0;
+ virtual void gotRectangle(
+ const DrawContext &dc,
+ const QPointArray &points) = 0;
+
+private:
+ // Debug support.
+
+ static const int s_area;
+
+ // Use unambiguous names for Microsoft types.
+
+ typedef short S16;
+ typedef int S32;
+ typedef unsigned int U32;
+
+ int m_dpi;
+ int m_windowOrgX;
+ int m_windowOrgY;
+ int m_windowFlipX;
+ int m_windowFlipY;
+ DrawContext m_dc;
+ QValueStack<DrawContext> m_savedDcs;
+ QPoint m_lineFrom;
+
+ // Windows handle management.
+
+ class WinObjHandle
+ {
+ public:
+ virtual ~WinObjHandle () {}
+ virtual void apply(KWmf &p) = 0;
+ };
+
+ class WinObjBrushHandle: public WinObjHandle
+ {
+ public:
+ virtual void apply(KWmf &p);
+ unsigned m_colour;
+ unsigned m_style;
+ };
+
+ class WinObjPenHandle: public WinObjHandle
+ {
+ public:
+ virtual void apply(KWmf &p);
+ unsigned m_colour;
+ unsigned m_style;
+ unsigned m_width;
+ };
+
+ int handleIndex(void) const;
+ WinObjPenHandle *handleCreatePen(void);
+ WinObjBrushHandle *handleCreateBrush(void);
+ void handleDelete(int idx);
+ static const int s_maxHandles;
+ WinObjHandle **m_objectHandles;
+
+ unsigned getColour(S32 colour);
+ QPoint normalisePoint(
+ QDataStream &operands);
+ QSize normaliseSize(
+ QDataStream &operands);
+ void genericArc(
+ QString type,
+ QDataStream &operands);
+
+ // Opcode handling and painter methods.
+
+ void walk(
+ U32 words,
+ QDataStream &stream);
+ void skip(
+ U32 words,
+ QDataStream &operands);
+ void invokeHandler(
+ S16 opcode,
+ U32 words,
+ QDataStream &operands);
+/*
+ // draw multiple polygons
+ void opPolypolygon(U32 words, QDataStream &operands);
+*/
+ void opArc(U32 words, QDataStream &operands);
+ // create a logical brush
+ void opBrushCreateIndirect(U32 words, QDataStream &operands);
+ void opEllipse(U32 words, QDataStream &operands);
+ // draw line to coord
+ void opLineTo(U32 words, QDataStream &operands);
+ // move pen to coord
+ void opMoveTo(U32 words, QDataStream &operands);
+ // do nothing
+ void opNoop(U32 words, QDataStream &operands);
+ // Free object handle
+ void opObjectDelete(U32 words, QDataStream &operands);
+ // Activate object handle
+ void opObjectSelect(U32 words, QDataStream &operands);
+ // create a logical pen
+ void opPenCreateIndirect(U32 words, QDataStream &operands);
+ void opPie(U32 words, QDataStream &operands);
+ // draw polygon
+ void opPolygon(U32 words, QDataStream &operands);
+ // set polygon fill mode
+ void opPolygonSetFillMode(U32 words, QDataStream &operands);
+ // draw series of lines
+ void opPolyline(U32 words, QDataStream &operands);
+ void opRectangle(U32 words, QDataStream &operands);
+ // restore drawing context
+ void opRestoreDc(U32 words, QDataStream &operands);
+ // save drawing context
+ void opSaveDc(U32 words, QDataStream &operands);
+ // set window origin
+ void opWindowSetOrg(U32 words, QDataStream &operands);
+ // set window extents
+ void opWindowSetExt(U32 words, QDataStream &operands);
+/*
+ // set background pen color
+ void opsetBkColor(U32 words, QDataStream &operands);
+ // set background pen mode
+ void opsetBkMode(U32 words, QDataStream &operands);
+ // Set raster operation mode
+ void opsetRop(U32 words, QDataStream &operands);
+ // Escape (enhanced command set)
+ void opescape(U32 words, QDataStream &operands);
+*/
+};
+
+#endif
diff --git a/lib/kwmf/metafuncs.h b/lib/kwmf/metafuncs.h
new file mode 100644
index 00000000..8675851e
--- /dev/null
+++ b/lib/kwmf/metafuncs.h
@@ -0,0 +1,90 @@
+/* WMF Metafile Function Description Table
+ * Author: Stefan Taferner <[email protected]>
+ */
+#ifndef metafunc_h
+#define metafunc_h
+
+class QWinMetaFile;
+
+static const struct MetaFuncRec
+{
+ const char* name;
+ unsigned short func;
+ void ( QWinMetaFile::*method )( long, short* );
+} metaFuncTab[] =
+ {
+ { "SETBKCOLOR", 0x0201, &QWinMetaFile::setBkColor },
+ { "SETBKMODE", 0x0102, &QWinMetaFile::setBkMode },
+ { "SETMAPMODE", 0x0103, &QWinMetaFile::noop },
+ { "SETROP2", 0x0104, &QWinMetaFile::setRop },
+ { "SETRELABS", 0x0105, &QWinMetaFile::noop },
+ { "SETPOLYFILLMODE", 0x0106, &QWinMetaFile::setPolyFillMode },
+ { "SETSTRETCHBLTMODE", 0x0107, &QWinMetaFile::noop },
+ { "SETTEXTCHAREXTRA", 0x0108, &QWinMetaFile::noop },
+ { "SETTEXTCOLOR", 0x0209, &QWinMetaFile::setTextColor },
+ { "SETTEXTJUSTIFICATION", 0x020A, &QWinMetaFile::noop },
+ { "SETWINDOWORG", 0x020B, &QWinMetaFile::setWindowOrg },
+ { "SETWINDOWEXT", 0x020C, &QWinMetaFile::setWindowExt },
+ { "SETVIEWPORTORG", 0x020D, &QWinMetaFile::noop },
+ { "SETVIEWPORTEXT", 0x020E, &QWinMetaFile::noop },
+ { "OFFSETWINDOWORG", 0x020F, &QWinMetaFile::noop },
+ { "SCALEWINDOWEXT", 0x0410, &QWinMetaFile::noop },
+ { "OFFSETVIEWPORTORG", 0x0211, &QWinMetaFile::noop },
+ { "SCALEVIEWPORTEXT", 0x0412, &QWinMetaFile::noop },
+ { "LINETO", 0x0213, &QWinMetaFile::lineTo },
+ { "MOVETO", 0x0214, &QWinMetaFile::moveTo },
+ { "EXCLUDECLIPRECT", 0x0415, &QWinMetaFile::excludeClipRect },
+ { "INTERSECTCLIPRECT", 0x0416, &QWinMetaFile::intersectClipRect },
+ { "ARC", 0x0817, &QWinMetaFile::arc },
+ { "ELLIPSE", 0x0418, &QWinMetaFile::ellipse },
+ { "FLOODFILL", 0x0419, &QWinMetaFile::noop },
+ { "PIE", 0x081A, &QWinMetaFile::pie },
+ { "RECTANGLE", 0x041B, &QWinMetaFile::rectangle },
+ { "ROUNDRECT", 0x061C, &QWinMetaFile::roundRect },
+ { "PATBLT", 0x061D, &QWinMetaFile::noop },
+ { "SAVEDC", 0x001E, &QWinMetaFile::saveDC },
+ { "SETPIXEL", 0x041F, &QWinMetaFile::setPixel },
+ { "OFFSETCLIPRGN", 0x0220, &QWinMetaFile::noop },
+ { "TEXTOUT", 0x0521, &QWinMetaFile::textOut },
+ { "BITBLT", 0x0922, &QWinMetaFile::noop },
+ { "STRETCHBLT", 0x0B23, &QWinMetaFile::noop },
+ { "POLYGON", 0x0324, &QWinMetaFile::polygon },
+ { "POLYLINE", 0x0325, &QWinMetaFile::polyline },
+ { "ESCAPE", 0x0626, &QWinMetaFile::noop },
+ { "RESTOREDC", 0x0127, &QWinMetaFile::restoreDC },
+ { "FILLREGION", 0x0228, &QWinMetaFile::noop },
+ { "FRAMEREGION", 0x0429, &QWinMetaFile::noop },
+ { "INVERTREGION", 0x012A, &QWinMetaFile::noop },
+ { "PAINTREGION", 0x012B, &QWinMetaFile::noop },
+ { "SELECTCLIPREGION", 0x012C, &QWinMetaFile::noop },
+ { "SELECTOBJECT", 0x012D, &QWinMetaFile::selectObject },
+ { "SETTEXTALIGN", 0x012E, &QWinMetaFile::setTextAlign },
+ { "CHORD", 0x0830, &QWinMetaFile::chord },
+ { "SETMAPPERFLAGS", 0x0231, &QWinMetaFile::noop },
+ { "EXTTEXTOUT", 0x0a32, &QWinMetaFile::extTextOut },
+ { "SETDIBTODEV", 0x0d33, &QWinMetaFile::noop },
+ { "SELECTPALETTE", 0x0234, &QWinMetaFile::noop },
+ { "REALIZEPALETTE", 0x0035, &QWinMetaFile::noop },
+ { "ANIMATEPALETTE", 0x0436, &QWinMetaFile::noop },
+ { "SETPALENTRIES", 0x0037, &QWinMetaFile::noop },
+ { "POLYPOLYGON", 0x0538, &QWinMetaFile::polyPolygon },
+ { "RESIZEPALETTE", 0x0139, &QWinMetaFile::noop },
+ { "DIBBITBLT", 0x0940, &QWinMetaFile::dibBitBlt },
+ { "DIBSTRETCHBLT", 0x0b41, &QWinMetaFile::dibStretchBlt },
+ { "DIBCREATEPATTERNBRUSH", 0x0142, &QWinMetaFile::dibCreatePatternBrush },
+ { "STRETCHDIB", 0x0f43, &QWinMetaFile::stretchDib },
+ { "EXTFLOODFILL", 0x0548, &QWinMetaFile::noop },
+ { "DELETEOBJECT", 0x01f0, &QWinMetaFile::deleteObject },
+ { "CREATEPALETTE", 0x00f7, &QWinMetaFile::createEmptyObject },
+ { "CREATEPATTERNBRUSH", 0x01F9, &QWinMetaFile::createEmptyObject },
+ { "CREATEPENINDIRECT", 0x02FA, &QWinMetaFile::createPenIndirect },
+ { "CREATEFONTINDIRECT", 0x02FB, &QWinMetaFile::createFontIndirect },
+ { "CREATEBRUSHINDIRECT", 0x02FC, &QWinMetaFile::createBrushIndirect },
+ { "CREATEREGION", 0x06FF, &QWinMetaFile::createEmptyObject },
+ { "END", 0, &QWinMetaFile::end },
+ // always the latest in the table : in case of unknown function
+ { NULL, 0, &QWinMetaFile::noop },
+ };
+
+
+#endif /*metafunc_h*/
diff --git a/lib/kwmf/qwmf.cc b/lib/kwmf/qwmf.cc
new file mode 100644
index 00000000..89e2f50f
--- /dev/null
+++ b/lib/kwmf/qwmf.cc
@@ -0,0 +1,1258 @@
+/* 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 <qfileinfo.h>
+#include <qpixmap.h>
+#include <qpainter.h>
+#include <qdatastream.h>
+#include <qapplication.h>
+#include <qbuffer.h>
+#include <kdebug.h>
+
+bool qwmfDebug = false;
+
+#include "qwmf.h"
+#include "wmfstruct.h"
+#include "metafuncs.h"
+
+#define QWMF_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( QPainter& p ) = 0;
+};
+
+class WinObjBrushHandle: public WinObjHandle
+{
+public:
+ virtual void apply( QPainter& p );
+ QBrush brush;
+ virtual ~WinObjBrushHandle() {};
+};
+
+class WinObjPenHandle: public WinObjHandle
+{
+public:
+ virtual void apply( QPainter& p );
+ QPen pen;
+ virtual ~WinObjPenHandle() {};
+};
+
+class WinObjPatternBrushHandle: public WinObjHandle
+{
+public:
+ virtual void apply( QPainter& p );
+ QBrush brush;
+ QPixmap image;
+ virtual ~WinObjPatternBrushHandle() {};
+};
+
+class WinObjFontHandle: public WinObjHandle
+{
+public:
+ virtual void apply( QPainter& p );
+ QFont font;
+ int rotation;
+ virtual ~WinObjFontHandle() {};
+};
+
+void WinObjBrushHandle::apply( QPainter& p )
+{
+ p.setBrush( brush );
+}
+
+void WinObjPenHandle::apply( QPainter& p )
+{
+ p.setPen( pen );
+}
+
+void WinObjPatternBrushHandle::apply( QPainter& p )
+{
+ p.setBrush( brush );
+}
+
+void WinObjFontHandle::apply( QPainter& 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 QString &filename )
+{
+ QFile file( filename );
+
+ if ( !file.exists() )
+ {
+ kdDebug() << "File " << QFile::encodeName(filename) << " does not exist" << endl;
+ return false;
+ }
+
+ if ( !file.open( IO_ReadOnly ) )
+ {
+ kdDebug() << "Cannot open file " << QFile::encodeName(filename) << endl;
+ return false;
+ }
+
+ QByteArray ba = file.readAll();
+ file.close();
+
+ QBuffer buffer( ba );
+ buffer.open( IO_ReadOnly );
+ return load( buffer );
+}
+
+//-----------------------------------------------------------------------------
+bool QWinMetaFile::load( QBuffer &buffer )
+{
+ QDataStream 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 = Qt::black;
+ if ( mFirstCmd ) delete mFirstCmd;
+ mFirstCmd = NULL;
+
+ st.setDevice( &buffer );
+ st.setByteOrder( QDataStream::LittleEndian ); // Great, I love Qt !
+
+ //----- 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 ( QWMF_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 ( QWMF_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 ( QWMF_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 QPaintDevice* 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.begin( aTarget );
+ if ( QWMF_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 ( QWMF_DEBUG ) {
+ QString 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 QPicture::setBoundingBox() is possible in KOClipart (QT31)
+ // because actually QPicture::boundingBox() != mBBox()
+ mWindowsCoord += 1;
+ if ( mWindowsCoord == 2 ) {
+ kdDebug() << "DRAW ANGLES " << endl;
+ mPainter.setPen( Qt::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 ) {
+ QRect 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 : QABS() forbidden
+ if ( mAbsoluteCoord ) {
+ QRect r = mPainter.window();
+ mPainter.setWindow( r.left(), r.top(), parm[ 1 ], parm[ 0 ] );
+ }
+ else {
+ if ( (parm[ 0 ] != 0) && (parm[ 1 ] != 0) ) {
+ QRect 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 )
+{
+ QPointArray* pa;
+
+ pa = pointArray( parm[ 0 ], &parm[ 1 ] );
+ mPainter.drawPolygon( *pa, mWinding );
+}
+
+
+//-----------------------------------------------------------------------------
+void QWinMetaFile::polyPolygon( long, short* parm )
+{
+ QRegion region;
+ int i, j, startPolygon;
+
+ mPainter.save();
+
+ // define clipping region
+ QRect win = bbox();
+ startPolygon = 1+parm[ 0 ];
+ for ( i=0 ; i < parm[ 0 ] ; i++ ) {
+ QPointArray pa1( parm[ 1+i ] );
+ for ( j=0 ; j < parm[ 1+i ] ; j++) {
+ pa1.setPoint ( j, parm[ startPolygon ], parm[ startPolygon+1 ] );
+ startPolygon += 2;
+ }
+ QRegion r( pa1 );
+ region = region.eor( r );
+ }
+ mPainter.setClipRegion( region, QPainter::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() != Qt::NoPen ) {
+ mPainter.setClipping( false );
+ mPainter.setBrush( Qt::NoBrush );
+
+ QPointArray* 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 )
+{
+ QPointArray* 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 )
+{
+ QPen pen = mPainter.pen();
+ mPainter.setPen( color( parm ) );
+ mPainter.drawPoint( parm[ 3 ], parm[ 2 ] );
+ mPainter.setPen( pen );
+}
+
+
+//-----------------------------------------------------------------------------
+void QWinMetaFile::setRop( long, short* parm )
+{
+ mPainter.setRasterOp( winToQtRaster( 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
+ QRegion region = mPainter.clipRegion();
+ if ( region.isEmpty() )
+ region = bbox();
+*/
+ QRegion region( bbox() );
+
+ QRegion newRegion( parm[ 3 ], parm[ 2 ], parm[ 1 ] - parm[ 3 ], parm[ 0 ] - parm[ 2 ] );
+ region = region.intersect( newRegion );
+
+ mPainter.setClipRegion( region, QPainter::CoordPainter );
+}
+
+
+//-----------------------------------------------------------------------------
+void QWinMetaFile::excludeClipRect( long, short* parm )
+{
+/* TODO: better implementation : need QT 3.0.2
+ QRegion region = mPainter.clipRegion();
+ if ( region.isEmpty() )
+ region = bbox();
+*/
+ QRegion region( bbox() );
+
+ QRegion newRegion( parm[ 3 ], parm[ 2 ], parm[ 1 ] - parm[ 3 ], parm[ 0 ] - parm[ 2 ] );
+ region = region.subtract( newRegion );
+
+ mPainter.setClipRegion( region, QPainter::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( &copyParm[ 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 ];
+
+ QCString text( ptStr, parm[ 2 ] + 1 );
+
+ QFontMetrics 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
+ QPoint 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 ] );
+ }
+
+ // alignment
+ 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, Qt::AlignLeft | Qt::AlignTop, text.mid(0, 1) );
+ for ( int i = 1; i < parm[ 2 ] ; i++ ) {
+ left += parm[ idxOffset + i - 1 ];
+ mPainter.drawText( left, y, width, height, Qt::AlignLeft | Qt::AlignTop, text.mid(i, 1) );
+ }
+ }
+ else {
+ mPainter.drawText( x, y, width, height, Qt::AlignLeft | Qt::AlignTop, text );
+ }
+
+ mPainter.restore();
+
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Bitmap
+//-----------------------------------------------------------------------------
+void QWinMetaFile::dibBitBlt( long num, short* parm )
+{
+ if ( num > 9 ) { // DIB image
+ QImage bmpSrc;
+
+ if ( dibToBmp( bmpSrc, (char*)&parm[ 8 ], (num - 8) * 2 ) ) {
+ long raster = toDWord( parm );
+
+ mPainter.setRasterOp( winToQtRaster( raster ) );
+
+ // wmf file allow negative width or height
+ mPainter.save();
+ if ( parm[ 5 ] < 0 ) { // width < 0 => horizontal flip
+ QWMatrix 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
+ QWMatrix 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 )
+{
+ QImage bmpSrc;
+
+ if ( dibToBmp( bmpSrc, (char*)&parm[ 10 ], (num - 10) * 2 ) ) {
+ long raster = toDWord( parm );
+
+ mPainter.setRasterOp( winToQtRaster( raster ) );
+
+ // wmf file allow negative width or height
+ mPainter.save();
+ if ( parm[ 7 ] < 0 ) { // width < 0 => horizontal flip
+ QWMatrix 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
+ QWMatrix 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 ( QImage::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 )
+{
+ QImage bmpSrc;
+
+ if ( dibToBmp( bmpSrc, (char*)&parm[ 11 ], (num - 11) * 2 ) ) {
+ long raster = toDWord( parm );
+
+ mPainter.setRasterOp( winToQtRaster( raster ) );
+
+ // wmf file allow negative width or height
+ mPainter.save();
+ if ( parm[ 8 ] < 0 ) { // width < 0 => horizontal flip
+ QWMatrix 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
+ QWMatrix 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 ( QImage::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 );
+ QImage 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
+/*
+ QRect 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 );
+
+ QString 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( QABS(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;
+}
+
+//-----------------------------------------------------------------------------
+QPointArray* 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;
+}
+
+
+//-----------------------------------------------------------------------------
+QColor 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 QColor( 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;
+ }
+}
+
+//-----------------------------------------------------------------------------
+Qt::RasterOp QWinMetaFile::winToQtRaster( short parm ) const
+{
+ static const Qt::RasterOp opTab[] =
+ {
+ Qt::CopyROP,
+ Qt::ClearROP, Qt::NandROP, Qt::NotAndROP, Qt::NotCopyROP,
+ Qt::AndNotROP, Qt::NotROP, Qt::XorROP, Qt::NorROP,
+ Qt::AndROP, Qt::NotXorROP, Qt::NopROP, Qt::NotOrROP,
+ Qt::CopyROP, Qt::OrNotROP, Qt::OrROP, Qt::SetROP
+ };
+
+ if ( parm > 0 && parm <= 16 )
+ return opTab[ parm ];
+ else
+ return Qt::CopyROP;
+}
+
+//-----------------------------------------------------------------------------
+Qt::RasterOp QWinMetaFile::winToQtRaster( 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;
+ Qt::RasterOp qtRasterOp;
+ } opTab[] =
+ {
+ { 0x00CC0020, Qt::CopyROP },
+ { 0x00EE0086, Qt::OrROP },
+ { 0x008800C6, Qt::AndROP },
+ { 0x00660046, Qt::XorROP },
+ { 0x00440328, Qt::AndNotROP },
+ { 0x00330008, Qt::NotCopyROP },
+ { 0x001100A6, Qt::NandROP },
+ { 0x00C000CA, Qt::CopyROP },
+ { 0x00BB0226, Qt::NotOrROP },
+ { 0x00F00021, Qt::CopyROP },
+ { 0x00FB0A09, Qt::CopyROP },
+ { 0x005A0049, Qt::CopyROP },
+ { 0x00550009, Qt::NotROP },
+ { 0x00000042, Qt::ClearROP },
+ { 0x00FF0062, Qt::SetROP }
+ };
+
+ int i;
+ for ( i=0 ; i < 15 ; i++ )
+ if ( opTab[ i ].winRasterOp == parm )
+ break;
+
+ if ( i < 15 )
+ return opTab[ i ].qtRasterOp;
+ else
+ return Qt::CopyROP;
+}
+
+//-----------------------------------------------------------------------------
+bool QWinMetaFile::dibToBmp( QImage& bmp, const char* dib, long size )
+{
+ typedef struct _BMPFILEHEADER {
+ WORD bmType;
+ DWORD bmSize;
+ WORD bmReserved1;
+ WORD bmReserved2;
+ DWORD bmOffBits;
+ } BMPFILEHEADER;
+
+ int sizeBmp = size + 14;
+
+ QByteArray 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;
+ }
+}
+
diff --git a/lib/kwmf/qwmf.h b/lib/kwmf/qwmf.h
new file mode 100644
index 00000000..1787f4c8
--- /dev/null
+++ b/lib/kwmf/qwmf.h
@@ -0,0 +1,231 @@
+/* Windows Meta File Loader
+ *
+ * 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.
+ */
+#ifndef qwmf_h
+#define qwmf_h
+
+#include <qstring.h>
+#include <qpainter.h>
+#include <qwmatrix.h>
+#include <qpointarray.h>
+#include <qpen.h>
+#include <qcolor.h>
+#include <qimage.h>
+#include <qrect.h>
+
+class QBuffer;
+class QString;
+class WmfCmd;
+class WinObjHandle;
+class WinObjPenHandle;
+class WinObjBrushHandle;
+struct WmfPlaceableHeader;
+
+/**
+ * QWinMetaFile is a WMF viewer based on QT toolkit
+ * How to use QWinMetaFile :
+ * <pre>
+ *�#include "qwmf.h"
+ * QWinMetaFile wmf;
+ * QPicture pic; // or QImage pic;
+ * if ( wmf.load( filename )
+ *� �wmf.paint( &pic );
+ * </pre>
+ */
+
+
+class QWinMetaFile
+{
+public:
+ QWinMetaFile();
+ virtual ~QWinMetaFile();
+
+ /**
+ * Load WMF file.
+ * @return true on success.
+ */
+ virtual bool load( const QString &fileName );
+ virtual bool load( QBuffer &buffer );
+
+ /**
+ * Paint metafile to given paint-device using absolute or relative coordinate.
+ * - absolute coord. Reset the world transfomation Matrix
+ * - relative coord. Use the existing world transfomation Matrix
+ *
+ * @return true on success.
+ */
+ virtual bool paint( const QPaintDevice* target, bool absolute=false );
+
+ /**
+ * @return true if the metafile is placeable.
+ */
+ bool isPlaceable( void ) const { return mIsPlaceable; }
+
+ /**
+ * @return true if the metafile is enhanced.
+ */
+ bool isEnhanced( void ) const { return mIsEnhanced; }
+
+ /**
+ * @return bounding rectangle
+ */
+ QRect bbox( void ) const { return mBBox; }
+
+public: // should be protected but cannot
+ /* Metafile painter methods */
+
+ /** set window origin */
+ void setWindowOrg( long num, short* parms );
+ /** set window extents */
+ void setWindowExt( long num, short* parms );
+
+ /****************** Drawing *******************/
+ /** draw line to coord */
+ void lineTo( long num, short* parms );
+ /** move pen to coord */
+ void moveTo( long num, short* parms );
+ /** draw ellipse */
+ void ellipse( long num, short* parms );
+ /** draw polygon */
+ void polygon( long num, short* parms );
+ /** draw a list of polygons */
+ void polyPolygon( long num, short* parms );
+ /** draw series of lines */
+ void polyline( long num, short* parms );
+ /** draw a rectangle */
+ void rectangle( long num, short* parms );
+ /** draw round rectangle */
+ void roundRect( long num, short* parms );
+ /** draw arc */
+ void arc( long num, short* parms );
+ /** draw chord */
+ void chord( long num, short* parms );
+ /** draw pie */
+ void pie( long num, short* parms );
+ /** set polygon fill mode */
+ void setPolyFillMode( long num, short* parms );
+ /** set background pen color */
+ void setBkColor( long num, short* parms );
+ /** set background pen mode */
+ void setBkMode( long num, short* parms );
+ /** set a pixel */
+ void setPixel( long num, short* parms );
+ /** Set raster operation mode */
+ void setRop( long num, short* parms );
+ /** save device context */
+ void saveDC( long num, short* parms );
+ /** restore device context */
+ void restoreDC( long num, short* parms );
+ /** clipping region is the intersection of this region and the original region */
+ void intersectClipRect( long num, short* parms );
+ /** delete a clipping rectangle of the original region */
+ void excludeClipRect( long num, short* parms );
+
+ /****************** Text *******************/
+ /** set text color */
+ void setTextColor( long num, short* parms );
+ /** set text alignment */
+ void setTextAlign( long num, short* parms );
+ /** draw text */
+ void textOut( long num, short* parms );
+ void extTextOut( long num, short* parms );
+
+ /****************** Bitmap *******************/
+ /** copies a DIB into a dest location */
+ void dibBitBlt( long num, short* parms );
+ /** stretches a DIB into a dest location */
+ void dibStretchBlt( long num, short* parms );
+ void stretchDib( long num, short* parms );
+ /** create a pattern brush */
+ void dibCreatePatternBrush( long num, short* parms );
+
+ /****************** Object handle *******************/
+ /** Activate object handle */
+ void selectObject( long num, short* parms );
+ /** Free object handle */
+ void deleteObject( long num, short* parms );
+ /** create an empty object in the object list */
+ void createEmptyObject( long num, short* parms );
+ /** create a logical brush */
+ void createBrushIndirect( long num, short* parms );
+ /** create a logical pen */
+ void createPenIndirect( long num, short* parms );
+ /** create a logical font */
+ void createFontIndirect( long num, short* parms );
+
+ /****************** misc *******************/
+ /** nothing to do */
+ void noop( long , short* );
+ /** end of meta file */
+ void end( long /*num*/, short* /*parms*/ );
+ /** Resolution of the image in dots per inch */
+ int dpi( void ) const { return mDpi; }
+
+protected:
+ /** Calculate header checksum */
+ unsigned short calcCheckSum( WmfPlaceableHeader* );
+
+ /** Find function in metafunc table by metafile-function.
+ Returns index or -1 if not found. */
+ virtual int findFunc( unsigned short aFunc ) const;
+
+ /** Fills given parms into mPoints. */
+ QPointArray* pointArray( short num, short* parms );
+
+ /** Returns color given by the two parameters */
+ QColor color( short* parm );
+
+ /** Converts two parameters to long */
+ unsigned int toDWord( short* parm );
+
+ /** Convert (x1,y1) and (x2, y2) positions in angle and angleLength */
+ void xyToAngle( int xStart, int yStart, int xEnd, int yEnd, int& angle, int& aLength );
+
+ /** Handle win-object-handles */
+ void addHandle( WinObjHandle* );
+ void deleteHandle( int );
+
+ /** Convert windows rasterOp in QT rasterOp */
+ Qt::RasterOp winToQtRaster( short parm ) const;
+ Qt::RasterOp winToQtRaster( long parm ) const;
+
+ /** Converts DIB to BMP */
+ bool dibToBmp( QImage& bmp, const char* dib, long size);
+
+protected:
+ QPainter mPainter;
+ bool mIsPlaceable, mIsEnhanced, mValid;
+
+ // coordinate system
+ bool mAbsoluteCoord;
+ QWMatrix mInternalWorldMatrix; // memorisation of WMF matrix transformation
+ QRect mHeaderBoundingBox;
+ QRect mBBox;
+
+ // information shared between Metafile Functions
+ QColor mTextColor;
+ int mTextAlign, mRotation;
+ bool mWinding;
+
+ WmfCmd* mFirstCmd;
+ WinObjHandle** mObjHandleTab;
+ QPointArray mPoints;
+ int mDpi;
+};
+
+#endif /*qwmf_h*/
diff --git a/lib/kwmf/wmfstruct.h b/lib/kwmf/wmfstruct.h
new file mode 100644
index 00000000..ca4f1f7d
--- /dev/null
+++ b/lib/kwmf/wmfstruct.h
@@ -0,0 +1,107 @@
+/* WMF Metafile Structures
+ * Author: Stefan Taferner <[email protected]>
+ */
+#ifndef wmfstruct_h
+#define wmfstruct_h
+
+typedef short WORD;
+typedef int DWORD;
+typedef Q_INT32 LONG;
+typedef void* _HANDLE;
+
+typedef struct _RECT
+{
+ WORD left;
+ WORD top;
+ WORD right;
+ WORD bottom;
+} RECT;
+
+typedef struct _RECTL
+{
+ LONG left;
+ LONG top;
+ LONG right;
+ LONG bottom;
+} RECTL;
+
+typedef struct _SIZE
+{
+ WORD width;
+ WORD height;
+} SIZE;
+
+typedef struct _SIZEL
+{
+ LONG width;
+ LONG height;
+} SIZEL;
+
+
+struct WmfEnhMetaHeader
+{
+ DWORD iType; // Record type EMR_HEADER
+ DWORD nSize; // Record size in bytes. This may be greater
+ // than the sizeof( ENHMETAHEADER ).
+ RECTL rclBounds; // Inclusive-inclusive bounds in device units
+ RECTL rclFrame; // Inclusive-inclusive Picture Frame of metafile
+ // in .01 mm units
+ DWORD dSignature; // Signature. Must be ENHMETA_SIGNATURE.
+ DWORD nVersion; // Version number
+ DWORD nBytes; // Size of the metafile in bytes
+ DWORD nRecords; // Number of records in the metafile
+ WORD nHandles; // Number of handles in the handle table
+ // Handle index zero is reserved.
+ WORD sReserved; // Reserved. Must be zero.
+ DWORD nDescription; // Number of chars in the unicode description string
+ // This is 0 if there is no description string
+ DWORD offDescription; // Offset to the metafile description record.
+ // This is 0 if there is no description string
+ DWORD nPalEntries; // Number of entries in the metafile palette.
+ SIZEL szlDevice; // Size of the reference device in pels
+ SIZEL szlMillimeters; // Size of the reference device in millimeters
+};
+#define ENHMETA_SIGNATURE 0x464D4520
+
+
+struct WmfMetaHeader
+{
+ WORD mtType;
+ WORD mtHeaderSize;
+ WORD mtVersion;
+ DWORD mtSize;
+ WORD mtNoObjects;
+ DWORD mtMaxRecord;
+ WORD mtNoParameters;
+};
+
+
+struct WmfPlaceableHeader
+{
+ DWORD key;
+ WORD hmf;
+ RECT bbox;
+ WORD inch;
+ DWORD reserved;
+ WORD checksum;
+};
+#define APMHEADER_KEY 0x9AC6CDD7
+
+
+struct WmfMetaRecord
+{
+ DWORD rdSize; // Record size ( in words ) of the function
+ WORD rdFunction; // Record function number
+ WORD rdParm[ 1 ]; // WORD array of parameters
+};
+
+
+struct WmfEnhMetaRecord
+{
+ DWORD iType; // Record type EMR_xxx
+ DWORD nSize; // Record size in bytes
+ DWORD dParm[ 1 ]; // DWORD array of parameters
+};
+
+
+#endif /*wmfstruct_h*/