r13903 by fschmid - Forked libwpg-0.1.3, this allows us to adjust the library for our special needs. First Improvements are: - Bitmaps are now imported with their native resolution. - Fill and stroke attributes are interpreted correctly now. - No more need to link to libwpg and libwpd

scribus-commit scribus-commit at lists.scribus.net
Wed Aug 26 05:53:56 CEST 2009


Revision: 13903
Author: fschmid
Date: 2009-08-23T17:46:57.797676Z
Commit message: Forked libwpg-0.1.3, this allows us to adjust the library for our special needs. 
First Improvements are:
- Bitmaps are now imported with their native resolution.
- Fill and stroke attributes are interpreted correctly now.
- No more need to link to libwpg and libwpd

Changeset: 
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/libwpg_utils.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/libwpd_types.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGRect.cpp
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGHeader.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGOLEStream.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGPath.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGStreamImplementation.cpp
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGGradient.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/libwpg.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGString.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGBitmap.cpp
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPG1Parser.cpp
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGColor.cpp
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPG2Parser.cpp
M  /trunk/Scribus/scribus/plugins/wpgimplugin/CMakeLists.txt
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGPen.cpp
M  /trunk/Scribus/scribus/plugins/wpgimplugin/importwpg.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGBinaryData.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGBrush.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGHeader.cpp
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGXParser.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGOLEStream.cpp
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGPath.cpp
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGInternalStream.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGGradient.cpp
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGPoint.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGraphics.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGPaintInterface.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGRect.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGString.cpp
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGStreamImplementation.h
M  /trunk/Scribus/scribus/plugins/wpgimplugin/importwpg.cpp
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGBinaryData.cpp
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPXStream.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGBitmap.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPG1Parser.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPG2Parser.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGBrush.cpp
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGColor.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGXParser.cpp
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGPen.h
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGInternalStream.cpp
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGPoint.cpp
A  /trunk/Scribus/scribus/plugins/wpgimplugin/wpg/WPGraphics.cpp

Diffs:
Index: scribus/plugins/wpgimplugin/importwpg.cpp
===================================================================
--- scribus/plugins/wpgimplugin/importwpg.cpp	(revision 13902)
+++ scribus/plugins/wpgimplugin/importwpg.cpp	(revision 13903)
@@ -50,7 +50,7 @@
 #include "util_icon.h"
 #include "util_math.h"
 #include <stdio.h>
-#include <libwpg/WPGStreamImplementation.h>
+#include "wpg/WPGStreamImplementation.h"
 
 extern SCRIBUS_API ScribusQApp * ScQApp;
 
@@ -72,6 +72,8 @@
 	fillrule = false;
 	gradientAngle = 0.0;
 	isGradient = false;
+	fillSet = false;
+	strokeSet = false;
 	currentGradient = VGradient(VGradient::linear);
 	currentGradient.clearStops();
 	currentGradient.setRepeatMethod( VGradient::none );
@@ -153,6 +155,7 @@
 				dashArray.append(pen.dashArray.at(i)*LineW);
 			}
 		}
+		strokeSet = true;
 	}
 }
 
@@ -236,6 +239,7 @@
 				currentGradient.addStop( ScColorEngine::getRGBColor(gradC, m_Doc), fabs(brush.gradient.stopOffset(c)), 0.5, 1.0, currStopColor, 100 );
 			}
 		}
+		fillSet = true;
 	}
 }
 
@@ -323,6 +327,16 @@
 	if (Coords.size() > 0)
 	{
 		int z;
+		if (fillSet)
+		{
+			if (!path.filled)
+				CurrColorFill = CommonStrings::None;
+		}
+		if (strokeSet)
+		{
+			if (!path.framed)
+				CurrColorStroke = CommonStrings::None;
+		}
 		if(path.closed)
 		{
 			Coords.svgClosePath();
@@ -369,6 +383,8 @@
 	ite->updateClip();
 	Elements.append(ite);
 	isGradient = false;
+	fillSet = false;
+	strokeSet = false;
 	CurrColorFill = "Black";
 	CurrFillShade = 100.0;
 	CurrColorStroke = "Black";
@@ -382,7 +398,7 @@
 	gradientAngle = 0.0;
 }
 
-void ScrPainter::drawBitmap(const libwpg::WPGBitmap& bitmap)
+void ScrPainter::drawBitmap(const libwpg::WPGBitmap& bitmap, double hres, double vres)
 {
 	QImage image = QImage(bitmap.width(), bitmap.height(), QImage::Format_RGB32);
 	for(int x = 0; x < bitmap.width(); x++)
@@ -393,15 +409,15 @@
 			image.setPixel(x, y, qRgb(color.red, color.green, color.blue));
 		}
 	}
-	int z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, bitmap.rect.x1+baseX, bitmap.rect.y1+baseY, bitmap.width(), bitmap.height(), 1, m_Doc->toolSettings.dBrushPict, CommonStrings::None, true);
+	int z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, bitmap.rect.x1+baseX, bitmap.rect.y1+baseY, bitmap.width() / hres * 72.0, bitmap.height() / vres * 72.0, 1, m_Doc->toolSettings.dBrushPict, CommonStrings::None, true);
 	PageItem *ite = m_Doc->Items->at(z);
 	ite->tempImageFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_svg_XXXXXX.png");
 	ite->tempImageFile->open();
 	QString fileName = getLongPathName(ite->tempImageFile->fileName());
 	ite->tempImageFile->close();
 	ite->isInlineImage = true;
-	image.setDotsPerMeterX(2834);
-	image.setDotsPerMeterY(2834);
+	image.setDotsPerMeterX ((int) (hres / 0.0254));
+	image.setDotsPerMeterY ((int) (vres / 0.0254));
 	image.save(fileName, "PNG");
 	m_Doc->LoadPict(fileName, z);
 	finishItem(ite);
Index: scribus/plugins/wpgimplugin/CMakeLists.txt
===================================================================
--- scribus/plugins/wpgimplugin/CMakeLists.txt	(revision 13902)
+++ scribus/plugins/wpgimplugin/CMakeLists.txt	(revision 13903)
@@ -1,42 +1,42 @@
-
-INCLUDE(FindPkgConfig)
-pkg_check_modules(LIBWPG libwpg-0.1)
-pkg_check_modules(LIBWPG_STREAM libwpg-stream-0.1)
-pkg_check_modules(LIBWPD libwpd-0.8)
-pkg_check_modules(LIBWPD_STREAM libwpd-stream-0.8)
-
-IF(LIBWPG_FOUND AND LIBWPD_FOUND AND LIBWPD_STREAM_FOUND AND LIBWPG_STREAM_FOUND)
-  INCLUDE_DIRECTORIES(
+INCLUDE_DIRECTORIES(
     ${CMAKE_SOURCE_DIR}
     ${CMAKE_SOURCE_DIR}/scribus
-    ${LIBWPG_INCLUDE_DIRS}
-    ${LIBWPD_INCLUDE_DIRS}
-    ${LIBWPD_STREAM_INCLUDE_DIRS}
-  )
+)
+LINK_DIRECTORIES(${PLUGIN_LIBRARIES})
 
-  SET(IMPORTWPG_PLUGIN_MOC_CLASSES
+SET(IMPORTWPG_PLUGIN_MOC_CLASSES
     importwpg.h
     importwpgplugin.h
   )
-
-  SET(IMPORTWPG_PLUGIN_SOURCES
+SET(IMPORTWPG_PLUGIN_SOURCES
     importwpg.cpp
     importwpgplugin.cpp
+    wpg/WPG1Parser.cpp
+    wpg/WPG2Parser.cpp
+    wpg/WPGBinaryData.cpp
+    wpg/WPGBitmap.cpp
+    wpg/WPGBrush.cpp
+    wpg/WPGColor.cpp
+    wpg/WPGGradient.cpp
+    wpg/WPGHeader.cpp
+    wpg/WPGInternalStream.cpp
+    wpg/WPGOLEStream.cpp
+    wpg/WPGPath.cpp
+    wpg/WPGPen.cpp
+    wpg/WPGPoint.cpp
+    wpg/WPGraphics.cpp
+    wpg/WPGRect.cpp
+    wpg/WPGStreamImplementation.cpp
+    wpg/WPGString.cpp
+    wpg/WPGXParser.cpp
   )
-
-  SET(SCRIBUS_IMPORTWPG_PLUGIN "importwpg")
-
-  QT4_WRAP_CPP(IMPORTWPG_PLUGIN_MOC_SOURCES ${IMPORTWPG_PLUGIN_MOC_CLASSES})
-
-  ADD_LIBRARY(${SCRIBUS_IMPORTWPG_PLUGIN} MODULE ${IMPORTWPG_PLUGIN_SOURCES} ${IMPORTWPG_PLUGIN_MOC_SOURCES})
-
-  TARGET_LINK_LIBRARIES(${SCRIBUS_IMPORTWPG_PLUGIN} ${PLUGIN_LIBRARIES} ${LIBWPG_LDFLAGS} ${LIBWPG_STREAM_LDFLAGS} ${LIBWPD_LDFLAGS} ${LIBWPD_STREAM_LDFLAGS})
-
-  INSTALL(TARGETS ${SCRIBUS_IMPORTWPG_PLUGIN}
+SET(SCRIBUS_IMPORTWPG_PLUGIN "importwpg")
+QT4_WRAP_CPP(IMPORTWPG_PLUGIN_MOC_SOURCES ${IMPORTWPG_PLUGIN_MOC_CLASSES})
+ADD_LIBRARY(${SCRIBUS_IMPORTWPG_PLUGIN} MODULE ${IMPORTWPG_PLUGIN_SOURCES} ${IMPORTWPG_PLUGIN_MOC_SOURCES})
+TARGET_LINK_LIBRARIES(${SCRIBUS_IMPORTWPG_PLUGIN} ${PLUGIN_LIBRARIES})
+INSTALL(TARGETS ${SCRIBUS_IMPORTWPG_PLUGIN}
     LIBRARY
     DESTINATION ${PLUGINDIR}
     PERMISSIONS ${PLUGIN_PERMISSIONS}
-  )
-
-  ADD_DEPENDENCIES(${SCRIBUS_IMPORTWPG_PLUGIN} ${EXE_NAME})
-ENDIF(LIBWPG_FOUND AND LIBWPD_FOUND AND LIBWPD_STREAM_FOUND AND LIBWPG_STREAM_FOUND)
+)
+ADD_DEPENDENCIES(${SCRIBUS_IMPORTWPG_PLUGIN} ${EXE_NAME})
Index: scribus/plugins/wpgimplugin/wpg/WPGBitmap.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGBitmap.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGBitmap.h	(revision 13903)
@@ -0,0 +1,78 @@
+/* libwpg
+ * Copyright (C) 2007 Ariya Hidayat (ariya at kde.org)
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ *
+ * 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; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __WPGBITMAP_H__
+#define __WPGBITMAP_H__
+
+#include "WPGRect.h"
+#include "WPGColor.h"
+#include "WPGString.h"
+
+namespace libwpg
+{
+
+class WPGBitmap
+{
+public:
+	WPGRect rect;
+
+	WPGBitmap(int width, int height);
+	
+	WPGBitmap(int width, int height, bool verticalFlip, bool horizontalFlip);
+
+	WPGBitmap(const WPGBitmap&);
+
+	WPGBitmap& operator=(const WPGBitmap&);
+
+	void copyFrom(const WPGBitmap&);
+
+	~WPGBitmap();
+
+	// return width in pixel
+	int width() const;
+
+	// return height in pixel
+	int height() const;
+
+	WPGColor pixel(int x, int y) const;
+
+	void setPixel(int x, int y, const WPGColor& color);
+	
+	void generateBase64DIB(WPGString& bmp) const;
+
+	static void base64Encode(WPGString& base64, const char *data, const int len);
+
+private:
+	class Private;
+	Private* const d;
+	static void writeU16(char *buffer, unsigned &position, const int value);
+	static void writeU32(char *buffer, unsigned &position, const int value);
+	static void writeU8(char *buffer, unsigned &position, const int value);
+};
+
+} // namespace libwpg
+
+#endif // __WPGBITMAP_H__
Index: scribus/plugins/wpgimplugin/wpg/WPXStream.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPXStream.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPXStream.h	(revision 13903)
@@ -0,0 +1,91 @@
+/* libwpd
+ * Copyright (C) 2004-2005 William Lachance (wrlach at gmail.com)
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ *
+ * For further information visit http://libwpd.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef WPXSTREAM_H
+#define WPXSTREAM_H
+#include <stdio.h>
+#include "libwpd_types.h"
+
+enum WPX_SEEK_TYPE
+{
+	WPX_SEEK_CUR,
+	WPX_SEEK_SET
+};
+
+class WPXInputStream
+{
+public:
+	WPXInputStream(bool supportsOLE) :
+		m_supportsOLE(supportsOLE) {}
+	virtual ~WPXInputStream() {}
+
+	/**
+	Analyses the content of the input stream to see whether it is an OLE2 storage.
+	\return A boolean value that should be true if the input stream is an OLE2 storage
+	and false if it is not the case
+	*/
+	virtual bool isOLEStream() = 0;
+	/**
+	Extracts a \c PerfectOffice_MAIN stream from an OLE2 storage.
+	\return Should be a pointer to WPXInputStream constructed from the \c PerfectOffice_MAIN stream if it exists.
+	\return Should be 0, if the \c PerfectOffice_MAIN stream does not exist inside the OLE2 storage
+	or if the input stream is not an OLE2 storage.
+	*/
+	virtual WPXInputStream * getDocumentOLEStream() = 0;
+
+	/**
+	Tries to read a given number of bytes starting from the current position inside the input stream.
+	\param numBytes Number of bytes desired to be read.
+	\param numBytesRead Number of bytes that were possible to be read.
+	\return Should be a pointer to an array of numBytesRead bytes (uint8_t[numBytesRead]).
+	\return Optionally it could be 0 if the desired number of bytes could not be read.
+	*/
+	const virtual uint8_t *read(size_t numBytes, size_t &numBytesRead) = 0;
+	/**
+	Moves to the next location inside the input stream.
+	\param offset The offset of the location inside the input stream to move to.
+	It is relative either to the current position or to the beginning of the input stream
+	depending on the value of the \c seekType parameter.
+	\param seekType Determines whether the \c offset is relative to the
+	beginning of the input stream (\c WPX_SEEK_SET) or to the current position (\c WPX_SEEK_CUR).
+	\return An integer value that should be 0 (zero) if the seek was successful and any other value
+	if it failed (i.e. the requested \c offset is beyond the end of the input stream or before its beginning).
+	*/
+	virtual int seek(long offset, WPX_SEEK_TYPE seekType) = 0;
+	/**
+	Returns the actual position inside the input stream.
+	\return A long integer value that should correspond to the position of the next location to be read in the input stream.
+	*/
+	virtual long tell() = 0;
+	/**
+	Determines whether the current position is at the end of the stream.
+	\return A boolean value that should be true if the next location to be read in the input stream
+	is beyond its end. In all other cases, it should be false.
+	*/
+	virtual bool atEOS() = 0;
+
+private:
+	bool m_supportsOLE;
+};
+#endif
Index: scribus/plugins/wpgimplugin/wpg/WPG1Parser.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPG1Parser.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPG1Parser.h	(revision 13903)
@@ -0,0 +1,79 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ * Copyright (C) 2005 Fridrich Strba (fridrich.strba at bluewin.ch)
+ * Copyright (C) 2004 Marc Oude Kotte (marc at solcon.nl)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __WPG1PARSER_H__
+#define __WPG1PARSER_H__
+
+#include "WPGXParser.h"
+#include "WPGBrush.h"
+#include "WPGPen.h"
+#include <vector>
+
+class WPG1Parser : public WPGXParser
+{
+public:
+	WPG1Parser(WPXInputStream *input, libwpg::WPGPaintInterface* painter);
+	bool parse();
+
+private:
+	void handleStartWPG();
+	void handleEndWPG();
+
+	void handleFillAttributes();
+	void handleLineAttributes();
+	void handleColormap();
+
+	void handleLine();
+	void handlePolyline();
+	void handleRectangle();
+	void handlePolygon();
+	void handleEllipse();
+	
+	void handleCurvedPolyline();
+
+	void decodeRLE(std::vector<unsigned char>& buffer, unsigned width, unsigned height, unsigned depth);
+	void fillPixels(libwpg::WPGBitmap& bitmap, const unsigned char* buffer, unsigned width, unsigned height, unsigned depth);
+	void handleBitmapTypeOne();
+	void handleBitmapTypeTwo();
+	void handlePostscriptTypeOne();
+	void handlePostscriptTypeTwo();
+	
+	void resetPalette();
+
+	// parsing context
+	int m_recordLength;
+	long m_recordEnd;
+	bool m_success;
+	bool m_exit;
+	bool m_graphicsStarted;
+	int m_width;
+	int m_height;
+	libwpg::WPGPen m_pen;
+	libwpg::WPGBrush m_brush;
+};
+
+#endif // __WPG1PARSER_H__
Index: scribus/plugins/wpgimplugin/wpg/WPG2Parser.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPG2Parser.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPG2Parser.h	(revision 13903)
@@ -0,0 +1,228 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ * Copyright (C) 2005 Fridrich Strba (fridrich.strba at bluewin.ch)
+ * Copyright (C) 2004 Marc Oude Kotte (marc at solcon.nl)
+ *
+ * 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; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __WPG2PARSER_H__
+#define __WPG2PARSER_H__
+
+#include "WPGXParser.h"
+#include "WPGBrush.h"
+#include "WPGPen.h"
+
+#include <map>
+#include <stack>
+#include <vector>
+
+class WPG2TransformMatrix
+{
+public:
+	double element[3][3];
+
+	WPG2TransformMatrix()
+	{
+		// identity transformation
+		element[0][0] = element[1][1] = 1; element[2][2] = 1;
+		element[0][1] = element[0][2] = 0;
+		element[1][0] = element[1][2] = 0;
+		element[2][0] = element[2][1] = 0;
+	}
+
+	void transform(long& x, long& y) const
+	{
+		long rx = (long)(element[0][0]*x + element[1][0]*y + element[2][0]);
+		long ry = (long)(element[0][1]*x + element[1][1]*y + element[2][1]);
+		x = rx;
+		y = ry;
+	}
+
+	libwpg::WPGPoint transform(const libwpg::WPGPoint& p) const
+	{
+		libwpg::WPGPoint point;
+		point.x = element[0][0]*p.x + element[1][0]*p.y + element[2][0];
+		point.y = element[0][1]*p.x + element[1][1]*p.y + element[2][1];
+		return point;
+	}
+
+	libwpg::WPGRect transform(const libwpg::WPGRect& r) const
+	{
+		libwpg::WPGRect rect;
+		rect.x1 = element[0][0]*r.x1 + element[1][0]*r.y1 + element[2][0];
+		rect.y1 = element[0][1]*r.x1 + element[1][1]*r.y1 + element[2][1];
+		rect.x2 = element[0][0]*r.x2 + element[1][0]*r.y2 + element[2][0];
+		rect.y2 = element[0][1]*r.x2 + element[1][1]*r.y2 + element[2][1];
+		return rect;
+	}
+
+	WPG2TransformMatrix& transformBy(const WPG2TransformMatrix& m)
+	{
+		double result[3][3];
+
+		for(int i = 0; i < 3; i++)
+			for(int j = 0; j < 3; j++)
+			{
+				result[i][j] = 0;
+				for(int k = 0; k < 3; k++)
+					result[i][j] += m.element[i][k]*element[k][j];
+			}
+
+		for(int x = 0; x < 3; x++)
+			for(int y = 0; y < 3; y++)
+				element[x][y] = result[x][y];
+
+		return *this;
+	}
+};
+
+class WPGCompoundPolygon
+{
+public:
+	WPG2TransformMatrix matrix;
+	bool isFilled;
+	bool isFramed;
+	bool isClosed;
+
+	WPGCompoundPolygon(): matrix(), isFilled(true), isFramed(true), isClosed(true) {}
+};
+
+class WPGGroupContext
+{
+public:
+	unsigned subIndex;
+	int parentType;
+	libwpg::WPGPath compoundPath;
+	WPG2TransformMatrix compoundMatrix;
+	bool compoundWindingRule;
+	bool compoundFilled;
+	bool compoundFramed;
+	bool compoundClosed;
+
+	WPGGroupContext(): subIndex(0), parentType(0),
+	compoundPath(), compoundMatrix(), compoundWindingRule(false),
+	compoundFilled(false), compoundFramed(true), compoundClosed(false)	{}
+
+	bool isCompoundPolygon() const { return parentType == 0x1a; }
+};
+
+class WPGBitmapContext
+{
+public:
+	double x1, y1, x2, y2;
+	long hres, vres;
+	WPGBitmapContext(): x1(0), y1(0), x2(0), y2(0), hres(100), vres(100) {}
+};
+
+class WPGBinaryDataContext
+{
+public:
+	double x1, y1, x2, y2;
+	int numObjects, objectIndex;
+	std::vector<libwpg::WPGString> mimeTypes;
+	WPGBinaryDataContext(): x1(0), y1(0), x2(0), y2(0), numObjects(0), objectIndex(0), mimeTypes() {}
+};
+
+class WPG2Parser : public WPGXParser
+{
+public:
+	WPG2Parser(WPXInputStream *input, libwpg::WPGPaintInterface* painter);
+	bool parse();
+
+private:
+	void handleStartWPG();
+	void handleEndWPG();
+	void handleLayer();
+	void handleCompoundPolygon();
+
+	void handlePenStyleDefinition();
+	void handlePatternDefinition();
+	void handleColorPalette();
+	void handleDPColorPalette();
+	void handlePenForeColor();
+	void handleDPPenForeColor();
+	void handlePenBackColor();
+	void handleDPPenBackColor();
+	void handlePenStyle();
+	void handlePenSize();
+	void handleDPPenSize();
+	void handleBrushGradient();
+	void handleDPBrushGradient();
+	void handleBrushForeColor();
+	void handleDPBrushForeColor();
+	void handleBrushBackColor();
+	void handleDPBrushBackColor();
+	void handleBrushPattern();
+
+	void handlePolyline();
+	void handlePolyspline();
+	void handlePolycurve();
+	void handleRectangle();
+	void handleArc();
+
+	void handleBitmap();
+	void handleBitmapData();
+	
+	void handleObjectCapsule();
+	void handleObjectImage();
+
+	void resetPalette();
+	void flushCompoundPolygon();
+
+	// parsing context
+	int m_recordLength;
+	long m_recordEnd;
+	bool m_success;
+	bool m_exit;
+	bool m_graphicsStarted;
+	unsigned int m_xres;
+	unsigned int m_yres;
+	long m_xofs;
+	long m_yofs;
+	long m_width;
+	long m_height;
+	bool m_doublePrecision;
+	libwpg::WPGPen m_pen;
+	libwpg::WPGBrush m_brush;
+	std::map<unsigned int,libwpg::WPGDashArray> m_penStyles;
+	bool m_layerOpened;
+	unsigned int m_layerId;
+	WPG2TransformMatrix m_matrix;
+	double m_gradientAngle;
+	libwpg::WPGPoint m_gradientRef;
+	std::stack<WPGGroupContext> m_groupStack;
+	WPG2TransformMatrix m_compoundMatrix;
+	bool m_compoundWindingRule;
+	bool m_compoundFilled;
+	bool m_compoundFramed;
+	bool m_compoundClosed;
+	WPGBitmapContext m_bitmap;
+	WPGBinaryDataContext m_binaryData;
+	bool m_hFlipped, m_vFlipped;
+
+	class ObjectCharacterization;
+	void parseCharacterization(ObjectCharacterization*);
+	unsigned m_binaryId;
+};
+
+#endif // __WPG2PARSER_H__
Index: scribus/plugins/wpgimplugin/wpg/WPGBrush.cpp
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGBrush.cpp	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGBrush.cpp	(revision 13903)
@@ -0,0 +1,63 @@
+/* libwpg
+ * Copyright (C) 2006 Fridrich Strba (fridrich.strba at bluewin.ch)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "WPGBrush.h"
+
+libwpg::WPGBrush::WPGBrush(): 
+	style(Solid), 
+	foreColor(0,0,0), 
+	backColor(0xFF,0xFF,0xFF),
+	gradient() 
+{}
+
+libwpg::WPGBrush::WPGBrush(const WPGColor& fore): 
+	style(Solid), 
+	foreColor(fore),  
+	backColor(0xFF,0xFF,0xFF),
+	gradient() 
+{}
+
+libwpg::WPGBrush::WPGBrush(const WPGColor& fore, const WPGColor& back): 
+	style(Solid), 
+	foreColor(fore),  
+	backColor(back),
+	gradient()
+{}
+
+libwpg::WPGBrush::WPGBrush(const WPGBrush& brush):
+	style(brush.style),
+	foreColor(brush.foreColor),
+	backColor(brush.backColor),
+	gradient(brush.gradient)
+{}
+
+libwpg::WPGBrush& libwpg::WPGBrush::operator=(const libwpg::WPGBrush& brush)
+{
+	style = brush.style;
+	foreColor = brush.foreColor; 
+	backColor = brush.backColor; 
+	gradient = brush.gradient;
+	return *this; 
+}
Index: scribus/plugins/wpgimplugin/wpg/WPGColor.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGColor.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGColor.h	(revision 13903)
@@ -0,0 +1,50 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __WPGCOLOR_H__
+#define __WPGCOLOR_H__
+
+namespace libwpg
+{
+
+class WPGColor
+{
+public:
+	int red, green, blue, alpha;
+	
+	WPGColor();
+	
+	WPGColor(int r, int g, int b);
+	
+	WPGColor(int r, int g, int b, int a);
+
+	WPGColor(const WPGColor& color);
+	
+	WPGColor& operator=(const WPGColor& color);
+};
+
+} // namespace libwpg
+
+#endif // __WPGCOLOR_H__
Index: scribus/plugins/wpgimplugin/wpg/WPGXParser.cpp
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGXParser.cpp	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGXParser.cpp	(revision 13903)
@@ -0,0 +1,113 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ * Copyright (C) 2004 Marc Oude Kotte (marc at solcon.nl)
+ * Copyright (C) 2005 Fridrich Strba (fridrich.strba at bluewin.ch)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+ 
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "WPGXParser.h"
+
+WPGXParser::WPGXParser(WPXInputStream *input, libwpg::WPGPaintInterface* painter):
+  m_input(input), m_painter(painter), m_colorPalette(std::map<int,libwpg::WPGColor>())
+{
+}
+
+WPGXParser::WPGXParser(const WPGXParser& parser):
+  m_input(parser.m_input), m_painter(parser.m_painter),
+  m_colorPalette(parser.m_colorPalette)
+{
+}
+
+unsigned char WPGXParser::readU8()
+{
+	if (!m_input || m_input->atEOS())
+		return (unsigned char)0;
+	size_t numBytesRead;
+	unsigned char const * p = m_input->read(sizeof(unsigned char), numBytesRead);
+	
+	if (p && numBytesRead == 1)
+		return *(unsigned char const *)(p);
+	return (unsigned char)0;
+}
+
+unsigned short WPGXParser::readU16()
+{
+	unsigned short p0 = (unsigned short)readU8();
+	unsigned short p1 = (unsigned short)readU8();
+	return (unsigned short)(p0|(p1<<8));
+}
+
+unsigned int WPGXParser::readU32()
+{
+	unsigned int p0 = (unsigned int)readU8();
+	unsigned int p1 = (unsigned int)readU8();
+	unsigned int p2 = (unsigned int)readU8();
+	unsigned int p3 = (unsigned int)readU8();
+	return (unsigned long)(p0|(p1<<8)|(p2<<16)|(p3<<24));
+}
+
+signed char WPGXParser::readS8()
+{
+	return (signed char)readU8();
+}
+
+short WPGXParser::readS16()
+{
+	return (short)readU16();
+}
+
+int WPGXParser::readS32()
+{
+	return (int)readU32();
+}
+
+unsigned int WPGXParser::readVariableLengthInteger()
+{
+	// read a byte
+	unsigned char value8 = readU8();
+	// if it's in the range 0-0xFE, then we have a 8-bit value
+	if (value8<=0xFE) {
+		return (unsigned int)value8;
+	} else {
+		// now read a 16 bit value
+		unsigned short value16 = readU16();
+		// if the MSB is 1, we have a 32 bit value
+		if (value16>>15) {
+			// read the next 16 bit value (LSB part, in value16 resides the MSB part)
+			unsigned long lvalue16 = readU16();
+			unsigned long value32 = value16 & 0x7fff;  // mask out the MSB
+			return (value32<<16)+lvalue16;
+		} else {
+			// we have a 16 bit value, return it
+			return (unsigned int)value16;
+		}
+	}
+}
+
+WPGXParser& WPGXParser::operator=(const WPGXParser& parser)
+{
+    m_input = parser.m_input;
+    m_painter = parser.m_painter;
+    m_colorPalette = parser.m_colorPalette;
+    return *this;
+}
Index: scribus/plugins/wpgimplugin/wpg/WPGPen.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGPen.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGPen.h	(revision 13903)
@@ -0,0 +1,74 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __WPGPEN_H__
+#define __WPGPEN_H__
+
+#include "WPGColor.h"
+
+namespace libwpg
+{
+
+class WPGDashArrayPrivate;
+
+class WPGDashArray
+{
+public:
+	WPGDashArray();
+	~WPGDashArray();
+	WPGDashArray(const WPGDashArray&);
+	WPGDashArray& operator=(const WPGDashArray&);
+	unsigned count() const;
+	double at(unsigned i) const;
+	void add(double p);
+
+private:
+	WPGDashArrayPrivate *d;
+};
+
+class WPGPen
+{
+public:
+	WPGColor foreColor;
+	WPGColor backColor;
+	double width;
+	double height;
+	bool solid;
+	WPGDashArray dashArray;
+
+	WPGPen(); 
+	WPGPen(const WPGColor& fore);
+	WPGPen(const WPGColor& fore, const WPGColor& back);
+	WPGPen(const WPGPen& pen);
+
+	WPGPen& operator=(const WPGPen& pen);
+	
+	static WPGPen NoPen;
+};
+
+} // namespace libwpg
+
+
+#endif // __WPGPEN_H__
Index: scribus/plugins/wpgimplugin/wpg/WPGInternalStream.cpp
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGInternalStream.cpp	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGInternalStream.cpp	(revision 13903)
@@ -0,0 +1,106 @@
+/* libwpg
+ * Copyright (C) 2004-2005 William Lachance (wrlach at gmail.com)
+ * Copyright (C) 2006 Fridrich Strba (fridrich.strba at bluewin.ch)
+ *  
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by 
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "WPGInternalStream.h"
+
+WPGInternalInputStream::WPGInternalInputStream(const unsigned char *data, const size_t size) :
+	WPXInputStream(false),
+	m_offset(0),
+	m_size(size),
+	m_data(data),
+	m_tmpBuf(0)
+{
+}
+
+WPGInternalInputStream::~WPGInternalInputStream()
+{
+	if (m_tmpBuf)
+		delete [] m_tmpBuf;
+}
+
+const uint8_t * WPGInternalInputStream::read(size_t numBytes, size_t &numBytesRead)
+{
+	numBytesRead = 0;
+	if (0 == numBytes)
+		return 0;
+
+	if (m_tmpBuf)
+		delete [] m_tmpBuf;
+	m_tmpBuf = 0;
+	int numBytesToRead;
+
+	if ((m_offset+numBytes) < m_size)
+		numBytesToRead = numBytes;
+	else
+		numBytesToRead = m_size - m_offset;
+	
+	numBytesRead = numBytesToRead; // about as paranoid as we can be..
+
+	if (numBytesToRead == 0)
+		return 0;
+
+	m_tmpBuf = new uint8_t[numBytesToRead];
+	for (size_t i=0; (long)i<(long)numBytesToRead; i++)
+	{
+		m_tmpBuf[i] = m_data[m_offset];
+		m_offset++;
+	}
+
+	return m_tmpBuf;
+}
+
+int WPGInternalInputStream::seek(long offset, WPX_SEEK_TYPE seekType)
+{
+	if (seekType == WPX_SEEK_CUR)
+		m_offset += offset;
+	else if (seekType == WPX_SEEK_SET)
+		m_offset = offset;
+
+	if (m_offset < 0)
+	{
+		m_offset = 0;
+		return 1;
+	}
+	if ((long)m_offset > (long)m_size)
+	{
+		m_offset = m_size;
+		return 1;
+	}
+
+	return 0;
+}
+
+long WPGInternalInputStream::tell()
+{
+	return m_offset;
+}
+
+bool WPGInternalInputStream::atEOS()
+{
+	if ((long)m_offset == (long)m_size) 
+		return true; 
+
+	return false;
+}
Index: scribus/plugins/wpgimplugin/wpg/WPGPoint.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGPoint.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGPoint.h	(revision 13903)
@@ -0,0 +1,70 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __WPGPOINT_H__
+#define __WPGPOINT_H__
+
+#include "WPGColor.h"
+
+namespace libwpg
+{
+
+class WPGPoint
+{
+public:
+	double x;
+	double y;
+
+	WPGPoint();
+
+	WPGPoint(double xx, double yy);
+
+	WPGPoint(const WPGPoint& point);
+
+	WPGPoint& operator=(const WPGPoint& point);
+};
+
+class WPGPointArrayPrivate;
+
+class WPGPointArray
+{
+public:
+	WPGPointArray();
+	~WPGPointArray();
+	WPGPointArray(const WPGPointArray&);
+	WPGPointArray& operator=(const WPGPointArray&);
+	unsigned count() const;
+	WPGPoint& at(unsigned i);
+	const WPGPoint& at(unsigned i) const;
+	const WPGPoint& operator[](unsigned i) const;
+	void add(const WPGPoint& p);
+	
+private:
+	WPGPointArrayPrivate *d;
+};
+
+} // namespace libwpg
+
+#endif // __WPGPOINT_H__
Index: scribus/plugins/wpgimplugin/wpg/WPGraphics.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGraphics.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGraphics.h	(revision 13903)
@@ -0,0 +1,51 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __WPGRAPHICS_H__
+#define __WPGRAPHICS_H__
+
+#include "WPGString.h"
+#include <stdio.h>
+
+class WPXInputStream;
+
+namespace libwpg
+{
+class WPGPaintInterface;
+
+class WPGraphics
+{
+public:
+	
+	static bool isSupported(WPXInputStream* input);
+	
+	static bool parse(WPXInputStream* input, WPGPaintInterface* painter);
+	static bool parse(const unsigned char* data, const size_t size, WPGPaintInterface* painter);
+
+};
+
+} // namespace libwpg
+
+#endif //  __WPGRAPHICS_H__
Index: scribus/plugins/wpgimplugin/wpg/WPGPaintInterface.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGPaintInterface.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGPaintInterface.h	(revision 13903)
@@ -0,0 +1,78 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ * Copyright (C) 2004 Marc Oude Kotte (marc at solcon.nl)
+ *
+ * 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; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __WPGPAINTINTERFACE_H__
+#define __WPGPAINTINTERFACE_H__
+
+#include "WPGBitmap.h"
+#include "WPGBinaryData.h"
+#include "WPGBrush.h"
+#include "WPGPath.h"
+#include "WPGPen.h"
+#include "WPGPoint.h"
+#include "WPGRect.h"
+
+namespace libwpg
+{
+
+class WPGPaintInterface {
+public:
+	virtual ~WPGPaintInterface() {}
+
+	// none of the other callback functions will be called before this function is called
+	virtual void startGraphics(double width, double height) = 0;
+
+	virtual void setPen(const WPGPen& pen) = 0;
+
+	virtual void setBrush(const WPGBrush& brush) = 0;
+
+	typedef enum { AlternatingFill, WindingFill } FillRule;
+	virtual void setFillRule(FillRule rule ) = 0;
+
+	virtual void startLayer(unsigned int id) = 0;
+
+	virtual void endLayer(unsigned int id) = 0;
+
+	virtual void drawRectangle(const WPGRect& rect, double rx, double ry) = 0;
+
+	virtual void drawEllipse(const WPGPoint& center, double rx, double ry) = 0;
+
+	virtual void drawPolygon(const WPGPointArray& vertices) = 0;
+
+	virtual void drawPath(const WPGPath& path) = 0;
+
+	virtual void drawBitmap(const WPGBitmap& bitmap, double hres, double vres) = 0;
+	
+	virtual void drawImageObject(const WPGBinaryData& binaryData) = 0;
+
+	// none of the other callback functions will be called after this function is called
+	virtual void endGraphics() = 0;
+};
+
+} // namespace libwpg
+
+#endif // __WPGPAINTINTERFACE_H__
+
Index: scribus/plugins/wpgimplugin/wpg/WPGRect.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGRect.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGRect.h	(revision 13903)
@@ -0,0 +1,56 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __WPGRECT_H__
+#define __WPGRECT_H__
+
+#include "WPGColor.h"
+
+namespace libwpg
+{
+
+class WPGRect
+{
+public:
+	double x1;
+	double y1;
+	double x2;
+	double y2;
+
+	WPGRect();
+
+	WPGRect(double xx1, double yy1, double xx2, double yy2);
+
+	WPGRect(const WPGRect& rect);
+
+	WPGRect& operator=(const WPGRect& rect);
+
+	double width() const;
+	double height() const;
+};
+
+} // namespace libwpg
+
+#endif // __WPGRECT_H__
Index: scribus/plugins/wpgimplugin/wpg/WPGString.cpp
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGString.cpp	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGString.cpp	(revision 13903)
@@ -0,0 +1,93 @@
+/* libwpg
+ * Copyright (C) 2006 Fridrich Strba (fridrich.strba at bluewin.ch)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "WPGString.h"
+#include <string>
+
+namespace libwpg
+{
+class WPGStringPrivate
+{
+public:
+	WPGStringPrivate() : str() {};
+	std::string str;
+};
+
+} // namespace libwpg
+
+libwpg::WPGString::WPGString() :
+	d(new WPGStringPrivate())
+{
+}
+
+
+libwpg::WPGString::WPGString(const char * str):
+	d(new WPGStringPrivate())
+{
+	d->str = str;
+}
+
+libwpg::WPGString::WPGString(const libwpg::WPGString& str):
+	d(new WPGStringPrivate())
+{
+	d->str = str.d->str;
+}
+
+libwpg::WPGString::~WPGString()
+{
+	delete d;
+}
+
+bool libwpg::WPGString::empty() const
+{
+	return d->str.empty();
+}
+
+const char * libwpg::WPGString::cstr() const
+{
+	return d->str.c_str();
+}
+
+long libwpg::WPGString::length() const
+{
+	return d->str.length();
+}
+
+void libwpg::WPGString::append(const char c)
+{
+	d->str.append(1,c);
+}
+
+libwpg::WPGString& libwpg::WPGString::operator=(const libwpg::WPGString& str)
+{
+	d->str = str.d->str;
+	return *this;
+}
+
+libwpg::WPGString& libwpg::WPGString::operator=(const char * str)
+{
+	d->str = str;
+	return *this;
+}
Index: scribus/plugins/wpgimplugin/wpg/WPGPoint.cpp
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGPoint.cpp	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGPoint.cpp	(revision 13903)
@@ -0,0 +1,108 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "WPGPoint.h"
+
+#include <vector>
+
+namespace libwpg
+{
+
+class WPGPointArrayPrivate
+{
+public:
+    WPGPointArrayPrivate() :
+        points(std::vector<WPGPoint>()) {};
+	std::vector<WPGPoint> points;
+};
+
+}
+
+libwpg::WPGPoint::WPGPoint():
+	x(0.0),
+	y(0.0)
+{}
+
+libwpg::WPGPoint::WPGPoint(double xx, double yy):
+	x(xx),
+	y(yy)
+{}
+
+libwpg::WPGPoint::WPGPoint(const WPGPoint& point):
+	x(point.x),
+	y(point.y)
+{}
+
+libwpg::WPGPoint& libwpg::WPGPoint::operator=(const libwpg::WPGPoint& point)
+{
+	x = point.x;
+	y = point.y;
+	return *this;
+}
+	
+libwpg::WPGPointArray::WPGPointArray(): d(new libwpg::WPGPointArrayPrivate())
+{}
+
+libwpg::WPGPointArray::~WPGPointArray()
+{
+	delete d;
+}
+
+libwpg::WPGPointArray::WPGPointArray(const libwpg::WPGPointArray& pa):
+	d(new libwpg::WPGPointArrayPrivate())
+{
+	d->points = pa.d->points;
+}
+
+libwpg::WPGPointArray& libwpg::WPGPointArray::operator=(const libwpg::WPGPointArray& pa)
+{
+	d->points = pa.d->points;
+	return *this;
+}
+
+unsigned libwpg::WPGPointArray::count() const
+{
+	return d->points.size();
+}
+
+libwpg::WPGPoint& libwpg::WPGPointArray::at(unsigned i)
+{
+	return d->points[i];
+}
+
+const libwpg::WPGPoint& libwpg::WPGPointArray::at(unsigned i) const
+{
+	return d->points[i];
+}
+
+const libwpg::WPGPoint& libwpg::WPGPointArray::operator[](unsigned i) const
+{
+	return d->points[i];
+}
+
+void libwpg::WPGPointArray::add(const libwpg::WPGPoint& p)
+{
+	d->points.push_back(p);
+}
Index: scribus/plugins/wpgimplugin/wpg/WPGraphics.cpp
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGraphics.cpp	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGraphics.cpp	(revision 13903)
@@ -0,0 +1,152 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ * Copyright (C) 2007 Fridrich Strba (fridrich.strba at bluewin.ch)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "WPGraphics.h"
+#include "WPGHeader.h"
+#include "WPGXParser.h"
+#include "WPG1Parser.h"
+#include "WPG2Parser.h"
+#include "libwpg_utils.h"
+#include "WPGInternalStream.h"
+#include "WPGPaintInterface.h"
+#include <sstream>
+
+/**
+Analyzes the content of an input stream to see if it can be parsed
+\param input The input stream
+\return A value that indicates whether the content from the input
+stream is a WordPerfect Graphics that libwpg is able to parse
+*/
+bool libwpg::WPGraphics::isSupported(WPXInputStream* input)
+{
+	input->seek(0, WPX_SEEK_SET);
+	WPXInputStream *graphics = 0;
+	bool isDocumentOLE = false;
+
+	if (input->isOLEStream())
+	{
+		graphics = input->getDocumentOLEStream();
+		if (graphics)
+			isDocumentOLE = true;
+		else
+			return false;
+	}
+	else
+		graphics = input;
+
+	WPGHeader header;
+	if(!header.load(graphics))
+	{
+		if (graphics && isDocumentOLE)
+			delete graphics;
+		return false;
+	}
+	
+	bool retVal = header.isSupported();
+	
+	if (graphics && isDocumentOLE)
+		delete graphics;
+	return retVal;
+}
+
+/**
+Parses the input stream content. It will make callbacks to the functions provided by a
+WPGPaintInterface class implementation when needed. This is often commonly called the
+'main parsing routine'.
+\param input The input stream
+\param painter A WPGPainterInterface implementation
+\return A value that indicates whether the parsing was successful
+*/
+bool libwpg::WPGraphics::parse(::WPXInputStream* input, libwpg::WPGPaintInterface* painter)
+{
+	input->seek(0, WPX_SEEK_CUR);
+	WPGXParser *parser = 0;
+	
+	WPXInputStream *graphics = 0;
+	bool isDocumentOLE = false;
+
+	if (input->isOLEStream())
+	{
+		graphics = input->getDocumentOLEStream();
+		if (graphics)
+			isDocumentOLE = true;
+		else
+			return false;
+	}
+	else
+		graphics = input;
+
+	WPG_DEBUG_MSG(("Loading header...\n"));
+	WPGHeader header;
+	if(!header.load(graphics))
+	{
+		if (graphics && isDocumentOLE)
+			delete graphics;
+		return false;
+	}
+	
+	if(!header.isSupported())
+	{
+		WPG_DEBUG_MSG(("Unsupported file format!\n"));
+		if (graphics && isDocumentOLE)
+			delete graphics;
+		return false;  
+	}
+
+	graphics->seek(header.startOfDocument(), WPX_SEEK_SET);
+
+	bool retval;
+	switch (header.majorVersion()) {
+		case 0x01: // WPG1
+			WPG_DEBUG_MSG(("Parsing WPG1\n"));
+			parser = new WPG1Parser(graphics, painter);
+			retval = parser->parse();
+			break;
+		case 0x02: // WPG2
+			WPG_DEBUG_MSG(("Parsing WPG2\n"));
+			parser = new WPG2Parser(graphics, painter);
+			retval = parser->parse();
+			break;
+		default: // other :-)
+			WPG_DEBUG_MSG(("Unknown format\n"));
+			if (graphics && isDocumentOLE)
+				delete graphics;
+			return false;
+	}
+	
+	if (parser)
+		delete parser;
+	if (graphics && isDocumentOLE)
+		delete graphics;
+	
+	return retval;
+}
+
+bool libwpg::WPGraphics::parse(const unsigned char* data, const size_t size, libwpg::WPGPaintInterface* painter)
+{
+	WPGInternalInputStream tmpStream(data, size);
+	return libwpg::WPGraphics::parse(&tmpStream, painter);
+}
Index: scribus/plugins/wpgimplugin/wpg/libwpg_utils.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/libwpg_utils.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/libwpg_utils.h	(revision 13903)
@@ -0,0 +1,50 @@
+/* libwpg
+ * Copyright (C) 2004 Marc Oude Kotte (marc at solcon.nl)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __LIBWPG_UTILS_H__
+#define __LIBWPG_UTILS_H__
+
+#include <stdio.h>
+
+//#define DEBUG // FIXME !
+
+// debug message includes source file and line number
+//#define VERBOSE_DEBUG 1
+
+// do nothing with debug messages in a release compile
+#ifdef DEBUG
+	#ifdef VERBOSE_DEBUG
+		#define WPG_DEBUG_MSG(M) printf("%15s:%5d: ", __FILE__, __LINE__); printf M
+		#define WPG_DEBUG(M) M
+	#else
+		#define WPG_DEBUG_MSG(M) printf M
+		#define WPG_DEBUG(M) M
+	#endif
+#else
+	#define WPG_DEBUG_MSG(M)
+	#define WPG_DEBUG(M)
+#endif
+
+#endif // __LIBWPG_UTILS_H__
Index: scribus/plugins/wpgimplugin/wpg/WPGStreamImplementation.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGStreamImplementation.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGStreamImplementation.h	(revision 13903)
@@ -0,0 +1,78 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+#ifndef __WPGSTREAMIMPLEMENTATION_H__
+#define __WPGSTREAMIMPLEMENTATION_H__
+
+#include "WPXStream.h"
+
+namespace libwpg
+{
+
+class WPGFileStreamPrivate;
+
+class WPGFileStream: public WPXInputStream
+{
+public:
+	explicit WPGFileStream(const char* filename);
+	~WPGFileStream();
+	
+	const uint8_t *read(size_t numBytes, size_t &numBytesRead);
+	long tell();
+	int seek(long offset, WPX_SEEK_TYPE seekType);
+	bool atEOS();
+
+	bool isOLEStream();
+	WPXInputStream *getDocumentOLEStream(const char * name);
+	WPXInputStream *getDocumentOLEStream();
+
+private:
+	WPGFileStreamPrivate* d;
+	WPGFileStream(const WPGFileStream&); // copy is not allowed
+	WPGFileStream& operator=(const WPGFileStream&); // assignment is not allowed
+};
+
+class WPGMemoryStreamPrivate;
+
+class WPGMemoryStream: public WPXInputStream
+{
+public:
+	WPGMemoryStream(const char *data, const unsigned int dataSize);
+	~WPGMemoryStream();
+
+	const uint8_t *read(size_t numBytes, size_t &numBytesRead);
+	long tell();
+	int seek(long offset, WPX_SEEK_TYPE seekType);
+	bool atEOS();
+
+	bool isOLEStream();
+	WPXInputStream *getDocumentOLEStream(const char * name);
+	WPXInputStream *getDocumentOLEStream();
+
+private:
+	WPGMemoryStreamPrivate* d;
+	WPGMemoryStream(const WPGMemoryStream&); // copy is not allowed
+	WPGMemoryStream& operator=(const WPGMemoryStream&); // assignment is not allowed
+};
+
+} // namespace libwpg
+
+#endif // __WPGSTREAMIMPLEMENTATION_H__
Index: scribus/plugins/wpgimplugin/wpg/WPGBinaryData.cpp
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGBinaryData.cpp	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGBinaryData.cpp	(revision 13903)
@@ -0,0 +1,114 @@
+/* libwpd
+ * Copyright (C) 2007 Fridrich Strba (fridrich.strba at bluewin.ch)
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ *
+ * For further information visit http://libwpd.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "WPGBinaryData.h"
+#include "WPGInternalStream.h"
+#include "WPGBitmap.h"
+
+#include <vector>
+#include <stdarg.h>
+#include <stdio.h>
+
+class libwpg::WPGBinaryDataImpl
+{
+public:
+	WPGBinaryDataImpl() : m_buf() {}
+	std::vector<char> m_buf;
+};
+
+libwpg::WPGBinaryData::~WPGBinaryData()
+{
+	delete m_binaryDataImpl;
+}
+
+libwpg::WPGBinaryData::WPGBinaryData() :
+	rect(),
+	mimeType(),
+	m_binaryDataImpl(new WPGBinaryDataImpl)
+{
+}
+
+libwpg::WPGBinaryData::WPGBinaryData(const WPGBinaryData &data) :
+	m_binaryDataImpl(new WPGBinaryDataImpl)
+{
+	m_binaryDataImpl->m_buf = data.m_binaryDataImpl->m_buf;
+}
+
+libwpg::WPGBinaryData::WPGBinaryData(const char *buffer, const size_t bufferSize) :
+	m_binaryDataImpl(new WPGBinaryDataImpl)
+{
+	m_binaryDataImpl->m_buf = std::vector<char> (bufferSize);
+	for (size_t i = 0; i < bufferSize; i++)
+		m_binaryDataImpl->m_buf[i] = buffer[i];
+}
+
+void libwpg::WPGBinaryData::append(const WPGBinaryData &data)
+{
+	size_t previousSize = m_binaryDataImpl->m_buf.size();
+	m_binaryDataImpl->m_buf.resize(previousSize + data.m_binaryDataImpl->m_buf.size());
+	for (size_t i = previousSize; i < previousSize + data.m_binaryDataImpl->m_buf.size(); i++)
+		m_binaryDataImpl->m_buf[previousSize + i] = data.m_binaryDataImpl->m_buf[i];
+}
+
+void libwpg::WPGBinaryData::append(const char *buffer, const size_t bufferSize )
+{
+	size_t previousSize = m_binaryDataImpl->m_buf.size();
+	m_binaryDataImpl->m_buf.resize(previousSize + bufferSize);
+	for (size_t i = previousSize; i < previousSize + bufferSize; i++)
+		m_binaryDataImpl->m_buf[previousSize + i] = buffer[i];
+}
+
+void libwpg::WPGBinaryData::append(const char c)
+{
+	m_binaryDataImpl->m_buf.push_back(c);
+}
+
+void libwpg::WPGBinaryData::clear()
+{
+	m_binaryDataImpl->m_buf.clear();
+}
+
+size_t libwpg::WPGBinaryData::size() const
+{ 
+	return (size_t)m_binaryDataImpl->m_buf.size(); 
+}
+
+libwpg::WPGBinaryData& libwpg::WPGBinaryData::operator=(const WPGBinaryData &dataBuf)
+{
+	m_binaryDataImpl->m_buf = dataBuf.m_binaryDataImpl->m_buf;
+	return *this;
+}
+
+const char * libwpg::WPGBinaryData::getDataBuffer() const
+{
+	return &(m_binaryDataImpl->m_buf[0]);
+}
+
+const libwpg::WPGString libwpg::WPGBinaryData::getBase64Data() const
+{
+	WPGString base64;	
+
+	libwpg::WPGBitmap::base64Encode(base64, &(m_binaryDataImpl->m_buf[0]), m_binaryDataImpl->m_buf.size());
+	return base64;
+}
Index: scribus/plugins/wpgimplugin/importwpg.h
===================================================================
--- scribus/plugins/wpgimplugin/importwpg.h	(revision 13902)
+++ scribus/plugins/wpgimplugin/importwpg.h	(revision 13903)
@@ -20,7 +20,7 @@
 #include <QMatrix>
 #include <QMultiMap>
 #include <QVector>
-#include <libwpg/libwpg.h>
+#include "wpg/libwpg.h"
 
 class MultiProgressDialog;
 class ScribusDoc;
@@ -45,7 +45,7 @@
 	void drawEllipse(const libwpg::WPGPoint& center, double rx, double ry);
 	void drawPolygon(const libwpg::WPGPointArray& vertices);
 	void drawPath(const libwpg::WPGPath& path);
-	void drawBitmap(const libwpg::WPGBitmap& bitmap);
+	void drawBitmap(const libwpg::WPGBitmap& bitmap, double hres, double vres);
 	void drawImageObject(const libwpg::WPGBinaryData& binaryData);
 	void finishItem(PageItem* ite);
 	QList<PageItem*> Elements;
@@ -63,6 +63,8 @@
 	bool fillrule;
 	double gradientAngle;
 	bool isGradient;
+	bool fillSet;
+	bool strokeSet;
 	VGradient currentGradient;
 	QVector<double> dashArray;
 	int flags;
Index: scribus/plugins/wpgimplugin/wpg/libwpd_types.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/libwpd_types.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/libwpd_types.h	(revision 13903)
@@ -0,0 +1,39 @@
+/* libwpd
+ * Copyright (C) 2005 William Lachance (wrlach at gmail.com)
+ *  
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ *
+ * For further information visit http://libwpd.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by 
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef LIBWPD_TYPES_H
+#define LIBWPD_TYPES_H
+
+#ifdef _MSC_VER
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+#else /* _MSC_VER */
+#include <inttypes.h>
+#endif /* _MSC_VER */
+
+#endif /* LIBWPD_TYPES_H */
Index: scribus/plugins/wpgimplugin/wpg/WPGRect.cpp
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGRect.cpp	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGRect.cpp	(revision 13903)
@@ -0,0 +1,66 @@
+/* libwpg
+ * Copyright (C) 2006 Fridrich Strba (fridrich.strba at bluewin.ch)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "WPGRect.h"
+
+libwpg::WPGRect::WPGRect():
+	x1(0.0),
+	y1(0.0),
+	x2(0.0),
+	y2(0.0)
+{}
+
+libwpg::WPGRect::WPGRect(double xx1, double yy1, double xx2, double yy2): 
+	x1(xx1),
+	y1(yy1),
+	x2(xx2),
+	y2(yy2)
+{}
+
+libwpg::WPGRect::WPGRect(const WPGRect& rect):
+	x1(rect.x1),
+	y1(rect.y1),
+	x2(rect.x2),
+	y2(rect.y2)
+{}
+
+libwpg::WPGRect&  libwpg::WPGRect::operator=(const WPGRect& rect)
+{
+	x1 = rect.x1;
+	y1 = rect.y1;
+	x2 = rect.x2;
+	y2 = rect.y2;
+	return *this;
+}
+
+double libwpg::WPGRect::width() const
+{
+	return x2-x1;
+}
+
+double libwpg::WPGRect::height() const
+{
+	return y2-y1;
+}
Index: scribus/plugins/wpgimplugin/wpg/WPGHeader.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGHeader.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGHeader.h	(revision 13903)
@@ -0,0 +1,61 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ * Copyright (C) 2004 Marc Oude Kotte (marc at solcon.nl)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __WPGHEADER_H__
+#define __WPGHEADER_H__
+
+#include "WPXStream.h"
+
+class WPGHeader 
+{
+public:
+	WPGHeader();
+	
+	bool load(WPXInputStream *input);
+	
+	bool isSupported() const;
+	
+	unsigned long startOfDocument() const;
+	
+	int majorVersion() const;
+
+private:
+	unsigned char m_identifier[4];          // should always be 0xFF followed by "WPC"
+	unsigned long m_startOfDocument;        // index into file
+	unsigned char m_productType;            // should always be 1 for WPG files
+	unsigned char m_fileType;               // should always be 22 for WPG files
+	unsigned char m_majorVersion;           // 2 for WPG 8.0 files
+	unsigned char m_minorVersion;           // 0 for WPG 8.0 files
+	unsigned int  m_encryptionKey;          // 0 when not encrypted
+	unsigned int  m_startOfPacketData;      // unused, since according to the docs no packets are defined
+	unsigned char m_entryCount;             // number of entries in extension
+	unsigned char m_resourceComplete;       // resource completeness indicator
+	unsigned int  m_encryptionBlockOffset;  // encryption block offset
+	unsigned long m_fileSize;               // size of the entire wpg file
+	unsigned int  m_encryptVersion;         // encryption version information
+};
+
+#endif // WPGHEADER
Index: scribus/plugins/wpgimplugin/wpg/WPGOLEStream.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGOLEStream.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGOLEStream.h	(revision 13903)
@@ -0,0 +1,120 @@
+/* POLE - Portable C++ library to access OLE Storage 
+   Copyright (C) 2002-2005 Ariya Hidayat <ariya at kde.org>
+
+   Redistribution and use in source and binary forms, with or without 
+   modification, are permitted provided that the following conditions 
+   are met:
+   * Redistributions of source code must retain the above copyright notice, 
+     this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright notice, 
+     this list of conditions and the following disclaimer in the documentation 
+     and/or other materials provided with the distribution.
+   * Neither the name of the authors nor the names of its contributors may be 
+     used to endorse or promote products derived from this software without 
+     specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
+   THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef WPGOLESTREAM_H
+#define WPGOLESTREAM_H
+
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <list>
+
+namespace libwpg
+{
+
+class StorageIO;
+class Stream;
+class StreamIO;
+
+class Storage
+{
+  friend class Stream;
+
+public:
+
+  // for Storage::result()
+  enum { Ok, OpenFailed, NotOLE, BadOLE, UnknownError };
+  
+  /**
+   * Constructs a storage with data.
+   **/
+  Storage( const std::stringstream &memorystream );
+
+  /**
+   * Destroys the storage.
+   **/
+  ~Storage();
+  
+  /**
+   * Checks whether the storage is OLE2 storage.
+   **/
+  bool isOLEStream();
+
+  /**
+   * Returns the error code of last operation.
+   **/
+  int result();
+  
+private:
+  StorageIO* io;
+  
+  // no copy or assign
+  Storage( const Storage& );
+  Storage& operator=( const Storage& );
+
+};
+
+class Stream
+{
+  friend class Storage;
+  friend class StorageIO;
+  
+public:
+
+  /**
+   * Creates a new stream.
+   */
+  // name must be absolute, e.g "/PerfectOffice_MAIN"
+  Stream( Storage* storage, const std::string& name );
+
+  /**
+   * Destroys the stream.
+   */
+  ~Stream();
+
+  /**
+   * Returns the stream size.
+   **/
+  unsigned long size();
+
+  /**
+   * Reads a block of data.
+   **/
+  unsigned long read( unsigned char* data, unsigned long maxlen );
+  
+private:
+  StreamIO* io;
+
+  // no copy or assign
+  Stream( const Stream& );
+  Stream& operator=( const Stream& );    
+};
+
+}  // namespace libwpg
+
+#endif // WPGOLESTREAM_H
Index: scribus/plugins/wpgimplugin/wpg/WPGPath.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGPath.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGPath.h	(revision 13903)
@@ -0,0 +1,91 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __WPGPATH_H__
+#define __WPGPATH_H__
+
+#include "WPGPoint.h"
+
+namespace libwpg
+{
+
+class WPGPathElement
+{
+public:
+	typedef enum 
+	{
+		NullElement,
+		MoveToElement,
+		LineToElement,
+		CurveToElement
+	} Type;
+	
+	Type type;
+	WPGPoint point;
+	WPGPoint extra1;
+	WPGPoint extra2;
+	
+	WPGPathElement();
+};
+
+class WPGPathPrivate;
+
+class WPGPath
+{
+public:
+
+	bool closed;
+	bool framed;
+	bool filled;
+	
+	WPGPath();
+	
+	~WPGPath();
+	
+	WPGPath(const WPGPath&);
+	
+	WPGPath& operator=(const WPGPath&);
+	
+	unsigned count() const;
+	
+	WPGPathElement element(unsigned index) const;
+	
+	void moveTo(const WPGPoint& point);
+	
+	void lineTo(const WPGPoint& point);
+
+	void curveTo(const WPGPoint& c1, const WPGPoint& c2, const WPGPoint& endPoint);
+	
+	void addElement(const WPGPathElement& elem);
+	
+	void append(const WPGPath& path);
+	
+private:
+	WPGPathPrivate *d;
+};
+
+} // namespace libwpg
+
+#endif // __WPGPATH_H__
Index: scribus/plugins/wpgimplugin/wpg/WPGStreamImplementation.cpp
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGStreamImplementation.cpp	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGStreamImplementation.cpp	(revision 13903)
@@ -0,0 +1,437 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+#include "WPGStreamImplementation.h"
+#include "WPGOLEStream.h"
+#include "libwpg.h"
+
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <limits>
+
+namespace libwpg
+{
+
+class WPGFileStreamPrivate
+{
+public:
+	WPGFileStreamPrivate();
+	~WPGFileStreamPrivate();
+	std::fstream file;
+	std::stringstream buffer;
+	unsigned long streamSize;
+	uint8_t *buf;
+	uint8_t *readBuffer;
+	unsigned long readBufferLength;
+	unsigned long readBufferPos;
+private:
+	WPGFileStreamPrivate(const WPGFileStreamPrivate&);
+	WPGFileStreamPrivate& operator=(const WPGFileStreamPrivate&);
+};
+
+class WPGMemoryStreamPrivate
+{
+public:
+	WPGMemoryStreamPrivate(const std::string str);
+	~WPGMemoryStreamPrivate();
+	std::stringstream buffer;
+	unsigned long streamSize;
+	uint8_t *buf;
+private:
+	WPGMemoryStreamPrivate(const WPGMemoryStreamPrivate&);
+	WPGMemoryStreamPrivate& operator=(const WPGMemoryStreamPrivate&);
+};
+
+} // namespace libwpg
+
+using namespace libwpg;
+
+WPGFileStreamPrivate::WPGFileStreamPrivate() :
+	file(),
+	buffer(std::ios::binary | std::ios::in | std::ios::out),
+	streamSize(0),
+	buf(0),
+	readBuffer(0),
+	readBufferLength(0),
+	readBufferPos(0)
+{	
+}
+
+WPGFileStreamPrivate::~WPGFileStreamPrivate()
+{
+	if (buf)
+		delete [] buf;
+	if (readBuffer)
+		delete [] readBuffer;
+}
+
+WPGMemoryStreamPrivate::WPGMemoryStreamPrivate(const std::string str) :
+	buffer(str, std::ios::binary | std::ios::in),
+	streamSize(0),
+	buf(0)
+{
+}
+
+WPGMemoryStreamPrivate::~WPGMemoryStreamPrivate()
+{
+	if (buf)
+		delete [] buf;
+}
+
+WPGFileStream::WPGFileStream(const char* filename) :
+	WPXInputStream(true),
+	d(new WPGFileStreamPrivate)
+{
+	d->file.open( filename, std::ios::binary | std::ios::in );
+	d->file.seekg( 0, std::ios::end );
+	d->streamSize = (d->file.good() ? (unsigned long)d->file.tellg() : (unsigned long)-1L);
+	if (d->streamSize == (unsigned long)-1) // tellg() returned ERROR
+		d->streamSize = 0;
+	 // preventing possible unsigned/signed issues later by truncating the file
+	if (d->streamSize > (std::numeric_limits<unsigned long>::max)() / 2)
+		d->streamSize = (std::numeric_limits<unsigned long>::max)() / 2;
+	d->file.seekg( 0, std::ios::beg );
+}
+
+WPGFileStream::~WPGFileStream()
+{
+	delete d;
+}
+
+#define BUFFER_MAX 65536
+
+const uint8_t *WPGFileStream::read(size_t numBytes, size_t &numBytesRead)
+{
+	numBytesRead = 0;
+	
+	if (numBytes == 0 || /* atEOS() || */ numBytes > (std::numeric_limits<unsigned long>::max)()/2
+		|| !d->file.good())
+		return 0;
+
+	// can we read from the buffer?
+	if (d->readBuffer && (d->readBufferPos + numBytes > d->readBufferPos)
+		&& (d->readBufferPos + numBytes <= d->readBufferLength))
+	{
+		const uint8_t *pTmp = d->readBuffer + d->readBufferPos;
+		d->readBufferPos += numBytes;
+		numBytesRead = numBytes;
+		return pTmp;
+	}
+
+	// hmm, we cannot: go back by the bytes we read ahead && invalidate the buffer
+	if (d->readBuffer)
+	{
+		d->file.seekg((unsigned long)d->file.tellg() - d->readBufferLength, std::ios::beg);
+		d->file.seekg(d->readBufferPos, std::ios::cur);
+		delete [] d->readBuffer;
+		d->readBuffer = 0; d->readBufferPos = 0; d->readBufferLength = 0;
+	}
+	
+	unsigned long curpos = tell();
+	if (curpos == (unsigned long)-1)  // tellg() returned ERROR
+		return 0;
+
+	if ( (curpos + numBytes < curpos) /*overflow*/ ||
+		(curpos + numBytes >= d->streamSize) ) /*reading more than available*/
+	{
+		numBytes = d->streamSize - curpos;
+	}
+
+	if (numBytes < BUFFER_MAX)
+	{
+		if (BUFFER_MAX < d->streamSize - curpos)
+			d->readBufferLength = BUFFER_MAX;
+		else /* BUFFER_MAX >= d->streamSize - curpos */
+			d->readBufferLength = d->streamSize - curpos;
+	}
+	else
+		d->readBufferLength = numBytes;
+	
+	d->file.seekg(d->readBufferLength, std::ios::cur);
+	d->file.seekg(curpos, std::ios::beg);
+	
+	d->readBuffer = new uint8_t[d->readBufferLength];
+	d->file.read((char *)(d->readBuffer), d->readBufferLength);
+	
+	if (!d->file.good())
+		d->file.clear();
+	d->readBufferPos = 0;
+	if (d->readBufferLength == 0)
+		return 0;
+
+	numBytesRead = numBytes;
+		
+	d->readBufferPos += numBytesRead;
+	return const_cast<const uint8_t*>( d->readBuffer );
+}
+
+long WPGFileStream::tell()
+{
+	return d->file.good() ? (long)((long)d->file.tellg() - d->readBufferLength + d->readBufferPos) : -1L;
+}
+
+int WPGFileStream::seek(long offset, WPX_SEEK_TYPE seekType)
+{
+	if (seekType == WPX_SEEK_CUR)
+		offset += tell();
+
+	if (offset < 0)
+		offset = 0;
+	if (offset > (long)d->streamSize)
+		offset = (long)d->streamSize;
+	
+	if (d->file.good() && offset < d->file.tellg() && (unsigned long)offset >= (unsigned long)d->file.tellg() - d->readBufferLength)
+	{
+		d->readBufferPos = offset + d->readBufferLength - d->file.tellg();
+		return 0;
+	}
+	
+	if (d->readBuffer) // seeking outside of the buffer, so invalidate the buffer
+	{
+		d->file.seekg((unsigned long)d->file.tellg() - d->readBufferLength, std::ios::beg);
+		d->file.seekg(d->readBufferPos, std::ios::cur);
+		delete [] d->readBuffer;
+		d->readBuffer = 0; d->readBufferPos = 0; d->readBufferLength = 0;
+	}
+	
+	if(d->file.good())
+	{
+		d->file.seekg(offset, std::ios::beg);
+		return (int) ((long)d->file.tellg() == -1) ;
+	}
+	else
+		return -1;
+}
+
+bool WPGFileStream::atEOS()
+{
+	return (tell() >= (long)d->streamSize);
+}
+
+bool WPGFileStream::isOLEStream()
+{
+	if (!d->file.good())
+		return false;
+
+	if (d->readBuffer)
+	{
+		d->file.seekg((unsigned long)d->file.tellg() - d->readBufferLength, std::ios::beg);
+		d->file.seekg(d->readBufferPos, std::ios::cur);
+		delete [] d->readBuffer;
+		d->readBuffer = 0; d->readBufferPos = 0; d->readBufferLength = 0;
+	}
+	
+	if (d->buffer.str().empty())
+		d->buffer << d->file.rdbuf();
+	Storage tmpStorage( d->buffer );
+	seek(0, WPX_SEEK_SET);
+	if (tmpStorage.isOLEStream())
+		return true;
+	return false;
+}
+
+::WPXInputStream* WPGFileStream::getDocumentOLEStream(const char * name)
+{
+	if (!d->file.good())
+		return (WPXInputStream*)0;
+
+	if (d->readBuffer)
+	{
+		d->file.seekg((unsigned long)d->file.tellg() - d->readBufferLength, std::ios::beg);
+		d->file.seekg(d->readBufferPos, std::ios::cur);
+		delete [] d->readBuffer;
+		d->readBuffer = 0; d->readBufferPos = 0; d->readBufferLength = 0;
+	}
+	
+	if (d->buffer.str().empty())
+		d->buffer << d->file.rdbuf();
+	Storage *tmpStorage = new Storage( d->buffer );
+	Stream tmpStream( tmpStorage, name );
+	if (!tmpStorage || (tmpStorage->result() != Storage::Ok)  || !tmpStream.size())
+	{
+		if (tmpStorage)
+			delete tmpStorage;
+		return (WPXInputStream*)0;
+	}
+	
+	if (d->buf)
+		delete [] d->buf;
+	d->buf = new unsigned char[tmpStream.size()];
+
+	unsigned long tmpLength;
+	tmpLength = tmpStream.read((unsigned char *)(d->buf), tmpStream.size());
+
+	// sanity check
+	if (tmpLength > tmpStream.size() || tmpLength < tmpStream.size())
+	/* something went wrong here and we do not trust the
+	   resulting buffer */
+	{
+		if (tmpStorage)
+			delete tmpStorage;
+		return (WPXInputStream*)0;
+	}
+
+	delete tmpStorage;
+	return new WPGMemoryStream((const char *)(d->buf), tmpLength);
+}
+
+::WPXInputStream* WPGFileStream::getDocumentOLEStream()
+{
+	return getDocumentOLEStream("PerfectOffice_MAIN");
+}
+
+WPGMemoryStream::WPGMemoryStream(const char *data, const unsigned int dataSize) :
+    WPXInputStream(true),
+    d(new WPGMemoryStreamPrivate(std::string(data, dataSize)))
+{
+	d->buffer.seekg( 0, std::ios::end );
+	d->streamSize = (d->buffer.good() ? (unsigned long)d->buffer.tellg() : (unsigned long)-1L);
+	if (d->streamSize == (unsigned long)-1)
+		d->streamSize = 0;
+	 // preventing possible unsigned/signed issues later by truncating the file
+	if (d->streamSize > (std::numeric_limits<unsigned long>::max)() / 2)
+		d->streamSize = (std::numeric_limits<unsigned long>::max)() / 2;
+	d->buffer.seekg( 0, std::ios::beg );
+}
+
+WPGMemoryStream::~WPGMemoryStream()
+{
+	delete d;
+}
+
+const uint8_t *WPGMemoryStream::read(size_t numBytes, size_t &numBytesRead)
+{
+	numBytesRead = 0;
+	
+	if (0 == numBytes)
+		return 0;
+
+	if (numBytes < 0 || atEOS() || numBytes > (std::numeric_limits<unsigned long>::max)()/2)
+		return 0;
+
+	unsigned long curpos = d->buffer.tellg();
+	if (curpos == (unsigned long)-1) //tellg() returned ERROR
+		return 0;
+
+	if ( (curpos + numBytes < curpos) /*overflow*/ ||
+		(curpos + numBytes > d->streamSize) ) /*reading more than available*/
+	{
+		numBytes = d->streamSize - curpos;
+	}
+
+	if (d->buf)
+		delete [] d->buf;
+	d->buf = new uint8_t[numBytes];
+
+	if(d->buffer.good())
+	{
+		d->buffer.read((char *)(d->buf), numBytes); 
+		numBytesRead = (long)d->buffer.tellg() - curpos;
+	}
+	
+	return d->buf;
+}
+
+long WPGMemoryStream::tell()
+{
+	return d->buffer.good() ? (long)d->buffer.tellg() : -1L;
+}
+
+int WPGMemoryStream::seek(long offset, WPX_SEEK_TYPE seekType)
+{
+	if (seekType == WPX_SEEK_SET)
+	{
+		if (offset < 0)
+			offset = 0;
+		if (offset > (long)d->streamSize)
+			offset = d->streamSize;
+	}
+
+	if (seekType == WPX_SEEK_CUR)
+	{
+		if (tell() + offset < 0)
+			offset = -tell();
+		if (tell() + offset > (long)d->streamSize)
+			offset = d->streamSize - tell();
+	}
+
+	if(d->buffer.good())
+	{
+		d->buffer.seekg(offset, ((seekType == WPX_SEEK_SET) ? std::ios::beg : std::ios::cur));
+		return (int) ( (long)d->buffer.tellg() == -1);
+	}
+	else
+		return -1;
+}
+
+bool WPGMemoryStream::atEOS()
+{
+	return (d->buffer.tellg() >= (long)d->streamSize);
+}
+
+bool WPGMemoryStream::isOLEStream()
+{
+	Storage tmpStorage( d->buffer );
+	if (tmpStorage.isOLEStream())
+	{
+		seek(0, WPX_SEEK_SET);
+		return true;
+	}
+	seek(0, WPX_SEEK_SET);
+	return false;
+}
+
+::WPXInputStream* WPGMemoryStream::getDocumentOLEStream(const char * name)
+{
+	Storage *tmpStorage = new Storage( d->buffer );
+	Stream tmpStream( tmpStorage, name );
+	if (!tmpStorage || (tmpStorage->result() != Storage::Ok)  || !tmpStream.size())
+	{
+		if (tmpStorage)
+			delete tmpStorage;
+		return (::WPXInputStream*)0;
+	}
+
+	if (d->buf)
+		delete [] d->buf;
+	d->buf = new uint8_t[tmpStream.size()];
+	unsigned long tmpLength;
+	tmpLength = tmpStream.read((unsigned char *)(d->buf), tmpStream.size());
+
+	// sanity check
+	if (tmpLength > tmpStream.size() || tmpLength < tmpStream.size())
+	/* something went wrong here and we do not trust the
+	   resulting buffer */
+	{
+		if (tmpStorage)
+			delete tmpStorage;
+		return (::WPXInputStream*)0;
+	}
+
+	delete tmpStorage;
+	return new WPGMemoryStream((const char *)(d->buf), tmpLength);
+}
+
+::WPXInputStream* WPGMemoryStream::getDocumentOLEStream()
+{
+	return getDocumentOLEStream("PerfectOffice_MAIN");
+}
Index: scribus/plugins/wpgimplugin/wpg/WPGGradient.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGGradient.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGGradient.h	(revision 13903)
@@ -0,0 +1,68 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __WPGGRADIENT_H__
+#define __WPGGRADIENT_H__
+
+#include "WPGColor.h"
+
+namespace libwpg
+{
+
+class WPGGradientPrivate;
+
+class WPGGradient
+{
+public:
+	
+	WPGGradient();
+	
+	~WPGGradient();
+	
+	WPGGradient(const WPGGradient&);
+	
+	WPGGradient& operator=(const WPGGradient&);
+	
+	double angle() const; // in radiant
+	
+	void setAngle(double angle);
+
+	unsigned count() const;
+	
+	double stopOffset(unsigned index) const;
+	
+	WPGColor stopColor(unsigned index) const;
+	
+	void clear();
+	
+	void addStop(double offset, const WPGColor& color);
+	
+private:
+	WPGGradientPrivate *d;
+};
+
+} // namespace libwpg
+
+#endif // __WPGGRADIENT_H__
Index: scribus/plugins/wpgimplugin/wpg/libwpg.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/libwpg.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/libwpg.h	(revision 13903)
@@ -0,0 +1,48 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ * Copyright (C) 2004 Marc Oude Kotte (marc at solcon.nl)
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __LIBWPG_H__
+#define __LIBWPG_H__
+
+#define LIBWPG_VERSION_MAJOR     0
+#define LIBWPG_VERSION_MINOR     1
+#define LIBWPG_VERSION_REVISION  4
+#define LIBWPG_VERSION_STRING    "0.1.4"
+
+#include "WPGraphics.h"
+#include "WPGPaintInterface.h"
+
+#include "WPGColor.h"
+#include "WPGPen.h"
+#include "WPGBrush.h"
+#include "WPGGradient.h"
+#include "WPGPath.h"
+#include "WPGPoint.h"
+#include "WPGRect.h"
+#include "WPGBitmap.h"
+#include "WPGBinaryData.h"
+
+#endif
Index: scribus/plugins/wpgimplugin/wpg/WPGString.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGString.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGString.h	(revision 13903)
@@ -0,0 +1,57 @@
+/* libwpg
+ * Copyright (C) 2006 Fridrich Strba (fridrich.strba at bluewin.ch)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __WPGSTRING_H__
+#define __WPGSTRING_H__
+
+namespace libwpg
+{
+class WPGStringPrivate;
+class WPGString
+{
+public:
+	WPGString();
+	WPGString(const char * str);
+	WPGString(const WPGString& str);
+	
+	~WPGString();
+
+	bool empty() const;
+
+	const char * cstr() const;
+
+	long length() const;
+	
+	void append(const char c);
+
+	WPGString& operator=(const WPGString& str);
+	WPGString& operator=(const char * str);
+private:
+	WPGStringPrivate * d;
+};
+
+} // namespace libwpg
+
+#endif // __WPGSTRING_H__
Index: scribus/plugins/wpgimplugin/wpg/WPGBitmap.cpp
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGBitmap.cpp	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGBitmap.cpp	(revision 13903)
@@ -0,0 +1,299 @@
+/* libwpg
+ * Copyright (C) 2007 Ariya Hidayat (ariya at kde.org)
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ *
+ * 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; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "WPGBitmap.h"
+#include "libwpg_utils.h"
+
+#include <sstream>
+
+#define DUMP_BITMAP 0
+
+#if DUMP_BITMAP
+static unsigned bitmapId = 0;
+#endif
+
+class libwpg::WPGBitmap::Private
+{
+public:
+	int width;
+	int height;
+	bool vFlip;
+	bool hFlip;
+	WPGColor* pixels;
+
+	Private(int w, int h): width(w), height(h), vFlip(false), hFlip(false), pixels(0) {}
+};
+
+libwpg::WPGBitmap::WPGBitmap(int width, int height): rect(), d(new Private(width, height))
+{
+	d->pixels = new WPGColor[width*height];
+}
+
+libwpg::WPGBitmap::WPGBitmap(int width, int height, bool verticalFlip, bool horizontalFlip) :
+	rect(),
+	d(new Private(width, height))
+{
+	d->vFlip = verticalFlip;
+	d->hFlip = horizontalFlip;
+	d->pixels = new WPGColor[width*height];
+}
+
+libwpg::WPGBitmap::~WPGBitmap()
+{
+	if (d)
+	{
+		if (d->pixels)
+			delete [] d->pixels;
+		delete d;
+	}
+}
+
+libwpg::WPGBitmap::WPGBitmap(const WPGBitmap& bitmap): rect(), d(new Private(0,0))
+{
+	copyFrom(bitmap);
+}
+
+libwpg::WPGBitmap& libwpg::WPGBitmap::operator=(const WPGBitmap& bitmap)
+{
+	copyFrom(bitmap);
+	return *this;
+}
+
+void libwpg::WPGBitmap::copyFrom(const WPGBitmap& bitmap)
+{
+	rect = bitmap.rect;
+	d->width = bitmap.d->width;
+	d->height = bitmap.d->height;
+	delete [] d->pixels;
+	d->pixels = new WPGColor[d->width*d->height];
+	for(int i=0; i < d->width*d->height; i++)
+		d->pixels[i] = bitmap.d->pixels[i];
+}
+
+int libwpg::WPGBitmap::width() const
+{
+	return d->width;
+}
+
+int libwpg::WPGBitmap::height() const
+{
+	return d->height;
+}
+
+libwpg::WPGColor libwpg::WPGBitmap::pixel(int x, int y) const
+{
+  if((x < 0) || (y <0) || (x >= d->width) || (y >= d->height))
+		return libwpg::WPGColor();
+
+	return d->pixels[y*d->width + x];
+}
+
+void libwpg::WPGBitmap::setPixel(int x, int y, const libwpg::WPGColor& color)
+{
+	if((x < 0) || (y <0) || (x >= d->width) || (y >= d->height))
+		return;
+
+	d->pixels[y*d->width + x] = color;
+}
+
+void libwpg::WPGBitmap::generateBase64DIB(libwpg::WPGString& bmp) const
+{
+	if (d->height <= 0 || d->width <= 0)
+		return;
+
+	unsigned tmpPixelSize = (unsigned)(d->height * d->width);
+	if (tmpPixelSize < (unsigned)d->height) // overflow
+		return;
+
+	unsigned tmpBufferPosition = 0;
+	unsigned tmpDIBImageSize = tmpPixelSize * 4;
+	if (tmpPixelSize > tmpDIBImageSize) // overflow !!!
+		return;
+
+	unsigned tmpDIBOffsetBits = 14 + 40;
+	unsigned tmpDIBFileSize = tmpDIBOffsetBits + tmpDIBImageSize;
+	if (tmpDIBImageSize > tmpDIBFileSize) // overflow !!!
+		return;
+
+	char *tmpDIBBuffer = new char[tmpDIBFileSize];
+
+	// Create DIB file header
+	writeU16(tmpDIBBuffer, tmpBufferPosition, 0x4D42);  // Type
+	writeU32(tmpDIBBuffer, tmpBufferPosition, tmpDIBFileSize); // Size
+	writeU16(tmpDIBBuffer, tmpBufferPosition, 0); // Reserved1
+	writeU16(tmpDIBBuffer, tmpBufferPosition, 0); // Reserved2
+	writeU32(tmpDIBBuffer, tmpBufferPosition, tmpDIBOffsetBits); // OffsetBits
+	
+	WPG_DEBUG_MSG(("WPGBitmap: DIB file header end = %i\n", tmpBufferPosition - 1));
+
+	// Create DIB Info header
+	writeU32(tmpDIBBuffer, tmpBufferPosition, 40); // Size
+	writeU32(tmpDIBBuffer, tmpBufferPosition, width());  // Width
+	writeU32(tmpDIBBuffer, tmpBufferPosition, height()); // Height
+	writeU16(tmpDIBBuffer, tmpBufferPosition, 1); // Planes
+	writeU16(tmpDIBBuffer, tmpBufferPosition, 32); // BitCount 
+	writeU32(tmpDIBBuffer, tmpBufferPosition, 0); // Compression
+	writeU32(tmpDIBBuffer, tmpBufferPosition, tmpDIBImageSize); // SizeImage
+	writeU32(tmpDIBBuffer, tmpBufferPosition, 0); // XPelsPerMeter
+	writeU32(tmpDIBBuffer, tmpBufferPosition, 0); // YPelsPerMeter
+	writeU32(tmpDIBBuffer, tmpBufferPosition, 0); // ColorsUsed
+	writeU32(tmpDIBBuffer, tmpBufferPosition, 0); // ColorsImportant
+	
+	WPG_DEBUG_MSG(("WPGBitmap: DIB info header end = %i\n", tmpBufferPosition - 1));
+
+	// Write DIB Image data
+	
+	int i = 0; int j = 0;
+	if (d->vFlip)
+		for	(i = 0; i < d->height && tmpBufferPosition < tmpDIBFileSize; i++)
+		{
+			if (d->hFlip)
+				for (j = d->width - 1; j >= 0 && tmpBufferPosition < tmpDIBFileSize; j--)
+				{
+					writeU8(tmpDIBBuffer, tmpBufferPosition, d->pixels[i*d->width + j].blue);
+					writeU8(tmpDIBBuffer, tmpBufferPosition, d->pixels[i*d->width + j].green);
+					writeU8(tmpDIBBuffer, tmpBufferPosition, d->pixels[i*d->width + j].red);
+					writeU8(tmpDIBBuffer, tmpBufferPosition, d->pixels[i*d->width + j].alpha);
+				}
+			else
+				for (int j = 0; j < d->width && tmpBufferPosition < tmpDIBFileSize; j++)
+				{
+					writeU8(tmpDIBBuffer, tmpBufferPosition, d->pixels[i*d->width + j].blue);
+					writeU8(tmpDIBBuffer, tmpBufferPosition, d->pixels[i*d->width + j].green);
+					writeU8(tmpDIBBuffer, tmpBufferPosition, d->pixels[i*d->width + j].red);
+					writeU8(tmpDIBBuffer, tmpBufferPosition, d->pixels[i*d->width + j].alpha);
+				}
+		}
+	else
+		for (int i = d->height - 1; i >= 0 && tmpBufferPosition < tmpDIBFileSize; i--)
+		{
+			if (d->hFlip)
+				for (j = d->width - 1; j >= 0 && tmpBufferPosition < tmpDIBFileSize; j--)
+				{
+					writeU8(tmpDIBBuffer, tmpBufferPosition, d->pixels[i*d->width + j].blue);
+					writeU8(tmpDIBBuffer, tmpBufferPosition, d->pixels[i*d->width + j].green);
+					writeU8(tmpDIBBuffer, tmpBufferPosition, d->pixels[i*d->width + j].red);
+					writeU8(tmpDIBBuffer, tmpBufferPosition, d->pixels[i*d->width + j].alpha);
+				}
+			else
+				for (int j = 0; j < d->width && tmpBufferPosition < tmpDIBFileSize; j++)
+				{
+					writeU8(tmpDIBBuffer, tmpBufferPosition, d->pixels[i*d->width + j].blue);
+					writeU8(tmpDIBBuffer, tmpBufferPosition, d->pixels[i*d->width + j].green);
+					writeU8(tmpDIBBuffer, tmpBufferPosition, d->pixels[i*d->width + j].red);
+					writeU8(tmpDIBBuffer, tmpBufferPosition, d->pixels[i*d->width + j].alpha);
+				}
+		}
+
+	WPG_DEBUG_MSG(("WPGBitmap: DIB file size = %i\n", tmpBufferPosition - 1));
+
+	base64Encode(bmp, tmpDIBBuffer, tmpDIBFileSize);
+	
+	// temporary for debug - dump the binary bmp (need to have write access in the current directory
+#if DUMP_BITMAP
+	std::ostringstream filename;
+	filename << "binarydump" << bitmapId++ << ".bmp";
+	FILE *f = fopen("binarydump.bmp", "wb");
+	if (f)
+	{
+		for (unsigned k = 0; k < tmpDIBFileSize; k++)
+			fprintf(f, "%c",tmpDIBBuffer[k]);
+		fclose(f);
+	}
+#endif
+
+	// Cleanup things before returning
+	delete [] tmpDIBBuffer;
+}
+
+void libwpg::WPGBitmap::writeU16(char *buffer, unsigned &position, const int value)
+{
+	buffer[position++] = (char)(value & 0xFF);
+	buffer[position++] = (char)((value >> 8) & 0xFF);
+}
+
+void libwpg::WPGBitmap::writeU32(char *buffer, unsigned &position, const int value)
+{
+	buffer[position++] = (char)(value & 0xFF);
+	buffer[position++] = (char)((value >> 8) & 0xFF);
+	buffer[position++] = (char)((value >> 16) & 0xFF);
+	buffer[position++] = (char)((value >> 24) & 0xFF);
+}
+
+void libwpg::WPGBitmap::writeU8(char *buffer, unsigned &position, const int value)
+{
+	buffer[position++] = (char)(value & 0xFF);
+}
+
+void libwpg::WPGBitmap::base64Encode(WPGString& base64, const char *data, const int len)
+{
+	static const char* base64Chars =
+		"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+	char tempCharsToEncode[3];
+	int i = 0; int j = 0; int modifiedLen;
+	if (len % 3)
+		modifiedLen = 3 * ((int)(len / 3) + 1);
+	else
+		modifiedLen = len;
+	
+	bool shouldIexit = false;	
+	for (; i < modifiedLen; i++)
+	{
+		if (i < len)
+			tempCharsToEncode[j++] = data[i];
+		else
+		{
+			tempCharsToEncode[j++] = '\0';
+			shouldIexit = true;
+		}
+		if (shouldIexit)
+		{
+			if (j == 3)
+			{
+				base64.append(base64Chars[(tempCharsToEncode[0] & 0xfc) >> 2]);
+				base64.append(base64Chars[((tempCharsToEncode[0] & 0x03) << 4) | ((tempCharsToEncode[1] & 0xf0) >> 4)]);
+				base64.append(base64Chars[((tempCharsToEncode[1] & 0x0f) << 2) | ((tempCharsToEncode[2] & 0xc0) >> 6)]);
+				base64.append('=');
+				break;
+			}
+			if (j == 2)
+			{
+				base64.append(base64Chars[(tempCharsToEncode[0] & 0xfc) >> 2]);
+				base64.append(base64Chars[((tempCharsToEncode[0] & 0x03) << 4) | ((tempCharsToEncode[1] & 0xf0) >> 4)]);
+				base64.append('='); base64.append('=');
+				break;
+			}
+		}
+		else if (j == 3)
+		{
+			base64.append(base64Chars[(tempCharsToEncode[0] & 0xfc) >> 2]);
+			base64.append(base64Chars[((tempCharsToEncode[0] & 0x03) << 4) | ((tempCharsToEncode[1] & 0xf0) >> 4)]);
+			base64.append(base64Chars[((tempCharsToEncode[1] & 0x0f) << 2) | ((tempCharsToEncode[2] & 0xc0) >> 6)]);
+			base64.append(base64Chars[tempCharsToEncode[2] & 0x3f]);
+			j = 0;
+		}
+	}
+}
Index: scribus/plugins/wpgimplugin/wpg/WPG1Parser.cpp
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPG1Parser.cpp	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPG1Parser.cpp	(revision 13903)
@@ -0,0 +1,861 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ * Copyright (C) 2005 Fridrich Strba (fridrich.strba at bluewin.ch)
+ * Copyright (C) 2004 Marc Oude Kotte (marc at solcon.nl)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "WPG1Parser.h"
+#include "WPGPaintInterface.h"
+#include "libwpg_utils.h"
+
+static const unsigned char defaultWPG1PaletteRed[] = {
+	0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7F, 0x7F,
+	0xC0, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x00, 0x14, 0x20, 0x2C, 0x38, 0x45, 0x51, 0x61,
+	0x71, 0x82, 0x92, 0xA2, 0xB6, 0xCB, 0xE3, 0xFF,
+	0x00, 0x41, 0x7D, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0x7D, 0x41,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x7D, 0x9E, 0xBE, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xBE, 0x9E,
+	0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D,
+	0xB6, 0xC7, 0xDB, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0xDB, 0xC7,
+	0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
+	0x00, 0x1C, 0x38, 0x55, 0x71, 0x71, 0x71, 0x71,
+	0x71, 0x71, 0x71, 0x71, 0x71, 0x55, 0x38, 0x1C,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x38, 0x45, 0x55, 0x61, 0x71, 0x71, 0x71, 0x71,
+	0x71, 0x71, 0x71, 0x71, 0x71, 0x61, 0x55, 0x45,
+	0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+	0x51, 0x59, 0x61, 0x69, 0x71, 0x71, 0x71, 0x71,
+	0x71, 0x71, 0x71, 0x71, 0x71, 0x69, 0x61, 0x59,
+	0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+	0x00, 0x10, 0x20, 0x30, 0x41, 0x41, 0x41, 0x41,
+	0x41, 0x41, 0x41, 0x41, 0x41, 0x30, 0x20, 0x10,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x20, 0x28, 0x30, 0x38, 0x41, 0x41, 0x41, 0x41,
+	0x41, 0x41, 0x41, 0x41, 0x41, 0x38, 0x30, 0x28,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x3C, 0x30, 0x34, 0x3C, 0x41, 0x41, 0x41, 0x41,
+	0x41, 0x41, 0x41, 0x41, 0x41, 0x3C, 0x34, 0x30,
+	0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const unsigned char defaultWPG1PaletteGreen[] = {
+	0x00, 0x00, 0x7F, 0x7F, 0x00, 0x00, 0x3F, 0x7F,
+	0xC0, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
+	0x00, 0x14, 0x20, 0x2C, 0x38, 0x45, 0x51, 0x61,
+	0x71, 0x82, 0x92, 0xA2, 0xB6, 0xCB, 0xE3, 0xFF,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x41, 0x7D, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0x7D, 0x41,
+	0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D,
+	0x7D, 0x9E, 0xBE, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xBE, 0x9E,
+	0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
+	0xB6, 0xC7, 0xDB, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0xDB, 0xC7,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x1C, 0x38, 0x55, 0x71, 0x71, 0x71, 0x71,
+	0x71, 0x71, 0x71, 0x71, 0x71, 0x55, 0x38, 0x1C,
+	0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+	0x38, 0x45, 0x55, 0x61, 0x71, 0x71, 0x71, 0x71,
+	0x71, 0x71, 0x71, 0x71, 0x71, 0x61, 0x55, 0x45,
+	0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+	0x51, 0x59, 0x61, 0x69, 0x71, 0x71, 0x71, 0x71,
+	0x71, 0x71, 0x71, 0x71, 0x71, 0x69, 0x61, 0x59,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x10, 0x20, 0x30, 0x41, 0x41, 0x41, 0x41,
+	0x41, 0x41, 0x41, 0x41, 0x41, 0x30, 0x20, 0x10,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x28, 0x30, 0x38, 0x41, 0x41, 0x41, 0x41,
+	0x41, 0x41, 0x41, 0x41, 0x41, 0x38, 0x30, 0x28,
+	0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C,
+	0x3C, 0x30, 0x34, 0x3C, 0x41, 0x41, 0x41, 0x41,
+	0x41, 0x41, 0x41, 0x41, 0x41, 0x3C, 0x34, 0x30,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const unsigned char defaultWPG1PaletteBlue[] = {
+	0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F,
+	0xC0, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
+	0x00, 0x14, 0x20, 0x2C, 0x38, 0x45, 0x51, 0x61,
+	0x71, 0x82, 0x92, 0xA2, 0xB6, 0xCB, 0xE3, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0x7D, 0x41,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x41, 0x7D, 0xBE, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xBE, 0x9E,
+	0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D,
+	0x7D, 0x9E, 0xBE, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0xDB, 0xC7,
+	0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
+	0xB6, 0xC7, 0xDB, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x71, 0x71, 0x71, 0x71, 0x71, 0x55, 0x38, 0x1C,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x1C, 0x38, 0x55, 0x71, 0x71, 0x71, 0x71,
+	0x71, 0x71, 0x71, 0x71, 0x71, 0x61, 0x55, 0x45,
+	0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+	0x38, 0x45, 0x55, 0x61, 0x71, 0x71, 0x71, 0x71,
+	0x71, 0x71, 0x71, 0x71, 0x71, 0x69, 0x61, 0x59,
+	0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
+	0x51, 0x59, 0x61, 0x69, 0x71, 0x71, 0x71, 0x71,
+	0x41, 0x41, 0x41, 0x41, 0x41, 0x30, 0x20, 0x10,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x10, 0x20, 0x30, 0x41, 0x41, 0x41, 0x41,
+	0x41, 0x41, 0x41, 0x41, 0x41, 0x38, 0x30, 0x28,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	0x20, 0x28, 0x30, 0x38, 0x41, 0x41, 0x41, 0x41,
+	0x41, 0x41, 0x41, 0x41, 0x41, 0x3C, 0x34, 0x30,
+	0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C,
+	0x2C, 0x30, 0x34, 0x3C, 0x41, 0x41, 0x41, 0x41,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+
+WPG1Parser::WPG1Parser(WPXInputStream *input, libwpg::WPGPaintInterface* painter):
+	WPGXParser(input, painter),
+	m_recordLength(0), m_recordEnd(0),
+	m_success(true), m_exit(false), m_graphicsStarted(false),
+	m_width(0), m_height(0), 
+	m_pen(libwpg::WPGPen()), m_brush(libwpg::WPGBrush())
+{
+}
+
+bool WPG1Parser::parse()
+{
+	typedef void (WPG1Parser::*Method)();
+
+	struct RecordHandler
+	{
+		int type;
+		const char *name;
+		Method handler;
+	};
+
+	static const struct RecordHandler handlers[] =
+	{
+		{ 0x01, "Fill Attributes",           &WPG1Parser::handleFillAttributes },	 
+		{ 0x02, "Line Attributes",           &WPG1Parser::handleLineAttributes },	 
+		{ 0x03, "Marker Atttibutes",         0 },	 
+		{ 0x04, "Polymarker",                0 },	 
+		{ 0x05, "Line",                      &WPG1Parser::handleLine },	 
+		{ 0x06, "Polyline",                  &WPG1Parser::handlePolyline },	 
+		{ 0x07, "Rectangle",                 &WPG1Parser::handleRectangle },	 
+		{ 0x08, "Polygon",                   &WPG1Parser::handlePolygon },	 
+		{ 0x09, "Ellipse",                   &WPG1Parser::handleEllipse },	 
+		{ 0x0a, "Reserved",                  0 },	 
+		{ 0x0b, "Bitmap (Type 1)",           &WPG1Parser::handleBitmapTypeOne },	 
+		{ 0x0c, "Graphics Text (Type 1)",    0 },	 
+		{ 0x0d, "Grephics Text Attributes",  0 },	 
+		{ 0x0e, "Colormap",                  &WPG1Parser::handleColormap },
+		{ 0x0f, "Start WPG",                 &WPG1Parser::handleStartWPG },
+		{ 0x10, "End WPG",                   &WPG1Parser::handleEndWPG },
+		{ 0x11, "Postscript Data (Type 1)",  &WPG1Parser::handlePostscriptTypeOne },	 
+		{ 0x12, "Output Attributes",         0 },	 
+		{ 0x13, "Curved Polyline",           &WPG1Parser::handleCurvedPolyline },	 
+		{ 0x14, "Bitmap (Type 2)",           &WPG1Parser::handleBitmapTypeTwo },	 
+		{ 0x15, "Start Figure",              0 },	 
+		{ 0x16, "Start Chart",               0 },	 
+		{ 0x17, "Planperfect Data",          0 },	 
+		{ 0x18, "Graphics Text (Type 2)",    0 },	 
+		{ 0x19, "Start WPG (Type 2)",        0 },	 
+		{ 0x1a, "Graphics Text (Type 3)",    0 },	 
+		{ 0x1b, "Postscript Data (Type 2)",  &WPG1Parser::handlePostscriptTypeTwo },	 
+		{ 0x00, 0, 0 } // end marker
+	};	 
+
+	// initialization
+	m_recordLength = 0;
+	m_recordEnd = 0;
+	m_success = true;
+	m_exit = false;
+	m_graphicsStarted = false;
+	
+	// default style
+	m_pen.foreColor = libwpg::WPGColor(0,0,0);
+	m_pen.backColor = libwpg::WPGColor(0,0,0);
+	m_pen.width = 0.001;
+	m_pen.height = 0.001;
+	m_pen.solid = true;
+	m_pen.dashArray = libwpg::WPGDashArray();
+	m_brush.foreColor = libwpg::WPGColor(0,0,0);
+	m_brush.backColor = libwpg::WPGColor(0,0,0);
+	resetPalette();
+
+	while(!m_input->atEOS())
+	{
+#ifdef DEBUG
+		long recordPos = m_input->tell();
+#endif
+		int recordType = readU8();
+		if (recordType == 0)
+			break;
+		m_recordLength = readVariableLengthInteger();
+		m_recordEnd = m_input->tell() + m_recordLength - 1;
+
+		// search function to handler this record
+		int index = -1;
+		for(int i = 0; (index < 0) && handlers[i].name; i++)
+			if(handlers[i].type == recordType)
+				index = i;
+				
+		WPG_DEBUG_MSG(("\n"));
+		if(index < 0)
+			WPG_DEBUG_MSG(("Unknown record type 0x%02x at %li  size %d\n", 
+				recordType, recordPos, m_recordLength));
+		else
+		{
+			Method recordHandler = handlers[index].handler;
+			if(!recordHandler)
+				WPG_DEBUG_MSG(("Record '%s' (ignored) type 0x%02x at %li  size %d\n", 
+					handlers[index].name, recordType, recordPos, m_recordLength));
+			else
+			{
+				WPG_DEBUG_MSG(("Record '%s' type 0x%02x at %li  size %d\n", 
+					handlers[index].name, recordType, recordPos, m_recordLength));
+					
+				// invoke the handler for this record
+				(this->*recordHandler)();
+			}
+		}
+
+		//if(m_input->tell() > m_recordEnd+1)
+		{
+			//WPG_DEBUG_MSG(("Record 0x%x consumes more bytes than necessary!\n", recordType));
+			WPG_DEBUG_MSG(("Current stream position: %li\n", m_input->tell()));
+		}
+	
+		if(m_exit) break;
+		
+		m_input->seek(m_recordEnd+1, WPX_SEEK_SET);
+	}
+
+	if (!m_exit)
+		handleEndWPG();
+
+	return m_success;
+}
+
+void WPG1Parser::handleStartWPG()
+{
+	if (m_graphicsStarted)
+	{
+		handleEndWPG();
+		return;
+	}
+	// unsigned char version = readU8();
+	// unsigned char bitFlags = readU8();
+	m_input->seek(2, WPX_SEEK_CUR);
+	m_width = readU16();
+	m_height = readU16();
+
+	double width = (double)m_width / 1200.0;
+	double height = (double)m_height / 1200.0;
+	m_painter->startGraphics(width, height);
+	m_graphicsStarted = true;
+
+	WPG_DEBUG_MSG(("StartWPG\n"));
+}
+
+void WPG1Parser::handleEndWPG()
+{
+	if (!m_graphicsStarted)
+		return;
+	m_painter->endGraphics();
+	m_exit = true;
+	
+	WPG_DEBUG_MSG(("EndWPG\n"));
+}
+
+void WPG1Parser::handleColormap()
+{
+	if (!m_graphicsStarted)
+		return;
+	unsigned startIndex = readU16();
+	unsigned numEntries = readU16();
+	if (startIndex > 255 || numEntries > 256 || startIndex + numEntries > 256)
+		return;
+
+	WPG_DEBUG_MSG(("Colormap\n"));
+	for(unsigned int i = 0; i < numEntries; i++)
+	{
+		libwpg::WPGColor color;
+		color.red = readU8();
+		color.green = readU8();
+		color.blue = readU8();
+		m_colorPalette[startIndex+i] = color;
+		WPG_DEBUG_MSG(("Index#%d: RGB %d %d %d\n", startIndex+i, color.red, color.green, color.blue));
+	}
+}
+
+void WPG1Parser::handleFillAttributes()
+{
+	if (!m_graphicsStarted)
+		return;
+	unsigned char style = readU8();
+	unsigned char color = readU8();
+
+	if(style == 0)
+		m_brush.style = libwpg::WPGBrush::NoBrush;
+	if(style == 1)
+		m_brush.style = libwpg::WPGBrush::Solid;
+
+	m_brush.foreColor = m_colorPalette[color];
+
+	WPG_DEBUG_MSG(("Fill Attributes\n"));
+	WPG_DEBUG_MSG(("         Fill style: %d\n", style));
+	WPG_DEBUG_MSG(("   Fill color index: %d\n", color));
+}
+
+void WPG1Parser::handleLineAttributes()
+{
+	if (!m_graphicsStarted)
+		return;
+	unsigned char style = readU8();
+	unsigned char color = readU8();
+	unsigned int width = readU16();
+
+	m_pen.solid = style != 0;
+	m_pen.foreColor = m_colorPalette[color];
+	if (!width && m_pen.solid)
+		m_pen.width = 0.001;
+	else
+		m_pen.width = (double)width / 1200.0;
+
+	WPG_DEBUG_MSG(("Line Attributes\n"));
+	WPG_DEBUG_MSG(("         Line style: %d\n", style));
+	WPG_DEBUG_MSG(("   Line color index: %d\n", color));
+	WPG_DEBUG_MSG(("         Line width: %d\n", width));
+}
+
+void WPG1Parser::handleLine()
+{
+	if (!m_graphicsStarted)
+		return;
+	int sx = readS16();
+	int sy = readS16();
+	int ex = readS16();
+	int ey = readS16();
+
+	libwpg::WPGPointArray points;
+	points.add(libwpg::WPGPoint((double)sx/1200.0, (double)(m_height-sy)/1200.0));
+	points.add(libwpg::WPGPoint((double)ex/1200.0, (double)(m_height-ey)/1200.0));
+
+	m_painter->setBrush(m_brush);
+	m_painter->setPen(m_pen);
+	m_painter->drawPolygon(points);
+
+	WPG_DEBUG_MSG(("Line\n"));
+	WPG_DEBUG_MSG(("    Starting point: %d,%d\n", sx, sy));
+	WPG_DEBUG_MSG(("         End point: %d,%d\n", ex, ey));
+}
+
+void WPG1Parser::handlePolyline()
+{
+	if (!m_graphicsStarted)
+		return;
+	unsigned int count = readU16();
+
+	libwpg::WPGPointArray points;
+	for(unsigned int i = 0; i < count; i++ )
+	{
+		long x = readS16();
+		long y = readS16();
+		points.add(libwpg::WPGPoint((double)x/1200.0, (double)(m_height-y)/1200.0));
+	}
+
+	m_painter->setBrush(libwpg::WPGBrush()); // not filled
+	m_painter->setPen(m_pen);
+	m_painter->drawPolygon(points);
+
+	WPG_DEBUG_MSG(("Polyline\n"));
+}
+
+void WPG1Parser::handleRectangle()
+{
+	if (!m_graphicsStarted)
+		return;
+	int x = readS16();
+	int y = readS16();
+	int w = readS16();
+	int h = readS16();
+
+	libwpg::WPGRect rect;
+	rect.x1 = (double)x/1200.0;
+	// in WPG, we have the coordinate of lower left point, in SVG-ish coordinates we have to get upper left
+	rect.y1 = (double)(m_height - h - y)/1200.0;
+	rect.x2 = rect.x1 + (double)w/1200.0;
+	rect.y2 = rect.y1 + (double)h/1200.0;
+
+	m_painter->setBrush(m_brush);
+	m_painter->setPen(m_pen);
+	m_painter->drawRectangle(rect, 0, 0);
+
+	WPG_DEBUG_MSG(("Line\n"));
+	WPG_DEBUG_MSG(("    Corner point: %d,%d\n", x, y));
+	WPG_DEBUG_MSG(("           Width: %d\n", w));
+	WPG_DEBUG_MSG(("          Height: %d\n", h));
+}
+
+void WPG1Parser::handlePolygon()
+{
+	if (!m_graphicsStarted)
+		return;
+	unsigned int count = readU16();
+
+	libwpg::WPGPointArray points;
+	for(unsigned int i = 0; i < count; i++ )
+	{
+		long x = readS16();
+		long y = readS16();
+		points.add(libwpg::WPGPoint((double)x/1200.0, (double)(m_height-y)/1200.0));
+	}
+
+	m_painter->setBrush(m_brush);
+	m_painter->setPen(m_pen);
+	m_painter->drawPolygon(points);
+
+	WPG_DEBUG_MSG(("Polygon\n"));
+}
+
+void WPG1Parser::handleEllipse()
+{
+	if (!m_graphicsStarted)
+		return;
+	int cx = readS16();
+	int cy = readS16();
+	int rx = readS16();
+	int ry = readS16();
+	readS16();
+	readS16();
+	readS16();
+	readS16();
+/*
+	int rotation = readS16();
+	int beginAngle = readS16();
+	int endAngle = readS16();
+	unsigned flags = readU16();
+*/
+	libwpg::WPGPoint center;
+	center.x = (double)cx/1200.0;
+	center.y = (double)(m_height-cy)/1200.0;
+
+	double radx = (double)rx/1200.0;
+	double rady = (double)ry/1200.0;
+
+	m_painter->setBrush(m_brush);
+	m_painter->setPen(m_pen);
+	m_painter->drawEllipse(center, radx, rady);
+
+	WPG_DEBUG_MSG(("Ellipse\n"));
+	WPG_DEBUG_MSG(("    Center point: %d,%d\n", cx, cy));
+	WPG_DEBUG_MSG(("        Radius x: %d\n", rx));
+	WPG_DEBUG_MSG(("        Radius y: %d\n", ry));
+}
+
+void WPG1Parser::handleCurvedPolyline()
+{
+	if (!m_graphicsStarted)
+		return;
+	readU32();
+	unsigned int count = readU16();
+	if (!count)
+		return;
+	libwpg::WPGPath path;
+	path.closed = false;
+	path.framed = true;
+	path.filled = true;
+	long xInitial = readS16();
+	long yInitial = readS16();
+	path.moveTo(libwpg::WPGPoint((double)xInitial/1200.0, (double)(m_height-yInitial)/1200.0));
+	for (unsigned i = 1; i < (count-1)/3; i++)
+	{
+		long xControl1 = readS16();
+		long yControl1 = readS16();
+		long xControl2 = readS16();
+		long yControl2 = readS16();
+		long xCoordinate = readS16();
+		long yCoordinate = readS16();
+		path.curveTo(libwpg::WPGPoint((double)xControl1/1200.0, (double)(m_height-yControl1)/1200.0),
+			libwpg::WPGPoint((double)xControl2/1200.0, (double)(m_height-yControl2)/1200.0),
+			libwpg::WPGPoint((double)xCoordinate/1200.0, (double)(m_height-yCoordinate)/1200.0));
+	}
+	
+	m_painter->setBrush(path.closed ? m_brush : libwpg::WPGBrush());
+	m_painter->setPen(m_pen);
+	m_painter->drawPath(path);
+	
+	WPG_DEBUG_MSG(("Curved Polyline\n"));
+}
+
+void WPG1Parser::decodeRLE(std::vector<unsigned char>& buffer, unsigned width, unsigned height, unsigned depth)
+{
+	buffer.clear();
+
+	// This are the known depth values for WPG1, no point to try to decode others since they are likely to indicate corruption
+	if (depth != 8 && depth != 4 && depth != 2 && depth != 1)
+		return;
+
+	// round to the next byte
+	unsigned scanline_width = (width * depth + 7)/8;
+	unsigned tmpBufferSize = scanline_width * height;
+	WPG_DEBUG_MSG(("Scanline width: %d\n", scanline_width));
+	WPG_DEBUG_MSG(("Output size: %d\n", scanline_width * height));
+
+	WPG_DEBUG_MSG(("Decoding RLE data\n"));
+
+	buffer.reserve(tmpBufferSize);
+ 	while (m_input->tell() < m_recordEnd && !m_input->atEOS() && buffer.size() < tmpBufferSize)
+	{
+		unsigned char opcode = readU8();
+
+		if(opcode & 0x80)
+		{
+			// run of byte
+			int count = (int)(opcode & 0x7f);
+			unsigned char pixel = (count > 0) ? readU8() : 0xff;
+			if(count == 0)
+				count = (int)readU8();
+			for( ; count ; --count)
+				buffer.push_back( pixel );
+		}
+		else
+		{
+			int count = (int)(opcode & 0x7f);
+			if(count > 0)
+			{
+				// literal byte copy
+				for( ; count ; --count)
+					buffer.push_back( readU8() );
+			}
+			else
+			{
+				// copy entire scan line
+				count = (int)readU8();
+				if (buffer.size() < scanline_width )
+				{
+					WPG_DEBUG_MSG(("Cannot copy the scanline, not enough data %li\n", (long)buffer.size()));
+					break;
+				}
+				unsigned raster_source = buffer.size() - scanline_width;
+				for( ; count; --count)
+					for(unsigned r = 0; r < scanline_width ; r++)
+					{
+						unsigned char pixel = buffer[raster_source + r];
+						buffer.push_back( pixel );
+					}
+			}
+		}
+	}
+	WPG_DEBUG_MSG(("Finish decoding RLE data\n"));
+	WPG_DEBUG_MSG(("Buffer length: %li\n", (long)buffer.size()));
+	
+	while (buffer.size() < tmpBufferSize)
+		buffer.push_back(0);
+}
+
+void WPG1Parser::fillPixels(libwpg::WPGBitmap& bitmap, const unsigned char* buffer, unsigned width, unsigned height, unsigned depth)
+{
+	// sanity
+	if(!buffer)
+		return;
+
+	if (depth != 8 && depth != 4 && depth != 2 && depth != 1)
+		return;
+
+	// round to the next byte
+	unsigned scanline_width = (width * depth + 7)/8;
+
+	// 1-bit image: black and white
+	if(depth == 1)
+	{
+		libwpg::WPGColor black(0, 0, 0);
+		libwpg::WPGColor white(255, 255, 255);
+		for(unsigned y = 0; y < height; y++)
+		{
+			const unsigned char* buf = buffer + y * scanline_width;
+			for(unsigned x = 0; x < width; x++)
+				if(buf[x/8] & (0x80 >> (x & 7)))
+					bitmap.setPixel(x, y, white);
+				else
+					bitmap.setPixel(x, y, black);
+		}
+	}
+	// 2-bit image: 4-color bitmap (indexed)
+	else if(depth == 2)
+	{
+		unsigned i = 0;
+		for (unsigned y = 0; y < height; y++)
+		for (unsigned x = 0; x < width; x++, i++)
+		{
+			if ((x==0) && (i % 4 != 0))
+				i = (i/4 + 1) * 4;
+			unsigned index = ((buffer[i/4] & (0x03 << 2*(3 - (i % 4)))) >> 2*(3 - (i % 4)));
+			const libwpg::WPGColor& color = m_colorPalette[index];
+			bitmap.setPixel(x, y, color);
+		}
+	}
+	// 4 -bit image: 16-colour bitmap (indexed)
+	else if(depth == 4)
+	{
+		unsigned i = 0;
+		for (unsigned y = 0; y < height; y++)
+		for (unsigned x = 0; x < width; x++, i++)
+		{
+			if ((x==0) && (i % 2 != 0))
+				i = (i/2 + 1) * 2;
+			unsigned index = ((buffer[i/2] & (0x0f << 4*(1 - (i % 2)))) >> 4*(1 - (i % 2)));
+			const libwpg::WPGColor& color = m_colorPalette[index];
+			bitmap.setPixel(x, y, color);
+		}
+	}
+	// 8-bit image: 256-colour image (indexed)
+	else if(depth == 8)
+	{
+		for(unsigned y = 0; y < height; y++)
+		{
+			const unsigned char* buf = buffer + y * scanline_width;
+			for(unsigned x = 0; x < width; x++)
+			{
+				const libwpg::WPGColor& color = m_colorPalette[buf[x]];
+				bitmap.setPixel(x, y, color);
+			}
+		}
+
+	}
+
+	// debugging only
+	if(buffer && 0)
+	{
+		for(unsigned x = 0; x < width; x++)
+		for(unsigned y = 0; y < height; y++)
+		{
+			libwpg::WPGColor color = bitmap.pixel(x,y);
+			WPG_DEBUG_MSG((" pixel at %d, %d: %3d %3d %3d\n", x, y, color.red, color.green, color.blue));
+		}
+	}
+}
+
+void WPG1Parser::handleBitmapTypeOne()
+{
+	if (!m_graphicsStarted)
+		return;
+	int width = readS16();
+	int height = readS16();
+	int depth = readS16();
+	int hres = readS16();
+	int vres = readS16();
+	
+	WPG_DEBUG_MSG(("Bitmap\n"));
+	WPG_DEBUG_MSG(("                Width: %d\n", width));
+	WPG_DEBUG_MSG(("               Height: %d\n", height));
+	WPG_DEBUG_MSG(("                Depth: %d\n", depth));
+	WPG_DEBUG_MSG(("Horizontal resolution: %d\n", hres));
+	WPG_DEBUG_MSG(("  Vertical resolution: %d\n", vres));
+
+	// if this happens, likely corruption, bail out.
+	if (depth != 1 && depth != 2 && depth != 4 && depth != 8)
+		return;
+		
+	// Sanity checks
+	if(hres <= 0)
+		hres = 1200;
+	if(vres <= 0)
+		vres = 1200;
+	if (width < 0)
+		width = 0;
+	if (height < 0)
+		height = 0;
+	if (depth < 0)
+		depth = 0;
+
+	// Bitmap Type 1 does not specify position
+	// Assume on the corner (0,0)
+	libwpg::WPGBitmap bitmap(width, height);
+	bitmap.rect.x1 = 0;
+	bitmap.rect.y1 = 0;
+	bitmap.rect.x2 = (double)width/(double)hres;
+	bitmap.rect.y2 = (double)height/(double)vres;
+
+	std::vector<unsigned char> buffer;
+	decodeRLE(buffer, width, height, depth);
+	if (buffer.size() && buffer.size() == (size_t)((width*depth + 7)/8)*height)
+	{
+		fillPixels(bitmap, &buffer[0], width, height, depth);
+		m_painter->drawBitmap(bitmap, hres, vres);
+	}
+}
+
+void WPG1Parser::handleBitmapTypeTwo()
+{
+	if (!m_graphicsStarted)
+		return;
+	int rotation = readS16();
+	int x1 = readS16();
+	int y1 = readS16();
+	int x2 = readS16();
+	int y2 = readS16();
+	int width = readS16();
+	int height = readS16();
+	int depth = readS16();
+	int hres = readS16();
+	int vres = readS16();
+	
+	WPG_DEBUG_MSG(("Bitmap\n"));
+	WPG_DEBUG_MSG(("       Rotation Angle: %d\n", rotation));
+	WPG_DEBUG_MSG(("      Top left corner: %d,%d\n", x1, y1));
+	WPG_DEBUG_MSG(("  Bottom right corner: %d,%d\n", x2, y2));
+	WPG_DEBUG_MSG(("                Width: %d\n", width));
+	WPG_DEBUG_MSG(("               Height: %d\n", height));
+	WPG_DEBUG_MSG(("                Depth: %d\n", depth));
+	WPG_DEBUG_MSG(("Horizontal resolution: %d\n", hres));
+	WPG_DEBUG_MSG(("  Vertical resolution: %d\n", vres));
+
+	// if this happens, likely corruption, bail out.
+	if (rotation < 0 || rotation > 359)
+		return;
+	if (depth != 1 && depth != 2 && depth != 4 && depth != 8)
+		return;
+		
+	// Sanity checks
+	if(hres <= 0)
+		hres = 1200;
+	if(vres <= 0)
+		vres = 1200;
+	if (width < 0)
+		width = 0;
+	if (height < 0)
+		height = 0;
+	if (depth < 0)
+		depth = 0;
+
+	y1 = m_height - y1;
+	y2 = m_height - y2;
+
+	long xs1 = (x1 <= x2) ? x1 : x2;
+	long xs2 = (x1 <= x2) ? x2 : x1;
+	long ys1 = (y1 <= y2) ? y1 : y2;
+	long ys2 = (y1 <= y2) ? y2 : y1;
+	WPG_DEBUG_MSG(("%li %li   %li %li\n", xs1, ys1, xs2, ys2));
+
+	libwpg::WPGBitmap bitmap(width, height);
+	bitmap.rect.x1 = (double)xs1/1200.0;
+	bitmap.rect.y1 = (double)(ys1)/1200.0;
+	bitmap.rect.x2 = (double)xs2/1200.0;
+	bitmap.rect.y2 = (double)(ys2)/1200.0;
+
+	std::vector<unsigned char> buffer;
+	decodeRLE(buffer, width, height, depth);
+	if (buffer.size() && buffer.size() == (size_t)((width*depth + 7)/8)*height)
+	{
+		fillPixels(bitmap, &buffer[0], width, height, depth);
+		m_painter->drawBitmap(bitmap, hres, vres);
+	}
+}
+
+void WPG1Parser::handlePostscriptTypeOne()
+{
+	if (!m_graphicsStarted)
+		return;
+	long x1 = readS16();
+	long y1 = readS16();
+	long x2 = readS16();
+	long y2 = readS16();
+	libwpg::WPGBinaryData data;
+	data.rect.x1 = (double)x1/72.0;
+	data.rect.y1 = (double)m_height/1200.0 - (double)y1/72.0;
+	data.rect.x2 = (double)x2/72.0;
+	data.rect.y2 = (double)m_height/1200.0 - (double)y2/72.0;
+	
+	data.clear();
+	while (m_input->tell() <= m_recordEnd)
+		data.append((char)readU8());
+	data.mimeType = "application/x-postscript";
+	if (data.size())
+		m_painter->drawImageObject(data);
+}
+
+void WPG1Parser::handlePostscriptTypeTwo()
+{
+	if (!m_graphicsStarted)
+		return;
+#ifdef DEBUG
+	unsigned lengthOfData = readU32();
+	int rotation = readS16();
+#else
+	readU32();
+	readS16();
+#endif
+	int x1 = readS16();
+	int y1 = readS16();
+	int x2 = readS16();
+	int y2 = readS16();
+
+	WPG_DEBUG_MSG(("Postscript (Type 2)\n"));
+	WPG_DEBUG_MSG(("       Length of Data: %d\n", lengthOfData));
+	WPG_DEBUG_MSG(("       Rotation Angle: %d\n", rotation));
+	WPG_DEBUG_MSG(("   Bottom left corner: %d,%d\n", x1, y1));
+	WPG_DEBUG_MSG(("     Top right corner: %d,%d\n", x2, y2));
+
+	y1 = m_height - y1;
+	y2 = m_height - y2;
+
+	long xs1 = (x1 <= x2) ? x1 : x2;
+	long xs2 = (x1 <= x2) ? x2 : x1;
+	long ys1 = (y1 <= y2) ? y1 : y2;
+	long ys2 = (y1 <= y2) ? y2 : y1;
+	WPG_DEBUG_MSG(("%li %li   %li %li\n", xs1, ys1, xs2, ys2));
+
+	libwpg::WPGBinaryData data;
+	data.rect.x1 = (double)xs1/1200.0;
+	data.rect.y1 = (double)(ys1)/1200.0;
+	data.rect.x2 = (double)xs2/1200.0;
+	data.rect.y2 = (double)(ys2)/1200.0;
+	
+	data.mimeType = "image/x-eps";
+
+	m_input->seek(48, WPX_SEEK_CUR);
+	
+	data.clear();
+	while (m_input->tell() <= m_recordEnd)
+		data.append((char)readU8());
+	if (data.size())
+		m_painter->drawImageObject(data);
+}
+
+void WPG1Parser::resetPalette()
+{
+	m_colorPalette.clear();
+	for (int i=0; i<256; i++)
+	{
+		libwpg::WPGColor color;
+		color.red = defaultWPG1PaletteRed[i];
+		color.green = defaultWPG1PaletteGreen[i];
+		color.blue = defaultWPG1PaletteBlue[i];
+		m_colorPalette[i] = color;
+	}
+}
+
Index: scribus/plugins/wpgimplugin/wpg/WPGColor.cpp
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGColor.cpp	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGColor.cpp	(revision 13903)
@@ -0,0 +1,63 @@
+/* libwpg
+ * Copyright (C) 2006 Fridrich Strba (fridrich.strba at bluewin.ch)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "WPGColor.h"
+
+libwpg::WPGColor::WPGColor():
+	red(0),
+	green(0),
+	blue(0),
+	alpha(1)
+{}
+
+libwpg::WPGColor::WPGColor(int r, int g, int b):
+	red(r),
+	green(g),
+	blue(b),
+	alpha(1)
+{}
+
+libwpg::WPGColor::WPGColor(int r, int g, int b, int a):
+	red(r),
+	green(g),
+	blue(b),
+	alpha(a)
+{}
+
+libwpg::WPGColor::WPGColor(const WPGColor& color):
+	red(color.red),
+	green(color.green),
+	blue(color.blue),
+	alpha(color.alpha)
+{}
+
+libwpg::WPGColor& libwpg::WPGColor::operator=(const libwpg::WPGColor& color)
+{
+	red = color.red;
+	green = color.green;
+	blue = color.blue;
+	alpha = color.alpha;
+	return *this;
+}
Index: scribus/plugins/wpgimplugin/wpg/WPG2Parser.cpp
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPG2Parser.cpp	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPG2Parser.cpp	(revision 13903)
@@ -0,0 +1,1912 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ * Copyright (C) 2005-2007 Fridrich Strba (fridrich.strba at bluewin.ch)
+ * Copyright (C) 2004 Marc Oude Kotte (marc at solcon.nl)
+ *
+ * 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; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "WPG2Parser.h"
+#include "WPGPaintInterface.h"
+#include "libwpg_utils.h"
+
+#include <math.h>
+#include <vector>
+#include <sstream>
+
+// MSVC++ 6.0 does not have the macro defined, so we define it
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#define DUMP_BINARY_DATA 0
+
+static const unsigned char defaultWPG2PaletteRed[] = {
+	0x00, 0xFF, 0x7F, 0xBF, 0x00, 0x00, 0x00, 0x7F,
+	0x7F, 0x7F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
+	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+	0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
+	0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE9, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE9, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE9, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x3D, 0x48, 0x53, 0x5E, 0x69, 0x74, 0x7F, 0x8A,
+	0x95, 0xA0, 0xAB, 0xB6, 0xC1, 0xCC, 0xD7, 0xE2,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+	0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+	0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+	0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+	0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+	0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+	0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
+	0x3D, 0x48, 0x53, 0x5E, 0x69, 0x74, 0x7F, 0x8A,
+	0x95, 0xA0, 0xAB, 0xB6, 0xC1, 0xCC, 0xD7, 0xE2,
+	0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE4, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE4, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x33, 0x47, 0x61, 0x73, 0x87, 0x9C, 0xB0, 0xC7,
+	0xCC, 0xD4, 0xDB, 0xE3, 0xE8, 0xF0, 0xF7, 0xFF,
+};
+
+static const unsigned char defaultWPG2PaletteGreen[] = {
+	0x00, 0xFF, 0x7F, 0xBF, 0x00, 0x7F, 0x7F, 0x00,
+	0x00, 0x7F, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF,
+	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+	0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+	0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
+	0x3D, 0x48, 0x53, 0x5E, 0x69, 0x74, 0x7F, 0x8A,
+	0x95, 0xA0, 0xAB, 0xB6, 0xC1, 0xCC, 0xD7, 0xE2,
+	0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE9, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE9, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE9, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE9, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE9, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x56, 0x64, 0x72, 0x80, 0x8E, 0x9C, 0xAA, 0xB1,
+	0xB8, 0xBF, 0xC6, 0xCD, 0xD4, 0xDB, 0xE2, 0xE9,
+	0x2B, 0x32, 0x39, 0x40, 0x47, 0x4E, 0x55, 0x63,
+	0x71, 0x7F, 0x8D, 0x9B, 0xA9, 0xB7, 0xC5, 0xD3,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+	0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+	0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+	0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+	0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
+	0x29, 0x38, 0x45, 0x4F, 0x5C, 0x63, 0x69, 0xD4,
+	0x87, 0x8F, 0x9C, 0xA8, 0xB3, 0xC4, 0xCF, 0xE0,
+};
+
+static const unsigned char defaultWPG2PaletteBlue[] = {
+	0x00, 0xFF, 0x7F, 0xBF, 0x7F, 0x00, 0x7F, 0x00,
+	0x7F, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
+	0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+	0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+	0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+	0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+	0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+	0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+	0x2C, 0x42, 0x58, 0x6E, 0x84, 0x9A, 0xB0, 0xC6,
+	0x3D, 0x48, 0x53, 0x5E, 0x69, 0x74, 0x7F, 0x8A,
+	0x95, 0xA0, 0xAB, 0xB6, 0xC1, 0xCC, 0xD7, 0xE2,
+	0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE9, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x7B, 0x91, 0xA7, 0xB0, 0xD3, 0xE4, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE4, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE4, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE4, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x7B, 0x91, 0xA7, 0xBD, 0xD3, 0xE4, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x3D, 0x48, 0x53, 0x5E, 0x69, 0x74, 0x7F, 0x8A,
+	0x95, 0xA0, 0xAB, 0xB6, 0xC1, 0xCC, 0xD7, 0xE2,
+	0x11, 0x17, 0x1C, 0x24, 0x29, 0x2B, 0x2B, 0x30,
+	0x47, 0x57, 0x69, 0x78, 0x8C, 0x9C, 0xB0, 0xC7,
+};
+
+class WPG2Parser::ObjectCharacterization
+{
+public:
+	bool taper;
+	bool translate;
+	bool skew;
+	bool scale;
+	bool rotate;
+	bool hasObjectId;
+	bool editLock;
+	bool windingRule;
+	bool filled;
+	bool closed;
+	bool framed;
+
+	unsigned long objectId;
+	unsigned long lockFlags;
+	long rotationAngle;
+	long sxcos;
+	long sycos;
+	long kxsin;
+	long kysin;
+	long txinteger;
+	unsigned short txfraction;
+	long tyinteger;
+	unsigned short tyfraction;
+	long px;
+	long py;
+
+	WPG2TransformMatrix matrix;
+
+	ObjectCharacterization():
+		taper(false),
+		translate(false),
+		skew(false),
+		scale(false),
+		rotate(false),
+		hasObjectId(false),
+		editLock(false),
+		windingRule(false),
+		filled(false),
+		closed(false),
+		framed(true),
+		objectId(0),
+		lockFlags(0),
+		rotationAngle(0),
+		sxcos(0),
+		sycos(0),
+		kxsin(0),
+		kysin(0),
+		txinteger(0),
+		txfraction(0),
+		tyinteger(0),
+		tyfraction(0),
+		px(0),
+		py(0),
+		matrix()
+			{}
+};
+
+WPG2Parser::WPG2Parser(WPXInputStream *input, libwpg::WPGPaintInterface* painter):
+	WPGXParser(input, painter),
+	m_recordLength(0),
+	m_recordEnd(0),
+	m_success(true), m_exit(false), m_graphicsStarted(false),
+	m_xres(1200), m_yres(1200),
+	m_xofs(0), m_yofs(0),
+	m_width(0), m_height(0),
+	m_doublePrecision(false),
+	m_pen(),
+	m_brush(),
+	m_penStyles(),
+	m_layerOpened(false), m_layerId(0),
+	m_matrix(),
+	m_gradientAngle(0.0f),
+	m_gradientRef(),
+	m_groupStack(),
+	m_compoundMatrix(),
+	m_compoundWindingRule(false),
+	m_compoundFilled(false),
+	m_compoundFramed(false),
+	m_compoundClosed(false),
+	m_bitmap(),
+	m_binaryData(),
+	m_hFlipped(false),
+	m_vFlipped(false),
+	m_binaryId(0)
+{
+}
+
+bool WPG2Parser::parse()
+{
+	typedef void (WPG2Parser::*Method)();
+
+	struct RecordHandler
+	{
+		int type;
+		const char *name;
+		Method handler;
+	};
+
+	static const struct RecordHandler handlers[] =
+	{
+		{ 0x01, "Start WPG",            &WPG2Parser::handleStartWPG },
+		{ 0x02, "End WPG",              &WPG2Parser::handleEndWPG },
+		{ 0x03, "Form Settings",        0 },     // ignored
+		{ 0x04, "Ruler Settings",       0 },     // ignored
+		{ 0x05, "Grid Settings",        0 },     // ignored
+		{ 0x06, "Layer",                &WPG2Parser::handleLayer },
+		{ 0x08, "Pen Style Definition", &WPG2Parser::handlePenStyleDefinition },
+		{ 0x09, "Pattern Definition",   0 },
+		{ 0x0a, "Comment",              0 },     // ignored
+		{ 0x0b, "Color Transfer",       0 },
+		{ 0x0c, "Color Palette",        &WPG2Parser::handleColorPalette },
+		{ 0x0d, "DP Color Palette",     &WPG2Parser::handleDPColorPalette },
+		{ 0x0e, "Bitmap Data",          &WPG2Parser::handleBitmapData },
+		{ 0x0f, "Text Data",            0 },
+		{ 0x10, "Chart Style",          0 },     // ignored
+		{ 0x11, "Chart Data",           0 },     // ignored
+		{ 0x12, "Object Image",         &WPG2Parser::handleObjectImage },
+		{ 0x15, "Polyline",             &WPG2Parser::handlePolyline },
+		{ 0x16, "Polyspline",           &WPG2Parser::handlePolyspline },
+		{ 0x17, "Polycurve",            &WPG2Parser::handlePolycurve },
+		{ 0x18, "Rectangle",            &WPG2Parser::handleRectangle },
+		{ 0x19, "Arc",                  &WPG2Parser::handleArc },
+		{ 0x1a, "Compound Polygon",     &WPG2Parser::handleCompoundPolygon },
+		{ 0x1b, "Bitmap",               &WPG2Parser::handleBitmap },
+		{ 0x1c, "Text Line",            0 },
+		{ 0x1d, "Text Block",           0 },
+		{ 0x1e, "Text Path",            0 },
+		{ 0x1f, "Chart",                0 },
+		{ 0x20, "Group",                0 },
+		{ 0x21, "Object Capsule",       &WPG2Parser::handleObjectCapsule },
+		{ 0x22, "Font Settings",        0 },
+		{ 0x25, "Pen Fore Color",       &WPG2Parser::handlePenForeColor },
+		{ 0x26, "DP Pen Fore Color",    &WPG2Parser::handleDPPenForeColor },
+		{ 0x27, "Pen Back Color",       &WPG2Parser::handlePenBackColor },
+		{ 0x28, "DP Pen Back Color",    &WPG2Parser::handleDPPenBackColor },
+		{ 0x29, "Pen Style",            &WPG2Parser::handlePenStyle },
+		{ 0x2a, "Pen Pattern",          0 },
+		{ 0x2b, "Pen Size",             &WPG2Parser::handlePenSize },
+		{ 0x2c, "DP Pen Size",          &WPG2Parser::handleDPPenSize  },
+		{ 0x2d, "Line Cap",             0 },
+		{ 0x2e, "Line Join",            0 },
+		{ 0x2f, "Brush Gradient",       &WPG2Parser::handleBrushGradient },
+		{ 0x30, "DP Brush Gradient",    &WPG2Parser::handleDPBrushGradient },
+		{ 0x31, "Brush Fore Color",     &WPG2Parser::handleBrushForeColor },
+		{ 0x32, "DP Brush Fore Color",  &WPG2Parser::handleDPBrushForeColor },
+		{ 0x33, "Brush Back Color",     &WPG2Parser::handleBrushBackColor },
+		{ 0x34, "DP Brush Back Color",  &WPG2Parser::handleDPBrushBackColor },
+		{ 0x35, "Brush Pattern",        &WPG2Parser::handleBrushPattern },
+		{ 0x36, "Horizontal Line",      0 },
+		{ 0x37, "Vertical Line",        0 },
+		{ 0x38, "Poster Settings",      0 },
+		{ 0x39, "Image State",          0 },
+		{ 0x3a, "Envelope Definition",  0 },
+		{ 0x3b, "Envelope",             0 },
+		{ 0x3c, "Texture Definition",   0 },
+		{ 0x3d, "Brush Texture",        0 },
+		{ 0x3e, "Texture Alignment",    0 },
+		{ 0x3f, "Pen Texture ",         0 },
+		{ 0x00, 0, 0 } // end marker
+	};
+	
+	// initialization
+	m_recordLength = 0;
+	m_recordEnd = 0;
+	m_success = true;
+	m_exit = false;
+	m_graphicsStarted = false;
+	m_xres = m_yres = 1200;
+	m_doublePrecision = false;
+	m_layerOpened = false;
+	m_matrix = WPG2TransformMatrix();
+	m_groupStack = std::stack<WPGGroupContext>();
+	m_compoundMatrix = WPG2TransformMatrix();
+	m_compoundWindingRule = false;
+	m_compoundFilled = false;
+	m_compoundFramed = true;
+	m_compoundClosed = false;
+
+	// default style
+	m_pen.foreColor = libwpg::WPGColor(0,0,0);
+	m_pen.backColor = libwpg::WPGColor(0,0,0);
+	m_pen.width = 0.001;
+	m_pen.height = 0.001;
+	m_pen.solid = true;
+	m_pen.dashArray = libwpg::WPGDashArray();
+	m_brush.foreColor = libwpg::WPGColor(0,0,0);
+	m_brush.backColor = libwpg::WPGColor(0,0,0);
+	resetPalette();
+
+	while(!m_input->atEOS())
+	{
+#ifdef DEBUG
+		long recordPos = m_input->tell();
+#endif
+		readU8();
+		int recordType = readU8();
+		if (recordType == 0 || recordType > (int)0x3f)
+			break;
+		int extension = readVariableLengthInteger();
+		m_recordLength = readVariableLengthInteger();
+		m_recordEnd = m_input->tell() + m_recordLength - 1;
+
+		// inside a subgroup, one less sub record
+		if(!m_groupStack.empty())
+			m_groupStack.top().subIndex--;
+
+		// search function to handler this record
+		int index = -1;
+		for(int i = 0; (index < 0) && handlers[i].name; i++)
+			if(handlers[i].type == recordType)
+				index = i;
+
+		WPG_DEBUG_MSG(("\n"));
+		if(index < 0)
+		{
+			WPG_DEBUG_MSG(("Unknown record type 0x%02x at %li  size %d  extension %d\n",
+				recordType, recordPos, m_recordLength, extension));
+		}
+		else
+		{
+			Method recordHandler = handlers[index].handler;
+
+			if(!recordHandler)
+				WPG_DEBUG_MSG(("Record '%s' (ignored) type 0x%02x at %li  size %d  extension %d\n",
+					handlers[index].name, recordType, recordPos, m_recordLength, extension));
+			else
+			{
+				WPG_DEBUG_MSG(("Record '%s' type 0x%02x at %li  size %d  extension %d\n",
+					handlers[index].name, recordType, recordPos, m_recordLength, extension));
+
+				// invoke the handler for this record
+				(this->*recordHandler)();
+			}
+		}
+
+		// the last subgroup
+		if(!m_groupStack.empty())
+		{
+			WPGGroupContext& context = m_groupStack.top();
+			if(context.subIndex == 0)
+			{
+				if(context.isCompoundPolygon())
+					flushCompoundPolygon();
+				m_groupStack.pop();
+			}
+		}
+
+		// we enter another subgroup, save the context to stack
+		if(extension > 0)
+		{
+			WPGGroupContext context;
+			context.parentType = recordType;
+			context.subIndex = extension;
+			if(context.isCompoundPolygon())
+			{
+				context.compoundMatrix = m_compoundMatrix;
+				context.compoundFilled = m_compoundFilled;
+				context.compoundFramed = m_compoundFramed;
+				context.compoundClosed = m_compoundClosed;
+			}
+			m_groupStack.push(context);
+		}
+
+		//if(m_input->tell() > m_recordEnd+1)
+		{
+			//WPG_DEBUG_MSG(("Record 0x%x consumes more bytes than necessary!\n", recordType));
+			WPG_DEBUG_MSG(("Current stream position: %li\n", m_input->tell()));
+		}
+
+		if(m_exit) break;
+
+		m_input->seek(m_recordEnd+1, WPX_SEEK_SET);
+	}
+	
+	if (!m_exit)
+		handleEndWPG();
+
+	return m_success;
+}
+
+#ifdef DEBUG
+static const char* describePrecision(unsigned char precision)
+{
+	const char* result = "Unknown";
+	switch(precision)
+	{
+		case 0: result = "single"; break;
+		case 1: result = "double"; break;
+		default: break;
+	}
+	return result;
+}
+
+static const char* describeGradient(unsigned char gradientType)
+{
+	const char* result = "Unknown";
+	switch(gradientType)
+	{
+		case 0: result = "None"; break;
+		case 1: result = "Linear"; break;
+		case 2: result = "Polygonal"; break;
+		case 3: result = "Concentric Circles"; break;
+		case 4: result = "Convergent Circles"; break;
+		case 5: result = "Concentric Ellipses"; break;
+		case 6: result = "Convergent Ellipses"; break;
+		case 7: result = "Concentric Squares"; break;
+		case 8: result = "Convergent Squares"; break;
+		case 9: result = "Concentric Rectangles"; break;
+		case 10: result = "Convergent Rectangles"; break;
+		default: break;
+	}
+	return result;
+}
+#endif
+
+#define TO_DOUBLE(x) ( (m_doublePrecision) ? ((double)(x)/65536.0) : (double)(x) )
+#define TRANSFORM_XY(x,y) { m_matrix.transform((x),(y)); (x)-= m_xofs; (y)-= m_yofs; (y)=m_height-(y); }
+
+void WPG2Parser::handleStartWPG()
+{
+	if (m_graphicsStarted) // second start wpg in the document == possible corruption, bail out
+	{
+		handleEndWPG();
+		return;
+	}
+		
+	unsigned int horizontalUnit = readU16();
+	unsigned int verticalUnit = readU16();
+	unsigned char precision = readU8();
+
+	// sanity check
+	m_xres = horizontalUnit;
+	m_yres = verticalUnit;
+	if((horizontalUnit==0) || (verticalUnit==0))
+	{
+		m_xres = m_yres = 1200;
+		WPG_DEBUG_MSG(("Warning ! Insane unit of measure"));
+	}
+
+	// danger if we do not recognize the precision code
+	if(precision != 0)
+	if(precision != 1)
+	{
+		m_success = false;
+		m_exit = true;
+		return;
+	}
+	m_doublePrecision = (precision == 1);
+
+#ifdef DEBUG
+	long viewportX1 = (m_doublePrecision) ? readS32() : readS16();
+	long viewportY1 = (m_doublePrecision) ? readS32() : readS16();
+	long viewportX2 = (m_doublePrecision) ? readS32() : readS16();
+	long viewportY2 = (m_doublePrecision) ? readS32() : readS16();
+#else
+	m_input->seek(((m_doublePrecision) ? 16 : 8), WPX_SEEK_CUR);
+#endif
+	long imageX1 = (m_doublePrecision) ? readS32() : readS16();
+	long imageY1 = (m_doublePrecision) ? readS32() : readS16();
+	long imageX2 = (m_doublePrecision) ? readS32() : readS16();
+	long imageY2 = (m_doublePrecision) ? readS32() : readS16();
+
+	// used to adjust coordinates
+	m_xofs = (imageX1 < imageX2) ? imageX1 : imageX2;
+	m_yofs = (imageY1 < imageY2) ? imageY1 : imageX2;
+	m_width = (imageX2 > imageX1 ) ? imageX2-imageX1 : imageX1-imageX2;
+	m_height = (imageY2 > imageY1) ? imageY2-imageY1 : imageY1-imageY2;
+
+	WPG_DEBUG_MSG(("StartWPG 2\n"));
+	WPG_DEBUG_MSG(("  Horizontal unit of measure : %d pixels/inch\n", horizontalUnit));
+	WPG_DEBUG_MSG(("    Vertical unit of measure : %d pixels/inch\n", verticalUnit));
+	WPG_DEBUG_MSG(("              Data precision : %d (%s)\n", precision, describePrecision(precision)));
+	WPG_DEBUG_MSG(("                 Viewport X1 : %li\n", viewportX1));
+	WPG_DEBUG_MSG(("                 Viewport Y1 : %li\n", viewportY1));
+	WPG_DEBUG_MSG(("                 Viewport X2 : %li\n", viewportX2));
+	WPG_DEBUG_MSG(("                 Viewport Y2 : %li\n", viewportY2));
+	WPG_DEBUG_MSG(("                    Image X1 : %li\n", imageX1));
+	WPG_DEBUG_MSG(("                    Image Y1 : %li\n", imageY1));
+	WPG_DEBUG_MSG(("                    Image X2 : %li\n", imageX2));
+	WPG_DEBUG_MSG(("                    Image Y2 : %li\n", imageY2));
+	WPG_DEBUG_MSG(("                    X offset : %li\n", m_xofs));
+	WPG_DEBUG_MSG(("                    Y offset : %li\n", m_yofs));
+	WPG_DEBUG_MSG(("                       width : %li\n", m_width));
+	WPG_DEBUG_MSG(("                      height : %li\n", m_height));
+
+	double width = (TO_DOUBLE(m_width)) / m_xres;
+	double height = (TO_DOUBLE(m_height)) / m_yres;
+
+	m_painter->startGraphics(width, height);
+
+	static const int WPG2_defaultPenDashes[] = {
+		1,   291,  0,                            // style #0 (actually solid)
+		1,   218, 73,                            // style #1
+		1,   145, 73,                            // style #2
+		1,    73, 73,                            // style #3
+		1,    36, 36,                            // style #4
+		1,    18, 18,                            // style #5
+		1,    18, 55,                            // style #6
+		3,    18, 55,  18, 55, 18, 127,          // style #7
+		2,   164, 55,  18, 55,                   // style #8
+		3,   145, 36, 138, 36, 18,  36,          // style #9
+		3,    91, 55,  91, 55, 18,  55,          // style #10
+		4,    91, 36,  91, 36, 18,  36, 18, 36,  // style #11
+		2,   182, 73,  73, 73,                   // style #12
+		3,   182, 36,  55, 36, 55,  36,          // style #13
+		3,   255, 73, 255, 73, 73,  73,          // style #14
+		4,   273, 36, 273, 36, 55,  36, 55, 36,  // style #15
+		0 // end marker
+	};
+
+	// create default pen styles
+	int styleNo = 0;
+	for(int i = 0; (long)i < (long)(sizeof(WPG2_defaultPenDashes)/sizeof(WPG2_defaultPenDashes[0]));)
+	{
+		int segments = 2 * WPG2_defaultPenDashes[i++];
+		if(segments == 0) break;
+		libwpg::WPGDashArray dashArray;
+		for(int j = 0; j < segments; j++, i++)
+			dashArray.add(WPG2_defaultPenDashes[i]*3.6/218.0);
+		m_penStyles[styleNo] = dashArray;
+		styleNo++;
+	}
+	m_graphicsStarted = true;
+}
+
+void WPG2Parser::handleEndWPG()
+{
+	if (!m_graphicsStarted)
+		return;
+	// sentinel
+	if(m_layerOpened)
+		m_painter->endLayer(m_layerId);
+
+	m_painter->endGraphics();
+	m_exit = true;
+}
+
+void WPG2Parser::handleLayer()
+{
+	if (!m_graphicsStarted)
+		return;
+	m_layerId = readU16();
+
+	// close previous one
+	if(m_layerOpened)
+		m_painter->endLayer(m_layerId);
+
+	m_painter->startLayer(m_layerId);
+	m_layerOpened = true;
+
+	WPG_DEBUG_MSG(("  Layer Id: %d\n", m_layerId));
+}
+
+void WPG2Parser::handleCompoundPolygon()
+{
+	if (!m_graphicsStarted)
+		return;
+	ObjectCharacterization objCh;
+	parseCharacterization(&objCh);
+
+	m_compoundWindingRule = objCh.windingRule;
+	m_compoundMatrix = objCh.matrix;
+	m_compoundFilled = objCh.filled;
+	m_compoundFramed = objCh.framed;
+	m_compoundClosed = objCh.closed;
+}
+
+void WPG2Parser::flushCompoundPolygon()
+{
+	if (!m_graphicsStarted)
+		return;
+	WPGGroupContext& context = m_groupStack.top();
+
+	m_painter->setBrush( context.compoundFilled ? m_brush : libwpg::WPGBrush() );
+	m_painter->setPen( context.compoundFramed ? m_pen : libwpg::WPGPen() );
+	if(context.compoundWindingRule)
+		m_painter->setFillRule(libwpg::WPGPaintInterface::WindingFill);
+	else
+		m_painter->setFillRule(libwpg::WPGPaintInterface::AlternatingFill);
+	context.compoundPath.closed = context.compoundClosed;
+	m_painter->drawPath(context.compoundPath);
+}
+
+void WPG2Parser::handlePenStyleDefinition()
+{
+	if (!m_graphicsStarted)
+		return;
+	unsigned int style = readU16();
+	unsigned int segments = readU16();
+
+	libwpg::WPGDashArray dashArray;
+	for(unsigned i = 0; i < segments; i++)
+	{
+		unsigned int p = (m_doublePrecision) ? readU32() : readU16();
+		unsigned int q = (m_doublePrecision) ? readU32() : readU16();
+		dashArray.add(TO_DOUBLE(p)*3.6/218.0);
+		dashArray.add(TO_DOUBLE(q)*3.6/218.0);
+	}
+	m_penStyles[style] = dashArray;
+
+	WPG_DEBUG_MSG(("          Style : %d\n", style));
+	WPG_DEBUG_MSG(("  Segment pairs : %d\n", segments));
+}
+
+// TODO
+void WPG2Parser::handlePatternDefinition()
+{
+	if (!m_graphicsStarted)
+		return;
+	WPG_DEBUG_MSG(("PatternDefinition\n"));
+}
+
+void WPG2Parser::handleColorPalette()
+{
+	if (!m_graphicsStarted)
+		return;
+	unsigned startIndex = readU16();
+	unsigned numEntries = readU16();
+
+	for(unsigned i = 0; i < numEntries; i++)
+	{
+		libwpg::WPGColor color;
+		color.red = readU8();
+		color.green = readU8();
+		color.blue = readU8();
+		color.alpha = readU8();
+		m_colorPalette[startIndex+i] = color;
+		WPG_DEBUG_MSG(("Index#%d: RGB %d %d %d\n", startIndex+i, color.red, color.green, color.blue));
+	}
+}
+
+void WPG2Parser::handleDPColorPalette()
+{
+	if (!m_graphicsStarted)
+		return;
+	unsigned startIndex = readU16();
+	unsigned numEntries = readU16();
+
+	for(unsigned int i = 0; i < numEntries; i++)
+	{
+		libwpg::WPGColor color;
+		color.red = readU16() >> 8 ;
+		color.green = readU16() >> 8 ;
+		color.blue = readU16() >> 8 ;
+		color.alpha = readU16() >> 8 ;
+		m_colorPalette[startIndex+i] = color;
+		WPG_DEBUG_MSG(("Index#%d: RGB %d %d %d\n", startIndex+i, color.red, color.green, color.blue));
+	}
+}
+
+void WPG2Parser::handlePenForeColor()
+{
+	if (!m_graphicsStarted)
+		return;
+	if (!m_groupStack.empty() && m_groupStack.top().isCompoundPolygon())
+		return;
+	unsigned char red = readU8();
+	unsigned char green = readU8();
+	unsigned char blue = readU8();
+	unsigned char alpha = readU8();
+
+	m_pen.foreColor = libwpg::WPGColor(red, green, blue, alpha);
+
+	WPG_DEBUG_MSG(("   Foreground color (RGBA): %d %d %d %d\n", red, green, blue, alpha));
+}
+
+void WPG2Parser::handleDPPenForeColor()
+{
+	if (!m_graphicsStarted)
+		return;
+	if (!m_groupStack.empty() && m_groupStack.top().isCompoundPolygon())
+		return;
+	// we just ignore the least significant 8 bits
+	unsigned int red = (m_doublePrecision)   ? readU16()>>8 : readU8();
+	unsigned int green = (m_doublePrecision) ? readU16()>>8 : readU8();
+	unsigned int blue = (m_doublePrecision)  ? readU16()>>8 : readU8();
+	unsigned int alpha = (m_doublePrecision) ? readU16()>>8 : readU8();
+
+	m_pen.foreColor = libwpg::WPGColor(red, green, blue, alpha);
+
+	WPG_DEBUG_MSG(("   Foreground color (RGBA): %d %d %d %d\n", red, green, blue, alpha));
+}
+
+void WPG2Parser::handlePenBackColor()
+{
+	if (!m_graphicsStarted)
+		return;
+	if (!m_groupStack.empty() && m_groupStack.top().isCompoundPolygon())
+		return;
+	unsigned char red = readU8();
+	unsigned char green = readU8();
+	unsigned char blue = readU8();
+	unsigned char alpha = readU8();
+
+	m_pen.backColor = libwpg::WPGColor(red, green, blue, alpha);
+
+	WPG_DEBUG_MSG(("   Background color (RGBA): %d %d %d %d\n", red, green, blue, alpha));
+}
+
+void WPG2Parser::handleDPPenBackColor()
+{
+	if (!m_graphicsStarted)
+		return;
+	if (!m_groupStack.empty() && m_groupStack.top().isCompoundPolygon())
+		return;
+	// we just ignore the least significant 8 bits
+	unsigned int red = (m_doublePrecision)   ? readU16()>>8 : readU8();
+	unsigned int green = (m_doublePrecision) ? readU16()>>8 : readU8();
+	unsigned int blue = (m_doublePrecision)  ? readU16()>>8 : readU8();
+	unsigned int alpha = (m_doublePrecision) ? readU16()>>8 : readU8();
+
+	m_pen.backColor = libwpg::WPGColor(red, green, blue, alpha);
+
+	WPG_DEBUG_MSG(("   Background color (RGBA): %d %d %d %d\n", red, green, blue, alpha));
+}
+
+void WPG2Parser::handlePenStyle()
+{
+	if (!m_graphicsStarted)
+		return;
+	if (!m_groupStack.empty() && m_groupStack.top().isCompoundPolygon())
+		return;
+	unsigned int style = readU16();
+
+	m_pen.dashArray = m_penStyles[style];
+	m_pen.solid = (style == 0);
+
+	WPG_DEBUG_MSG(("   Pen style : %d\n", style));
+	WPG_DEBUG_MSG(("   Segments : %d\n", m_pen.dashArray.count()));
+}
+
+void WPG2Parser::handlePenSize()
+{
+	if (!m_graphicsStarted)
+		return;
+	if (!m_groupStack.empty() && m_groupStack.top().isCompoundPolygon())
+		return;
+	unsigned int width = readU16();
+	unsigned int height = readU16();
+
+	m_pen.width = TO_DOUBLE(width) / m_xres;
+	m_pen.height = TO_DOUBLE(height) / m_yres;
+
+	WPG_DEBUG_MSG(("   Width: %d\n", width));
+	WPG_DEBUG_MSG(("   Height: %d\n", height));
+}
+
+void WPG2Parser::handleDPPenSize()
+{
+	if (!m_graphicsStarted)
+		return;
+	if (!m_groupStack.empty() && m_groupStack.top().isCompoundPolygon())
+		return;
+	unsigned long width = readU32();
+	unsigned long height = readU32();
+
+	m_pen.width = TO_DOUBLE(width) / m_xres / 256;
+	m_pen.height = TO_DOUBLE(height) / m_yres / 256;
+
+	WPG_DEBUG_MSG(("   Width: %li\n", width));
+	WPG_DEBUG_MSG(("  Height: %li\n", height));
+}
+
+void WPG2Parser::handleBrushGradient()
+{
+	if (!m_graphicsStarted)
+		return;
+	if (!m_groupStack.empty() && m_groupStack.top().isCompoundPolygon())
+		return;
+	unsigned angleFraction = readU16();
+	unsigned angleInteger = readU16();
+	unsigned xref = readU16();
+	unsigned yref = readU16();
+#ifdef DEBUG
+	unsigned flag = readU16();
+	bool granular = ((flag & (1<<6))>>6) == 1;
+	bool anchor = ((flag & (1<<7))>>7) == 1;
+#else
+	readU16();
+#endif
+
+	// TODO: get gradient extent
+
+	m_gradientAngle = angleInteger + (double)angleFraction/65536.0;
+	m_gradientRef.x = xref;
+	m_gradientRef.y = yref;
+
+	WPG_DEBUG_MSG(("       Gradient angle : %d.%d\n", angleInteger, angleFraction));
+	WPG_DEBUG_MSG(("   Gradient reference : %d.%d\n", xref, yref));
+	WPG_DEBUG_MSG(("   Granular : %s\n", (granular ? "yes" : "no")));
+	WPG_DEBUG_MSG(("   Anchored : %s\n", (anchor ? "yes" : "no")));
+}
+
+void WPG2Parser::handleDPBrushGradient()
+{
+	if (!m_graphicsStarted)
+		return;
+	if (!m_groupStack.empty() && m_groupStack.top().isCompoundPolygon())
+		return;
+	unsigned angleFraction = readU16();
+	unsigned angleInteger = readU16();
+	unsigned xref = readU16();
+	unsigned yref = readU16();
+#ifdef DEBUG
+	unsigned flag = readU16();
+	bool granular = (flag & (1<<6)) == 1;
+	bool anchor = (flag & (1<<7)) == 1;
+#else
+	readU16();
+#endif
+
+	// TODO: get gradient extent (in double precision)
+
+	m_gradientAngle = angleFraction + (double)angleInteger/65536.0;
+	m_gradientRef.x = xref;
+	m_gradientRef.y = yref;
+
+	WPG_DEBUG_MSG(("       Gradient angle : %d.%d\n", angleInteger, angleFraction));
+	WPG_DEBUG_MSG(("   Gradient reference : %d.%d\n", xref, yref));
+	WPG_DEBUG_MSG(("   Granular : %s\n", (granular ? "yes" : "no")));
+	WPG_DEBUG_MSG(("   Anchored : %s\n", (anchor ? "yes" : "no")));
+}
+
+void WPG2Parser::handleBrushForeColor()
+{
+	if (!m_graphicsStarted)
+		return;
+	if (!m_groupStack.empty() && m_groupStack.top().isCompoundPolygon())
+		return;
+	unsigned char gradientType = readU8();
+	WPG_DEBUG_MSG(("   Gradient type : %d (%s)\n", gradientType, describeGradient(gradientType)));
+
+	if(gradientType == 0)
+	{
+		unsigned char red = readU8();
+		unsigned char green = readU8();
+		unsigned char blue = readU8();
+		unsigned char alpha = readU8();
+		WPG_DEBUG_MSG(("   Foreground color (RGBA): %d %d %d %d\n", red, green, blue, alpha));
+
+		m_brush.foreColor = libwpg::WPGColor(red, green, blue, alpha);
+		if(m_brush.style != libwpg::WPGBrush::Gradient)
+			m_brush.style = libwpg::WPGBrush::Solid;
+	}
+	else
+	{
+		unsigned count = readU16();
+		std::vector<libwpg::WPGColor> colors;
+		std::vector<double> positions;
+		WPG_DEBUG_MSG(("  Gradient colors : %d\n", count));
+
+		for(unsigned i = 0; i < count; i++)
+		{
+			unsigned char red = readU8();
+			unsigned char green = readU8();
+			unsigned char blue = readU8();
+			unsigned char alpha = readU8();
+			libwpg::WPGColor color(red, green, blue, alpha);
+			colors.push_back(color);
+			WPG_DEBUG_MSG(("   Color #%d (RGBA): %d %d %d %d\n", i+1, red, green, blue, alpha));
+		}
+
+		for(unsigned j = 0; j < count-1; j++)
+		{
+			unsigned pos = readU16();
+			positions.push_back(TO_DOUBLE(pos));
+			WPG_DEBUG_MSG(("   Position #%d : %d\n", j+1, pos));
+		}
+
+		// looks like Corel Presentations only create 2 colors gradient
+		// and they are actually in reverse order
+		if(count == 2)
+		{
+			double xref = (double)m_gradientRef.x/65536.0;
+			double yref = (double)m_gradientRef.y/65536.0;
+			double angle = m_gradientAngle*M_PI/180.0;
+			double tanangle = tan(angle);
+			double ref = (tanangle < 1e2 && tanangle > -1e2) ? (yref+xref*tanangle)/(1+tanangle) : xref;
+			libwpg::WPGGradient gradient;
+			gradient.setAngle(-m_gradientAngle); // upside down
+			gradient.addStop(0, colors[1]);
+			gradient.addStop(ref, colors[0]);
+			if((m_gradientRef.x != 65535) && (m_gradientRef.y != 65535))
+				gradient.addStop(1, colors[1]);
+			m_brush.gradient = gradient;
+			m_brush.style = libwpg::WPGBrush::Gradient;
+		}
+	}
+}
+
+void WPG2Parser::handleDPBrushForeColor()
+{
+	if (!m_graphicsStarted)
+		return;
+	if (!m_groupStack.empty() && m_groupStack.top().isCompoundPolygon())
+		return;
+	unsigned char gradientType = readU8();
+	WPG_DEBUG_MSG(("   Gradient type : %d (%s)\n", gradientType, describeGradient(gradientType)));
+
+	if(gradientType == 0)
+	{
+		unsigned char red = (m_doublePrecision)   ? readU16()>>8 : readU8();
+		unsigned char green = (m_doublePrecision)   ? readU16()>>8 : readU8();
+		unsigned char blue = (m_doublePrecision)   ? readU16()>>8 : readU8();
+		unsigned char alpha = (m_doublePrecision)   ? readU16()>>8 : readU8();
+		WPG_DEBUG_MSG(("   Foreground color (RGBA): %d %d %d %d\n", red, green, blue, alpha));
+
+		m_brush.foreColor = libwpg::WPGColor(red, green, blue, alpha);
+		if(m_brush.style != libwpg::WPGBrush::NoBrush)
+			m_brush.style = libwpg::WPGBrush::Solid;
+	}
+	else
+	{
+		unsigned count = readU16();
+		std::vector<libwpg::WPGColor> colors;
+		std::vector<double> positions;
+		WPG_DEBUG_MSG(("  Gradient colors : %d\n", count));
+
+		for(unsigned i = 0; i < count; i++)
+		{
+			unsigned char red = (m_doublePrecision)   ? readU16()>>8 : readU8();
+			unsigned char green = (m_doublePrecision)   ? readU16()>>8 : readU8();
+			unsigned char blue = (m_doublePrecision)   ? readU16()>>8 : readU8();
+			unsigned char alpha = (m_doublePrecision)   ? readU16()>>8 : readU8();
+			libwpg::WPGColor color(red, green, blue, alpha);
+			colors.push_back(color);
+			WPG_DEBUG_MSG(("   Color #%d (RGBA): %d %d %d %d\n", i+1, red, green, blue, alpha));
+		}
+
+		for(unsigned j = 0; j < count-1; j++)
+		{
+			unsigned pos = readU16();
+			positions.push_back(TO_DOUBLE(pos));
+			WPG_DEBUG_MSG(("   Position #%d : %d\n", j+1, pos));
+		}
+
+		// looks like Corel Presentations only create 2 colors gradient
+		// and they are actually in reverse order
+		if(count == 2)
+		{
+			double xref = (double)m_gradientRef.x/65536.0;
+			double yref = (double)m_gradientRef.y/65536.0;
+			double angle = m_gradientAngle*M_PI/180.0;
+			double tanangle = tan(angle);
+			double ref = (tanangle<1e2) ? (yref+xref*tanangle)/(1+tanangle) : xref;
+			libwpg::WPGGradient gradient;
+			gradient.setAngle(-m_gradientAngle); // upside down
+			gradient.addStop(0, colors[1]);
+			gradient.addStop(ref, colors[0]);
+			if((m_gradientRef.x != 65535) && (m_gradientRef.y != 65536))
+				gradient.addStop(1, colors[1]);
+			m_brush.gradient = gradient;
+			m_brush.style = libwpg::WPGBrush::Gradient;
+		}
+	}
+}
+
+void WPG2Parser::handleBrushBackColor()
+{
+	if (!m_graphicsStarted)
+		return;
+	if (!m_groupStack.empty() && m_groupStack.top().isCompoundPolygon())
+		return;
+	unsigned char red = readU8();
+	unsigned char green = readU8();
+	unsigned char blue = readU8();
+	unsigned char alpha = readU8();
+
+	m_brush.backColor = libwpg::WPGColor(red, green, blue, alpha);
+	if(m_brush.style == libwpg::WPGBrush::NoBrush)
+		m_brush.style = libwpg::WPGBrush::Solid;
+
+	WPG_DEBUG_MSG(("   Backround color (RGBA): %d %d %d %d\n", red, green, blue, alpha));
+}
+
+void WPG2Parser::handleDPBrushBackColor()
+{
+	if (!m_graphicsStarted)
+		return;
+	if (!m_groupStack.empty() && m_groupStack.top().isCompoundPolygon())
+		return;
+	// we just ignore the least significant 8 bits
+	unsigned int red = (m_doublePrecision)   ? readU16()>>8 : readU8();
+	unsigned int green = (m_doublePrecision) ? readU16()>>8 : readU8();
+	unsigned int blue = (m_doublePrecision)  ? readU16()>>8 : readU8();
+	unsigned int alpha = (m_doublePrecision) ? readU16()>>8 : readU8();
+
+	m_brush.backColor = libwpg::WPGColor(red, green, blue, alpha);
+	if(m_brush.style == libwpg::WPGBrush::NoBrush)
+		m_brush.style = libwpg::WPGBrush::Solid;
+
+	WPG_DEBUG_MSG(("   Background color (RGBA): %d %d %d %d\n", red, green, blue, alpha));
+}
+
+void WPG2Parser::handleBrushPattern()
+{
+	if (!m_graphicsStarted)
+		return;
+	if (!m_groupStack.empty() && m_groupStack.top().isCompoundPolygon())
+		return;
+#ifdef DEBUG
+	unsigned int pattern = readU16();
+#endif
+
+	// TODO
+
+	WPG_DEBUG_MSG(("   Pattern : %d\n", pattern));
+}
+
+void WPG2Parser::parseCharacterization(ObjectCharacterization* ch)
+{
+	// sanity check
+	if(!ch) return;
+
+	// identity
+	ch->matrix = WPG2TransformMatrix();
+
+	unsigned int flags = readU16();
+	ch->taper = (flags & 0x01) != 0;
+	ch->translate = (flags & 0x02) != 0;
+	ch->skew = (flags & 0x04) != 0;
+	ch->scale = (flags & 0x08) != 0;
+	ch->rotate = (flags & 0x10) != 0;
+	ch->hasObjectId = (flags & 0x20) != 0;
+	ch->editLock = (flags & 0x80) != 0;
+	ch->windingRule = (flags & (1<<12)) != 0;
+	ch->filled = (flags & (1<<13)) != 0;
+	ch->closed = (flags & (1<<14)) != 0;
+	ch->framed = (flags & (1<<15)) != 0;
+
+	if(ch->editLock) ch->lockFlags = readU32();
+
+	// object ID can be 2 or 4 bytes
+	if(ch->hasObjectId) ch->objectId = readU16();
+	if(ch->objectId >> 15) ch->objectId = ((ch->objectId  & 0x7fff) << 16) | readU16();
+
+	if(ch->rotate) ch->rotationAngle = readS32();
+
+	if(ch->rotate || ch->scale)
+	{
+		ch->sxcos = readS32();
+		ch->sycos = readS32();
+		ch->matrix.element[0][0] = (double)(ch->sxcos)/65536;
+		ch->matrix.element[1][1] = (double)(ch->sxcos)/65536;
+	}
+
+	if(ch->rotate || ch->skew)
+	{
+		ch->kxsin = readS32();
+		ch->kysin = readS32();
+		ch->matrix.element[1][0] = (double)(ch->kxsin)/65536;
+		ch->matrix.element[0][1] = (double)(ch->kysin)/65536;
+	}
+
+	if(ch->translate)
+	{
+		ch->txfraction = readU16();
+		ch->txinteger = readS32();
+		ch->tyfraction = readU16();
+		ch->tyinteger = readS32();
+		ch->matrix.element[2][0] = (double)(ch->txinteger);
+		ch->matrix.element[2][1] = (double)(ch->tyinteger);
+	}
+
+	if(ch->taper)
+	{
+		ch->px = readS32();
+		ch->py = readS32();
+		ch->matrix.element[0][2] = (double)(ch->px);
+		ch->matrix.element[1][2] = (double)(ch->py);
+	}
+
+	WPG_DEBUG_MSG(("ObjectCharacterization\n"));
+	WPG_DEBUG_MSG(("       taper : %s\n", (ch->taper ? "yes" : "no")));
+	WPG_DEBUG_MSG(("   translate : %s\n", (ch->translate ? "yes" : "no")));
+	WPG_DEBUG_MSG(("        skew : %s\n", (ch->skew ? "yes" : "no")));
+	WPG_DEBUG_MSG(("       scale : %s\n", (ch->scale ? "yes" : "no")));
+	WPG_DEBUG_MSG(("      rotate : %s\n", (ch->rotate ? "yes" : "no")));
+	WPG_DEBUG_MSG((" hasObjectId : %s\n", (ch->hasObjectId ? "yes" : "no")));
+	WPG_DEBUG_MSG(("    editLock : %s\n", (ch->editLock ? "yes" : "no")));
+	WPG_DEBUG_MSG(("      closed : %s\n", (ch->closed ? "yes" : "no")));
+	WPG_DEBUG_MSG(("      framed : %s\n", (ch->framed ? "yes" : "no")));
+	WPG_DEBUG_MSG(("      filled : %s\n", (ch->filled ? "yes" : "no")));
+#ifdef DEBUG
+	if(ch->editLock) WPG_DEBUG_MSG(("  lock flags : 0x%x\n", (unsigned)ch->lockFlags));
+	if(ch->hasObjectId) WPG_DEBUG_MSG(("   object ID : 0x%x\n", (unsigned)ch->objectId));
+	if(ch->translate) WPG_DEBUG_MSG(("    tx : %li %d\n", ch->txinteger, ch->txfraction));
+	if(ch->translate) WPG_DEBUG_MSG(("    ty : %li %d\n", ch->tyinteger, ch->tyfraction));
+#endif
+	WPG_DEBUG_MSG(("transform matrix:\n"));
+	WPG_DEBUG_MSG(("%f %f %f\n", ch->matrix.element[0][0], ch->matrix.element[0][1],ch->matrix.element[0][2]));
+	WPG_DEBUG_MSG(("%f %f %f\n", ch->matrix.element[1][0], ch->matrix.element[1][1],ch->matrix.element[1][2]));
+	WPG_DEBUG_MSG(("%f %f %f\n", ch->matrix.element[2][0], ch->matrix.element[2][1],ch->matrix.element[2][2]));
+}
+
+void WPG2Parser::handlePolyline()
+{
+	if (!m_graphicsStarted)
+		return;
+	ObjectCharacterization objCh;
+	parseCharacterization(&objCh);
+	m_matrix = objCh.matrix;
+
+	bool insideCompound = m_groupStack.empty() ? false :
+		m_groupStack.top().isCompoundPolygon();
+
+	// inside a compound, so take the parent transformation into account
+	if(insideCompound)
+		m_matrix.transformBy(m_groupStack.top().compoundMatrix);
+
+	unsigned long count = readU16();
+
+	libwpg::WPGPointArray points;
+	for(unsigned long i = 0; i < count; i++ )
+	{
+		long x = (m_doublePrecision) ? readS32() : readS16();
+		long y = (m_doublePrecision) ? readS32() : readS16();
+		TRANSFORM_XY(x,y);
+		libwpg::WPGPoint p(TO_DOUBLE(x)/m_xres, TO_DOUBLE(y)/m_yres);
+		points.add(p);
+	}
+
+	if(insideCompound)
+	{
+		if(count > 0)
+		{
+			// inside a compound ? convert it into path because for compound
+			// we will only use paths
+			libwpg::WPGPath& path = m_groupStack.top().compoundPath;
+			path.moveTo(points[0]);
+			for(unsigned long ii = 1; ii < count; ii++)
+				path.lineTo(points[ii]);
+		}
+	}
+	else
+	{
+		// otherwise draw directly
+		m_painter->setBrush( objCh.filled ? m_brush : libwpg::WPGBrush() );
+		m_painter->setPen( objCh.framed ? m_pen : libwpg::WPGPen() );
+		if(objCh.windingRule)
+			m_painter->setFillRule(libwpg::WPGPaintInterface::WindingFill);
+		else
+			m_painter->setFillRule(libwpg::WPGPaintInterface::AlternatingFill);
+		m_painter->drawPolygon(points);
+	}
+
+	WPG_DEBUG_MSG(("   Vertices count : %li\n", count));
+	for(unsigned int j = 0; j < count; j++ )
+		WPG_DEBUG_MSG(("        Point #%d : %g,%g\n", j+1, points[j].x, points[j].y));
+}
+
+void WPG2Parser::handlePolyspline()
+{
+	if (!m_graphicsStarted)
+		return;
+	// We have never seen a polyspline in a WPG file and we are not even able to generate
+	// one, so, we draw a polyline instead and wait for bug reports :)
+	handlePolyline();
+}
+
+void WPG2Parser::handlePolycurve()
+{
+	if (!m_graphicsStarted)
+		return;
+	ObjectCharacterization objCh;
+	parseCharacterization(&objCh);
+	m_matrix = objCh.matrix;
+
+	bool insideCompound = m_groupStack.empty() ? false :
+		m_groupStack.top().isCompoundPolygon();
+
+	// inside a compound, so take the parent transformation into account
+	if(insideCompound)
+		m_matrix.transformBy(m_groupStack.top().compoundMatrix);
+
+	unsigned int count = readU16();
+
+	libwpg::WPGPointArray vertices;
+	libwpg::WPGPointArray controlPoints;
+	for(unsigned int i = 0; i < count; i++ )
+	{
+		long ix = (m_doublePrecision) ? readS32() : readS16();
+		long iy = (m_doublePrecision) ? readS32() : readS16();
+		TRANSFORM_XY(ix,iy);
+		libwpg::WPGPoint initialPoint( TO_DOUBLE(ix)/m_xres, TO_DOUBLE(iy)/m_yres );
+
+		long ax = (m_doublePrecision) ? readS32() : readS16();
+		long ay = (m_doublePrecision) ? readS32() : readS16();
+		TRANSFORM_XY(ax,ay);
+		libwpg::WPGPoint anchorPoint( TO_DOUBLE(ax)/m_xres, TO_DOUBLE(ay)/m_yres );
+
+		long tx = (m_doublePrecision) ? readS32() : readS16();
+		long ty = (m_doublePrecision) ? readS32() : readS16();
+		TRANSFORM_XY(tx,ty);
+		libwpg::WPGPoint terminalPoint( TO_DOUBLE(tx)/m_xres, TO_DOUBLE(ty)/m_yres );
+
+		vertices.add(anchorPoint);
+		if(i > 0)
+			controlPoints.add(initialPoint);
+		controlPoints.add(terminalPoint);
+	}
+
+	libwpg::WPGPath path;
+	path.closed = objCh.closed;
+	path.framed = objCh.framed;
+	path.filled = objCh.filled;
+	path.moveTo(vertices[0]);
+	for(unsigned j = 1; j < vertices.count(); j++)
+		path.curveTo(controlPoints[j*2-2], controlPoints[j*2-1], vertices[j]);
+
+	if(insideCompound)
+		// inside a compound ? just collect the path together
+		m_groupStack.top().compoundPath.append(path);
+	else
+	{
+		// otherwise draw directly
+		m_painter->setBrush( objCh.filled ? m_brush : libwpg::WPGBrush() );
+		m_painter->setPen( objCh.framed ? m_pen : libwpg::WPGPen() );
+		if(objCh.windingRule)
+			m_painter->setFillRule(libwpg::WPGPaintInterface::WindingFill);
+		else
+			m_painter->setFillRule(libwpg::WPGPaintInterface::AlternatingFill);
+		m_painter->drawPath(path);
+	}
+}
+
+void WPG2Parser::handleRectangle()
+{
+	if (!m_graphicsStarted)
+		return;
+	ObjectCharacterization objCh;
+	parseCharacterization(&objCh);
+	m_matrix = objCh.matrix;
+
+	long x1 = (m_doublePrecision) ? readS32() : readS16();
+	long y1 = (m_doublePrecision) ? readS32() : readS16();
+	TRANSFORM_XY(x1,y1);
+
+	long x2 = (m_doublePrecision) ? readS32() : readS16();
+	long y2 = (m_doublePrecision) ? readS32() : readS16();
+	TRANSFORM_XY(x2,y2);
+
+	long xs1 = (x1 <= x2) ? x1 : x2;
+	long xs2 = (x1 <= x2) ? x2 : x1;
+	long ys1 = (y1 <= y2) ? y1 : y2;
+	long ys2 = (y1 <= y2) ? y2 : y1;
+
+	long rx = (m_doublePrecision) ? readS32() : readS16();
+	long ry = (m_doublePrecision) ? readS32() : readS16();
+
+	libwpg::WPGRect rect;
+	rect.x1 = TO_DOUBLE(xs1) / m_xres;
+	rect.x2 = TO_DOUBLE(xs2) / m_xres;
+	rect.y1 = TO_DOUBLE(ys1) / m_yres;
+	rect.y2 = TO_DOUBLE(ys2) / m_yres;
+
+	double roundx = TO_DOUBLE(rx)/m_xres;
+	double roundy = TO_DOUBLE(ry)/m_yres;
+
+	m_painter->setBrush( objCh.filled ? m_brush : libwpg::WPGBrush() );
+	m_painter->setPen( objCh.framed ? m_pen : libwpg::WPGPen() );
+	m_painter->drawRectangle(rect, roundx, roundy);
+
+	WPG_DEBUG_MSG(("      X1 : %li\n", x1));
+	WPG_DEBUG_MSG(("      Y1 : %li\n", y1));
+	WPG_DEBUG_MSG(("      X2 : %li\n", x2));
+	WPG_DEBUG_MSG(("      Y2 : %li\n", y2));
+	WPG_DEBUG_MSG((" Round X : %li\n", rx));
+	WPG_DEBUG_MSG((" Round Y : %li\n", ry));
+}
+
+void WPG2Parser::handleArc()
+{
+	if (!m_graphicsStarted)
+		return;
+	ObjectCharacterization objCh;
+	parseCharacterization(&objCh);
+	m_matrix = objCh.matrix;
+
+	long cx = (m_doublePrecision) ? readS32() : readS16();
+	long cy = (m_doublePrecision) ? readS32() : readS16();
+	TRANSFORM_XY(cx,cy);
+
+	long radx = (m_doublePrecision) ? readS32() : readS16();
+	long rady = (m_doublePrecision) ? readS32() : readS16();
+
+	long ix = (m_doublePrecision) ? readS32() : readS16();
+	long iy = (m_doublePrecision) ? readS32() : readS16();
+	TRANSFORM_XY(ix,iy);
+
+	long ex = (m_doublePrecision) ? readS32() : readS16();
+	long ey = (m_doublePrecision) ? readS32() : readS16();
+	TRANSFORM_XY(ex,ey);
+
+	if((ix==ex) && (iy==ey))
+	{
+		libwpg::WPGPoint center;
+		center.x = TO_DOUBLE(cx) / m_xres;
+		center.y = TO_DOUBLE(cy) / m_xres;
+		double rx = TO_DOUBLE(radx) / m_xres;
+		double ry = TO_DOUBLE(rady) / m_xres;
+
+		m_painter->setBrush( objCh.filled ? m_brush : libwpg::WPGBrush() );
+		m_painter->setPen( objCh.framed ? m_pen : libwpg::WPGPen() );
+		m_painter->drawEllipse(center, rx, ry);
+	}
+
+	WPG_DEBUG_MSG(("   Center point x : %li\n", cx));
+	WPG_DEBUG_MSG(("   Center point y : %li\n", cy));
+	WPG_DEBUG_MSG(("         Radius x : %li\n", radx));
+	WPG_DEBUG_MSG(("         Radius y : %li\n", rady));
+	WPG_DEBUG_MSG(("  Initial point x : %li\n", ix));
+	WPG_DEBUG_MSG(("  Initial point y : %li\n", iy));
+	WPG_DEBUG_MSG(("      End point x : %li\n", ex));
+	WPG_DEBUG_MSG(("      End point y : %li\n", ey));
+}
+
+void WPG2Parser::handleBitmap()
+{
+	if (!m_graphicsStarted)
+		return;
+	ObjectCharacterization objCh;
+	parseCharacterization(&objCh);
+	
+	if (objCh.scale)
+	{
+		if (objCh.sxcos < 0)
+			m_hFlipped = true;
+		if (objCh.sycos < 0)
+			m_vFlipped = true;
+	}
+	m_matrix = objCh.matrix;
+
+	long x1 = (m_doublePrecision) ? readS32() : readS16();
+	long y1 = (m_doublePrecision) ? readS32() : readS16();
+	long x2 = (m_doublePrecision) ? readS32() : readS16();
+	long y2 = (m_doublePrecision) ? readS32() : readS16();
+	TRANSFORM_XY(x1,y1);
+	TRANSFORM_XY(x2,y2);
+
+	long hres = (m_doublePrecision) ? readS32() : readS16();
+	long vres = (m_doublePrecision) ? readS32() : readS16();
+
+	long xs1 = (x1 <= x2) ? x1 : x2;
+	long xs2 = (x1 <= x2) ? x2 : x1;
+	long ys1 = (y1 <= y2) ? y1 : y2;
+	long ys2 = (y1 <= y2) ? y2 : y1;
+
+	m_bitmap.x1 = TO_DOUBLE(xs1) / m_xres;
+	m_bitmap.y1 = TO_DOUBLE(ys1) / m_yres;
+	m_bitmap.x2 = TO_DOUBLE(xs2) / m_xres;
+	m_bitmap.y2 = TO_DOUBLE(ys2) / m_yres;
+        m_bitmap.hres = hres;
+        m_bitmap.vres = vres;
+
+	WPG_DEBUG_MSG(("   x1 : %li\n", x1));
+	WPG_DEBUG_MSG(("   y1 : %li\n", y1));
+	WPG_DEBUG_MSG(("   x2 : %li\n", x2));
+	WPG_DEBUG_MSG(("   y2 : %li\n", y2));
+	WPG_DEBUG_MSG((" hres : %li (pixel per inch)\n", hres));
+	WPG_DEBUG_MSG((" vres : %li (pixel per inch)\n", vres));
+}
+
+void WPG2Parser::handleBitmapData()
+{
+	if (!m_graphicsStarted)
+		return;
+	unsigned width = readU16();
+	unsigned height = readU16();
+	unsigned color_format = readU8();
+	unsigned compression_format = readU8();
+
+	WPG_DEBUG_MSG(("     dimension : %g, %g  %g, %g\n", m_bitmap.x1, m_bitmap.y1, m_bitmap.x2, m_bitmap.y2));
+	WPG_DEBUG_MSG(("         width : %i pixels\n", width));
+	WPG_DEBUG_MSG(("        height : %i pixels\n", height));
+	WPG_DEBUG_MSG(("  color format : %d\n", color_format));
+	WPG_DEBUG_MSG(("   compression : %d (%s)\n", compression_format,
+		(compression_format==0) ? "uncompressed":
+		(compression_format==1) ? "run-length encoding" : "unknown"));
+
+	if (color_format > 12) // not documented and we are likely not knowing what to do with this
+		return;
+	unsigned tmpBufferSize;
+	unsigned raster_len = width;
+	if (color_format == 1)
+	{
+		tmpBufferSize = (width/8+1)*height;
+		raster_len = width/8 + ((width % 8) ? 1 : 0);
+	}
+	else if (color_format == 2)
+	{
+		tmpBufferSize = (width/4+1)*height;
+		raster_len = width/4 + ((width % 4) ? 1 : 0);
+	}
+	else if (color_format == 3)
+	{
+		tmpBufferSize = (width/2+1)*height;
+		raster_len = width/2 + ((width % 2) ? 1 : 0);
+	}
+	else if (color_format == 5 || color_format == 6 || color_format == 7)
+		tmpBufferSize = 2*width*height;
+	else if (color_format == 8)
+		tmpBufferSize = 3*width*height;
+	else if (color_format == 9)
+		tmpBufferSize = 4*width*height;
+	else if (color_format == 10)
+		tmpBufferSize = 6*width*height;
+	else if (color_format == 11)
+		tmpBufferSize = 8*width*height;
+	else
+		tmpBufferSize = width*height;
+	
+	
+	std::vector<unsigned char> buffer;
+	buffer.reserve(tmpBufferSize);
+
+	// plain data, uncompression
+	if(compression_format==0)
+		for(unsigned ii=0; ii < tmpBufferSize && m_input->tell() <= m_recordEnd; ii++)
+			buffer.push_back( readU8() );
+	// run-length encoding
+	else if(compression_format==1)
+	{
+		unsigned char data[256];
+		bool xor_raster = false;
+		unsigned next_scanline = 0;
+		unsigned data_size = 1;
+
+		WPG_DEBUG_MSG(("Decoding RLE data\n"));
+
+		// FIXME check for ptr, it should not go out of bound!!
+		while (m_input->tell() <= m_recordEnd && !m_input->atEOS() && buffer.size() < tmpBufferSize)
+		{
+			unsigned char opcode = readU8();
+			// specify data size
+			if(opcode == 0x7d)
+			{
+				unsigned new_data_size = readU8();
+				if(new_data_size != data_size)
+				{
+					data_size = new_data_size;
+					if (tmpBufferSize < data_size*width*height)
+					{
+						tmpBufferSize = data_size*width*height;
+						buffer.reserve(tmpBufferSize);
+					}
+					raster_len = data_size*width;
+				}
+			}
+
+			// a run of black (index #0)
+			else if(opcode == 0x7f)
+			{
+				unsigned count = 1 + readU8();
+				for( ; count ; --count )
+					for(unsigned j = 0; j < data_size && !m_input->atEOS(); j++)
+						buffer.push_back( 0 );
+				
+			}
+
+			// a run of white (index #255)
+			else if(opcode == 0xff)
+			{
+				unsigned count = 1 + readU8();
+
+				for( ; count ; --count )
+					for(unsigned j = 0; j < data_size && !m_input->atEOS(); j++)
+						buffer.push_back( 255 );
+			}
+
+			// extend previous run
+			else if(opcode == 0xfd)
+			{
+				unsigned count = 1 + readU8();
+				for( ; count; --count)
+					for(unsigned j = 0; j < data_size && !m_input->atEOS(); j++)
+						buffer.push_back( data[j] );
+			}
+
+			// repeat raster
+			else if(opcode == 0xfe)
+			{
+				unsigned count = 1 + readU8();
+				if ( buffer.size() < raster_len )
+					break;
+				unsigned raster_source = buffer.size() - raster_len;
+				for( ; count; --count)
+					for(unsigned long r = 0; r < raster_len; r++)
+					{
+						unsigned char pixel = buffer[raster_source + r];
+						buffer.push_back( pixel );
+					}
+			}
+
+			// XOR
+			else if(opcode == 0x7e)
+			{
+				// Xor-ing will happen when about to enter next raster
+				// see after the last if down below
+				xor_raster = true;
+				next_scanline = buffer.size() + raster_len;
+			}
+
+			// NOTE: the following two IFs here must be the last ones
+
+			// a run of data
+			else if(opcode >= 0x80)
+			{
+				unsigned count = 1 + (opcode & 0x7f);
+				for(unsigned i = 0; i < data_size && !m_input->atEOS(); i++)
+					data[i] = readU8();
+				for( ; count; --count)
+					for(unsigned j = 0; j < data_size; j++)
+						buffer.push_back( data[j] );
+			}
+
+			// simple copy
+			else if(opcode <= 0x7f)
+			{
+				unsigned count = opcode + 1;
+				for( ; count; --count)
+					for(unsigned j = 0; j < data_size && !m_input->atEOS(); j++)
+						buffer.push_back( readU8() );
+			}
+
+			// unreachable: only sentinel
+			else 
+			{
+				WPG_DEBUG_MSG(("  ! unknown opcode %02x\n", opcode));
+				break;
+			}
+
+			// new raster/scanline? if necessary do the XOR now
+			if(xor_raster && buffer.size() >= next_scanline)
+			{
+				// reset, because XOR in one raster at a time
+				xor_raster = false;
+
+				// current raster must be XORed with previous raster
+				unsigned current = next_scanline - raster_len;
+				unsigned previous = current - raster_len;
+				if (current >= buffer.size() || previous >= buffer.size())
+					return;
+				for( unsigned r = 0; r < raster_len; r++)
+					buffer[current++] ^= buffer[previous++];
+
+			}
+
+		}
+
+		WPG_DEBUG_MSG(("Finish decoding RLE data\n"));
+	} 
+	
+	// no buffer? format is unknown 
+	if(!buffer.size()) return;
+	
+	while (buffer.size() < tmpBufferSize)
+		buffer.push_back(0);
+
+	// prepare the bitmap structure for the listener
+	libwpg::WPGBitmap bitmap(width, height, m_vFlipped, m_hFlipped);
+	bitmap.rect.x1 = m_bitmap.x1;
+	bitmap.rect.y1 = m_bitmap.y1;
+	bitmap.rect.x2 = m_bitmap.x2;
+	bitmap.rect.y2 = m_bitmap.y2;
+
+	// format 1: each byte represents 8 pixels, the color fetched from the palette
+	if(color_format == 1)
+	{
+		int i = 0;
+		for (unsigned long y = 0; y < height; y++)
+		for (unsigned long x = 0; x < width; x++, i++)
+		{
+			if ((x==0) && (i % 8 != 0))
+				i = (i/8 + 1) * 8;
+			unsigned index = ((buffer[i/8] & (0x01 << (7 - (i % 8)))) >> (7 - (i % 8)));
+			const libwpg::WPGColor& color = m_colorPalette[index];
+			bitmap.setPixel(x, y, color);
+		}
+		m_painter->drawBitmap(bitmap, m_bitmap.hres, m_bitmap.vres);
+	}
+	// format 2: each byte represents 4 pixels, the color fetched from the palette
+	else if(color_format == 2)
+	{
+		int i = 0;
+		for (unsigned long y = 0; y < height; y++)
+		for (unsigned long x = 0; x < width; x++, i++)
+		{
+			if ((x==0) && (i % 4 != 0))
+				i = (i/4 + 1) * 4;
+			unsigned index = ((buffer[i/4] & (0x03 << 2*(3 - (i % 4)))) >> 2*(3 - (i % 4)));
+			const libwpg::WPGColor& color = m_colorPalette[index];
+			bitmap.setPixel(x, y, color);
+		}
+		m_painter->drawBitmap(bitmap, m_bitmap.hres, m_bitmap.vres);
+	}
+	// format 3: each byte represents 2 pixels, the color fetched from the palette
+	else if(color_format == 3)
+	{
+		int i = 0;
+		for (unsigned long y = 0; y < height; y++)
+		for (unsigned long x = 0; x < width; x++, i++)
+		{
+			if ((x==0) && (i % 2 != 0))
+				i = (i/2 + 1) * 2;
+			unsigned index = ((buffer[i/2] & (0x0f << 4*(1 - (i % 2)))) >> 4*(1 - (i % 2)));
+			const libwpg::WPGColor& color = m_colorPalette[index];
+			bitmap.setPixel(x, y, color);
+		}
+		m_painter->drawBitmap(bitmap, m_bitmap.hres, m_bitmap.vres);
+	}
+	// format 4: each byte represents a pixel, the color fetched from the palette
+	else if(color_format == 4)
+	{
+		int i = 0;
+		for(unsigned long y = 0; y < height; y++)
+		for(unsigned long x = 0; x < width; x++, i++)
+		{
+			const libwpg::WPGColor& color = m_colorPalette[buffer[i]];
+			bitmap.setPixel(x, y, color);
+		}
+
+		m_painter->drawBitmap(bitmap, m_bitmap.hres, m_bitmap.vres);
+	}
+	// format 5: greyscale of 16 bits
+	else if (color_format == 5)
+	{
+		int i = 0;
+		for (unsigned long y = 0; y < height; y++)
+		for (unsigned long x = 0; x < width; x++, i++)
+		{
+			
+			const libwpg::WPGColor color(buffer[2*i+1], buffer[2*i+1], buffer[2*i+1]);
+			bitmap.setPixel(x, y, color);
+		}
+
+		m_painter->drawBitmap(bitmap, m_bitmap.hres, m_bitmap.vres);
+	}
+	// format 6: RGB, with 5 bits per colour
+	else if (color_format == 6)
+	{
+		int i = 0;
+		for (unsigned long y = 0; y < height; y++)
+		for (unsigned long x = 0; x < width; x++, i++)
+		{
+			unsigned short tmpColor = (unsigned short)(buffer[2*i] | (buffer[2*i+1] << 8));
+			const libwpg::WPGColor color((tmpColor >> 10) & 0x1f, (tmpColor >> 5) & 0x1f, tmpColor & 0x1f);
+			bitmap.setPixel(x, y, color);
+		}
+
+		m_painter->drawBitmap(bitmap, m_bitmap.hres, m_bitmap.vres);
+	}
+	// format 7: 
+	else if (color_format == 7)
+	{
+		int i = 0;
+		for (unsigned long y = 0; y < height; y++)
+		for (unsigned long x = 0; x < width; x++, i++)
+		{
+			unsigned short tmpColor = (unsigned short)(buffer[2*i] | (buffer[2*i+1] << 8));
+			const libwpg::WPGColor color(tmpColor & 0x0f, (tmpColor >> 4) & 0x0f, (tmpColor >> 8) & 0x0f, (tmpColor >> 12) & 0x0f);
+			bitmap.setPixel(x, y, color);
+		}
+
+		m_painter->drawBitmap(bitmap, m_bitmap.hres, m_bitmap.vres);
+	}
+	else if (color_format == 8)
+	{
+		int i = 0;
+		for (unsigned long y = 0; y < height; y++)
+		for (unsigned long x = 0; x < width; x++, i++)
+		{
+			const libwpg::WPGColor color(buffer[3*i+2] & 0xff, buffer[3*i+1] & 0xff, buffer[3*i] & 0xff);
+			bitmap.setPixel(x, y, color);
+		}
+
+		m_painter->drawBitmap(bitmap, m_bitmap.hres, m_bitmap.vres);
+	}
+	else if (color_format == 9)
+	{
+		int i = 0;
+		for (unsigned long y = 0; y < height; y++)
+		for (unsigned long x = 0; x < width; x++, i++)
+		{
+			const libwpg::WPGColor color(buffer[4*i+3], buffer[4*i+2] & 0xff, buffer[4*i+1] & 0xff, buffer[4*i] & 0xff);
+			bitmap.setPixel(x, y, color);
+		}
+
+		m_painter->drawBitmap(bitmap, m_bitmap.hres, m_bitmap.vres);
+	}
+	else if (color_format == 12)
+	{
+		int i = 0;
+		for (unsigned long y = 0; y < height; y++)
+		for (unsigned long x = 0; x < width; x++, i++)
+		{
+			
+			const libwpg::WPGColor color(buffer[i], buffer[i], buffer[i]);
+			bitmap.setPixel(x, y, color);
+		}
+
+		m_painter->drawBitmap(bitmap, m_bitmap.hres, m_bitmap.vres);
+	}
+	
+	
+#ifdef DEBUG
+	// debugging only
+	if(buffer.size() && 0)
+	{
+		for(unsigned long x = 0; x < width; x++)
+		for(unsigned long y = 0; y < height; y++)
+		{
+			libwpg::WPGColor color = bitmap.pixel(x,y);
+			WPG_DEBUG_MSG((" pixel at %li, %li: %3d %3d %3d\n", x, y, color.red, color.green, color.blue));
+		}
+	}
+#endif
+}
+
+void WPG2Parser::handleObjectCapsule()
+{
+	if (!m_graphicsStarted)
+		return;
+	ObjectCharacterization objCh;
+	parseCharacterization(&objCh);
+	m_matrix = objCh.matrix;
+
+	long x1 = (m_doublePrecision) ? readS32() : readS16();
+	long y1 = (m_doublePrecision) ? readS32() : readS16();
+	long x2 = (m_doublePrecision) ? readS32() : readS16();
+	long y2 = (m_doublePrecision) ? readS32() : readS16();
+	TRANSFORM_XY(x1,y1);
+	TRANSFORM_XY(x2,y2);
+
+	long xs1 = (x1 <= x2) ? x1 : x2;
+	long xs2 = (x1 <= x2) ? x2 : x1;
+	long ys1 = (y1 <= y2) ? y1 : y2;
+	long ys2 = (y1 <= y2) ? y2 : y1;
+
+	m_binaryData.x1 = TO_DOUBLE(xs1) / m_xres;
+	m_binaryData.y1 = TO_DOUBLE(ys1) / m_yres;
+	m_binaryData.x2 = TO_DOUBLE(xs2) / m_xres;
+	m_binaryData.y2 = TO_DOUBLE(ys2) / m_yres;
+	
+	unsigned long numDescriptions = readU16();
+	
+	m_binaryData.mimeTypes.clear();
+	m_binaryData.mimeTypes.reserve(numDescriptions);
+	
+	static const char* mimeTypesMap[] =
+	{
+		"", // 0
+		"", // "image/x-wpg",
+		"", // "image/x-wpg",
+		"",
+		"",
+		"", // 5
+		"image/bmp",
+		"image/cgm",
+		"",
+		"image/x-dxf",
+		"image/x-eps", // 0xA
+		"",
+		"image/gif",
+		"application/vnd.hp-hpgl",
+		"",
+		"", // 0xF
+		"", // 0x10
+		"",
+		"",
+		"image/x-pcx ",
+		"image/x-lotus-pic",
+		"", // Ox15
+		"",
+		"image/x-quicktime",
+		"",
+		"application/x-postscript",
+		"", // 0x1A
+		"",
+		"image/x-targa",
+		"image/tiff",
+		"",
+		"image/wmf", // 0x1f
+		"", // 0x20
+		"",
+		"",
+		"",
+		"",
+		"image/png",
+		"image/gif" // 0x26
+	};
+
+	for (unsigned long i = 0; m_input->tell() <= m_recordEnd && !m_input->atEOS() && i < numDescriptions; i++)
+	{
+		unsigned char description = readU8();
+		if (description < 0x27)
+			m_binaryData.mimeTypes.push_back(libwpg::WPGString(mimeTypesMap[description]));
+		m_input->seek(7, WPX_SEEK_CUR);
+	}
+
+	m_binaryData.objectIndex = 0;
+
+	WPG_DEBUG_MSG(("             x1 : %li\n", x1));
+	WPG_DEBUG_MSG(("             y1 : %li\n", y1));
+	WPG_DEBUG_MSG(("             x2 : %li\n", x2));
+	WPG_DEBUG_MSG(("             y2 : %li\n", y2));
+	WPG_DEBUG_MSG(("numDescriptions : %li\n", numDescriptions));
+}
+
+void WPG2Parser::handleObjectImage()
+{
+	if (!m_graphicsStarted)
+		return;
+	if ((size_t)m_binaryData.objectIndex >= m_binaryData.mimeTypes.size())
+		return;
+	unsigned accessoryDataLength = readU16();
+	m_input->seek(accessoryDataLength, WPX_SEEK_CUR);
+	libwpg::WPGBinaryData binaryData;
+	binaryData.rect.x1 = m_binaryData.x1;
+	binaryData.rect.y1 = m_binaryData.y1;
+	binaryData.rect.x2 = m_binaryData.x2;
+	binaryData.rect.y2 = m_binaryData.y2;
+	binaryData.mimeType = m_binaryData.mimeTypes[m_binaryData.objectIndex];
+	
+	WPG_DEBUG_MSG(("Image Object Mime Type : %s\n", binaryData.mimeType.cstr()));
+
+	while (m_input->tell() <= m_recordEnd)
+		binaryData.append((char)readU8());
+	WPG_DEBUG_MSG(("     Image Object Size : %li\n", (unsigned long)binaryData.size()));
+
+	// temporary for debug - dump the binary data (need to have write access in the current directory
+#if DUMP_BINARY_DATA
+	std::ostringstream filename;
+	filename << "binarydump" << m_binaryId++ << ".bin";
+	FILE *f = fopen(filename.str().c_str(), "wb");
+	if (f)
+	{
+		const char *tmpBinaryBuffer = binaryData.getDataBuffer();
+		const size_t tmpBufferSize = binaryData.size();
+		for (size_t k = 0; k < tmpBufferSize; k++)
+			fprintf(f, "%c",tmpBinaryBuffer[k]);
+		fclose(f);
+	}
+#endif
+
+
+	m_painter->drawImageObject(binaryData);
+	m_binaryData.objectIndex++;
+}
+
+void WPG2Parser::resetPalette()
+{
+	m_colorPalette.clear();
+	for (int i=0; i<256; i++)
+	{
+		libwpg::WPGColor color;
+		color.red = defaultWPG2PaletteRed[i];
+		color.green = defaultWPG2PaletteGreen[i];
+		color.blue = defaultWPG2PaletteBlue[i];
+		m_colorPalette[i] = color;
+	}
+}
Index: scribus/plugins/wpgimplugin/wpg/WPGPen.cpp
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGPen.cpp	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGPen.cpp	(revision 13903)
@@ -0,0 +1,126 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "WPGPen.h"
+
+#include <vector>
+
+namespace libwpg
+{
+class WPGDashArrayPrivate
+{
+public:
+    WPGDashArrayPrivate() : dashes(std::vector<double>()) {};
+	std::vector<double> dashes;
+};
+}
+	
+libwpg::WPGDashArray::WPGDashArray() : d(new libwpg::WPGDashArrayPrivate())
+{
+}
+
+libwpg::WPGDashArray::~WPGDashArray()
+{
+	delete d;
+}
+
+libwpg::WPGDashArray::WPGDashArray(const libwpg::WPGDashArray& dash):
+	d(new libwpg::WPGDashArrayPrivate())
+{
+	d->dashes = dash.d->dashes;
+}
+
+libwpg::WPGDashArray& libwpg::WPGDashArray::operator=(const libwpg::WPGDashArray& dash)
+{
+	d->dashes = dash.d->dashes;
+	return *this;
+}
+
+unsigned libwpg::WPGDashArray::count() const
+{
+	return d->dashes.size();
+}
+
+double libwpg::WPGDashArray::at(unsigned i) const
+{
+	return d->dashes[i];
+}
+
+void libwpg::WPGDashArray::add(double p)
+{
+	d->dashes.push_back(p);
+}
+
+libwpg::WPGPen::WPGPen(): 
+	foreColor(0,0,0), 
+	backColor(0xFF,0xFF,0xFF), 
+	width(0), 
+	height(0), 
+	solid(true) ,
+	dashArray(WPGDashArray())
+{
+}
+
+libwpg::WPGPen::WPGPen(const WPGColor& fore): 
+	foreColor(fore), 
+	backColor(0xFF,0xFF,0xFF), 
+	width(0), 
+	height(0), 
+	solid(true),
+	dashArray(WPGDashArray()) 
+{
+}
+
+libwpg::WPGPen::WPGPen(const WPGColor& fore, const WPGColor& back): 
+	foreColor(fore),  
+	backColor(back), 
+	width(0), 
+	height(0), 
+	solid(true) ,
+	dashArray(WPGDashArray())
+{
+}
+
+libwpg::WPGPen::WPGPen(const WPGPen& pen):
+	foreColor(pen.foreColor),
+	backColor(pen.backColor),
+	width(pen.width),
+	height(pen.height),
+	solid(pen.solid),
+	dashArray(pen.dashArray)
+{
+}
+
+libwpg::WPGPen& libwpg::WPGPen::operator=(const libwpg::WPGPen& pen)
+{ 
+	foreColor = pen.foreColor; 
+	backColor = pen.backColor;
+	width = pen.width;
+	height = pen.height;
+	solid = pen.solid;
+	dashArray = pen.dashArray;
+	return *this;
+}
+
Index: scribus/plugins/wpgimplugin/wpg/WPGBinaryData.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGBinaryData.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGBinaryData.h	(revision 13903)
@@ -0,0 +1,66 @@
+/* libwpd
+ * Copyright (C) 2007 Fridrich Strba (fridrich.strba at bluewin.ch)
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ *
+ * For further information visit http://libwpd.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef WPGBINARYDATA_H
+#define WPGBINARYDATA_H
+
+#include "WPGString.h"
+#include "WPGRect.h"
+#include <stdio.h>
+
+class WPXInputStream;
+
+namespace libwpg
+{
+
+class WPGBinaryDataImpl;
+
+class WPGBinaryData
+{
+public:
+	WPGBinaryData();
+	WPGBinaryData(const WPGBinaryData &);
+	WPGBinaryData(const char *buffer, const size_t bufferSize);
+	~WPGBinaryData();
+
+	void append(const WPGBinaryData &data);
+	void append(const char *buffer, const size_t bufferSize);
+	void append(const char c);
+	void clear();
+	
+	size_t size() const;
+	const char *getDataBuffer() const;
+	const WPGString getBase64Data() const;
+
+	WPGBinaryData& operator=(const WPGBinaryData &);
+
+	WPGRect rect;
+	WPGString mimeType;
+
+private:
+	WPGBinaryDataImpl *m_binaryDataImpl;
+};
+
+} // namespace libwpg
+#endif
Index: scribus/plugins/wpgimplugin/wpg/WPGHeader.cpp
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGHeader.cpp	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGHeader.cpp	(revision 13903)
@@ -0,0 +1,121 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ * Copyright (C) 2004 Marc Oude Kotte (marc at solcon.nl)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "WPGHeader.h"
+#include "libwpg_utils.h"
+
+namespace
+{
+static inline unsigned short readU16( const void* p )
+{
+	const unsigned char* ptr = (const unsigned char*) p;
+	return (unsigned short)(ptr[0]+(ptr[1]<<8));
+}
+
+static inline unsigned long readU32( const void* p )
+{
+	const unsigned char* ptr = (const unsigned char*) p;
+	return ptr[0]+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
+}
+}
+
+WPGHeader::WPGHeader() :
+    m_identifier(),
+    m_startOfDocument(0L),
+    m_productType(0x01),
+    m_fileType(0x16),
+    m_majorVersion(0x02),
+    m_minorVersion(0x00),
+    m_encryptionKey(0x00),
+    m_startOfPacketData(0),
+    m_entryCount(0),
+    m_resourceComplete(0),
+    m_encryptionBlockOffset(0),
+    m_fileSize(0),
+    m_encryptVersion(0)
+{
+    m_identifier[0] = 0xff;
+    m_identifier[1] = 'W';
+    m_identifier[2] = 'P';
+    m_identifier[3] = 'C';
+}
+
+bool WPGHeader::load(WPXInputStream *input)
+{
+	input->seek(0, WPX_SEEK_SET);
+	
+	size_t n = 0;
+	unsigned char * prefix = (unsigned char *) input->read(26, n);
+	if(n < 26)
+        return false;
+	
+	m_identifier[0] = prefix[0];  
+	m_identifier[1] = prefix[1];  
+	m_identifier[2] = prefix[2];  
+	m_identifier[3] = prefix[3];  
+	m_startOfDocument = readU32(prefix+4);
+	m_productType = prefix[8];
+	m_fileType = prefix[9];
+	m_majorVersion = prefix[10];
+	m_minorVersion = prefix[11];
+	m_encryptionKey = readU16(prefix+12);
+	m_startOfPacketData = readU16(prefix+14);
+	
+	WPG_DEBUG_MSG(("Header Identifier  = %c%c%c\n", m_identifier[1], 
+	m_identifier[2], m_identifier[3]));
+	WPG_DEBUG_MSG(("Product type       = 0x%x\n",  m_productType));
+	WPG_DEBUG_MSG(("File type          = 0x%x\n",  m_fileType));
+	WPG_DEBUG_MSG(("Major version      = 0x%x\n",  m_majorVersion));
+	WPG_DEBUG_MSG(("Minor version      = 0x%x\n",  m_minorVersion));
+	WPG_DEBUG_MSG(("Encryption key     = 0x%x\n",  m_encryptionKey));
+	
+	return true;
+}
+
+bool WPGHeader::isSupported() const
+{
+	return (
+		(m_identifier[0] == 0xFF) &&
+		(m_identifier[1] == 'W') &&
+		(m_identifier[2] == 'P') &&
+		(m_identifier[3] == 'C') &&
+		(m_productType == 0x01) &&
+		(m_fileType == 0x16) &&
+		(m_encryptionKey == 0x00) &&     // we don't support encryption
+		((m_majorVersion == 0x02) || (m_majorVersion == 0x01)) &&
+		(m_minorVersion == 0x00) 
+);
+}
+
+unsigned long WPGHeader::startOfDocument() const
+{
+	return m_startOfDocument;
+}
+
+int WPGHeader::majorVersion() const
+{
+	return m_majorVersion;
+}
Index: scribus/plugins/wpgimplugin/wpg/WPGBrush.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGBrush.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGBrush.h	(revision 13903)
@@ -0,0 +1,66 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __WPGBRUSH_H__
+#define __WPGBRUSH_H__
+
+#include "WPGColor.h"
+#include "WPGGradient.h"
+
+namespace libwpg
+{
+
+class WPGBrush
+{
+public:
+
+	typedef enum
+	{
+		NoBrush,
+		Solid,
+		Pattern,
+		Gradient
+	} WPGBrushStyle;
+	
+	WPGBrushStyle style;
+	WPGColor foreColor;
+	WPGColor backColor;
+	
+	WPGGradient gradient;
+
+	WPGBrush();
+
+	explicit WPGBrush(const WPGColor& fore);
+
+	WPGBrush(const WPGColor& fore, const WPGColor& back);
+
+	WPGBrush(const WPGBrush& brush);
+
+	WPGBrush& operator=(const WPGBrush& brush);
+};
+
+} // namespace libwpg
+
+#endif // __WPGBRUSH_H__
Index: scribus/plugins/wpgimplugin/wpg/WPGXParser.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGXParser.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGXParser.h	(revision 13903)
@@ -0,0 +1,60 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ * Copyright (C) 2004 Marc Oude Kotte (marc at solcon.nl)
+ * Copyright (C) 2005 Fridrich Strba (fridrich.strba at bluewin.ch)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef __WPGXPARSER_H__
+#define __WPGXPARSER_H__
+
+#include "WPGPaintInterface.h"
+#include "WPXStream.h"
+#include "WPGColor.h"
+
+#include <map>
+
+class WPGXParser
+{
+public:
+	WPGXParser(WPXInputStream *input, libwpg::WPGPaintInterface* painter);
+	WPGXParser(const WPGXParser& parser);
+	virtual ~WPGXParser() {};
+	virtual bool parse() = 0;
+	
+	unsigned char readU8();
+	unsigned short readU16();  
+	unsigned int readU32();  
+	signed char readS8();
+	short readS16();  
+	int readS32();  
+	unsigned int readVariableLengthInteger();
+	WPGXParser& operator=(const WPGXParser& parser);
+	
+protected:
+	WPXInputStream* m_input;
+	libwpg::WPGPaintInterface* m_painter;
+	std::map<int,libwpg::WPGColor> m_colorPalette;
+};
+
+#endif // __WPGXPARSER_H__
Index: scribus/plugins/wpgimplugin/wpg/WPGOLEStream.cpp
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGOLEStream.cpp	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGOLEStream.cpp	(revision 13903)
@@ -0,0 +1,1012 @@
+/* POLE - Portable C++ library to access OLE Storage 
+   Copyright (C) 2002-2005 Ariya Hidayat <ariya at kde.org>
+
+   Redistribution and use in source and binary forms, with or without 
+   modification, are permitted provided that the following conditions 
+   are met:
+   * Redistributions of source code must retain the above copyright notice, 
+     this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright notice, 
+     this list of conditions and the following disclaimer in the documentation 
+     and/or other materials provided with the distribution.
+   * Neither the name of the authors nor the names of its contributors may be 
+     used to endorse or promote products derived from this software without 
+     specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
+   THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ This file taken from libwpg WPGOLEStream.cpp 1.5 Thu Aug 17 21:21:30 2006
+*/
+
+#include "WPGOLEStream.h"
+
+#include <sstream>
+#include <iostream>
+#include <list>
+#include <string>
+#include <vector>
+
+#include <string.h>
+
+namespace libwpg
+{
+
+class Header
+{
+  public:
+    unsigned char id[8];       // signature, or magic identifier
+    unsigned b_shift;          // bbat->blockSize = 1 << b_shift
+    unsigned s_shift;          // sbat->blockSize = 1 << s_shift
+    unsigned num_bat;          // blocks allocated for big bat
+    unsigned dirent_start;     // starting block for directory info
+    unsigned threshold;        // switch from small to big file (usually 4K)
+    unsigned sbat_start;       // starting block index to store small bat
+    unsigned num_sbat;         // blocks allocated for small bat
+    unsigned mbat_start;       // starting block to store meta bat
+    unsigned num_mbat;         // blocks allocated for meta bat
+    unsigned long bb_blocks[109];
+    
+    Header();
+    bool valid();
+    void load( const unsigned char* buffer );
+    void save( unsigned char* buffer );
+    void debug();
+};
+
+class AllocTable
+{
+  public:
+    static const unsigned Eof;
+    static const unsigned Avail;
+    static const unsigned Bat;    
+    static const unsigned MetaBat;    
+    unsigned blockSize;
+    AllocTable();
+    void clear();
+    unsigned long count();
+    void resize( unsigned long newsize );
+    void preserve( unsigned long n );
+    void set( unsigned long index, unsigned long val );
+    unsigned unused();
+    void setChain( std::vector<unsigned long> );
+    std::vector<unsigned long> follow( unsigned long start );
+    unsigned long operator[](unsigned long index );
+    void load( const unsigned char* buffer, unsigned len );
+    void save( unsigned char* buffer );
+  private:
+    std::vector<unsigned long> data;
+    AllocTable( const AllocTable& );
+    AllocTable& operator=( const AllocTable& );
+};
+
+class DirEntry
+{
+  public:
+    DirEntry() : valid(false), name(), dir(false), size(0), start(0),
+    	prev(0), next(0), child(0) {};
+    bool valid;            // false if invalid (should be skipped)
+    std::string name;      // the name, not in unicode anymore 
+    bool dir;              // true if directory   
+    unsigned long size;    // size (not valid if directory)
+    unsigned long start;   // starting block
+    unsigned prev;         // previous sibling
+    unsigned next;         // next sibling
+    unsigned child;        // first child
+};
+
+class DirTree
+{
+  public:
+    static const unsigned End;
+    DirTree();
+    void clear();
+    unsigned entryCount();
+    DirEntry* entry( unsigned index );
+    DirEntry* entry( const std::string& name );
+    int parent( unsigned index );
+    std::string fullName( unsigned index );
+    std::vector<unsigned> children( unsigned index );
+    void load( unsigned char* buffer, unsigned len );
+    void save( unsigned char* buffer );
+  private:
+    std::vector<DirEntry> entries;
+    DirTree( const DirTree& );
+    DirTree& operator=( const DirTree& );
+};
+
+class StorageIO
+{
+  public:
+    Storage* storage;         // owner
+    std::stringstream buf;
+    int result;               // result of operation
+    unsigned long bufsize;    // size of the buffer
+    
+    Header* header;           // storage header 
+    DirTree* dirtree;         // directory tree
+    AllocTable* bbat;         // allocation table for big blocks
+    AllocTable* sbat;         // allocation table for small blocks
+    
+    std::vector<unsigned long> sb_blocks; // blocks for "small" files
+       
+    std::list<Stream*> streams;
+
+    StorageIO( Storage* storage, const std::stringstream &memorystream );
+    ~StorageIO();
+    
+    bool isOLEStream();
+    void load();
+
+    unsigned long loadBigBlocks( std::vector<unsigned long> blocks, unsigned char* buffer, unsigned long maxlen );
+
+    unsigned long loadBigBlock( unsigned long block, unsigned char* buffer, unsigned long maxlen );
+
+    unsigned long loadSmallBlocks( std::vector<unsigned long> blocks, unsigned char* buffer, unsigned long maxlen );
+
+    unsigned long loadSmallBlock( unsigned long block, unsigned char* buffer, unsigned long maxlen );
+    
+    StreamIO* streamIO( const std::string& name ); 
+
+  private:  
+    // no copy or assign
+    StorageIO( const StorageIO& );
+    StorageIO& operator=( const StorageIO& );
+
+};
+
+class StreamIO
+{
+  public:
+    StorageIO* io;
+    DirEntry* entry;
+    std::string fullName;
+    bool eof;
+    bool fail;
+
+    StreamIO( StorageIO* io, DirEntry* entry );
+    ~StreamIO();
+    unsigned long size();
+    unsigned long tell();
+    int getch();
+    unsigned long read( unsigned char* data, unsigned long maxlen );
+    unsigned long read( unsigned long pos, unsigned char* data, unsigned long maxlen );
+
+
+  private:
+    std::vector<unsigned long> blocks;
+
+    // no copy or assign
+    StreamIO( const StreamIO& );
+    StreamIO& operator=( const StreamIO& );
+
+    // pointer for read
+    unsigned long m_pos;
+
+    // simple cache system to speed-up getch()
+    unsigned char* cache_data;
+    unsigned long cache_size;
+    unsigned long cache_pos;
+    void updateCache();
+};
+
+} // namespace libwpg
+
+static inline unsigned long readU16( const unsigned char* ptr )
+{
+  return ptr[0]+(ptr[1]<<8);
+}
+
+static inline unsigned long readU32( const unsigned char* ptr )
+{
+  return ptr[0]+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
+}
+
+static const unsigned char wpsole_magic[] =
+ { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 };
+
+
+// =========== Header ==========
+
+libwpg::Header::Header() :
+	b_shift(9),
+	s_shift(6),
+	num_bat(0),
+	dirent_start(0),
+	threshold(4096),
+	sbat_start(0),
+	num_sbat(0),
+	mbat_start(0),
+	num_mbat(0)
+{
+  for( unsigned i = 0; i < 8; i++ )
+    id[i] = wpsole_magic[i];
+  for( unsigned j=0; j<109; j++ )
+    bb_blocks[j] = libwpg::AllocTable::Avail;
+}
+
+bool libwpg::Header::valid()
+{
+  if( threshold != 4096 ) return false;
+  if( num_bat == 0 ) return false;
+  if( (num_bat > 109) && (num_bat > (num_mbat * 127) + 109)) return false;
+  if( (num_bat < 109) && (num_mbat != 0) ) return false;
+  if( s_shift > b_shift ) return false;
+  if( b_shift <= 6 ) return false;
+  if( b_shift >=31 ) return false;
+
+  return true;
+}
+
+void libwpg::Header::load( const unsigned char* buffer )
+{
+  b_shift      = readU16( buffer + 0x1e );
+  s_shift      = readU16( buffer + 0x20 );
+  num_bat      = readU32( buffer + 0x2c );
+  dirent_start = readU32( buffer + 0x30 );
+  threshold    = readU32( buffer + 0x38 );
+  sbat_start   = readU32( buffer + 0x3c );
+  num_sbat     = readU32( buffer + 0x40 );
+  mbat_start   = readU32( buffer + 0x44 );
+  num_mbat     = readU32( buffer + 0x48 );
+
+  for( unsigned i = 0; i < 8; i++ )
+    id[i] = buffer[i];
+  for( unsigned j=0; j<109; j++ )
+    bb_blocks[j] = readU32( buffer + 0x4C+j*4 );
+}
+
+
+ 
+// =========== AllocTable ==========
+
+const unsigned libwpg::AllocTable::Avail = 0xffffffff;
+const unsigned libwpg::AllocTable::Eof = 0xfffffffe;
+const unsigned libwpg::AllocTable::Bat = 0xfffffffd;
+const unsigned libwpg::AllocTable::MetaBat = 0xfffffffc;
+
+libwpg::AllocTable::AllocTable() :
+	blockSize(4096),
+	data()
+{
+  // initial size
+  resize( 128 );
+}
+
+unsigned long libwpg::AllocTable::count()
+{
+  return data.size();
+}
+
+void libwpg::AllocTable::resize( unsigned long newsize )
+{
+  unsigned oldsize = data.size();
+  data.resize( newsize );
+  if( newsize > oldsize )
+    for( unsigned i = oldsize; i<newsize; i++ )
+      data[i] = Avail;
+}
+
+// make sure there're still free blocks
+void libwpg::AllocTable::preserve( unsigned long n )
+{
+  std::vector<unsigned long> pre;
+  for( unsigned i=0; i < n; i++ )
+    pre.push_back( unused() );
+}
+
+unsigned long libwpg::AllocTable::operator[]( unsigned long index )
+{
+  unsigned long result;
+  result = data[index];
+  return result;
+}
+
+void libwpg::AllocTable::set( unsigned long index, unsigned long value )
+{
+  if( index >= count() ) resize( index + 1);
+  data[ index ] = value;
+}
+
+void libwpg::AllocTable::setChain( std::vector<unsigned long> chain )
+{
+  if( chain.size() )
+  {
+    for( unsigned i=0; i<chain.size()-1; i++ )
+      set( chain[i], chain[i+1] );
+    set( chain[ chain.size()-1 ], AllocTable::Eof );
+  }
+}
+
+// TODO: optimize this with better search
+static bool already_exist(const std::vector<unsigned long>& chain,
+unsigned long item)
+{
+ for(unsigned i = 0; i < chain.size(); i++)
+   if(chain[i] == item) return true;
+
+ return false;
+} 
+
+// follow 
+std::vector<unsigned long> libwpg::AllocTable::follow( unsigned long start )
+{
+  std::vector<unsigned long> chain;
+
+  if( start >= count() ) return chain; 
+
+  unsigned long p = start;
+  while( p < count() )
+  {
+    if( p == (unsigned long)Eof ) break;
+    if( p == (unsigned long)Bat ) break;
+    if( p == (unsigned long)MetaBat ) break;
+    if( already_exist(chain, p) ) break; 
+    chain.push_back( p );
+    if( data[p] >= count() ) break;
+    p = data[ p ];
+  }
+
+  return chain;
+}
+
+unsigned libwpg::AllocTable::unused()
+{
+  // find first available block
+  for( unsigned i = 0; i < data.size(); i++ )
+    if( data[i] == Avail )
+      return i;
+  
+  // completely full, so enlarge the table
+  unsigned block = data.size();
+  resize( data.size()+10 );
+  return block;      
+}
+
+void libwpg::AllocTable::load( const unsigned char* buffer, unsigned len )
+{
+  resize( len / 4 );
+  for( unsigned i = 0; i < count(); i++ )
+    set( i, readU32( buffer + i*4 ) );
+}
+
+// =========== DirTree ==========
+
+const unsigned libwpg::DirTree::End = 0xffffffff;
+
+libwpg::DirTree::DirTree() :
+	entries()
+{
+  clear();
+}
+
+void libwpg::DirTree::clear()
+{
+  // leave only root entry
+  entries.resize( 1 );
+  entries[0].valid = true;
+  entries[0].name = "Root Entry";
+  entries[0].dir = true;
+  entries[0].size = 0;
+  entries[0].start = End;
+  entries[0].prev = End;
+  entries[0].next = End;
+  entries[0].child = End;
+}
+
+unsigned libwpg::DirTree::entryCount()
+{
+  return entries.size();
+}
+
+libwpg::DirEntry* libwpg::DirTree::entry( unsigned index )
+{
+  if( index >= entryCount() ) return (libwpg::DirEntry*) 0;
+  return &entries[ index ];
+}
+
+int libwpg::DirTree::parent( unsigned index )
+{
+  // brute-force, basically we iterate for each entries, find its children
+  // and check if one of the children is 'index'
+  for( unsigned j=0; j<entryCount(); j++ )
+  {
+    std::vector<unsigned> chi = children( j );
+    for( unsigned i=0; i<chi.size();i++ )
+      if( chi[i] == index )
+        return j;
+  }
+        
+  return -1;
+}
+
+std::string libwpg::DirTree::fullName( unsigned index )
+{
+  // don't use root name ("Root Entry"), just give "/"
+  if( index == 0 ) return "/";
+
+  std::string result = entry( index )->name;
+  result.insert( 0,  "/" );
+  int p = parent( index );
+  DirEntry * _entry = 0;
+  while( p > 0 )
+  {
+    _entry = entry( p );
+    if (_entry->dir && _entry->valid)
+    {
+      result.insert( 0,  _entry->name);
+      result.insert( 0,  "/" );
+    }
+    --p;
+    index = p;
+    if( index <= 0 ) break;
+  }
+  return result;
+}
+
+// given a fullname (e.g "/ObjectPool/_1020961869"), find the entry
+libwpg::DirEntry* libwpg::DirTree::entry( const std::string& name )
+{
+
+   if( !name.length() ) return (libwpg::DirEntry*)0;
+ 
+   // quick check for "/" (that's root)
+   if( name == "/" ) return entry( 0 );
+   
+   // split the names, e.g  "/ObjectPool/_1020961869" will become:
+   // "ObjectPool" and "_1020961869" 
+   std::list<std::string> names;
+   std::string::size_type start = 0, end = 0;
+   if( name[0] == '/' ) start++;
+   while( start < name.length() )
+   {
+     end = name.find_first_of( '/', start );
+     if( end == std::string::npos ) end = name.length();
+     names.push_back( name.substr( start, end-start ) );
+     start = end+1;
+   }
+  
+   // start from root 
+   int index = 0 ;
+
+   // trace one by one   
+   std::list<std::string>::iterator it; 
+
+   for( it = names.begin(); it != names.end(); ++it )
+   {
+     // find among the children of index
+     std::vector<unsigned> chi = children( index );
+     unsigned child = 0;
+     for( unsigned i = 0; i < chi.size(); i++ )
+     {
+       libwpg::DirEntry* ce = entry( chi[i] );
+       if( ce ) 
+       if( ce->valid && ( ce->name.length()>1 ) )
+       if( ce->name == *it )
+             child = chi[i];
+     }
+     
+     // traverse to the child
+     if( child > 0 ) index = child;
+     else return (libwpg::DirEntry*)0;
+   }
+
+   return entry( index );
+}
+
+// helper function: recursively find siblings of index
+void dirtree_find_siblings( libwpg::DirTree* dirtree, std::vector<unsigned>& result, 
+  unsigned index )
+{
+  libwpg::DirEntry* e = dirtree->entry( index );
+  if( !e ) return;
+  if( !e->valid ) return;
+
+  // prevent infinite loop  
+  for( unsigned i = 0; i < result.size(); i++ )
+    if( result[i] == index ) return;
+
+  // add myself    
+  result.push_back( index );
+  
+  // visit previous sibling, don't go infinitely
+  unsigned prev = e->prev;
+  if( ( prev > 0 ) && ( prev < dirtree->entryCount() ) )
+  {
+    for( unsigned i = 0; i < result.size(); i++ )
+      if( result[i] == prev ) prev = 0;
+    if( prev ) dirtree_find_siblings( dirtree, result, prev );
+  }
+    
+  // visit next sibling, don't go infinitely
+  unsigned next = e->next;
+  if( ( next > 0 ) && ( next < dirtree->entryCount() ) )
+  {
+    for( unsigned i = 0; i < result.size(); i++ )
+      if( result[i] == next ) next = 0;
+    if( next ) dirtree_find_siblings( dirtree, result, next );
+  }
+}
+
+std::vector<unsigned> libwpg::DirTree::children( unsigned index )
+{
+  std::vector<unsigned> result;
+  
+  DirEntry* e = entry( index );
+  if( e ) if( e->valid && e->child < entryCount() )
+    dirtree_find_siblings( this, result, e->child );
+    
+  return result;
+}
+
+void libwpg::DirTree::load( unsigned char* buffer, unsigned size )
+{
+  entries.clear();
+  
+  for( unsigned i = 0; i < size/128; i++ )
+  {
+    unsigned p = i * 128;
+    
+    // would be < 32 if first char in the name isn't printable
+    unsigned prefix = 32;
+    
+    // parse name of this entry, which stored as Unicode 16-bit
+    std::string name;
+    int name_len = readU16( buffer + 0x40+p );
+    if( name_len > 64 ) name_len = 64;
+    for( int j=0; ( buffer[j+p]) && (j<name_len); j+= 2 )
+      name.append( 1, buffer[j+p] );
+      
+    // first char isn't printable ? remove it...
+    if( buffer[p] < 32 )
+    { 
+      prefix = buffer[0]; 
+      name.erase( 0,1 ); 
+    }
+    
+    // 2 = file (aka stream), 1 = directory (aka storage), 5 = root
+    unsigned type = buffer[ 0x42 + p];
+    
+    libwpg::DirEntry e;
+    e.valid = true;
+    e.name = name;
+    e.start = readU32( buffer + 0x74+p );
+    e.size = readU32( buffer + 0x78+p );
+    e.prev = readU32( buffer + 0x44+p );
+    e.next = readU32( buffer + 0x48+p );
+    e.child = readU32( buffer + 0x4C+p );
+    e.dir = ( type!=2 );
+    
+    // sanity checks
+    if( (type != 2) && (type != 1 ) && (type != 5 ) ) e.valid = false;
+    if( name_len < 1 ) e.valid = false;
+    
+    entries.push_back( e );
+  }  
+}
+
+// =========== StorageIO ==========
+
+libwpg::StorageIO::StorageIO( libwpg::Storage* st, const std::stringstream &memorystream ) :
+	storage(st),
+	buf( memorystream.str(), std::ios::binary | std::ios::in ),
+	result(libwpg::Storage::Ok),
+	bufsize(0),
+	header(new libwpg::Header()),
+	dirtree(new libwpg::DirTree()),
+	bbat(new libwpg::AllocTable()),
+	sbat(new libwpg::AllocTable()),
+	sb_blocks(),
+	streams()
+{
+  bbat->blockSize = 1 << header->b_shift;
+  sbat->blockSize = 1 << header->s_shift;
+}
+
+libwpg::StorageIO::~StorageIO()
+{
+  delete sbat;
+  delete bbat;
+  delete dirtree;
+  delete header;
+
+  std::list<libwpg::Stream*>::iterator it;
+  for( it = streams.begin(); it != streams.end(); ++it )
+    delete *it;
+}
+
+bool libwpg::StorageIO::isOLEStream()
+{
+  load();
+  return (result == libwpg::Storage::Ok);
+}
+
+void libwpg::StorageIO::load()
+{
+  unsigned char* buffer = 0;
+  unsigned long buflen = 0;
+  std::vector<unsigned long> blocks;
+  
+  // find size of input file
+  buf.seekg( 0, std::ios::end );
+  bufsize = buf.tellg();
+
+  // load header
+  buffer = new unsigned char[512];
+  buf.seekg( 0 ); 
+  buf.read( (char*)buffer, 512 );
+  header->load( buffer );
+  delete[] buffer;
+
+  // check OLE magic id
+  result = libwpg::Storage::NotOLE;
+  for( unsigned i=0; i<8; i++ )
+    if( header->id[i] != wpsole_magic[i] )
+      return;
+ 
+  // sanity checks
+  result = libwpg::Storage::BadOLE;
+  if( !header->valid() ) return;
+  if( header->threshold != 4096 ) return;
+
+  // important block size
+  bbat->blockSize = 1 << header->b_shift;
+  sbat->blockSize = 1 << header->s_shift;
+  
+  // find blocks allocated to store big bat
+  // the first 109 blocks are in header, the rest in meta bat
+  blocks.clear();
+  blocks.resize( header->num_bat );
+  for( unsigned j = 0; j < 109; j++ )
+    if( j >= header->num_bat ) break;
+    else blocks[j] = header->bb_blocks[j];
+  if( (header->num_bat > 109) && (header->num_mbat > 0) )
+  {
+    unsigned char* buffer2 = new unsigned char[ bbat->blockSize ];
+    unsigned k = 109;
+    for( unsigned r = 0; r < header->num_mbat; r++ )
+    {
+      loadBigBlock( header->mbat_start+r, buffer2, bbat->blockSize );
+      for( unsigned s=0; s < bbat->blockSize; s+=4 )
+      {
+        if( k >= header->num_bat ) break;
+        else  blocks[k++] = readU32( buffer2 + s );
+      }  
+     }    
+    delete[] buffer2;
+  }
+
+  // load big bat
+  buflen = blocks.size()*bbat->blockSize;
+  if( buflen > 0 )
+  {
+    buffer = new unsigned char[ buflen ];  
+    loadBigBlocks( blocks, buffer, buflen );
+    bbat->load( buffer, buflen );
+    delete[] buffer;
+  }  
+
+  // load small bat
+  blocks.clear();
+  blocks = bbat->follow( header->sbat_start );
+  buflen = blocks.size()*bbat->blockSize;
+  if( buflen > 0 )
+  {
+    buffer = new unsigned char[ buflen ];  
+    loadBigBlocks( blocks, buffer, buflen );
+    sbat->load( buffer, buflen );
+    delete[] buffer;
+  }  
+  
+  // load directory tree
+  blocks.clear();
+  blocks = bbat->follow( header->dirent_start );
+  buflen = blocks.size()*bbat->blockSize;
+  buffer = new unsigned char[ buflen ];  
+  loadBigBlocks( blocks, buffer, buflen );
+  dirtree->load( buffer, buflen );
+  unsigned sb_start = readU32( buffer + 0x74 );
+  delete[] buffer;
+  
+  // fetch block chain as data for small-files
+  sb_blocks = bbat->follow( sb_start ); // small files
+  
+  // so far so good
+  result = libwpg::Storage::Ok;
+}
+
+libwpg::StreamIO* libwpg::StorageIO::streamIO( const std::string& name )
+{
+  load();
+
+  // sanity check
+  if( !name.length() ) return (libwpg::StreamIO*)0;
+
+  // search in the entries
+  libwpg::DirEntry* entry = dirtree->entry( name );
+  if( !entry ) return (libwpg::StreamIO*)0;
+  if( entry->dir ) return (libwpg::StreamIO*)0;
+
+  libwpg::StreamIO* result = new libwpg::StreamIO( this, entry );
+  result->fullName = name;
+  
+  return result;
+}
+
+unsigned long libwpg::StorageIO::loadBigBlocks( std::vector<unsigned long> blocks,
+  unsigned char* data, unsigned long maxlen )
+{
+  // sentinel
+  if( !data ) return 0;
+  if( blocks.size() < 1 ) return 0;
+  if( maxlen == 0 ) return 0;
+
+  // read block one by one, seems fast enough
+  unsigned long bytes = 0;
+  for( unsigned long i=0; (i < blocks.size() ) & ( bytes<maxlen ); i++ )
+  {
+    unsigned long block = blocks[i];
+    unsigned long pos =  bbat->blockSize * ( block+1 );
+    unsigned long p = (bbat->blockSize < maxlen-bytes) ? bbat->blockSize : maxlen-bytes;
+    if( pos + p > bufsize ) p = bufsize - pos;
+    buf.seekg( pos );
+    buf.read( (char*)data + bytes, p );
+    bytes += p;
+  }
+
+  return bytes;
+}
+
+unsigned long libwpg::StorageIO::loadBigBlock( unsigned long block,
+  unsigned char* data, unsigned long maxlen )
+{
+  // sentinel
+  if( !data ) return 0;
+
+  // wraps call for loadBigBlocks
+  std::vector<unsigned long> blocks;
+  blocks.resize( 1 );
+  blocks[ 0 ] = block;
+  
+  return loadBigBlocks( blocks, data, maxlen );
+}
+
+// return number of bytes which has been read
+unsigned long libwpg::StorageIO::loadSmallBlocks( std::vector<unsigned long> blocks,
+  unsigned char* data, unsigned long maxlen )
+{
+  // sentinel
+  if( !data ) return 0;
+  if( blocks.size() < 1 ) return 0;
+  if( maxlen == 0 ) return 0;
+
+  // our own local buffer
+  unsigned char* buf = new unsigned char[ bbat->blockSize ];
+
+  // read small block one by one
+  unsigned long bytes = 0;
+  for( unsigned long i=0; ( i<blocks.size() ) & ( bytes<maxlen ); i++ )
+  {
+    unsigned long block = blocks[i];
+
+    // find where the small-block exactly is
+    unsigned long pos = block * sbat->blockSize;
+    unsigned long bbindex = pos / bbat->blockSize;
+    if( bbindex >= sb_blocks.size() ) break;
+
+    loadBigBlock( sb_blocks[ bbindex ], buf, bbat->blockSize );
+
+    // copy the data
+    unsigned offset = pos % bbat->blockSize;
+    unsigned long p = (maxlen-bytes < bbat->blockSize-offset ) ? maxlen-bytes :  bbat->blockSize-offset;
+    p = (sbat->blockSize<p ) ? sbat->blockSize : p;
+    memcpy( data + bytes, buf + offset, p );
+    bytes += p;
+  }
+  
+  delete[] buf;
+
+  return bytes;
+}
+
+unsigned long libwpg::StorageIO::loadSmallBlock( unsigned long block,
+  unsigned char* data, unsigned long maxlen )
+{
+  // sentinel
+  if( !data ) return 0;
+
+  // wraps call for loadSmallBlocks
+  std::vector<unsigned long> blocks;
+  blocks.resize( 1 );
+  blocks.assign( 1, block );
+
+  return loadSmallBlocks( blocks, data, maxlen );
+}
+
+// =========== StreamIO ==========
+
+libwpg::StreamIO::StreamIO( libwpg::StorageIO* s, libwpg::DirEntry* e) :
+	io(s),
+	entry(e),
+	fullName(),
+	eof(false),
+	fail(false),
+	blocks(),
+	m_pos(0),
+	cache_data(0),
+	cache_size(4096),
+	cache_pos(0)
+{
+  if( entry->size >= io->header->threshold ) 
+    blocks = io->bbat->follow( entry->start );
+  else
+    blocks = io->sbat->follow( entry->start );
+
+  // prepare cache
+  cache_data = new unsigned char[cache_size];
+  updateCache();
+}
+
+// FIXME tell parent we're gone
+libwpg::StreamIO::~StreamIO()
+{
+  delete[] cache_data;  
+}
+
+unsigned long libwpg::StreamIO::tell()
+{
+  return m_pos;
+}
+
+int libwpg::StreamIO::getch()
+{
+  // past end-of-file ?
+  if( m_pos > entry->size ) return -1;
+
+  // need to update cache ?
+  if( !cache_size || ( m_pos < cache_pos ) ||
+    ( m_pos >= cache_pos + cache_size ) )
+      updateCache();
+
+  // something bad if we don't get good cache
+  if( !cache_size ) return -1;
+
+  int data = cache_data[m_pos - cache_pos];
+  m_pos++;
+
+  return data;
+}
+
+unsigned long libwpg::StreamIO::read( unsigned long pos, unsigned char* data, unsigned long maxlen )
+{
+  // sanity checks
+  if( !data ) return 0;
+  if( maxlen == 0 ) return 0;
+
+  unsigned long totalbytes = 0;
+  
+  if ( entry->size < io->header->threshold )
+  {
+    // small file
+    unsigned long index = pos / io->sbat->blockSize;
+
+    if( index >= blocks.size() ) return 0;
+
+    unsigned char* buf = new unsigned char[ io->sbat->blockSize ];
+    unsigned long offset = pos % io->sbat->blockSize;
+    while( totalbytes < maxlen )
+    {
+      if( index >= blocks.size() ) break;
+      io->loadSmallBlock( blocks[index], buf, io->bbat->blockSize );
+      unsigned long count = io->sbat->blockSize - offset;
+      if( count > maxlen-totalbytes ) count = maxlen-totalbytes;
+      memcpy( data+totalbytes, buf + offset, count );
+      totalbytes += count;
+      offset = 0;
+      index++;
+    }
+    delete[] buf;
+
+  }
+  else
+  {
+    // big file
+    unsigned long index = pos / io->bbat->blockSize;
+    
+    if( index >= blocks.size() ) return 0;
+    
+    unsigned char* buf = new unsigned char[ io->bbat->blockSize ];
+    unsigned long offset = pos % io->bbat->blockSize;
+    while( totalbytes < maxlen )
+    {
+      if( index >= blocks.size() ) break;
+      io->loadBigBlock( blocks[index], buf, io->bbat->blockSize );
+      unsigned long count = io->bbat->blockSize - offset;
+      if( count > maxlen-totalbytes ) count = maxlen-totalbytes;
+      memcpy( data+totalbytes, buf + offset, count );
+      totalbytes += count;
+      index++;
+      offset = 0;
+    }
+    delete [] buf;
+
+  }
+
+  return totalbytes;
+}
+
+unsigned long libwpg::StreamIO::read( unsigned char* data, unsigned long maxlen )
+{
+  unsigned long bytes = read( tell(), data, maxlen );
+  m_pos += bytes;
+  return bytes;
+}
+
+void libwpg::StreamIO::updateCache()
+{
+  // sanity check
+  if( !cache_data ) return;
+
+  cache_pos = m_pos - ( m_pos % cache_size );
+  unsigned long bytes = cache_size;
+  if( cache_pos + bytes > entry->size ) bytes = entry->size - cache_pos;
+  cache_size = read( cache_pos, cache_data, bytes );
+}
+
+
+// =========== Storage ==========
+
+libwpg::Storage::Storage( const std::stringstream &memorystream ) :
+	io(NULL)
+{
+	io = new StorageIO( this, memorystream );
+}
+
+libwpg::Storage::~Storage()
+{
+  delete io;
+}
+
+int libwpg::Storage::result()
+{
+  return io->result;
+}
+
+bool libwpg::Storage::isOLEStream()
+{
+  return io->isOLEStream();
+}
+
+// =========== Stream ==========
+
+libwpg::Stream::Stream( libwpg::Storage* storage, const std::string& name ) :
+	io(storage->io->streamIO( name ))
+{
+}
+
+// FIXME tell parent we're gone
+libwpg::Stream::~Stream()
+{
+  delete io;
+}
+
+unsigned long libwpg::Stream::size()
+{
+  return io ? io->entry->size : 0;
+}
+
+unsigned long libwpg::Stream::read( unsigned char* data, unsigned long maxlen )
+{
+  return io ? io->read( data, maxlen ) : 0;
+}
Index: scribus/plugins/wpgimplugin/wpg/WPGPath.cpp
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGPath.cpp	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGPath.cpp	(revision 13903)
@@ -0,0 +1,114 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "WPGPath.h"
+#include "WPGPoint.h"
+
+#include <vector>
+
+namespace libwpg
+{
+
+class WPGPathPrivate
+{
+public:
+    WPGPathPrivate() : elements(std::vector<WPGPathElement>()) {};
+	std::vector<WPGPathElement> elements;
+};
+
+} // namespace libwpg
+
+libwpg::WPGPathElement::WPGPathElement():
+	type(NullElement),
+	point(WPGPoint()),
+	extra1(WPGPoint()),
+	extra2(WPGPoint())
+{}
+
+libwpg::WPGPath::WPGPath(): closed(true), d(new libwpg::WPGPathPrivate())
+{}
+	
+libwpg::WPGPath::~WPGPath()
+{
+	delete d;
+}
+	
+libwpg::WPGPath::WPGPath(const libwpg::WPGPath& path): closed(path.closed), framed(path.framed), filled(path.filled), d(new libwpg::WPGPathPrivate())
+{
+	d->elements = std::vector<WPGPathElement>(path.d->elements);
+}
+	
+libwpg::WPGPath& libwpg::WPGPath::operator=(const libwpg::WPGPath& path)
+{
+	d->elements = std::vector<WPGPathElement>(path.d->elements);
+	return *this;
+}
+	
+unsigned libwpg::WPGPath::count() const
+{
+	return d->elements.size();
+}
+	
+libwpg::WPGPathElement libwpg::WPGPath::element(unsigned index) const
+{
+	return d->elements[index];
+}
+	
+void libwpg::WPGPath::moveTo(const libwpg::WPGPoint& point)
+{
+	libwpg::WPGPathElement tmpElement;
+	tmpElement.type = libwpg::WPGPathElement::MoveToElement;
+	tmpElement.point = point;
+	addElement(tmpElement);
+}
+	
+void libwpg::WPGPath::lineTo(const libwpg::WPGPoint& point)
+{
+	libwpg::WPGPathElement tmpElement;
+	tmpElement.type = libwpg::WPGPathElement::LineToElement;
+	tmpElement.point = point;
+	addElement(tmpElement);
+}
+	
+void libwpg::WPGPath::curveTo(const libwpg::WPGPoint& c1, const libwpg::WPGPoint& c2, const libwpg::WPGPoint& endPoint)
+{
+	libwpg::WPGPathElement tmpElement;
+	tmpElement.type = libwpg::WPGPathElement::CurveToElement;
+	tmpElement.point = endPoint;
+	tmpElement.extra1 = c1;
+	tmpElement.extra2 = c2;
+	addElement(tmpElement);
+}
+	
+void libwpg::WPGPath::addElement(const libwpg::WPGPathElement& elem)
+{
+	d->elements.push_back(elem);
+}
+
+void libwpg::WPGPath::append(const libwpg::WPGPath& path)
+{
+	for(unsigned i = 0; i < path.count(); i++)
+		addElement(path.element(i));
+}
Index: scribus/plugins/wpgimplugin/wpg/WPGInternalStream.h
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGInternalStream.h	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGInternalStream.h	(revision 13903)
@@ -0,0 +1,52 @@
+/* libwpg
+ * Copyright (C) 2004-2005 William Lachance (wrlach at gmail.com)
+ *  
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by 
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#ifndef WPGINTERNALSTREAM_H
+#define WPGINTERNALSTREAM_H
+#include "WPXStream.h"
+
+class WPGInternalInputStream : public WPXInputStream
+{
+public:
+	WPGInternalInputStream(const unsigned char *data, const size_t size);
+	virtual ~WPGInternalInputStream();
+
+	virtual bool isOLEStream() { return false; }
+	virtual WPXInputStream * getDocumentOLEStream() { return 0; }
+	
+	const virtual uint8_t *read(size_t numBytes, size_t &numBytesRead);
+	virtual int seek(long offset, WPX_SEEK_TYPE seekType);
+	virtual long tell();
+	virtual bool atEOS();
+
+private:
+	long m_offset;
+	const size_t m_size;
+	const unsigned char *m_data;
+	unsigned char *m_tmpBuf;
+	WPGInternalInputStream(const WPGInternalInputStream&);
+	WPGInternalInputStream& operator=(const WPGInternalInputStream&);
+};
+
+#endif
Index: scribus/plugins/wpgimplugin/wpg/WPGGradient.cpp
===================================================================
--- scribus/plugins/wpgimplugin/wpg/WPGGradient.cpp	(revision 0)
+++ scribus/plugins/wpgimplugin/wpg/WPGGradient.cpp	(revision 13903)
@@ -0,0 +1,115 @@
+/* libwpg
+ * Copyright (C) 2006 Ariya Hidayat (ariya at kde.org)
+ *
+ * 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; if not, write to the 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02111-1301 USA
+ *
+ * For further information visit http://libwpg.sourceforge.net
+ */
+
+/* "This product is not manufactured, approved, or supported by
+ * Corel Corporation or Corel Corporation Limited."
+ */
+
+#include "WPGGradient.h"
+#include "WPGColor.h"
+
+#include <vector>
+
+namespace libwpg
+{
+
+class WPGGradientStop
+{
+public:
+	double offset;
+	WPGColor color;
+	
+	WPGGradientStop(): offset(0), color(WPGColor()) {}
+	
+	WPGGradientStop(double ofs, const WPGColor& c): offset(ofs), color(c) {}
+};
+
+class WPGGradientPrivate
+{
+public:
+    WPGGradientPrivate() :
+        gradientStops(std::vector<WPGGradientStop>()),
+        angle(0.0) {};
+	std::vector<WPGGradientStop> gradientStops;
+	double angle;
+};
+
+} // namespace libwpg
+
+libwpg::WPGGradient::WPGGradient() :
+    d(new WPGGradientPrivate())
+{
+}
+
+libwpg::WPGGradient::~WPGGradient()
+{
+	delete d;
+}
+
+libwpg::WPGGradient::WPGGradient(const libwpg::WPGGradient& g) :
+    d(new libwpg::WPGGradientPrivate())
+{
+	d->angle = g.d->angle;
+	d->gradientStops = g.d->gradientStops;
+}
+	
+libwpg::WPGGradient& libwpg::WPGGradient::operator=(const libwpg::WPGGradient& g)
+{
+	d->angle = g.d->angle;
+	d->gradientStops = g.d->gradientStops;
+	return *this;
+}
+
+double libwpg::WPGGradient::angle() const
+{
+	return d->angle;
+}
+
+void libwpg::WPGGradient::setAngle(double a)
+{
+	d->angle = a;
+}
+	
+unsigned libwpg::WPGGradient::count() const
+{
+	return d->gradientStops.size();
+}
+
+double libwpg::WPGGradient::stopOffset(unsigned index) const
+{
+	return d->gradientStops[index].offset;
+}
+
+libwpg::WPGColor libwpg::WPGGradient::stopColor(unsigned index) const
+{
+	return d->gradientStops[index].color;
+}
+
+void libwpg::WPGGradient::clear()
+{
+	d->gradientStops.clear();
+}
+
+void libwpg::WPGGradient::addStop(double offset, const libwpg::WPGColor& color)
+{
+	libwpg::WPGGradientStop stop(offset, color);
+	d->gradientStops.push_back(stop);
+}




More information about the scribus-commit mailing list