Sophie

Sophie

distrib > Fedora > 13 > i386 > media > updates-src > by-pkgid > cd8ce32c919af60229fca1d7f792c60e > files > 11

openoffice.org-3.2.0-12.35.fc13.src.rpm

diff -ruN OOO310_m6.orig/filter/source/config/fragments/fcfg_drawgraphics.mk OOO310_m6/filter/source/config/fragments/fcfg_drawgraphics.mk
--- OOO310_m6.orig/filter/source/config/fragments/fcfg_drawgraphics.mk	2009-03-17 14:58:31.000000000 +0000
+++ OOO310_m6/filter/source/config/fragments/fcfg_drawgraphics.mk	2009-03-17 14:59:37.000000000 +0000
@@ -54,6 +54,7 @@
     SGF___StarOffice_Writer_SGF \
     SGV___StarDraw_2_0 \
     SVM___StarView_Metafile \
+    SVG___Scalable_Vector_Graphics \
     TGA___Truevision_TARGA \
     TIF___Tag_Image_File \
     WMF___MS_Windows_Metafile \
diff -ruN OOO310_m6.orig/filter/source/config/fragments/fcfg_internalgraphics.mk OOO310_m6/filter/source/config/fragments/fcfg_internalgraphics.mk
--- OOO310_m6.orig/filter/source/config/fragments/fcfg_internalgraphics.mk	2009-03-17 14:58:31.000000000 +0000
+++ OOO310_m6/filter/source/config/fragments/fcfg_internalgraphics.mk	2009-03-17 14:59:37.000000000 +0000
@@ -68,6 +68,7 @@
     sgf_Import \
     sgv_Import \
     svg_Export \
+    svg_Import \
     svm_Export \
     svm_Import \
     tga_Import \
diff -ruN OOO310_m6.orig/filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics.xcu OOO310_m6/filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics.xcu
--- OOO310_m6.orig/filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics.xcu	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics.xcu	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,13 @@
+	<node oor:name="SVG - Scalable Vector Graphics" oor:op="replace">
+		<prop oor:name="Flags"><value>IMPORT ALIEN USESOPTIONS 3RDPARTYFILTER PREFERRED</value></prop>
+		<prop oor:name="UIComponent"/>
+		<prop oor:name="FilterService"><value>com.sun.star.comp.Draw.SVGFilter</value></prop>
+		<prop oor:name="UserData"><value></value></prop>
+		<prop oor:name="UIName">
+			<value xml:lang="x-default">SVG - Scalable Vector Graphics</value>
+		</prop>
+		<prop oor:name="FileFormatVersion"><value>0</value></prop>
+		<prop oor:name="Type"><value>svg_Scalable_Vector_Graphics</value></prop>
+		<prop oor:name="TemplateName"/>
+		<prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+	</node>
diff -ruN OOO310_m6.orig/filter/source/config/fragments/internalgraphicfilters/svg_Import.xcu OOO310_m6/filter/source/config/fragments/internalgraphicfilters/svg_Import.xcu
--- OOO310_m6.orig/filter/source/config/fragments/internalgraphicfilters/svg_Import.xcu	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/config/fragments/internalgraphicfilters/svg_Import.xcu	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,10 @@
+	<node oor:name="svg_Import" oor:op="replace"  >
+		<prop oor:name="Type"><value>svg_Scalable_Vector_Graphics</value></prop>
+        <prop oor:name="FormatName"><value>svgfilter</value></prop>
+        <prop oor:name="RealFilterName"/>
+		<prop oor:name="UIComponent"/>
+		<prop oor:name="UIName">
+			<value xml:lang="en-US">SVG - Scalable Vector Graphics</value>
+		</prop>
+		<prop oor:name="Flags"><value>IMPORT</value></prop>
+	</node>
diff -ruN OOO310_m6.orig/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu OOO310_m6/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu
--- OOO310_m6.orig/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu	2009-03-17 14:58:31.000000000 +0000
+++ OOO310_m6/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu	2009-03-17 14:59:37.000000000 +0000
@@ -1,10 +1,10 @@
 	<node oor:name="svg_Scalable_Vector_Graphics" oor:op="replace" >
-		<prop oor:name="DetectService"/>
+		<prop oor:name="DetectService"><value>com.sun.star.comp.Draw.SVGFilter</value></prop>
 		<prop oor:name="URLPattern"/>
 		<prop oor:name="Extensions"><value>svg</value></prop>
 		<prop oor:name="MediaType"><value>image/svg+xml</value></prop>
-		<prop oor:name="Preferred"><value>false</value></prop>
-		<prop oor:name="PreferredFilter"/>
+		<prop oor:name="Preferred"><value>true</value></prop>
+		<prop oor:name="PreferredFilter"><value>SVG - Scalable Vector Graphics</value></prop>
 		<prop oor:name="UIName">
 			<value>SVG - Scalable Vector Graphics</value>
 		</prop>
diff -ruN OOO310_m6.orig/filter/source/svg/b2dellipse.cxx OOO310_m6/filter/source/svg/b2dellipse.cxx
--- OOO310_m6.orig/filter/source/svg/b2dellipse.cxx	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/b2dellipse.cxx	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,139 @@
+/*************************************************************************
+ *
+ *    OpenOffice.org - a multi-platform office productivity suite
+ *
+ *    Author:
+ *      Fridrich Strba  <fridrich.strba@bluewin.ch>
+ *      Thorsten Behrens <tbehrens@novell.com>	   	
+ *
+ *      Copyright (C) 2008, Novell Inc.
+ *
+ *   The Contents of this file are made available subject to
+ *   the terms of GNU Lesser General Public License Version 2.1.
+ *
+ ************************************************************************/
+
+#include "b2dellipse.hxx"
+
+#include <osl/diagnose.h>
+
+#include <basegfx/point/b2dpoint.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+#include <rtl/instance.hxx>
+
+#include <boost/scoped_ptr.hpp>
+#include <vector>
+#include <algorithm>
+
+class ImplB2DEllipse
+{
+	 basegfx::B2DPoint maCenter;
+	 basegfx::B2DTuple maRadius;
+
+public:
+	ImplB2DEllipse()
+	:	maCenter(0.0f, 0.0f),
+		maRadius(0.0f, 0.0f)
+	{}
+
+	ImplB2DEllipse(const ImplB2DEllipse& rToBeCopied)
+	:	maCenter(rToBeCopied.maCenter),
+		maRadius(rToBeCopied.maRadius)
+	{}
+	
+    ImplB2DEllipse& operator=( const ImplB2DEllipse& rToBeCopied )
+    {
+		maCenter = rToBeCopied.maCenter;
+		maRadius = rToBeCopied.maRadius;
+
+        return *this;
+    }
+
+	bool isEqual(const ImplB2DEllipse& rCandidate) const
+	{
+		return (maCenter == rCandidate.maCenter)
+			&& (maRadius == rCandidate.maRadius);
+	}
+
+	basegfx::B2DPoint getCenter() const
+	{
+		return maCenter;
+	}
+	
+	void setCenter(const basegfx::B2DPoint& rCenter)
+	{
+		maCenter = rCenter;
+	}
+		
+	basegfx::B2DTuple getRadius() const
+	{
+		return maRadius;
+	}
+	
+	void setRadius(const basegfx::B2DTuple& rRadius)
+	{
+		maRadius = rRadius;
+	}
+		
+
+	void transform(const basegfx::B2DHomMatrix& /* rMatrix */)
+	{
+	}
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+
+	B2DEllipse::B2DEllipse() 
+	{}
+
+	B2DEllipse::B2DEllipse(const basegfx::B2DPoint& rCenter, const basegfx::B2DTuple& rRadius)
+	:	maCenter(rCenter), maRadius(rRadius)
+	{
+	}
+
+	B2DEllipse::~B2DEllipse()
+	{
+	}
+
+	bool B2DEllipse::operator==(const B2DEllipse& rEllipse) const
+	{
+		return (maCenter == rEllipse.maCenter) && (maRadius == rEllipse.maRadius);
+	}
+
+	bool B2DEllipse::operator!=(const B2DEllipse& rEllipse) const
+	{
+        return !(*this == rEllipse);
+	}
+
+	basegfx::B2DPoint B2DEllipse::getB2DEllipseCenter() const
+	{
+		return maCenter;
+	}
+
+	void B2DEllipse::setB2DEllipseCenter(const basegfx::B2DPoint& rCenter)
+	{
+		maCenter = rCenter;
+	}
+
+	basegfx::B2DTuple B2DEllipse::getB2DEllipseRadius() const
+	{
+		return maRadius;
+	}
+
+	void B2DEllipse::setB2DEllipseRadius(const basegfx::B2DTuple& rRadius)
+	{
+		maRadius = rRadius;
+	}
+
+	void B2DEllipse::transform(const basegfx::B2DHomMatrix& /* rMatrix */)
+	{
+	}
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+// eof
diff -ruN OOO310_m6.orig/filter/source/svg/b2dellipse.hxx OOO310_m6/filter/source/svg/b2dellipse.hxx
--- OOO310_m6.orig/filter/source/svg/b2dellipse.hxx	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/b2dellipse.hxx	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,77 @@
+/*************************************************************************
+ *
+ *    OpenOffice.org - a multi-platform office productivity suite
+ *
+ *    Author:
+ *      Fridrich Strba  <fridrich.strba@bluewin.ch>
+ *      Thorsten Behrens <tbehrens@novell.com>	   	
+ *
+ *      Copyright (C) 2008, Novell Inc.
+ *
+ *   The Contents of this file are made available subject to
+ *   the terms of GNU Lesser General Public License Version 2.1.
+ *
+ ************************************************************************/
+
+#ifndef _BASEGFX_B2DELLIPSE_HXX
+#define _BASEGFX_B2DELLIPSE_HXX
+
+#include <sal/types.h>
+
+#include <o3tl/cow_wrapper.hxx>
+
+#include <basegfx/point/b2dpoint.hxx>
+
+#include <basegfx/tuple/b2dtuple.hxx>
+
+#include <basegfx/vector/b2enums.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+// predeclarations
+class ImplB2DEllipse;
+
+namespace basegfx
+{
+	class B2DPoint;
+	class B2DVector;
+	class B2DHomMatrix;
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+	class B2DEllipse
+	{
+	private:
+	 basegfx::B2DPoint maCenter;
+	 basegfx::B2DTuple maRadius;
+
+	public:
+		B2DEllipse();
+		B2DEllipse(const B2DEllipse& rEllipse);
+		B2DEllipse(const basegfx::B2DPoint& rCenter, const basegfx::B2DTuple& rRadius);
+		~B2DEllipse();
+
+		// assignment operator
+		B2DEllipse& operator=(const B2DEllipse& rEllipse);
+
+		// compare operators
+		bool operator==(const B2DEllipse& rEllipse) const;
+		bool operator!=(const B2DEllipse& rEllipse) const;
+
+		// Coordinate interface
+		basegfx::B2DPoint getB2DEllipseCenter() const;
+		void setB2DEllipseCenter(const basegfx::B2DPoint& rCenter);
+		
+		basegfx::B2DTuple getB2DEllipseRadius() const;
+		void setB2DEllipseRadius(const basegfx::B2DTuple& rRadius);
+		
+		// apply transformation given in matrix form to the Ellipse
+		void transform(const basegfx::B2DHomMatrix& rMatrix);
+	};
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+#endif /* _BASEGFX_B2DELLIPSE_HXX */
diff -ruN OOO310_m6.orig/filter/source/svg/exports.map OOO310_m6/filter/source/svg/exports.map
--- OOO310_m6.orig/filter/source/svg/exports.map	2009-03-17 14:58:30.000000000 +0000
+++ OOO310_m6/filter/source/svg/exports.map	2009-03-17 14:59:37.000000000 +0000
@@ -1,9 +1,10 @@
-PDFFILTER_1_0 {
+SVGFILTER_1_0 {
         global:
                 component_getImplementationEnvironment;
                 component_getFactory;
                 component_writeInfo;
+                GraphicImport;
 
         local:
                 *;
-}; 
\ No newline at end of file
+}; 
diff -ruN OOO310_m6.orig/filter/source/svg/gentoken.pl OOO310_m6/filter/source/svg/gentoken.pl
--- OOO310_m6.orig/filter/source/svg/gentoken.pl	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/gentoken.pl	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,58 @@
+# from oox/source/token - should really put this into solenv
+
+$ARGV0 = shift @ARGV;
+$ARGV1 = shift @ARGV;
+$ARGV2 = shift @ARGV;
+
+open ( TOKENS, $ARGV0 ) || die "can't open token file: $!";
+my %tokens;
+
+while ( defined ($line = <TOKENS>) )
+{
+	if( !($line =~ /^#/) )
+	{
+		chomp($line);
+		@token = split(/\s+/,$line);
+		if ( not defined ($token[1]) )
+		{
+			$token[1] = "XML_".$token[0];
+			$token[1] =~ tr/\-\.\:/___/;
+			$token[1] =~ s/\+/PLUS/g;
+			$token[1] =~ s/\-/MINUS/g;
+		}
+
+		$tokens{$token[0]} = uc($token[1]);
+	}
+}
+close ( TOKENS );
+
+open ( HXX, ">$ARGV1" ) || die "can't open tokens.hxx file: $!";
+open ( GPERF, ">$ARGV2" ) || die "can't open tokens.gperf file: $!";
+
+print ( GPERF "%language=C++\n" );
+print ( GPERF "%global-table\n" );
+print ( GPERF "%null-strings\n" );
+print ( GPERF "%struct-type\n" );
+print ( GPERF "struct xmltoken\n" );
+print ( GPERF "{\n" );
+print ( GPERF "  const sal_Char *name; sal_Int32 nToken; \n" );
+print ( GPERF "};\n" );
+print ( GPERF "%%\n" );
+
+print ( HXX "#ifndef INCLUDED_AUTOGEN_TOKEN_HXX\n" );
+print ( HXX "#define INCLUDED_AUTOGEN_TOKEN_HXX\n\n" );
+print ( HXX "#include <sal/types.h>\n\n" );
+
+$i = 0;
+foreach( sort(keys(%tokens)) )
+{
+	print( HXX "const sal_Int32 $tokens{$_} = $i;\n" );
+	print( GPERF "$_,$tokens{$_}\n" );
+	$i = $i + 1;
+}
+print ( GPERF "%%\n" );
+print ( HXX "const sal_Int32 XML_TOKEN_COUNT = $i;\n" );
+print ( HXX "const sal_Int32 XML_TOKEN_INVALID = -1;\n\n" );
+print ( HXX "#endif\n" );
+close ( HXX );
+close ( GPERF );
diff -ruN OOO310_m6.orig/filter/source/svg/gfxtypes.hxx OOO310_m6/filter/source/svg/gfxtypes.hxx
--- OOO310_m6.orig/filter/source/svg/gfxtypes.hxx	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/gfxtypes.hxx	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,343 @@
+/*************************************************************************
+ *
+ *    OpenOffice.org - a multi-platform office productivity suite
+ *
+ *    Author:
+ *      Fridrich Strba  <fridrich.strba@bluewin.ch>
+ *      Thorsten Behrens <tbehrens@novell.com>	   	
+ *
+ *      Copyright (C) 2008, Novell Inc.
+ *
+ *   The Contents of this file are made available subject to
+ *   the terms of GNU Lesser General Public License Version 2.1.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_GFXTYPES_HXX
+#define INCLUDED_GFXTYPES_HXX
+
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
+
+#include <hash_set>
+#include <hash_map>
+#include <rtl/ustring.hxx>
+
+namespace svgi
+{
+
+struct ARGBColor
+{
+    double toDoubleColor( sal_uInt8 val ) { return val/255.0; }
+
+    ARGBColor() : a(1.0), r(0.0), g(0.0), b(0.0)
+    {}
+    explicit ARGBColor(double fGrey) : a(1.0), r(fGrey), g(fGrey), b(fGrey)
+    {}
+    ARGBColor( double r_, double g_, double b_ ) : 
+        a(1.0), r(r_), g(g_), b(b_)
+    {}
+    ARGBColor( double a_, double r_, double g_, double b_ ) : 
+        a(a_), r(r_), g(g_), b(b_)
+    {}
+    ARGBColor( int r_, int g_, int b_ ) : 
+        a(1.0),
+        r(toDoubleColor(sal::static_int_cast<sal_uInt8>(r_))), 
+        g(toDoubleColor(sal::static_int_cast<sal_uInt8>(g_))), 
+        b(toDoubleColor(sal::static_int_cast<sal_uInt8>(b_)))
+    {}
+    ARGBColor( int a_, int r_, int g_, int b_ ) : 
+        a(toDoubleColor(sal::static_int_cast<sal_uInt8>(a_))), 
+        r(toDoubleColor(sal::static_int_cast<sal_uInt8>(r_))), 
+        g(toDoubleColor(sal::static_int_cast<sal_uInt8>(g_))), 
+        b(toDoubleColor(sal::static_int_cast<sal_uInt8>(b_)))
+    {}
+    double a;
+    double r;
+    double g;
+    double b;
+};
+inline bool operator==( const ARGBColor& rLHS, const ARGBColor& rRHS )
+{ return rLHS.a==rRHS.a && rLHS.r==rRHS.r && rLHS.g==rRHS.g && rLHS.b==rRHS.b; }
+inline bool operator!=( const ARGBColor& rLHS, const ARGBColor& rRHS )
+{ return !(rLHS==rRHS); }
+
+struct GradientStop
+{
+    GradientStop() : maStopColor(), mnStopPosition(0.0)
+    {}
+    ARGBColor     maStopColor;
+    double        mnStopPosition;
+};
+inline bool operator==( const GradientStop& rLHS, const GradientStop& rRHS )
+{ return rLHS.mnStopPosition==rRHS.mnStopPosition && rLHS.maStopColor==rRHS.maStopColor; }
+
+struct Gradient
+{
+    enum GradientType { LINEAR, RADIAL};
+    std::vector<sal_Size> maStops;
+    basegfx::B2DHomMatrix maTransform;
+    GradientType          meType;
+    union
+    {
+        double test;
+        struct
+        {
+            double                mfX1;
+            double                mfX2;
+            double                mfY1;
+            double                mfY2;
+        } linear;
+        struct
+        {
+            double                mfCX;
+            double                mfCY;
+            double                mfFX;
+            double                mfFY;
+            double                mfR;
+        } radial;
+    } maCoords;
+    sal_Int32             mnId;
+    bool                  mbBoundingBoxUnits;
+    bool                  mbLinearBoundingBoxUnits;
+
+//    explicit Gradient(GradientType eType) : maStops(), maTransform(), meType(eType), maCoords.mfCX(0.0), maCoords.mfCY(0.0), maCoords.mfFX(0.0), maCoords.mfFY(0.0), maCoords.mfR(0.0), mnId(0), mbBoundingBoxUnits(false) 
+    explicit Gradient(GradientType eType) : maStops(), maTransform(), meType(eType), mnId(0), mbBoundingBoxUnits(false) 
+    {
+        maCoords.radial.mfCX = 0.0;
+        maCoords.radial.mfCY = 0.0;
+        maCoords.radial.mfFX = 0.0;
+        maCoords.radial.mfFY = 0.0;
+        maCoords.radial.mfR  = 0.0;
+    }
+};
+
+inline bool operator==( const Gradient& rLHS, const Gradient& rRHS )
+{
+    if( rLHS.meType != rRHS.meType )
+        return false;
+    if( rLHS.meType == Gradient::LINEAR )
+        return rLHS.mbBoundingBoxUnits==rRHS.mbBoundingBoxUnits && rLHS.maStops==rRHS.maStops &&
+            rLHS.maCoords.linear.mfX1 == rRHS.maCoords.linear.mfX1 && rLHS.maCoords.linear.mfX2 == rRHS.maCoords.linear.mfX2 && 
+            rLHS.maCoords.linear.mfY1 == rRHS.maCoords.linear.mfY1 && rLHS.maCoords.linear.mfY2 == rRHS.maCoords.linear.mfY2;
+    else
+        return rLHS.mbBoundingBoxUnits==rRHS.mbBoundingBoxUnits && rLHS.maStops==rRHS.maStops &&
+            rLHS.maCoords.radial.mfCX == rRHS.maCoords.radial.mfCX && rLHS.maCoords.radial.mfCY == rRHS.maCoords.radial.mfCY && 
+            rLHS.maCoords.radial.mfFX == rRHS.maCoords.radial.mfFX && rLHS.maCoords.radial.mfFY == rRHS.maCoords.radial.mfFY && 
+            rLHS.maCoords.radial.mfR == rRHS.maCoords.radial.mfR;
+}
+
+enum PaintType
+{
+    NONE,
+    SOLID,
+    GRADIENT
+};
+
+enum FillRule
+{
+    NON_ZERO,
+    EVEN_ODD
+};
+
+enum TextAlign
+{
+    BEFORE,
+    CENTER,
+    AFTER
+};
+
+enum CapStyle
+{
+    BUTT,
+    RECT,
+    ROUND
+};
+
+struct State
+{
+    State() :
+        maCTM(),
+        maTransform(),
+        maViewport(),
+        maViewBox(),
+        maFontFamily(), // app-default
+        mnFontSize(12.0),
+        maFontStyle(RTL_CONSTASCII_USTRINGPARAM("normal")),
+        maFontVariant(RTL_CONSTASCII_USTRINGPARAM("normal")),
+        mnFontWeight(400.0),
+        meTextAnchor(BEFORE),
+        meTextDisplayAlign(BEFORE),
+        mnTextLineIncrement(0.0),
+        maCurrentColor(1.0),
+        mbVisibility(true),
+        meFillType(SOLID),
+        mnFillOpacity(1.0),
+        meStrokeType(NONE),
+        mnStrokeOpacity(1.0),
+        meViewportFillType(NONE),
+        mnViewportFillOpacity(1.0),
+        maFillColor(0.0),
+        maFillGradient(Gradient::LINEAR),
+        meFillRule(NON_ZERO),
+        maStrokeColor(0.0),
+        maStrokeGradient(Gradient::LINEAR),
+        maDashArray(),
+        mnDashOffset(0.0),
+        meLineCap(BUTT),
+        meLineJoin(basegfx::B2DLINEJOIN_MITER),
+        mnMiterLimit(4.0),
+        mnStrokeWidth(1.0),
+        maViewportFillColor(1.0),
+        maViewportFillGradient(Gradient::LINEAR),
+        mnStyleId(0)
+    {}
+
+    basegfx::B2DHomMatrix       maCTM;
+    basegfx::B2DHomMatrix       maTransform;
+    basegfx::B2DRange           maViewport;
+    basegfx::B2DRange           maViewBox;
+
+    rtl::OUString               maFontFamily;
+    /** Absolute: xx-small=6.94 | x-small=8.33 | small=10 | medium=12 | large=14.4 | x-large=17.28 | xx-large=20.736
+
+        Relative(to parent): larger (enlarge by 1.2)
+                             smaller (shrink by 1.2)
+
+     */
+    double                      mnFontSize;
+    rtl::OUString               maFontStyle;
+    rtl::OUString               maFontVariant;
+    double                      mnFontWeight;
+
+    TextAlign                   meTextAnchor; // text-anchor
+    TextAlign                   meTextDisplayAlign; // display-align
+    double                      mnTextLineIncrement; // 0.0 means auto
+
+    ARGBColor                   maCurrentColor;
+    bool                        mbVisibility;
+
+    PaintType                   meFillType;
+    double                      mnFillOpacity;
+    PaintType                   meStrokeType;
+    double                      mnStrokeOpacity;
+    PaintType                   meViewportFillType;
+    double                      mnViewportFillOpacity;
+
+    ARGBColor                   maFillColor;
+    Gradient                    maFillGradient;
+    FillRule                    meFillRule;
+
+    ARGBColor                   maStrokeColor;
+    Gradient                    maStrokeGradient;
+    std::vector<double>         maDashArray;
+    double                      mnDashOffset;
+    CapStyle                    meLineCap;
+    basegfx::B2DLineJoin        meLineJoin;
+    double                      mnMiterLimit;
+    double                      mnStrokeWidth;
+
+    ARGBColor                   maViewportFillColor;
+    Gradient                    maViewportFillGradient;
+
+    sal_Int32                   mnStyleId;
+};
+
+inline bool operator==(const State& rLHS, const State& rRHS )
+{
+    return rLHS.maCTM==rRHS.maCTM &&
+        rLHS.maTransform==rRHS.maTransform &&
+        rLHS.maViewport==rRHS.maViewport &&
+        rLHS.maViewBox==rRHS.maViewBox &&
+        rLHS.maFontFamily==rRHS.maFontFamily &&
+        rLHS.mnFontSize==rRHS.mnFontSize &&
+        rLHS.maFontStyle==rRHS.maFontStyle &&
+        rLHS.maFontVariant==rRHS.maFontVariant &&
+        rLHS.mnFontWeight==rRHS.mnFontWeight &&
+        rLHS.meTextAnchor==rRHS.meTextAnchor &&
+        rLHS.meTextDisplayAlign==rRHS.meTextDisplayAlign &&
+        rLHS.mnTextLineIncrement==rRHS.mnTextLineIncrement &&
+        rLHS.maCurrentColor==rRHS.maCurrentColor &&
+        rLHS.mbVisibility==rRHS.mbVisibility &&
+        rLHS.meFillType==rRHS.meFillType &&
+        rLHS.mnFillOpacity==rRHS.mnFillOpacity &&
+        rLHS.meStrokeType==rRHS.meStrokeType &&
+        rLHS.mnStrokeOpacity==rRHS.mnStrokeOpacity &&
+        rLHS.meViewportFillType==rRHS.meViewportFillType &&
+        rLHS.mnViewportFillOpacity==rRHS.mnViewportFillOpacity &&
+        rLHS.maFillColor==rRHS.maFillColor &&
+        rLHS.maFillGradient==rRHS.maFillGradient &&
+        rLHS.meFillRule==rRHS.meFillRule &&
+        rLHS.maStrokeColor==rRHS.maStrokeColor &&
+        rLHS.maStrokeGradient==rRHS.maStrokeGradient &&
+        rLHS.maDashArray==rRHS.maDashArray &&
+        rLHS.mnDashOffset==rRHS.mnDashOffset &&
+        rLHS.meLineCap==rRHS.meLineCap &&
+        rLHS.meLineJoin==rRHS.meLineJoin &&
+        rLHS.mnMiterLimit==rRHS.mnMiterLimit &&
+        rLHS.mnStrokeWidth==rRHS.mnStrokeWidth &&
+        rLHS.maViewportFillColor==rRHS.maViewportFillColor &&
+        rLHS.maViewportFillGradient==rRHS.maViewportFillGradient;
+}
+        
+struct StateHash
+{
+    size_t operator()(const State& rState ) const
+    {
+        return size_t(rState.maCTM.get( 0, 0 ))
+            ^  size_t(rState.maCTM.get( 1, 0 ))
+            ^  size_t(rState.maCTM.get( 0, 1 ))
+            ^  size_t(rState.maCTM.get( 1, 1 ))
+            ^  size_t(rState.maCTM.get( 0, 2 ))
+            ^  size_t(rState.maCTM.get( 1, 2 ))
+            ^  size_t(rState.maViewport.getWidth())
+            ^  size_t(rState.maViewport.getHeight())
+            ^  size_t(rState.maViewBox.getWidth())
+            ^  size_t(rState.maViewBox.getHeight())
+            ^  size_t(rState.maFontFamily.hashCode())
+            ^  size_t(rState.mnFontSize)
+            ^  size_t(rState.maFontStyle.hashCode())
+            ^  size_t(rState.maFontVariant.hashCode())
+            ^  size_t(rState.mnFontWeight)
+            ^  size_t(rState.meTextAnchor)
+            ^  size_t(rState.meTextDisplayAlign)
+            ^  size_t(rState.mnTextLineIncrement)
+            ^  size_t(rState.mbVisibility)
+            ^  size_t(rState.meFillType)
+            ^  size_t(rState.mnFillOpacity)
+            ^  size_t(rState.meStrokeType)
+            ^  size_t(rState.mnStrokeOpacity)
+            ^  size_t(rState.meViewportFillType)
+            ^  size_t(rState.mnViewportFillOpacity)
+            ^  size_t(rState.maFillColor.a)
+            ^  size_t(rState.maFillColor.r)
+            ^  size_t(rState.maFillColor.g)
+            ^  size_t(rState.maFillColor.b)
+            ^  size_t(rState.maFillGradient.maStops.size())
+            ^  size_t(rState.meFillRule)
+            ^  size_t(rState.maStrokeColor.a)
+            ^  size_t(rState.maStrokeColor.r)
+            ^  size_t(rState.maStrokeColor.g)
+            ^  size_t(rState.maStrokeColor.b)
+            ^  size_t(rState.maStrokeGradient.maStops.size())
+            ^  size_t(rState.maDashArray.size())
+            ^  size_t(rState.mnDashOffset)
+            ^  size_t(rState.meLineCap)
+            ^  size_t(rState.meLineJoin)
+            ^  size_t(rState.mnMiterLimit)
+            ^  size_t(rState.mnStrokeWidth)
+            ^  size_t(rState.maViewportFillColor.a)
+            ^  size_t(rState.maViewportFillColor.r)
+            ^  size_t(rState.maViewportFillColor.g)
+            ^  size_t(rState.maViewportFillColor.b)
+            ^  size_t(rState.maViewportFillGradient.maStops.size());
+    }
+};
+
+typedef std::hash_set<State, StateHash> StatePool;
+typedef std::hash_map<sal_Int32, State> StateMap;
+
+} // namespace svgi
+
+#endif
diff -ruN OOO310_m6.orig/filter/source/svg/makefile.mk OOO310_m6/filter/source/svg/makefile.mk
--- OOO310_m6.orig/filter/source/svg/makefile.mk	2009-03-17 14:58:30.000000000 +0000
+++ OOO310_m6/filter/source/svg/makefile.mk	2009-03-17 14:59:37.000000000 +0000
@@ -30,25 +30,35 @@
 #*************************************************************************
 
 PRJ=..$/..
+
 PRJNAME=filter
 TARGET=svgfilter
-
 ENABLE_EXCEPTIONS=TRUE
 VISIBILITY_HIDDEN=TRUE
 
 # --- Settings ----------------------------------
 
-.INCLUDE :  	settings.mk
+.INCLUDE :  settings.mk
+.INCLUDE :	libs.mk
 
 # --- Types -------------------------------------
 
-SLOFILES=	$(SLO)$/svguno.obj			\
-			$(SLO)$/svgfilter.obj		\
+SLOFILES= \
+			$(SLO)$/b2dellipse.obj	\
+			$(SLO)$/parserfragments.obj \
 			$(SLO)$/svgexport.obj		\
+			$(SLO)$/svgfilter.obj		\
 			$(SLO)$/svgfontexport.obj	\
-			$(SLO)$/svgwriter.obj	
-.IF "$(SOLAR_JAVA)"!=""
-SLOFILES+=		$(SLO)$/svgimport.obj
+			$(SLO)$/svgimport.obj		\
+			$(SLO)$/svgreader.obj		\
+			$(SLO)$/svgwriter.obj		\
+			$(SLO)$/tokenmap.obj        \
+			$(SLO)$/units.obj
+
+.IF "$(COMID)"=="gcc3"
+.IF "$(CCNUMVER)">="000400000000" || "$(SYSTEM_BOOST)"=="YES"
+CFLAGS+=-DUSE_MODERN_SPIRIT
+.ENDIF
 .ENDIF
 
 # --- Library -----------------------------------
@@ -58,19 +68,17 @@
 SHL1STDLIBS=\
 	$(SVXCORELIB)			\
 	$(XMLOFFLIB)		\
-	$(GOODIESLIB)		\
+	$(SVTOOLLIB)        \
+	$(BASEGFXLIB)           \
 	$(VCLLIB)			\
 	$(UNOTOOLSLIB)		\
 	$(TOOLSLIB)			\
 	$(COMPHELPERLIB)	\
+	$(SVTOOLLIB)        \
 	$(CPPUHELPERLIB)	\
 	$(CPPULIB)			\
-	$(SALLIB) 
-
-.IF "$(SOLAR_JAVA)"!=""
-SHL1STDLIBS+=\
-	$(JVMACCESSLIB)
-.ENDIF
+	$(SALLIB)			\
+	$(LIBXML)
 
 
 SHL1DEPN=
@@ -84,3 +92,16 @@
 # --- Targets ----------------------------------
 
 .INCLUDE : target.mk
+
+# Generate gperf files - from oox/source/token
+$(INCCOM)$/tokens.hxx $(MISC)$/tokens.gperf : tokens.txt gentoken.pl
+		$(PERL) gentoken.pl tokens.txt $(INCCOM)$/tokens.hxx $(MISC)$/tokens.gperf
+
+$(INCCOM)$/tokens.cxx : $(MISC)$/tokens.gperf makefile.mk
+		gperf --compare-strncmp -C -m 20 $(MISC)$/tokens.gperf | $(SED) -e "s/(char\*)0/(char\*)0, 0/g" >$(INCCOM)$/tokens.cxx
+
+$(SLO)$/tokenmap.obj : $(INCCOM)$/tokens.cxx $(INCCOM)$/tokens.hxx
+
+$(SLO)$/parserfragments.obj : $(INCCOM)$/tokens.cxx $(INCCOM)$/tokens.hxx
+
+$(SLO)$/svgreader.obj : $(INCCOM)$/tokens.cxx $(INCCOM)$/tokens.hxx
diff -ruN OOO310_m6.orig/filter/source/svg/parserfragments.cxx OOO310_m6/filter/source/svg/parserfragments.cxx
--- OOO310_m6.orig/filter/source/svg/parserfragments.cxx	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/parserfragments.cxx	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,600 @@
+/*************************************************************************
+ *
+ *    OpenOffice.org - a multi-platform office productivity suite
+ *
+ *    Author:
+ *      Fridrich Strba  <fridrich.strba@bluewin.ch>
+ *      Thorsten Behrens <tbehrens@novell.com>	   	
+ *
+ *      Copyright (C) 2008, Novell Inc.
+ *
+ *   The Contents of this file are made available subject to
+ *   the terms of GNU Lesser General Public License Version 2.1.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_filter.hxx"
+
+#include "parserfragments.hxx"
+#include "spirit_supplements.hxx"
+#include "gfxtypes.hxx"
+
+#include <basegfx/tools/canvastools.hxx>
+#include <com/sun/star/geometry/AffineMatrix2D.hpp>
+
+#include <string.h>
+#include <limits.h>
+#include <boost/bind.hpp>
+#include <boost/spirit.hpp>
+#include <boost/spirit/dynamic/while.hpp>
+#include <numeric>
+#include <algorithm>
+
+#include "units.hxx"
+#include "tokenmap.hxx"
+
+using namespace ::com::sun::star;
+
+namespace svgi
+{
+
+inline sal_uInt8 hex2int( char val )
+{
+    return val <= '9' ? val-'0' : (val < 'a' ? val+10-'A' : val+10-'a');
+}
+
+void setFourBitColor( double& rChannel, char nChar )
+{
+    const sal_uInt8 nVal(hex2int(nChar));
+    OSL_TRACE( "setFourBitCOlor %d color", nVal );
+    rChannel = (nVal*16+nVal)/255.0;
+}
+
+void setEightBitColor( double& rChannel, const char* pStart, const char* )
+{
+    const sal_uInt8 nVal0(hex2int(pStart[0]));
+    const sal_uInt8 nVal1(hex2int(pStart[1]));
+    OSL_TRACE( "setEightbitCOlor %d, %d color", nVal0, nVal1 );
+    rChannel = (nVal0*16+nVal1)/255.0;
+}
+
+void setIntColor( double& rChannel, sal_uInt8 nVal )
+{
+    OSL_TRACE( "setIntColor %d color", nVal );
+    rChannel = nVal/255.0;
+}
+
+void calcRotation(std::vector<geometry::AffineMatrix2D>& rTransforms,
+                  geometry::AffineMatrix2D&              rCurrTransform,
+                  double                                 fRotationAngle)
+{
+    ::basegfx::B2DHomMatrix aCurr;
+    aCurr.translate(-rCurrTransform.m02,-rCurrTransform.m12);
+    aCurr.rotate(fRotationAngle*M_PI/180);
+    aCurr.translate(rCurrTransform.m02,rCurrTransform.m12);
+
+	OSL_TRACE("calcRotation - fRotationAngle - %f", fRotationAngle);
+    rTransforms.push_back(
+        basegfx::unotools::affineMatrixFromHomMatrix(
+            rCurrTransform,
+            aCurr));
+}
+
+void calcSkewX(std::vector<geometry::AffineMatrix2D>& rTransforms,
+               double                                 fSkewAngle)
+{
+    geometry::AffineMatrix2D aMat(1.0,0.0,0.0,
+                                  tan(fSkewAngle*M_PI/180),1.0,0.0);
+    rTransforms.push_back(aMat);
+}
+
+void calcSkewY(std::vector<geometry::AffineMatrix2D>& rTransforms,
+               double                                 fSkewAngle)
+{
+    geometry::AffineMatrix2D aMat(1.0,tan(fSkewAngle*M_PI/180),0.0,
+                                  0.0,1.0,0.0);
+    rTransforms.push_back(aMat);
+}
+
+void assign_twice(double& r_oVal1, double& r_oVal2, const double& rInVal )
+{
+    r_oVal1 = r_oVal2 = rInVal;
+}
+
+geometry::AffineMatrix2D multiplyMatrix( const geometry::AffineMatrix2D& rLHS,
+                                         const geometry::AffineMatrix2D& rRHS )
+{
+    basegfx::B2DHomMatrix aLHS;
+    basegfx::B2DHomMatrix aRHS;
+
+    basegfx::unotools::homMatrixFromAffineMatrix(aLHS,rLHS);
+    basegfx::unotools::homMatrixFromAffineMatrix(aRHS,rRHS);
+
+    aRHS*=aLHS;
+
+    geometry::AffineMatrix2D aRet;
+    return basegfx::unotools::affineMatrixFromHomMatrix(aRet,aRHS);
+}
+
+namespace
+{
+    struct ColorGrammar : public ::boost::spirit::grammar< ColorGrammar >
+    {
+    public:
+        ARGBColor& m_rColor;
+        explicit ColorGrammar( ARGBColor& rColor ) : m_rColor(rColor) {}
+        template< typename ScannerT > 
+        struct definition
+        {
+            ::boost::spirit::rule< ScannerT > colorExpression;
+            definition( const ColorGrammar& self )
+            {
+                using namespace ::boost::spirit;
+
+                int_parser<sal_uInt8,10,1,3> byte_p;
+                colorExpression = 
+                    (
+                        // the #rrggbb form
+                        ('#' >> (xdigit_p >> xdigit_p)[boost::bind(&setEightBitColor,
+                                                                   boost::ref(self.m_rColor.r),_1,_2)]
+                             >> (xdigit_p >> xdigit_p)[boost::bind(&setEightBitColor,
+                                                                   boost::ref(self.m_rColor.g),_1,_2)]
+                             >> (xdigit_p >> xdigit_p)[boost::bind(&setEightBitColor,
+                                                                   boost::ref(self.m_rColor.b),_1,_2)]) 
+                        |
+                        // the #rgb form
+                        ('#' >> xdigit_p[boost::bind(&setFourBitColor,
+                                                     boost::ref(self.m_rColor.r),_1)] 
+                             >> xdigit_p[boost::bind(&setFourBitColor,
+                                                     boost::ref(self.m_rColor.g),_1)] 
+                             >> xdigit_p[boost::bind(&setFourBitColor,
+                                                     boost::ref(self.m_rColor.b),_1)]) 
+                        |
+                        // rgb() form
+                        (str_p("rgb") 
+                            >> '(' >>
+                            (
+                	            // rgb(int,int,int)
+                    	        (byte_p[boost::bind(&setIntColor,
+                                                    boost::ref(self.m_rColor.r),_1)] >> ',' >>
+	                             byte_p[boost::bind(&setIntColor,
+                                                    boost::ref(self.m_rColor.g),_1)] >> ',' >>
+        	                     byte_p[boost::bind(&setIntColor,
+                                                    boost::ref(self.m_rColor.b),_1)])
+                             |  
+                    	        // rgb(double,double,double)
+                        	    (real_p[assign_a(self.m_rColor.r)] >> ',' >>
+                                 real_p[assign_a(self.m_rColor.g)] >> ',' >>
+                                 real_p[assign_a(self.m_rColor.b)])
+                             )
+                         >> ')')
+                     );
+            }
+            ::boost::spirit::rule<ScannerT> const& start() const { return colorExpression; }
+        };
+    };
+}
+
+bool parseColor( const char* sColor, ARGBColor& rColor  )
+{
+    using namespace ::boost::spirit;
+
+    if( parse(sColor,
+              ColorGrammar(rColor) >> end_p,
+              space_p).full )
+    {
+        // free-form color found & parsed
+        return true;
+    }
+
+    // no free-form color - maybe a color name?
+    // trim white space before 
+    while( *sColor && 
+           (*sColor==' ' || *sColor=='\t' || *sColor=='\r' || *sColor=='\n') )
+        ++sColor;
+    // trim white space after 
+    int nLen=strlen(sColor)-1;
+    while( nLen && 
+           (sColor[nLen]==' ' || sColor[nLen]=='\t' || sColor[nLen]=='\r' || sColor[nLen]=='\n') )
+        --nLen;
+	switch (getTokenId(sColor, nLen+1))
+	{
+        case XML_ALICEBLUE: rColor = ARGBColor(240,248,255); return true;
+        case XML_ANTIQUEWHITE: rColor = ARGBColor(250,235,215); return true;
+        case XML_AQUA: rColor = ARGBColor(0,255,255); return true;
+        case XML_AQUAMARINE: rColor = ARGBColor(127,255,212); return true;
+        case XML_AZURE: rColor = ARGBColor(240,255,255); return true;
+        case XML_BEIGE: rColor = ARGBColor(245,245,220); return true;
+        case XML_BISQUE: rColor = ARGBColor(255,228,196); return true;
+        case XML_BLACK: rColor = ARGBColor(0,0,0); return true;
+        case XML_BLANCHEDALMOND: rColor = ARGBColor(255,235,205); return true;
+        case XML_BLUE: rColor = ARGBColor(0,0,255); return true;
+        case XML_BLUEVIOLET: rColor = ARGBColor(138,43,226); return true;
+        case XML_BROWN: rColor = ARGBColor(165,42,42); return true;
+        case XML_BURLYWOOD: rColor = ARGBColor(222,184,135); return true;
+        case XML_CADETBLUE: rColor = ARGBColor(95,158,160); return true;
+        case XML_CHARTREUSE: rColor = ARGBColor(127,255,0); return true;
+        case XML_CHOCOLATE: rColor = ARGBColor(210,105,30); return true;
+        case XML_CORAL: rColor = ARGBColor(255,127,80); return true;
+        case XML_CORNFLOWERBLUE: rColor = ARGBColor(100,149,237); return true;
+        case XML_CORNSILK: rColor = ARGBColor(255,248,220); return true;
+        case XML_CRIMSON: rColor = ARGBColor(220,20,60); return true;
+        case XML_CYAN: rColor = ARGBColor(0,255,255); return true;
+        case XML_DARKBLUE: rColor = ARGBColor(0,0,139); return true;
+        case XML_DARKCYAN: rColor = ARGBColor(0,139,139); return true;
+        case XML_DARKGOLDENROD: rColor = ARGBColor(184,134,11); return true;
+        case XML_DARKGRAY: rColor = ARGBColor(169,169,169); return true;
+        case XML_DARKGREEN: rColor = ARGBColor(0,100,0); return true;
+        case XML_DARKGREY: rColor = ARGBColor(169,169,169); return true;
+        case XML_DARKKHAKI: rColor = ARGBColor(189,183,107); return true;
+        case XML_DARKMAGENTA: rColor = ARGBColor(139,0,139); return true;
+        case XML_DARKOLIVEGREEN: rColor = ARGBColor(85,107,47); return true;
+        case XML_DARKORANGE: rColor = ARGBColor(255,140,0); return true;
+        case XML_DARKORCHID: rColor = ARGBColor(153,50,204); return true;
+        case XML_DARKRED: rColor = ARGBColor(139,0,0); return true;
+        case XML_DARKSALMON: rColor = ARGBColor(233,150,122); return true;
+        case XML_DARKSEAGREEN: rColor = ARGBColor(143,188,143); return true;
+        case XML_DARKSLATEBLUE: rColor = ARGBColor(72,61,139); return true;
+        case XML_DARKSLATEGRAY: rColor = ARGBColor(47,79,79); return true;
+        case XML_DARKSLATEGREY: rColor = ARGBColor(47,79,79); return true;
+        case XML_DARKTURQUOISE: rColor = ARGBColor(0,206,209); return true;
+        case XML_DARKVIOLET: rColor = ARGBColor(148,0,211); return true;
+        case XML_DEEPPINK: rColor = ARGBColor(255,20,147); return true;
+        case XML_DEEPSKYBLUE: rColor = ARGBColor(0,191,255); return true;
+        case XML_DIMGRAY: rColor = ARGBColor(105,105,105); return true;
+        case XML_DIMGREY: rColor = ARGBColor(105,105,105); return true;
+        case XML_DODGERBLUE: rColor = ARGBColor(30,144,255); return true;
+        case XML_FIREBRICK: rColor = ARGBColor(178,34,34); return true;
+        case XML_FLORALWHITE: rColor = ARGBColor(255,250,240); return true;
+        case XML_FORESTGREEN: rColor = ARGBColor(34,139,34); return true;
+        case XML_FUCHSIA: rColor = ARGBColor(255,0,255); return true;
+        case XML_GAINSBORO: rColor = ARGBColor(220,220,220); return true;
+        case XML_GHOSTWHITE: rColor = ARGBColor(248,248,255); return true;
+        case XML_GOLD: rColor = ARGBColor(255,215,0); return true;
+        case XML_GOLDENROD: rColor = ARGBColor(218,165,32); return true;
+        case XML_GRAY: rColor = ARGBColor(128,128,128); return true;
+        case XML_GREY: rColor = ARGBColor(128,128,128); return true;
+        case XML_GREEN: rColor = ARGBColor(0,128,0); return true;
+        case XML_GREENYELLOW: rColor = ARGBColor(173,255,47); return true;
+        case XML_HONEYDEW: rColor = ARGBColor(240,255,240); return true;
+        case XML_HOTPINK: rColor = ARGBColor(255,105,180); return true;
+        case XML_INDIANRED: rColor = ARGBColor(205,92,92); return true;
+        case XML_INDIGO: rColor = ARGBColor(75,0,130); return true;
+        case XML_IVORY: rColor = ARGBColor(255,255,240); return true;
+        case XML_KHAKI: rColor = ARGBColor(240,230,140); return true;
+        case XML_LAVENDER: rColor = ARGBColor(230,230,250); return true;
+        case XML_LAVENDERBLUSH: rColor = ARGBColor(255,240,245); return true;
+        case XML_LAWNGREEN: rColor = ARGBColor(124,252,0); return true;
+        case XML_LEMONCHIFFON: rColor = ARGBColor(255,250,205); return true;
+        case XML_LIGHTBLUE: rColor = ARGBColor(173,216,230); return true;
+        case XML_LIGHTCORAL: rColor = ARGBColor(240,128,128); return true;
+        case XML_LIGHTCYAN: rColor = ARGBColor(224,255,255); return true;
+        case XML_LIGHTGOLDENRODYELLOW: rColor = ARGBColor(250,250,210); return true;
+        case XML_LIGHTGRAY: rColor = ARGBColor(211,211,211); return true;
+        case XML_LIGHTGREEN: rColor = ARGBColor(144,238,144); return true;
+        case XML_LIGHTGREY: rColor = ARGBColor(211,211,211); return true;
+        case XML_LIGHTPINK: rColor = ARGBColor(255,182,193); return true;
+        case XML_LIGHTSALMON: rColor = ARGBColor(255,160,122); return true;
+        case XML_LIGHTSEAGREEN: rColor = ARGBColor(32,178,170); return true;
+        case XML_LIGHTSKYBLUE: rColor = ARGBColor(135,206,250); return true;
+        case XML_LIGHTSLATEGRAY: rColor = ARGBColor(119,136,153); return true;
+        case XML_LIGHTSLATEGREY: rColor = ARGBColor(119,136,153); return true;
+        case XML_LIGHTSTEELBLUE: rColor = ARGBColor(176,196,222); return true;
+        case XML_LIGHTYELLOW: rColor = ARGBColor(255,255,224); return true;
+        case XML_LIME: rColor = ARGBColor(0,255,0); return true;
+        case XML_LIMEGREEN: rColor = ARGBColor(50,205,50); return true;
+        case XML_LINEN: rColor = ARGBColor(250,240,230); return true;
+        case XML_MAGENTA: rColor = ARGBColor(255,0,255); return true;
+        case XML_MAROON: rColor = ARGBColor(128,0,0); return true;
+        case XML_MEDIUMAQUAMARINE: rColor = ARGBColor(102,205,170); return true;
+        case XML_MEDIUMBLUE: rColor = ARGBColor(0,0,205); return true;
+        case XML_MEDIUMORCHID: rColor = ARGBColor(186,85,211); return true;
+        case XML_MEDIUMPURPLE: rColor = ARGBColor(147,112,219); return true;
+        case XML_MEDIUMSEAGREEN: rColor = ARGBColor(60,179,113); return true;
+        case XML_MEDIUMSLATEBLUE: rColor = ARGBColor(123,104,238); return true;
+        case XML_MEDIUMSPRINGGREEN: rColor = ARGBColor(0,250,154); return true;
+        case XML_MEDIUMTURQUOISE: rColor = ARGBColor(72,209,204); return true;
+        case XML_MEDIUMVIOLETRED: rColor = ARGBColor(199,21,133); return true;
+        case XML_MIDNIGHTBLUE: rColor = ARGBColor(25,25,112); return true;
+        case XML_MINTCREAM: rColor = ARGBColor(245,255,250); return true;
+        case XML_MISTYROSE: rColor = ARGBColor(255,228,225); return true;
+        case XML_MOCCASIN: rColor = ARGBColor(255,228,181); return true;
+        case XML_NAVAJOWHITE: rColor = ARGBColor(255,222,173); return true;
+        case XML_NAVY: rColor = ARGBColor(0,0,128); return true;
+        case XML_OLDLACE: rColor = ARGBColor(253,245,230); return true;
+        case XML_OLIVE: rColor = ARGBColor(128,128,0); return true;
+        case XML_OLIVEDRAB: rColor = ARGBColor(107,142,35); return true;
+        case XML_ORANGE: rColor = ARGBColor(255,165,0); return true;
+        case XML_ORANGERED: rColor = ARGBColor(255,69,0); return true;
+        case XML_ORCHID: rColor = ARGBColor(218,112,214); return true;
+        case XML_PALEGOLDENROD: rColor = ARGBColor(238,232,170); return true;
+        case XML_PALEGREEN: rColor = ARGBColor(152,251,152); return true;
+        case XML_PALETURQUOISE: rColor = ARGBColor(175,238,238); return true;
+        case XML_PALEVIOLETRED: rColor = ARGBColor(219,112,147); return true;
+        case XML_PAPAYAWHIP: rColor = ARGBColor(255,239,213); return true;
+        case XML_PEACHPUFF: rColor = ARGBColor(255,218,185); return true;
+        case XML_PERU: rColor = ARGBColor(205,133,63); return true;
+        case XML_PINK: rColor = ARGBColor(255,192,203); return true;
+        case XML_PLUM: rColor = ARGBColor(221,160,221); return true;
+        case XML_POWDERBLUE: rColor = ARGBColor(176,224,230); return true;
+        case XML_PURPLE: rColor = ARGBColor(128,0,128); return true;
+        case XML_RED: rColor = ARGBColor(255,0,0); return true;
+        case XML_ROSYBROWN: rColor = ARGBColor(188,143,143); return true;
+        case XML_ROYALBLUE: rColor = ARGBColor(65,105,225); return true;
+        case XML_SADDLEBROWN: rColor = ARGBColor(139,69,19); return true;
+        case XML_SALMON: rColor = ARGBColor(250,128,114); return true;
+        case XML_SANDYBROWN: rColor = ARGBColor(244,164,96); return true;
+        case XML_SEAGREEN: rColor = ARGBColor(46,139,87); return true;
+        case XML_SEASHELL: rColor = ARGBColor(255,245,238); return true;
+        case XML_SIENNA: rColor = ARGBColor(160,82,45); return true;
+        case XML_SILVER: rColor = ARGBColor(192,192,192); return true;
+        case XML_SKYBLUE: rColor = ARGBColor(135,206,235); return true;
+        case XML_SLATEBLUE: rColor = ARGBColor(106,90,205); return true;
+        case XML_SLATEGRAY: rColor = ARGBColor(112,128,144); return true;
+        case XML_SLATEGREY: rColor = ARGBColor(112,128,144); return true;
+        case XML_SNOW: rColor = ARGBColor(255,250,250); return true;
+        case XML_SPRINGGREEN: rColor = ARGBColor(0,255,127); return true;
+        case XML_STEELBLUE: rColor = ARGBColor(70,130,180); return true;
+        case XML_TAN: rColor = ARGBColor(210,180,140); return true;
+        case XML_TEAL: rColor = ARGBColor(0,128,128); return true;
+        case XML_THISTLE: rColor = ARGBColor(216,191,216); return true;
+        case XML_TOMATO: rColor = ARGBColor(255,99,71); return true;
+        case XML_TURQUOISE: rColor = ARGBColor(64,224,208); return true;
+        case XML_VIOLET: rColor = ARGBColor(238,130,238); return true;
+        case XML_WHEAT: rColor = ARGBColor(245,222,179); return true;
+        case XML_WHITE: rColor = ARGBColor(255,255,255); return true;
+        case XML_WHITESMOKE: rColor = ARGBColor(245,245,245); return true;
+        case XML_YELLOW: rColor = ARGBColor(255,255,0); return true;
+        case XML_YELLOWGREEN: rColor = ARGBColor(154,205,50); return true;
+	
+        default: 
+            return false; // no color at all, I'd guess.
+	}
+}
+
+bool parseOpacity (const char* sOpacity, ARGBColor& rColor )
+{
+	using namespace ::boost::spirit;
+	
+	if( parse(sOpacity,
+              // Begin grammar  
+              (
+                  real_p[assign_a(rColor.a)] 
+                  ) >> end_p,
+              // End grammar  
+              space_p).full )
+	{
+		return true;
+	}
+	return false;
+}			
+
+//////////////////////////////////////////////////////////////
+
+bool parseTransform( const char* sTransform, basegfx::B2DHomMatrix& rTransform )
+{
+    using namespace ::boost::spirit;
+
+    double fRefOffsetX(0.0);
+    double fRefOffsetY(0.0);
+    bool   bRefTransform(false);
+
+    double fRotationAngle=0.0;
+    double fSkewAngle=0.0;
+    geometry::AffineMatrix2D aIdentityTransform;
+    geometry::AffineMatrix2D aCurrTransform;
+    std::vector<geometry::AffineMatrix2D> aTransforms;
+    aIdentityTransform.m00 = 1.0; aIdentityTransform.m11 = 1.0;
+    aCurrTransform = aIdentityTransform;
+    
+    const bool bRes = parse(sTransform,
+        //  Begin grammar
+        (
+            // identity transform
+            str_p("none")
+          |
+            // the ref() form
+            (str_p("ref")
+             >> '('
+             >> str_p("svg")[assign_a(bRefTransform,true)] 
+             >> !(real_p[assign_a(fRefOffsetX)] >> (',' | eps_p) >>
+                  real_p[assign_a(fRefOffsetY)])
+             >> ')')
+          |
+            // the transform-list form
+            (list_p(
+               (   
+                 // matrix(a,b,c,d,e,f)  
+                 (str_p("matrix") 
+                  >> '('
+                  >> real_p[assign_a(aCurrTransform.m00)] >> (',' | eps_p)
+                  >> real_p[assign_a(aCurrTransform.m10)] >> (',' | eps_p) 
+                  >> real_p[assign_a(aCurrTransform.m01)] >> (',' | eps_p)
+                  >> real_p[assign_a(aCurrTransform.m11)] >> (',' | eps_p)
+                  >> real_p[assign_a(aCurrTransform.m02)] >> (',' | eps_p)
+                  >> real_p[assign_a(aCurrTransform.m12)]
+                  >> ')')[push_back_a(aTransforms,aCurrTransform)]
+               |  
+                 // translate(x,[y])
+                 (str_p("translate") 
+                  >> '('
+                  >> real_p[boost::bind(&assign_twice,
+                                        boost::ref(aCurrTransform.m02),
+                                        boost::ref(aCurrTransform.m12),_1)]
+                  >> !((',' | eps_p) >> real_p[assign_a(aCurrTransform.m12)])
+                  >> ')')[push_back_a(aTransforms,aCurrTransform)]
+               |  
+                 // scale(x,[y])
+                 (str_p("scale") 
+                  >> '('
+                  >> real_p[boost::bind(&assign_twice,
+                                        boost::ref(aCurrTransform.m00),
+                                        boost::ref(aCurrTransform.m11),_1)]
+                  >> !((',' | eps_p) >> real_p[assign_a(aCurrTransform.m11)])
+                  >> ')')[push_back_a(aTransforms,aCurrTransform)]
+               |  
+                 // rotate(phi,[cx, cy])
+                 (str_p("rotate") 
+                  >> '('
+                  >> real_p[assign_a(fRotationAngle)]
+                  >> !((',' | eps_p) >> real_p[assign_a(aCurrTransform.m02)]
+                       >> real_p[assign_a(aCurrTransform.m12)])
+                  >> ')')[boost::bind(&calcRotation,
+                                      boost::ref(aTransforms),
+                                      boost::ref(aCurrTransform),
+                                      boost::cref(fRotationAngle))]
+               |  
+                 // skewX(phi)
+                 (str_p("skewX") 
+                  >> '(' 
+                  >> real_p[assign_a(fSkewAngle)] 
+                  >> ')')[boost::bind(&calcSkewX,
+                                      boost::ref(aTransforms),
+                                      boost::cref(fSkewAngle))]
+               |  
+                 // skewY(phi)
+                 (str_p("skewY") 
+                  >> '(' 
+                  >> real_p[assign_a(fSkewAngle)] 
+                  >> ')')[boost::bind(&calcSkewY,
+                                      boost::ref(aTransforms),
+                                      boost::cref(fSkewAngle))]
+                 // reset current transform after every push
+               )[assign_a(aCurrTransform,aIdentityTransform)],
+                 // list delimiter is either ',' or space
+               ',' | eps_p ))
+        ) >> end_p,
+        //  End grammar
+        space_p).full;
+
+    if( !bRes )
+        return false;
+
+    // fold all transformations into one
+    const geometry::AffineMatrix2D aTotalTransform(
+        std::accumulate(aTransforms.begin(),
+                        aTransforms.end(),
+                        aIdentityTransform,
+                        &multiplyMatrix));
+
+    basegfx::unotools::homMatrixFromAffineMatrix(
+        rTransform,
+        aTotalTransform);
+
+    // TODO(F1): handle the ref case
+    return bRes;
+}
+
+//////////////////////////////////////////////////////////////
+
+bool parseViewBox( const char* sViewbox, basegfx::B2DRange& rRect )
+{
+    using namespace ::boost::spirit;
+
+    double x=0.0,y=0.0,w=0.0,h=0.0;
+    
+    const bool bRes = parse(sViewbox,
+        //  Begin grammar
+        (
+            // either comma- or space-delimited list of four doubles    
+            real_p[assign_a(x)] >> (',' | eps_p) >>
+            real_p[assign_a(y)] >> (',' | eps_p) >>
+            real_p[assign_a(w)] >> (',' | eps_p) >>
+            real_p[assign_a(h)] >> end_p
+        ),
+        //  End grammar
+        space_p).full;
+
+    if( !bRes )
+        return false;
+
+    rRect = basegfx::B2DRange(x,y,x+w,y+h);
+
+    return true;
+}
+
+//////////////////////////////////////////////////////////////
+
+bool parseDashArray( const char* sDashArray, std::vector<double>& rOutputVector )
+{
+    using namespace ::boost::spirit;
+    
+    rOutputVector.clear();
+    return parse(sDashArray,
+        //  Begin grammar
+        (
+            // parse comma-delimited list of doubles (have to use the
+            // 'direct' variant, as otherwise spirit refactors our
+            // parser to push both real num and comma to push_back_a)
+            list_p.direct
+            (
+                real_p[push_back_a(rOutputVector)], 
+                // list delimiter is either ',' or space
+                ',' | eps_p
+            )
+        ) >> end_p,
+        //  End grammar
+        space_p).full;
+}
+
+//////////////////////////////////////////////////////////////
+
+bool parsePaintUri( std::pair<const char*,const char*>& o_rPaintUri,
+                    std::pair<ARGBColor,bool>&          io_rColor,
+                    const char*                         sPaintUri )
+{
+    using namespace ::boost::spirit;
+
+    const bool bRes = parse(sPaintUri,
+        //  Begin grammar
+        (
+            str_p("url(#") >>
+            (+alnum_p)[assign_a(o_rPaintUri)] >> 
+            str_p(")") >>
+            *( str_p("none")[assign_a(io_rColor.second,false)] | 
+               str_p("currentColor")[assign_a(io_rColor.second,true)] |
+               ColorGrammar(io_rColor.first)
+               // TODO(F1): named color
+             )
+        ) >> end_p,
+        //  End grammar
+        space_p).full;
+
+    return bRes;
+}
+
+//////////////////////////////////////////////////////////////
+
+namespace
+{
+void appendChar( std::string& str, char character)
+{
+	str.append(1,character);
+}
+}
+
+bool parseXlinkHref( const char* sXlinkHref, std::string& data )
+{
+	using namespace ::boost::spirit;
+	
+	data.erase(data.begin(),data.end());
+
+    std::string sLink(sXlinkHref);
+
+    if (!sLink.compare(0,5,"data:"))
+    {
+        // the inplace "data" uri
+        size_t position = sLink.rfind(',');
+        if (position > 0 && position < std::string::npos)
+        {
+            data = sLink.substr(position+1);
+            OSL_TRACE("%s", data.c_str());
+            return true;
+        }
+    }
+
+    return false;
+}
+
+} // namespace svgi
diff -ruN OOO310_m6.orig/filter/source/svg/parserfragments.hxx OOO310_m6/filter/source/svg/parserfragments.hxx
--- OOO310_m6.orig/filter/source/svg/parserfragments.hxx	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/parserfragments.hxx	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,74 @@
+/*************************************************************************
+ *
+ *    OpenOffice.org - a multi-platform office productivity suite
+ *
+ *    Author:
+ *      Fridrich Strba  <fridrich.strba@bluewin.ch>
+ *      Thorsten Behrens <tbehrens@novell.com>	   	
+ *
+ *      Copyright (C) 2008, Novell Inc.
+ *
+ *   The Contents of this file are made available subject to
+ *   the terms of GNU Lesser General Public License Version 2.1.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_PARSERFRAGMENTS_HXX
+#define INCLUDED_PARSERFRAGMENTS_HXX
+
+#include <sal/config.h>
+#include <vector>
+#include <utility>
+#include <string>
+
+namespace basegfx
+{ 
+    class B2DHomMatrix; 
+    class B2DRange; 
+}
+namespace svgi
+{
+    struct ARGBColor;
+
+    /// Parse given string for one of the SVG color grammars
+    bool parseColor( const char* sColor, ARGBColor& rColor );
+	bool parseOpacity( const char* sOpacity, ARGBColor& rColor );
+
+    /// Parse given string for one of the SVG transformation grammars
+    bool parseTransform( const char* sTransform, basegfx::B2DHomMatrix& rTransform );
+
+    /// Parse given string for the viewBox attribute
+    bool parseViewBox( const char* sViewbox, basegfx::B2DRange& rRect );
+
+    /// Parse given string for a list of double values, comma-delimited
+    bool parseDashArray( const char* sDashArray, std::vector<double>& rOutputVector );
+	
+    /** Parse paint uri
+
+        @param o_rPaintUri
+        Start and end ptr for uri substring (within
+        [sPaintUri,sPaintUri+strlen(sPaintUri)]
+
+        @param io_rColor
+        The optional paint color to use. if o_rPaintUri is empty,
+        parser sets io_rColor.second to false for color="None", to
+        true and keeps current io_rColor.first entry for
+        "currentColor", and to true and sets io_rColor.first to parsed
+        color otherwise.
+
+        @param sPaintUri
+        String to parse. Permitted to contain the optional paint
+        stuff, like fallback color.
+
+        @return true, if a paint uri was successfully parsed.
+     */
+    bool parsePaintUri( std::pair<const char*,const char*>& o_rPaintUri,
+                        std::pair<ARGBColor,bool>&          io_rColor,
+                        const char*                         sPaintUri );
+
+	/// Parse given string for the xlink attribute
+	bool parseXlinkHref( const char* xlink, std::string& data );
+
+} // namespace svgi
+
+#endif
diff -ruN OOO310_m6.orig/filter/source/svg/spirit_supplements.hxx OOO310_m6/filter/source/svg/spirit_supplements.hxx
--- OOO310_m6.orig/filter/source/svg/spirit_supplements.hxx	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/spirit_supplements.hxx	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,115 @@
+/*************************************************************************
+ *
+ *    OpenOffice.org - a multi-platform office productivity suite
+ *
+ *    Author:
+ *      Fridrich Strba  <fridrich.strba@bluewin.ch>
+ *      Thorsten Behrens <tbehrens@novell.com>	   	
+ *
+ *      Copyright (C) 2008, Novell Inc.
+ *
+ *   The Contents of this file are made available subject to
+ *   the terms of GNU Lesser General Public License Version 2.1.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SPIRIT_SUPPLEMENTS_HXX
+#define INCLUDED_SPIRIT_SUPPLEMENTS_HXX
+
+# ifndef USE_MODERN_SPIRIT
+# include <boost/spirit.hpp>
+
+namespace boost { namespace spirit
+{
+    template <>
+    class assign_actor< std::pair<const char*,const char*> >
+    {
+    public:
+        explicit assign_actor(std::pair<const char*,const char*>& ref_)
+            : ref(ref_) {}
+
+        template <typename T2>
+        void operator()(T2 const& val) const
+        { ref = val; }
+        
+        template <typename IteratorT>
+        void operator()(IteratorT const& f, IteratorT const& l) const
+        { 
+            ref.first = f, ref.second = l;
+        }
+
+    private:
+        std::pair<const char*,const char*>& ref;
+    };
+
+    template<typename Target, typename Value> struct assigner
+    {
+        assigner( Target& rTarget, Value aValue ) : 
+            mrTarget(rTarget), maValue(aValue)
+        {}
+
+        void assign() const { mrTarget=maValue; }
+
+        void operator()() const { assign(); }
+        template<typename T1> void operator()(T1) const { assign(); }
+        template<typename T1,typename T2> void operator()(T1,T2) const { assign(); }
+        template<typename T1,typename T2,typename T3> void operator()(T1,T2,T3) const { assign(); }
+
+        Target&     mrTarget;
+        const Value maValue;
+    };
+
+    template<typename Target, typename Value> inline assigner<Target,Value> 
+    assign_a( Target& rTarget, Value aValue )
+    {
+        return assigner<Target,Value>(rTarget,aValue);
+    }
+
+    template <typename Target> inline assign_actor<Target>
+    assign_a(Target& rTarget)
+    {
+        return assign_actor<Target>(rTarget);
+    }
+
+    template<typename Target, typename Value> struct back_pusher
+    {
+        back_pusher( Target& rTarget, const Value& rValue ) : 
+            mrTarget(rTarget), mrValue(rValue)
+        {}
+
+        void push_back() const { mrTarget.push_back(mrValue); }
+
+        void operator()() const { push_back(); }
+        template<typename T1> void operator()(T1) const { push_back(); }
+        template<typename T1,typename T2> void operator()(T1,T2) const { push_back(); }
+        template<typename T1,typename T2,typename T3> void operator()(T1,T2,T3) const { push_back(); }
+
+        Target&      mrTarget;
+        const Value& mrValue;
+    };
+
+    template<typename Target, typename Value> inline back_pusher<Target,Value> 
+    push_back_a( Target& rTarget, const Value& rValue )
+    {
+        return back_pusher<Target,Value>(rTarget,rValue);
+    }
+
+    template<typename Target> struct value_back_pusher
+    {
+        explicit value_back_pusher( Target& rTarget ) : 
+            mrTarget(rTarget)
+        {}
+        template<typename T1> void operator()(T1 val) const { mrTarget.push_back(val); }
+
+        Target&      mrTarget;
+    };
+
+    template<typename Target> inline value_back_pusher<Target> 
+    push_back_a( Target& rTarget )
+    {
+        return value_back_pusher<Target>(rTarget);
+    }
+} }
+
+# endif
+#endif
diff -ruN OOO310_m6.orig/filter/source/svg/svgfilter.cxx OOO310_m6/filter/source/svg/svgfilter.cxx
--- OOO310_m6.orig/filter/source/svg/svgfilter.cxx	2009-03-17 14:58:30.000000000 +0000
+++ OOO310_m6/filter/source/svg/svgfilter.cxx	2009-03-17 14:59:37.000000000 +0000
@@ -33,13 +33,16 @@
 
 #include <cstdio>
 
-#include "svgfilter.hxx" 
+#include <comphelper/servicedecl.hxx>
+#include <uno/environment.h>
 #include <com/sun/star/drawing/XDrawPage.hpp>
 #include <com/sun/star/drawing/XDrawView.hpp>
 #include <com/sun/star/frame/XDesktop.hdl>
 #include <com/sun/star/frame/XController.hdl>
 #include <vos/mutex.hxx>
 
+#include "svgfilter.hxx" 
+
 using ::rtl::OUString;
 using namespace ::com::sun::star;
 
@@ -47,8 +50,9 @@
 // - SVGFilter -
 // -------------
 
-SVGFilter::SVGFilter( const Reference< XMultiServiceFactory > &rxMSF ) :
-    mxMSF( rxMSF ),
+SVGFilter::SVGFilter( const Reference< XComponentContext >& rxCtx ) :
+    mxMSF( rxCtx->getServiceManager(),
+           uno::UNO_QUERY_THROW ),
     mpSVGDoc( NULL ),
     mpSVGExport( NULL ),
 	mpSVGFontExport( NULL ),
@@ -83,11 +87,9 @@
     if( pFocusWindow )
     	pFocusWindow->EnterWait();
 
-#ifdef SOLAR_JAVA
     if( mxDstDoc.is() )
         bRet = implImport( rDescriptor );
     else
-#endif
     if( mxSrcDoc.is() )
 	{
 		uno::Reference< frame::XDesktop > xDesktop( mxMSF->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.frame.Desktop" ) ), 
@@ -156,77 +158,80 @@
 
 // -----------------------------------------------------------------------------
 
-#ifdef SOLAR_JAVA
 void SAL_CALL SVGFilter::setTargetDocument( const Reference< XComponent >& xDoc ) 
 	throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException)
 {
 	mxDstDoc = xDoc;
 }
-#endif
 
 // -----------------------------------------------------------------------------
 
-void SAL_CALL SVGFilter::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& /* aArguments */ ) 
-	throw (Exception, RuntimeException)
+rtl::OUString SAL_CALL SVGFilter::detect( Sequence< PropertyValue >& io_rDescriptor ) throw (RuntimeException)
 {
-}
+    uno::Reference< io::XInputStream > xInput;
+    rtl::OUString aURL;
 
-// -----------------------------------------------------------------------------
+    const beans::PropertyValue* pAttribs = io_rDescriptor.getConstArray();
+    const sal_Int32 nAttribs = io_rDescriptor.getLength();
+    for( sal_Int32 i = 0; i < nAttribs; i++ )
+    {
+        if( pAttribs[i].Name.equalsAscii( "InputStream" ) )
+            pAttribs[i].Value >>= xInput;
+    }
 
-OUString SVGFilter_getImplementationName ()
-	throw (RuntimeException)
-{
-	return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Draw.SVGFilter" ) );
-}
+    if( !xInput.is() )
+        return rtl::OUString();
 
-// -----------------------------------------------------------------------------
+    uno::Reference< io::XSeekable > xSeek( xInput, uno::UNO_QUERY );
+    if( xSeek.is() )
+        xSeek->seek( 0 );
 
-#define SERVICE_NAME "com.sun.star.document.SVGFilter"
+    // read the first 1024 bytes & check a few magic string
+    // constants (heuristically)
+    const sal_Int32 nLookAhead = 1024;
+    uno::Sequence< sal_Int8 > aBuf( nLookAhead );
+    const sal_uInt64 nBytes=xInput->readBytes(aBuf, nLookAhead);
+    const sal_Int8* const pBuf=aBuf.getConstArray();
 
-sal_Bool SAL_CALL SVGFilter_supportsService( const OUString& ServiceName ) 
-	throw (RuntimeException)
-{
-    return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
-}
+    sal_Int8 aMagic1[] = {'<', 's', 'v', 'g'};
+    if( std::search(pBuf, pBuf+nBytes, 
+                    aMagic1, aMagic1+sizeof(aMagic1)/sizeof(*aMagic1)) != pBuf+nBytes )
+        return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("svg_Scalable_Vector_Graphics") );
 
-// -----------------------------------------------------------------------------
+    sal_Int8 aMagic2[] = {'D', 'O', 'C', 'T', 'Y', 'P', 'E', ' ', 's', 'v', 'g'};
+    if( std::search(pBuf, pBuf+nBytes, 
+                    aMagic2, aMagic2+sizeof(aMagic2)/sizeof(*aMagic2)) != pBuf+nBytes )
+        return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("svg_Scalable_Vector_Graphics") );
 
-Sequence< OUString > SAL_CALL SVGFilter_getSupportedServiceNames(  ) throw (RuntimeException)
-{
-	Sequence < OUString > aRet(1);
-    OUString* pArray = aRet.getArray();
-    pArray[0] =  OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
-    return aRet;
+    return rtl::OUString();
 }
 
-#undef SERVICE_NAME
-
 // -----------------------------------------------------------------------------
 
-Reference< XInterface > SAL_CALL SVGFilter_createInstance( const Reference< XMultiServiceFactory > & rSMgr) throw( Exception )
+class FilterConfigItem;
+extern "C" SAL_DLLPUBLIC_EXPORT BOOL __LOADONCALLAPI GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem*, BOOL )
 {
-	return (cppu::OWeakObject*) new SVGFilter( rSMgr );
+    BOOL bRet = FALSE;
+    try
+    {
+        bRet = importSvg( rStream, rGraphic );
+    }
+    catch (const uno::Exception&) {
+    }
+    return bRet;
 }
 
 // -----------------------------------------------------------------------------
 
-OUString SAL_CALL SVGFilter::getImplementationName(  ) 
-	throw (RuntimeException)
-{
-	return SVGFilter_getImplementationName();
-}
+namespace sdecl = comphelper::service_decl;
+ sdecl::class_<SVGFilter> serviceImpl;
+ const sdecl::ServiceDecl svgFilter(
+     serviceImpl,
+     "com.sun.star.comp.Draw.SVGFilter",
+     "com.sun.star.document.ImportFilter;"
+     "com.sun.star.document.ExportFilter;"
+     "com.sun.star.document.ExtendedTypeDetection" );
 
-// -----------------------------------------------------------------------------
+// The C shared lib entry points
+COMPHELPER_SERVICEDECL_EXPORTS1(svgFilter)
 
-sal_Bool SAL_CALL SVGFilter::supportsService( const OUString& rServiceName ) 
-	throw (RuntimeException)
-{
-    return SVGFilter_supportsService( rServiceName );
-}
-
-// -----------------------------------------------------------------------------
-
-::com::sun::star::uno::Sequence< OUString > SAL_CALL SVGFilter::getSupportedServiceNames(  ) throw (RuntimeException)
-{
-    return SVGFilter_getSupportedServiceNames();
-}
diff -ruN OOO310_m6.orig/filter/source/svg/svgfilter.hxx OOO310_m6/filter/source/svg/svgfilter.hxx
--- OOO310_m6.orig/filter/source/svg/svgfilter.hxx	2009-03-17 14:58:30.000000000 +0000
+++ OOO310_m6/filter/source/svg/svgfilter.hxx	2009-03-17 14:59:37.000000000 +0000
@@ -38,20 +38,14 @@
 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
 #include <com/sun/star/presentation/XPresentationSupplier.hpp>
 #include <com/sun/star/document/XFilter.hpp>
-#ifdef SOLAR_JAVA
 #include <com/sun/star/document/XImporter.hpp>
-#endif // SOLAR_JAVA
 #include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/document/XExtendedFilterDetection.hpp>
 #include <com/sun/star/lang/XInitialization.hpp>
 #include <com/sun/star/lang/XServiceInfo.hpp>
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <com/sun/star/lang/XComponent.hpp>
-#include <cppuhelper/implbase1.hxx>
-#ifdef SOLAR_JAVA
-#include <cppuhelper/implbase5.hxx>
-#else // !SOLAR_JAVA
 #include <cppuhelper/implbase4.hxx>
-#endif
 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
 #include <com/sun/star/io/XActiveDataSource.hpp>
 #include <com/sun/star/presentation/AnimationEffect.hpp>
@@ -178,18 +172,10 @@
 class SVGActionWriter;
 class EditFieldInfo;
 
-#ifdef SOLAR_JAVA
-class SVGFilter : public cppu::WeakImplHelper5 < XFilter,
-											     XImporter,
-                                                 XExporter,
-												 XInitialization,
-												 XServiceInfo >
-#else // !SOLAR_JAVA
 class SVGFilter : public cppu::WeakImplHelper4 < XFilter,
+											     XImporter,
                                                  XExporter,
-                                                 XInitialization,
-                                                 XServiceInfo >
-#endif
+                                                 XExtendedFilterDetection >
 {
 	typedef ::std::hash_map< Reference< XInterface >, ObjectRepresentation, HashReferenceXInterface > ObjectMap;
 
@@ -206,15 +192,11 @@
 
 	ObjectMap*							mpObjects;
 	Reference< XComponent >				mxSrcDoc;
-#ifdef SOLAR_JAVA
 	Reference< XComponent >				mxDstDoc;
-#endif
 	Reference< XDrawPage > 				mxDefaultPage;
 	Link								maOldFieldHdl;
 
-#ifdef SOLAR_JAVA
     sal_Bool                            implImport( const Sequence< PropertyValue >& rDescriptor ) throw (RuntimeException);
-#endif
 
     sal_Bool                            implExport( const Sequence< PropertyValue >& rDescriptor ) throw (RuntimeException);
     Reference< XDocumentHandler >       implCreateExportDocumentHandler( const Reference< XOutputStream >& rxOStm );
@@ -253,26 +235,19 @@
     virtual sal_Bool SAL_CALL filter( const Sequence< PropertyValue >& rDescriptor ) throw(RuntimeException);
     virtual void SAL_CALL cancel( ) throw (RuntimeException);
 
-#ifdef SOLAR_JAVA
 	// XImporter
     virtual void SAL_CALL setTargetDocument( const Reference< XComponent >& xDoc ) throw(IllegalArgumentException, RuntimeException);
-#endif
 
 	// XExporter
     virtual void SAL_CALL setSourceDocument( const Reference< XComponent >& xDoc ) throw(IllegalArgumentException, RuntimeException);
 
-	// XInitialization
-    virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException);
-
-	// XServiceInfo
-    virtual ::rtl::OUString SAL_CALL getImplementationName() throw(RuntimeException);
-    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(RuntimeException);
-    virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames()  throw(RuntimeException);
+    // XExtendedFilterDetection
+    virtual rtl::OUString SAL_CALL detect( Sequence< PropertyValue >& io_rDescriptor ) throw (RuntimeException);
 
 public:
 	
-				SVGFilter( const Reference< XMultiServiceFactory > &rxMSF );
-	virtual		~SVGFilter();
+    explicit SVGFilter( const Reference< XComponentContext >& rxCtx );
+	virtual	~SVGFilter();
 };
 
 // -----------------------------------------------------------------------------
@@ -296,4 +271,11 @@
 SAL_CALL SVGFilter_createInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & rSMgr)
 	throw ( ::com::sun::star::uno::Exception );
 
+// -----------------------------------------------------------------------------
+
+class SvStream;
+class Graphic;
+
+bool importSvg(SvStream & rStream, Graphic & rGraphic );
+
 #endif // SVGFILTER_HXX
diff -ruN OOO310_m6.orig/filter/source/svg/svgimport.cxx OOO310_m6/filter/source/svg/svgimport.cxx
--- OOO310_m6.orig/filter/source/svg/svgimport.cxx	2009-03-17 14:58:30.000000000 +0000
+++ OOO310_m6/filter/source/svg/svgimport.cxx	2009-03-17 14:59:37.000000000 +0000
@@ -32,160 +32,59 @@
 #include "precompiled_filter.hxx"
 
 #include "svgfilter.hxx" 
+#include "svgreader.hxx" 
+
 #include "rtl/ref.hxx"
-#include "jvmaccess/virtualmachine.hxx"
-// -------------
-// - SVGFilter -
-// -------------
+
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+#include <com/sun/star/lang/XComponent.hpp>
+
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Type.hxx>
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include <com/sun/star/xml/sax/XParser.hpp>
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#include <com/sun/star/xml/XImportFilter.hpp>
+
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <com/sun/star/task/XStatusIndicator.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::svgi;
 
 sal_Bool SVGFilter::implImport( const Sequence< PropertyValue >& rDescriptor )
 	throw (RuntimeException)
 {
-    Reference< XMultiServiceFactory >	xServiceFactory( ::comphelper::getProcessServiceFactory() ) ;
-	rtl::OUString							aTmpFileName;
-	String								aFileName;
-	sal_Int32							nLength = rDescriptor.getLength();
-	const PropertyValue*				pValue = rDescriptor.getConstArray();
-	sal_Bool							bRet = sal_False;
-	
-	for( sal_Int32 i = 0 ; ( i < nLength ) && !aTmpFileName.getLength(); i++)
-		if( pValue[ i ].Name.equalsAscii( "FileName" ) )
-			pValue[ i ].Value >>= aTmpFileName;
-
-    if( aTmpFileName.getLength() && xServiceFactory.is() )
-    {
-
-	    Reference< XJavaVM >    xJavaVM( xServiceFactory->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.java.JavaVirtualMachine") ) ), UNO_QUERY );
-        Sequence< sal_Int8 >    aProcessID( 17 );
-		String					aLocalFile;
-
-		if( ::utl::LocalFileHelper::ConvertURLToPhysicalName( aTmpFileName, aLocalFile ) && aLocalFile.Len() )
+    rtl::OUString aURL;
+    uno::Reference< io::XInputStream > xInputStream;
+    uno::Reference< task::XStatusIndicator > xStatus;
+    const sal_Int32 nLength = rDescriptor.getLength();
+    const beans::PropertyValue* pAttribs = rDescriptor.getConstArray();
+    for ( sal_Int32 i=0 ; i<nLength; ++i, ++pAttribs )
+	{
+        if( pAttribs->Name.equalsAscii( "InputStream" ) )
         {
-			rtl_getGlobalProcessId( (sal_uInt8 *) aProcessID.getArray() );
-            aProcessID[16] = 0;            
-		
-            OSL_ENSURE(sizeof (sal_Int64)
-                       >= sizeof (jvmaccess::VirtualMachine *),
-                       "Pointer cannot be represented as sal_Int64");
-            sal_Int64 nPointer = reinterpret_cast< sal_Int64 >(
-                static_cast< jvmaccess::VirtualMachine * >(0));
-            xJavaVM->getJavaVM(aProcessID) >>= nPointer;
-            rtl::Reference<jvmaccess::VirtualMachine> _virtualMachine =
-                reinterpret_cast< jvmaccess::VirtualMachine * >(nPointer);
-            if (!_virtualMachine.is())
-                return bRet;
-            
-            jobjectArray    aArgs;
-            jclass          aClass;
-            jmethodID       aMId;
-            jstring         aJStr;
-            
-            try
-            {
-                jvmaccess::VirtualMachine::AttachGuard vmGuard(_virtualMachine);
-                
-                JNIEnv * pEnv = vmGuard.getEnvironment();
-                
-                aClass = pEnv->FindClass( "SOTranscoder" );
-                
-                if( aClass )
-                {
-					aMId = pEnv->GetStaticMethodID( aClass, "main", "([Ljava/lang/String;)V" );
-					if ( aMId )
-					{
-
-						::utl::TempFile aTempFile;
-						String			aOutputURL( aTempFile.GetURL() );
-						String			aOutputFile;
-	                    
-						aTempFile.EnableKillingFile();
-	                    
-						if( ::utl::LocalFileHelper::ConvertURLToPhysicalName( aOutputURL, aOutputFile ) && aOutputFile.Len() )
-						{
-							aJStr = pEnv->NewStringUTF( ByteString( aLocalFile.GetBuffer(), RTL_TEXTENCODING_UTF8 ).GetBuffer() );
-							aArgs = static_cast<jobjectArray>(pEnv->NewObjectArray( 2, pEnv->FindClass( "java/lang/String" ), aJStr ));
-							aJStr = pEnv->NewStringUTF( ByteString( aOutputFile.GetBuffer(), RTL_TEXTENCODING_UTF8 ).GetBuffer() );
-							pEnv->SetObjectArrayElement( aArgs, 1, aJStr );
-							pEnv->CallStaticVoidMethod( aClass, aMId, aArgs );
-	                        
-							Graphic		aGraphic;
-							SvStream*	pIStm = ::utl::UcbStreamHelper::CreateStream( aOutputURL, STREAM_READ );
-	                        
-							if( pIStm )
-							{
-								GraphicConverter::Import( *pIStm, aGraphic );
-								delete pIStm;
-							}
-	                        
-							Reference< XDrawPagesSupplier > xDrawPagesSupplier( mxDstDoc, UNO_QUERY );
-	                        
-							if( xDrawPagesSupplier.is() && ( aGraphic.GetType() != GRAPHIC_NONE ) )
-							{
-								Reference< XDrawPages > xDrawPages( xDrawPagesSupplier->getDrawPages() );
-	                            
-								if( xDrawPages.is() && xDrawPages->getCount() )
-								{
-									Reference< XDrawPage >	xDrawPage;
-	                                
-									if( xDrawPages->getByIndex( 0 ) >>= xDrawPage )
-									{
-										Reference< XShapes >		xShapes( xDrawPage, UNO_QUERY );
-										Reference< XPropertySet>	xPagePropSet( xDrawPage, UNO_QUERY );
-										Reference< XShape >			xShape( Reference< XMultiServiceFactory >( mxDstDoc, UNO_QUERY )->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.GraphicObjectShape" ) ) ), UNO_QUERY );
-	                                    
-										if( xPagePropSet.is() && xShapes.is() && xShape.is() )
-										{
-											Reference< XPropertySet >	xPropSet( xShape, UNO_QUERY );
-											sal_Int32					nPageWidth = 0, nPageHeight = 0;
-	                                        
-											xPagePropSet->getPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Width" ) ) ) >>= nPageWidth;
-											xPagePropSet->getPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Height" ) ) ) >>= nPageHeight;
-	                                        
-											if( xPropSet.is() && nPageWidth && nPageHeight )
-											{
-												xShapes->add( xShape );
-	                                            
-												::com::sun::star::awt::Point	aPos;
-												::com::sun::star::awt::Size		aSize;
-												GraphicObject					aGraphObj( aGraphic );
-												String							aGraphURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.GraphicObject:" ) );
-												Any								aValue;
-												Size							aGraphicSize;
-												const MapMode					aTargetMapMode( MAP_100TH_MM );
-	                                            
-												if( aGraphObj.GetPrefMapMode().GetMapUnit() == MAP_PIXEL )
-													aGraphicSize = Application::GetDefaultDevice()->PixelToLogic( aGraphObj.GetPrefSize(), aTargetMapMode );
-												else
-													aGraphicSize = OutputDevice::LogicToLogic( aGraphObj.GetPrefSize(), aGraphObj.GetPrefMapMode(), aTargetMapMode );
-	                                            
-												aGraphURL += String( aGraphObj.GetUniqueID(), RTL_TEXTENCODING_ASCII_US );
-												aValue <<= rtl::OUString( aGraphURL );
-												xPropSet->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ), aValue );
-	                                            
-												aPos.X = ( nPageWidth - aGraphicSize.Width() ) >> 1;
-												aPos.Y = ( nPageHeight - aGraphicSize.Height() ) >> 1;
-	                                            
-												aSize.Width = aGraphicSize.Width();
-												aSize.Height = aGraphicSize.Height();
-	                                                
-												xShape->setPosition( aPos );
-												xShape->setSize( aSize );
-	                                            
-												bRet = sal_True;
-											}
-										}
-									}
-								}
-							}
-						}
-                    }
-                }
-            }
-            catch (jvmaccess::VirtualMachine::AttachGuard::CreationException &)
-            {
-            }
-        }            
-    }
-    return bRet;
+            pAttribs->Value >>= xInputStream;
+        }
+        else if( pAttribs->Name.equalsAscii( "StatusIndicator" ) )
+            pAttribs->Value >>= xStatus;
+	}
+
+    OSL_ASSERT(xInputStream.is());
+    if(!xInputStream.is()) 
+        return sal_False;
+
+	rtl::OUString sXMLImportService ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Draw.XMLOasisImporter" ) );
+	Reference < XDocumentHandler > xInternalHandler( mxMSF->createInstance( sXMLImportService ), UNO_QUERY );
+
+	// The XImporter sets up an empty target document for XDocumentHandler to write to.. 
+	uno::Reference < XImporter > xImporter(xInternalHandler, UNO_QUERY);
+	xImporter->setTargetDocument(mxDstDoc);
+
+    SVGReader aReader(mxMSF, xInputStream, xInternalHandler);
+    return aReader.parseAndConvert();
 }
     
diff -ruN OOO310_m6.orig/filter/source/svg/svgreader.cxx OOO310_m6/filter/source/svg/svgreader.cxx
--- OOO310_m6.orig/filter/source/svg/svgreader.cxx	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/svgreader.cxx	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,2773 @@
+/*************************************************************************
+ *
+ *    OpenOffice.org - a multi-platform office productivity suite
+ *
+ *    Author:
+ *      Fridrich Strba  <fridrich.strba@bluewin.ch>
+ *      Thorsten Behrens <tbehrens@novell.com>	   	
+ *
+ *      Copyright (C) 2008, Novell Inc.
+ *      Parts copyright 2005 by Sun Microsystems, Inc.
+ *
+ *   The Contents of this file are made available subject to
+ *   the terms of GNU Lesser General Public License Version 2.1.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_filter.hxx"
+
+#include "svgreader.hxx"
+#include <xmloff/attrlist.hxx>
+#include "gfxtypes.hxx"
+#include "units.hxx"
+#include "parserfragments.hxx"
+#include "tokenmap.hxx"
+#include "b2dellipse.hxx"
+
+#include <rtl/math.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <basegfx/vector/b2enums.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/xml/sax/XParser.hpp>
+#include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
+#include <com/sun/star/xml/dom/NodeType.hpp>
+
+#include <comphelper/processfactory.hxx>
+#include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
+#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
+#include <unotools/streamwrap.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/gradient.hxx>
+#include <svx/impgrf.hxx>
+#include <tools/zcodec.hxx>
+
+#include <boost/bind.hpp>
+#include <hash_set>
+#include <map>
+#include <string.h>
+
+#define USTR(x) rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
+#define OASIS_STR "urn:oasis:names:tc:opendocument:xmlns:"
+
+using namespace ::com::sun::star;
+
+namespace svgi
+{
+namespace
+{
+
+/** visits all children of the specified type with the given functor
+ */
+template<typename Func> void visitChildren(const Func& rFunc,
+                                           const uno::Reference<xml::dom::XElement> xElem,
+                                           xml::dom::NodeType eChildType )
+{
+    uno::Reference<xml::dom::XNodeList> xChildren( xElem->getChildNodes() );
+    const sal_Int32 nNumNodes( xChildren->getLength() );
+    for( sal_Int32 i=0; i<nNumNodes; ++i )
+    {
+        if( xChildren->item(i)->getNodeType() == eChildType )
+            rFunc( *xChildren->item(i).get() );
+    }
+}
+
+/** Visit all elements of the given tree (in-order traversal)
+
+    Given functor is called for every element, and passed the
+    element's attributes, if any
+ */
+template<typename Func> void visitElements(Func& rFunc,
+                                           const uno::Reference<xml::dom::XElement> xElem)
+{
+    if( xElem->hasAttributes() )
+        rFunc(xElem,xElem->getAttributes());
+    else
+        rFunc(xElem);
+
+    // notify children processing
+    rFunc.push();
+
+    // recurse over children
+    uno::Reference<xml::dom::XNodeList> xChildren( xElem->getChildNodes() );
+    const sal_Int32 nNumNodes( xChildren->getLength() );
+    for( sal_Int32 i=0; i<nNumNodes; ++i )
+    {
+        if( xChildren->item(i)->getNodeType() == xml::dom::NodeType_ELEMENT_NODE )
+            visitElements( rFunc,
+                           uno::Reference<xml::dom::XElement>(
+                               xChildren->item(i),
+                               uno::UNO_QUERY_THROW) );
+    }
+
+    // children processing done
+    rFunc.pop();
+}
+
+template<typename value_type> value_type square(value_type v)
+{
+    return v*v;
+}
+
+double colorDiffSquared(const ARGBColor& rCol1, const ARGBColor& rCol2)
+{
+    return 
+        square(rCol1.a-rCol2.a) 
+        + square(rCol1.r-rCol2.r)
+        + square(rCol1.g-rCol2.g)
+        + square(rCol1.b-rCol2.b);
+}
+
+typedef std::map<rtl::OUString,sal_Size> ElementRefMapType;
+
+struct AnnotatingVisitor
+{
+    AnnotatingVisitor(StatePool&                                        rStatePool,
+                      StateMap&                                         rStateMap,
+                      const State&                                       rInitialState,
+                      const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler) :
+        mnCurrStateId(0),
+        maCurrState(),
+        maParentStates(),
+        mrStates(rStatePool),
+        mrStateMap(rStateMap),
+        mxDocumentHandler(xDocumentHandler),
+		maGradientVector(),
+        maGradientStopVector()
+    {
+        maParentStates.push_back(rInitialState);
+    }
+
+    void operator()( const uno::Reference<xml::dom::XElement>& )
+    {}
+
+    void operator()( const uno::Reference<xml::dom::XElement>&      xElem,
+                     const uno::Reference<xml::dom::XNamedNodeMap>& xAttributes )
+    {
+		const sal_Int32 nTagId(getTokenId(xElem->getTagName()));
+		switch (nTagId)
+		{
+			case XML_LINEARGRADIENT:
+			{
+				const sal_Int32 nNumAttrs( xAttributes->getLength() );
+				rtl::OUString sAttributeValue;
+				maGradientVector.push_back(Gradient(Gradient::LINEAR)); 
+                
+                // do we have a reference to a parent gradient? parse
+                // that first, as it sets our defaults here (manually
+                // tracking default state on each Gradient variable is
+                // much more overhead)
+                uno::Reference<xml::dom::XNode> xNode(xAttributes->getNamedItem(USTR("href")));
+                if(xNode.is())
+                {
+                    const rtl::OUString sValue(xNode->getNodeValue());
+                    ElementRefMapType::iterator aFound=maGradientIdMap.end();
+                    if (sValue.copy(0,1).equalsAscii("#"))
+                        aFound = maGradientIdMap.find(sValue.copy(1));
+                    else
+                        aFound = maGradientIdMap.find(sValue);;
+
+                    if( aFound != maGradientIdMap.end() )
+                        maGradientVector.back() = maGradientVector[aFound->second];
+                }
+
+                // do that after dereferencing, to prevent hyperlinked
+                // gradient to clobber our Id again
+                maGradientVector.back().mnId = maGradientVector.size()-1;
+                maGradientVector.back().meType = Gradient::LINEAR; // has been clobbered as well
+
+				for( sal_Int32 i=0; i<nNumAttrs; ++i )
+				{
+					parseLinearGradientData( maGradientVector.back(),
+                                             maGradientVector.size()-1,
+                                             getTokenId(xAttributes->item(i)->getNodeName()), 
+                                             xAttributes->item(i)->getNodeValue() );
+				}
+				break;
+			}
+            case XML_RADIALGRADIENT:
+			{
+				const sal_Int32 nNumAttrs( xAttributes->getLength() );
+				rtl::OUString sAttributeValue;
+				maGradientVector.push_back(Gradient(Gradient::RADIAL)); 
+
+                // do we have a reference to a parent gradient? parse
+                // that first, as it sets our defaults here (manually
+                // tracking default state on each Gradient variable is
+                // much more overhead)
+                uno::Reference<xml::dom::XNode> xNode(xAttributes->getNamedItem(USTR("href")));
+                if(xNode.is())
+                {
+                    const rtl::OUString sValue(xNode->getNodeValue());
+                    ElementRefMapType::iterator aFound=maGradientIdMap.end();
+                    if (sValue.copy(0,1).equalsAscii("#"))
+                        aFound = maGradientIdMap.find(sValue.copy(1));
+                    else
+                        aFound = maGradientIdMap.find(sValue);;
+
+                    if( aFound != maGradientIdMap.end() )
+                        maGradientVector.back() = maGradientVector[aFound->second];
+                }
+
+                // do that after dereferencing, to prevent hyperlinked
+                // gradient to clobber our Id again
+                maGradientVector.back().mnId = maGradientVector.size()-1;
+                maGradientVector.back().meType = Gradient::RADIAL; // has been clobbered as well
+
+				for( sal_Int32 i=0; i<nNumAttrs; ++i )
+				{
+					parseRadialGradientData( maGradientVector.back(),
+                                             maGradientVector.size()-1,
+                                             getTokenId(xAttributes->item(i)->getNodeName()), 
+                                             xAttributes->item(i)->getNodeValue() );
+				}
+				break;
+			}
+			case XML_STOP:
+			{
+				const sal_Int32 nNumAttrs( xAttributes->getLength() );
+				rtl::OUString sAttributeValue;
+				maGradientStopVector.push_back(GradientStop());
+				maGradientVector.back().maStops.push_back(maGradientStopVector.size()-1);
+				for( sal_Int32 i=0; i<nNumAttrs; ++i )
+				{
+					parseGradientStop( maGradientStopVector.back(),
+                                       maGradientStopVector.size()-1,
+                                       getTokenId(xAttributes->item(i)->getNodeName()), 
+                                       xAttributes->item(i)->getNodeValue() );
+				}
+				break;
+			}
+			default:
+			{
+		        // init state. inherit defaults from parent.
+    		    maCurrState = maParentStates.back(); 
+        		maCurrState.maTransform.identity();
+                maCurrState.maViewBox.reset();
+
+		        // scan for style info
+    		    const sal_Int32 nNumAttrs( xAttributes->getLength() );
+        		rtl::OUString sAttributeValue;
+	        	for( sal_Int32 i=0; i<nNumAttrs; ++i )
+	    	    {
+    	    	    sAttributeValue = xAttributes->item(i)->getNodeValue();
+        	    	const sal_Int32 nTokenId( 
+            	    	getTokenId(xAttributes->item(i)->getNodeName()));
+	            	if( XML_STYLE == nTokenId )
+    	            	parseStyle(sAttributeValue);
+	        	    else 
+    	        	    parseAttribute(nTokenId, 
+            	        	           sAttributeValue);
+		        }
+
+    		    // all attributes parsed, can calc total CTM now
+                basegfx::B2DHomMatrix aLocalTransform;
+        		if( !maCurrState.maViewBox.isEmpty() &&
+            		maCurrState.maViewBox.getWidth() != 0.0 && 
+		            maCurrState.maViewBox.getHeight() != 0.0 )
+    		    {
+        		    // transform aViewBox into viewport, such that they
+            		// coincide
+	            	aLocalTransform.translate(-maCurrState.maViewBox.getMinX(),
+                                              -maCurrState.maViewBox.getMinY());
+	        	    aLocalTransform.scale(maCurrState.maViewport.getWidth()/maCurrState.maViewBox.getWidth(),
+                                          maCurrState.maViewport.getHeight()/maCurrState.maViewBox.getHeight());
+	    	    }
+    	    	maCurrState.maCTM = maCurrState.maCTM*maCurrState.maTransform*aLocalTransform;
+
+		        OSL_TRACE("annotateStyle - CTM is: %f %f %f %f %f %f", 
+    		              maCurrState.maCTM.get(0,0),
+        		          maCurrState.maCTM.get(0,1),
+            		      maCurrState.maCTM.get(0,2),
+                		  maCurrState.maCTM.get(1,0),
+	                	  maCurrState.maCTM.get(1,1),
+	    	              maCurrState.maCTM.get(1,2));
+        
+    	    	// if necessary, serialize to automatic-style section
+        		writeStyle(xElem,nTagId);
+			}
+		}	
+    }
+
+    rtl::OUString getStyleName( const char* sPrefix, sal_Int32 nId )
+    {
+        return rtl::OUString::createFromAscii(sPrefix)+rtl::OUString::valueOf(nId);
+    }
+
+    bool hasGradientOpacity( const Gradient& rGradient )
+    {
+        return 
+            maGradientStopVector[
+                rGradient.maStops[0]].maStopColor.a != 1.0 ||
+            maGradientStopVector[
+                rGradient.maStops[1]].maStopColor.a != 1.0;
+    }
+
+    struct StopSorter
+    {
+        explicit StopSorter( const std::vector< GradientStop >& rStopVec ) :
+            mrStopVec(rStopVec)
+        {}
+
+        bool operator()( sal_Size rLHS, sal_Size rRHS )
+        {
+            return mrStopVec[rLHS].mnStopPosition < mrStopVec[rRHS].mnStopPosition;
+        }
+        
+        const std::vector< GradientStop >& mrStopVec;
+    };
+
+    void optimizeGradientStops( Gradient& rGradient )
+    {
+        // sort for increasing stop position
+        std::sort(rGradient.maStops.begin(),rGradient.maStops.end(),
+                  StopSorter(maGradientStopVector));
+
+        if( rGradient.maStops.size() < 3 )
+            return; //easy! :-)
+        
+        // join similar colors
+        std::vector<sal_Size> aNewStops(1,rGradient.maStops.front());
+        for( sal_Size i=1; i<rGradient.maStops.size(); ++i )
+        {
+            if( maGradientStopVector[rGradient.maStops[i]].maStopColor != 
+                maGradientStopVector[aNewStops.back()].maStopColor )
+                aNewStops.push_back(rGradient.maStops[i]);
+        }
+
+        rGradient.maStops = aNewStops;
+
+        // axial gradient, maybe?
+        if( rGradient.meType == Gradient::LINEAR &&
+            rGradient.maStops.size() == 3 && 
+            maGradientStopVector[rGradient.maStops.front()].maStopColor ==
+            maGradientStopVector[rGradient.maStops.back()].maStopColor )
+        {
+            // yep - keep it at that
+            return;
+        }
+
+        // find out most significant color difference, and limit to
+        // those two stops around this border (metric is
+        // super-simplistic: take euclidean distance of colors, weigh
+        // with stop distance)
+        sal_Size nMaxIndex=0;
+        double    fMaxDistance=0.0;
+        for( sal_Size i=1; i<rGradient.maStops.size(); ++i )
+        {
+            const double fCurrDistance( 
+                colorDiffSquared(
+                    maGradientStopVector[rGradient.maStops[i-1]].maStopColor,
+                    maGradientStopVector[rGradient.maStops[i]].maStopColor) *
+                (square(maGradientStopVector[rGradient.maStops[i-1]].mnStopPosition) +
+                 square(maGradientStopVector[rGradient.maStops[i]].mnStopPosition)) );
+
+            if( fCurrDistance > fMaxDistance )
+            {
+                nMaxIndex = i-1;
+                fMaxDistance = fCurrDistance;
+            }
+        }
+        rGradient.maStops[0] = rGradient.maStops[nMaxIndex];
+        rGradient.maStops[1] = rGradient.maStops[nMaxIndex+1];
+        rGradient.maStops.erase(rGradient.maStops.begin()+2,rGradient.maStops.end());
+    }
+
+    sal_Int8 toByteColor( double val )
+    {
+        // TODO(Q3): duplicated from vcl::unotools
+        return sal::static_int_cast<sal_Int8>(
+            basegfx::fround(val*255.0));
+    }
+
+    rtl::OUString getOdfColor( const ARGBColor& rColor )
+    {
+        // TODO(Q3): duplicated from pdfimport
+        rtl::OUStringBuffer aBuf( 7 );
+        const sal_uInt8 nRed  ( toByteColor(rColor.r)   );
+        const sal_uInt8 nGreen( toByteColor(rColor.g) );
+        const sal_uInt8 nBlue ( toByteColor(rColor.b)  );
+        aBuf.append( sal_Unicode('#') );
+        if( nRed < 10 )
+            aBuf.append( sal_Unicode('0') );
+        aBuf.append( sal_Int32(nRed), 16 );
+        if( nGreen < 10 )
+            aBuf.append( sal_Unicode('0') );
+        aBuf.append( sal_Int32(nGreen), 16 );
+        if( nBlue < 10 )
+            aBuf.append( sal_Unicode('0') );
+        aBuf.append( sal_Int32(nBlue), 16 );
+
+        // TODO(F3): respect alpha transparency (polygons etc.)
+        OSL_ASSERT(rColor.a == 1.0);
+
+        return aBuf.makeStringAndClear();
+    }
+
+    rtl::OUString getOdfAlign( TextAlign eAlign )
+    {
+        static ::rtl::OUString aStart(USTR("start"));
+        static ::rtl::OUString aEnd(USTR("end"));
+        // static ::rtl::OUString aJustify(USTR("justify"));
+        static ::rtl::OUString aCenter(USTR("center"));
+        switch(eAlign)
+        {
+            default:
+            case BEFORE:
+                return aStart;
+            case CENTER:
+                return aCenter;
+            case AFTER:
+                return aEnd;
+        }
+    }
+
+    bool writeStyle(State& rState, const sal_Int32 nTagId)
+    {
+        rtl::Reference<SvXMLAttributeList> xAttrs( new SvXMLAttributeList() );
+        uno::Reference<xml::sax::XAttributeList> xUnoAttrs( xAttrs.get() );
+
+        std::pair<StatePool::iterator,
+                  bool> aRes = mrStates.insert(rState);
+        if( !aRes.second )
+            return false; // not written
+
+        ++mnCurrStateId;
+
+        // mnStyleId does not take part in hashing/comparison
+        const_cast<State&>(*aRes.first).mnStyleId = mnCurrStateId;
+        mrStateMap.insert(std::make_pair(
+                              mnCurrStateId,
+                              rState));
+
+        // find two representative stop colors (as odf only support
+        // start&end color)
+        optimizeGradientStops(rState.maFillGradient);
+
+        if( !mxDocumentHandler.is() )
+            return true; // cannot write style, svm import case
+
+        // do we have a gradient fill? then write out gradient as well
+        if( rState.meFillType == GRADIENT && rState.maFillGradient.maStops.size() > 1 )
+        {
+            // TODO(F3): ODF12 supposedly also groks svg:linear/radialGradient. But CL says: nope.
+            xAttrs->AddAttribute( USTR( "draw:name" ), getStyleName("svggradient", rState.maFillGradient.mnId) );
+            if( rState.maFillGradient.meType == Gradient::LINEAR )
+            {
+                // should the optimizeGradientStops method decide that
+                // this is a three-color gradient, it prolly wanted us
+                // to take axial instead
+                xAttrs->AddAttribute( USTR( "draw:style" ), 
+                                      rState.maFillGradient.maStops.size() == 3 ?
+                                      USTR("axial") :
+                                      USTR("linear") );
+            }
+            else
+            {
+                xAttrs->AddAttribute( USTR( "draw:style" ), USTR("ellipsoid") );
+                xAttrs->AddAttribute( USTR( "draw:cx" ), USTR("50%") );
+                xAttrs->AddAttribute( USTR( "draw:cy" ), USTR("50%") );
+            }
+
+            basegfx::B2DTuple rScale, rTranslate;
+            double rRotate, rShearX;
+            if( rState.maFillGradient.maTransform.decompose(rScale, rTranslate, rRotate, rShearX) )
+                xAttrs->AddAttribute( USTR( "draw:angle" ), 
+                                      rtl::OUString::valueOf(rRotate*1800.0/M_PI ) );
+            xAttrs->AddAttribute( USTR( "draw:start-color" ), 
+                                  getOdfColor(
+                                      maGradientStopVector[
+                                          rState.maFillGradient.maStops[0]].maStopColor) );
+            xAttrs->AddAttribute( USTR( "draw:end-color" ), 
+                                  getOdfColor(
+                                      maGradientStopVector[
+                                          rState.maFillGradient.maStops[1]].maStopColor) );
+            xAttrs->AddAttribute( USTR( "draw:border" ), USTR("0%") );
+            mxDocumentHandler->startElement( USTR("draw:gradient"), 
+                                             xUnoAttrs );
+            mxDocumentHandler->endElement( USTR("draw:gradient") );
+
+            if( hasGradientOpacity(rState.maFillGradient) )
+            {
+                // need to write out opacity style as well
+                xAttrs->Clear();
+                xAttrs->AddAttribute( USTR( "draw:name" ), getStyleName("svgopacity", rState.maFillGradient.mnId) );
+                if( rState.maFillGradient.meType == Gradient::LINEAR )
+                {
+                    xAttrs->AddAttribute( USTR( "draw:style" ), USTR("linear") );
+                }
+                else
+                {
+                    xAttrs->AddAttribute( USTR( "draw:style" ), USTR("ellipsoid") );
+                    xAttrs->AddAttribute( USTR( "draw:cx" ), USTR("50%") );
+                    xAttrs->AddAttribute( USTR( "draw:cy" ), USTR("50%") );
+                }
+
+                // modulate gradient opacity with overall fill opacity
+                xAttrs->AddAttribute( USTR( "draw:end" ), 
+                                      rtl::OUString::valueOf(
+                                          maGradientStopVector[
+                                              rState.maFillGradient.maStops[0]].maStopColor.a*
+                                          maCurrState.mnFillOpacity*100.0)+USTR("%" ) );
+                xAttrs->AddAttribute( USTR( "draw:start" ), 
+                                      rtl::OUString::valueOf(
+                                          maGradientStopVector[
+                                              rState.maFillGradient.maStops[1]].maStopColor.a*
+                                          maCurrState.mnFillOpacity*100.0)+USTR("%" ) );
+                xAttrs->AddAttribute( USTR( "draw:border" ), USTR("0%") );
+                mxDocumentHandler->startElement( USTR("draw:opacity"), 
+                                                 xUnoAttrs );
+                mxDocumentHandler->endElement( USTR("draw:opacity") );
+            }
+        }
+
+        // serialize to automatic-style section
+        if( nTagId == XML_TEXT )
+        {
+            // write paragraph style attributes
+            xAttrs->Clear();
+
+            xAttrs->AddAttribute( USTR( "style:name" ), getStyleName("svgparagraphstyle", mnCurrStateId) );
+            xAttrs->AddAttribute( USTR( "style:family" ), USTR("paragraph") );
+            mxDocumentHandler->startElement( USTR("style:style"), 
+                                             xUnoAttrs );
+        
+            xAttrs->Clear();
+            xAttrs->AddAttribute( USTR( "fo:text-align"), getOdfAlign(rState.meTextAnchor));
+
+            mxDocumentHandler->startElement( USTR("style:paragraph-properties"), 
+                                             xUnoAttrs );
+            mxDocumentHandler->endElement( USTR("style:paragraph-properties") );
+            mxDocumentHandler->endElement( USTR("style:style") );
+
+            // write text style attributes
+            xAttrs->Clear();
+
+            xAttrs->AddAttribute( USTR( "style:name" ), getStyleName("svgtextstyle", mnCurrStateId) );
+            xAttrs->AddAttribute( USTR( "style:family" ), USTR("text") );
+            mxDocumentHandler->startElement( USTR("style:style"), 
+                                             xUnoAttrs );
+            xAttrs->Clear();
+            xAttrs->AddAttribute( USTR( "fo:font-family"), rState.maFontFamily);
+            xAttrs->AddAttribute( USTR( "fo:font-size"), 
+                                  rtl::OUString::valueOf(pt2mm(rState.mnFontSize))+USTR("mm"));
+            xAttrs->AddAttribute( USTR( "fo:font-style"), rState.maFontStyle);
+            xAttrs->AddAttribute( USTR( "fo:font-variant"), rState.maFontVariant);
+            xAttrs->AddAttribute( USTR( "fo:font-weight"), 
+                                  rtl::OUString::valueOf(rState.mnFontWeight));
+            xAttrs->AddAttribute( USTR( "fo:color"), getOdfColor(rState.maFillColor));
+
+            mxDocumentHandler->startElement( USTR("style:text-properties"), 
+                                             xUnoAttrs );
+            mxDocumentHandler->endElement( USTR("style:text-properties") );
+            mxDocumentHandler->endElement( USTR("style:style") );
+        }
+
+        xAttrs->Clear();
+		xAttrs->AddAttribute( USTR( "style:name" ), getStyleName("svggraphicstyle", mnCurrStateId) );
+		xAttrs->AddAttribute( USTR( "style:family" ), USTR("graphic") );
+        mxDocumentHandler->startElement( USTR("style:style"), 
+                                         xUnoAttrs );
+        
+        xAttrs->Clear();
+        // text or shape? if the former, no use in processing any
+        // graphic attributes except stroke color, ODF can do ~nothing
+        // with text shapes
+        if( nTagId == XML_TEXT )
+        {
+            //xAttrs->AddAttribute( USTR( "draw:auto-grow-height"), USTR("true"));
+            xAttrs->AddAttribute( USTR( "draw:auto-grow-width"), USTR("true"));
+            xAttrs->AddAttribute( USTR( "draw:textarea-horizontal-align"), USTR("left"));
+            //xAttrs->AddAttribute( USTR( "draw:textarea-vertical-align"), USTR("top"));
+            xAttrs->AddAttribute( USTR( "fo:min-height"), USTR("0cm"));
+
+            xAttrs->AddAttribute( USTR( "fo:padding-top"), USTR("0cm"));
+            xAttrs->AddAttribute( USTR( "fo:padding-left"), USTR("0cm"));
+            xAttrs->AddAttribute( USTR( "fo:padding-right"), USTR("0cm"));
+            xAttrs->AddAttribute( USTR( "fo:padding-bottom"), USTR("0cm"));
+
+            // disable any background shape
+            xAttrs->AddAttribute( USTR( "draw:stroke" ), USTR("none"));
+            xAttrs->AddAttribute( USTR( "draw:fill" ), USTR("none"));
+        }
+        else
+        {
+            if( rState.meFillType != NONE )
+            {
+                if( rState.meFillType == GRADIENT )
+                {
+                    xAttrs->AddAttribute( USTR( "draw:fill" ), USTR("gradient"));
+                    xAttrs->AddAttribute( USTR( "draw:fill-gradient-name" ), 
+                                          getStyleName("svggradient", rState.maFillGradient.mnId) );
+                    if( hasGradientOpacity(rState.maFillGradient) )
+                    {
+                        // needs transparency gradient as well
+                        xAttrs->AddAttribute( USTR( "draw:opacity-name" ), 
+                                              getStyleName("svgopacity", rState.maFillGradient.mnId) );
+                    }
+                    else if( maCurrState.mnFillOpacity != 1.0 )
+                        xAttrs->AddAttribute( USTR( "draw:opacity" ), 
+                                              rtl::OUString::valueOf(100.0*maCurrState.mnFillOpacity)+USTR("%") );
+                }
+                else
+                {
+                    xAttrs->AddAttribute( USTR( "draw:fill" ), USTR("solid"));
+                    xAttrs->AddAttribute( USTR( "draw:fill-color" ), getOdfColor(rState.maFillColor));
+                    if( maCurrState.mnFillOpacity != 1.0 )
+                        xAttrs->AddAttribute( USTR( "draw:opacity" ), 
+                                              rtl::OUString::valueOf(100.0*maCurrState.mnFillOpacity)+USTR("%") );
+                }
+            }
+            else
+                xAttrs->AddAttribute( USTR( "draw:fill" ), USTR("none"));
+
+            if( rState.meStrokeType != NONE )
+            {
+                xAttrs->AddAttribute( USTR( "draw:stroke" ), USTR("solid"));
+                xAttrs->AddAttribute( USTR( "svg:stroke-color" ), getOdfColor(rState.maStrokeColor));
+            }
+            else
+                xAttrs->AddAttribute( USTR( "draw:stroke" ), USTR("none"));
+
+            if( maCurrState.mnStrokeWidth != 0.0 )
+            {
+                ::basegfx::B2DVector aVec(maCurrState.mnStrokeWidth,0);
+                aVec *= maCurrState.maCTM;
+                xAttrs->AddAttribute( USTR("svg:stroke-width"), rtl::OUString::valueOf( pt2mm(aVec.getLength()) )+USTR("mm"));
+            }
+            if( maCurrState.meLineJoin == basegfx::B2DLINEJOIN_MITER )
+                xAttrs->AddAttribute( USTR( "draw:stroke-linejoin"), USTR("miter"));
+            else if( maCurrState.meLineJoin == basegfx::B2DLINEJOIN_ROUND )
+                xAttrs->AddAttribute( USTR( "draw:stroke-linejoin"), USTR("round"));
+            else if( maCurrState.meLineJoin == basegfx::B2DLINEJOIN_BEVEL )
+                xAttrs->AddAttribute( USTR( "draw:stroke-linejoin"), USTR("bevel"));
+            if( maCurrState.mnStrokeOpacity != 1.0 )
+                xAttrs->AddAttribute( USTR("svg:stroke-opacity"), 
+                                      rtl::OUString::valueOf(100.0*maCurrState.mnStrokeOpacity)+USTR("%"));
+        }
+
+        mxDocumentHandler->startElement( USTR("style:graphic-properties"), 
+                                         xUnoAttrs );
+        mxDocumentHandler->endElement( USTR("style:graphic-properties") );
+        mxDocumentHandler->endElement( USTR("style:style") );
+
+        return true; // newly written
+    }
+
+    void writeStyle(const uno::Reference<xml::dom::XElement>& xElem, const sal_Int32 nTagId)
+    {
+        sal_Int32 nEmulatedStyleId=0;
+        if( maCurrState.maDashArray.size() && 
+            maCurrState.meStrokeType != NONE )
+        {
+            // ODF dashing is severly borked - generate filled shape
+            // instead (further down the road - here, we simply
+            // emulate a filled style with the next id)
+
+            // move all stroke attribs to fill, Clear stroking
+            State aEmulatedStrokeState( maCurrState );
+            aEmulatedStrokeState.meFillType = maCurrState.meStrokeType;
+            aEmulatedStrokeState.mnFillOpacity = maCurrState.mnStrokeOpacity;
+            aEmulatedStrokeState.maFillColor = maCurrState.maStrokeColor;
+            aEmulatedStrokeState.maFillGradient = maCurrState.maStrokeGradient;
+            aEmulatedStrokeState.meFillRule = EVEN_ODD;
+            aEmulatedStrokeState.meStrokeType = NONE;
+
+            if( writeStyle(aEmulatedStrokeState, nTagId) )
+                nEmulatedStyleId = mnCurrStateId;
+            else
+                nEmulatedStyleId = mrStates.find(aEmulatedStrokeState)->mnStyleId;
+        }
+
+        sal_Int32 nStyleId=0;
+        if( writeStyle(maCurrState, nTagId) )
+            nStyleId = mnCurrStateId;
+        else
+            nStyleId = mrStates.find(maCurrState)->mnStyleId;
+
+        xElem->setAttribute(USTR("internal-style-ref"),
+                            rtl::OUString::valueOf(
+                                nStyleId)
+                            +USTR("$")
+                            +rtl::OUString::valueOf(
+                                nEmulatedStyleId));
+    }
+
+    void push()
+    {
+        maParentStates.push_back(maCurrState);
+    }
+
+    void pop()
+    {
+        maParentStates.pop_back();
+    }
+	
+	void parseLinearGradientData( Gradient& io_rCurrGradient,
+                                  const sal_Int32 nGradientNumber,
+                                  const sal_Int32 nTokenId,
+                                  const rtl::OUString& sValue )
+	{
+		switch(nTokenId)
+		{
+            case XML_GRADIENTTRANSFORM:
+            {
+                rtl::OString aValueUtf8( sValue.getStr(), 
+                                         sValue.getLength(), 
+                                         RTL_TEXTENCODING_UTF8 );
+                parseTransform(aValueUtf8.getStr(),io_rCurrGradient.maTransform);
+                break;
+            }
+			case XML_X1:
+				io_rCurrGradient.maCoords.linear.mfX1 = convLength(sValue,maCurrState,'h');
+				break;
+			case XML_X2:
+				io_rCurrGradient.maCoords.linear.mfX2 = convLength(sValue,maCurrState,'h');
+				break;
+			case XML_Y1:
+				io_rCurrGradient.maCoords.linear.mfY1 = convLength(sValue,maCurrState,'v');
+				break;
+			case XML_Y2:
+				io_rCurrGradient.maCoords.linear.mfY2 = convLength(sValue,maCurrState,'v');
+				break;
+			case XML_ID:
+                maGradientIdMap.insert(std::make_pair(sValue,nGradientNumber));
+				break;
+			case XML_GRADIENTUNITS:
+				if (getTokenId(sValue) == XML_OBJECTBOUNDINGBOX)
+					io_rCurrGradient.mbBoundingBoxUnits = true;
+				else
+					io_rCurrGradient.mbBoundingBoxUnits = false;
+				break;
+			default:
+				break;
+		}
+	}
+	
+	void parseRadialGradientData( Gradient& io_rCurrGradient,
+                                  const sal_Int32 nGradientNumber,
+                                  const sal_Int32 nTokenId,
+                                  const rtl::OUString& sValue )
+	{
+		switch(nTokenId)
+		{
+            case XML_GRADIENTTRANSFORM:
+            {
+                rtl::OString aValueUtf8( sValue.getStr(), 
+                                         sValue.getLength(), 
+                                         RTL_TEXTENCODING_UTF8 );
+                parseTransform(aValueUtf8.getStr(),io_rCurrGradient.maTransform);
+                break;
+            }
+			case XML_CX:
+				io_rCurrGradient.maCoords.radial.mfCX = convLength(sValue,maCurrState,'h');
+				break;
+			case XML_CY:
+				io_rCurrGradient.maCoords.radial.mfCY = convLength(sValue,maCurrState,'v');
+				break;
+			case XML_FX:
+				io_rCurrGradient.maCoords.radial.mfFX = convLength(sValue,maCurrState,'h');
+				break;
+			case XML_FY:
+				io_rCurrGradient.maCoords.radial.mfFY = convLength(sValue,maCurrState,'v');
+				break;
+			case XML_R:
+				io_rCurrGradient.maCoords.radial.mfR = convLength(sValue,maCurrState,'r');
+				break;
+			case XML_ID:
+                maGradientIdMap.insert(std::make_pair(sValue,nGradientNumber));
+				break;
+			case XML_GRADIENTUNITS:
+				if (getTokenId(sValue) == XML_OBJECTBOUNDINGBOX)
+					io_rCurrGradient.mbBoundingBoxUnits = true;
+				else
+					io_rCurrGradient.mbBoundingBoxUnits = false;
+				break;
+			default:
+				break;
+		}
+	}
+	
+	void parseGradientStop( GradientStop& io_rGradientStop,
+                            const sal_Int32 nStopNumber,
+                            const sal_Int32 nTokenId, 
+							const rtl::OUString& sValue )
+	{
+		switch(nTokenId)
+		{
+			case XML_HREF:
+            {
+                ElementRefMapType::iterator aFound=maStopIdMap.end();
+				if (sValue.copy(0,1).equalsAscii("#"))
+					aFound = maStopIdMap.find(sValue.copy(1));
+				else
+					aFound = maStopIdMap.find(sValue);;
+
+                if( aFound != maStopIdMap.end() )
+                    io_rGradientStop =  maGradientStopVector[aFound->second];
+				break;
+            }
+			case XML_ID:
+                maStopIdMap.insert(std::make_pair(sValue,nStopNumber));
+				break;
+			case XML_OFFSET:
+				io_rGradientStop.mnStopPosition = sValue.toDouble();
+				break;
+			case XML_STYLE:
+				parseStyle( sValue );
+				break;
+			default:
+				break;
+		}
+	}
+	
+    void parseAttribute( const sal_Int32      nTokenId, 
+                         const rtl::OUString& sValue )
+    {
+        rtl::OString aValueUtf8( sValue.getStr(), 
+                                 sValue.getLength(), 
+                                 RTL_TEXTENCODING_UTF8 );
+        switch(nTokenId)
+        {
+            case XML_WIDTH:
+            {
+                const double fViewPortWidth(
+                    convLength(sValue,maCurrState,'h'));
+            
+                maCurrState.maViewport.expand(
+                    basegfx::B2DTuple(fViewPortWidth,0.0));
+                break;
+            }
+            case XML_HEIGHT:
+            {
+                const double fViewPortHeight(
+                    convLength(sValue,maCurrState,'v'));
+            
+                maCurrState.maViewport.expand(
+                    basegfx::B2DTuple(0.0,fViewPortHeight));
+                break;
+            }
+            case XML_VIEWBOX:
+            {
+                // TODO(F1): preserveAspectRatio
+                parseViewBox(
+                    aValueUtf8,
+                    maCurrState.maViewBox);
+                break;
+            }
+            case XML_FILL_RULE:
+            {
+                if( aValueUtf8 == "evenodd" )
+                    maCurrState.meFillRule = EVEN_ODD;
+                else if( aValueUtf8 == "nonzero" )
+                    maCurrState.meFillRule = NON_ZERO;
+                else if( aValueUtf8 == "inherit" )
+                    maCurrState.meFillRule = maParentStates.back().meFillRule;
+                break;
+            }
+            case XML_FILL_OPACITY:
+                if( aValueUtf8 == "inherit" )
+                    maCurrState.mnFillOpacity = maParentStates.back().mnFillOpacity;
+                else
+                    maCurrState.mnFillOpacity = aValueUtf8.toDouble();
+                break;
+            case XML_STROKE_WIDTH:
+            {
+                if( aValueUtf8 == "inherit" )
+                    maCurrState.mnStrokeWidth = maParentStates.back().mnStrokeWidth;
+                else
+                    maCurrState.mnStrokeWidth = convLength(sValue,maCurrState,'r');
+                break;
+            }
+            case XML_STROKE_LINECAP:
+            {
+                if( aValueUtf8 == "butt" )
+                    maCurrState.meLineCap = BUTT;
+                else if( aValueUtf8 == "round" )
+                    maCurrState.meLineCap = ROUND;
+                else if( aValueUtf8 == "square" )
+                    maCurrState.meLineCap = RECT;
+                else if( aValueUtf8 == "inherit" )
+                    maCurrState.meLineCap = maParentStates.back().meLineCap;
+                break;
+            }
+            case XML_STROKE_LINEJOIN:
+            {
+                if( aValueUtf8 == "miter" )
+                    maCurrState.meLineJoin = basegfx::B2DLINEJOIN_MITER;
+                else if( aValueUtf8 == "round" )
+                    maCurrState.meLineJoin = basegfx::B2DLINEJOIN_ROUND;
+                else if( aValueUtf8 == "bevel" )
+                    maCurrState.meLineJoin = basegfx::B2DLINEJOIN_BEVEL;
+                else if( aValueUtf8 == "inherit" )
+                    maCurrState.meLineJoin = maParentStates.back().meLineJoin;
+                break;
+            }
+            case XML_STROKE_MITERLIMIT:
+            {
+                if( aValueUtf8 == "inherit" )
+                    maCurrState.mnMiterLimit = maParentStates.back().mnMiterLimit;
+                else
+                    maCurrState.mnMiterLimit = aValueUtf8.toDouble();
+                break;
+            }
+            case XML_STROKE_DASHOFFSET:
+            {
+                if( aValueUtf8 == "inherit" )
+                    maCurrState.mnDashOffset = maParentStates.back().mnDashOffset;
+                else
+                    maCurrState.mnDashOffset = convLength(sValue,maCurrState,'r');
+                break;
+            }
+            case XML_STROKE_DASHARRAY:
+            {
+                if( aValueUtf8 == "none" )
+                    maCurrState.maDashArray.clear();
+                else if( aValueUtf8 == "inherit" )
+                    maCurrState.maDashArray = maParentStates.back().maDashArray;
+                else
+                    parseDashArray(aValueUtf8.getStr(),
+                                   maCurrState.maDashArray);
+                break;
+            }
+            case XML_STROKE_OPACITY:
+                if( aValueUtf8 == "inherit" )
+                    maCurrState.mnStrokeOpacity = maParentStates.back().mnStrokeOpacity;
+                else
+                    maCurrState.mnStrokeOpacity = aValueUtf8.toDouble();
+                break;
+            case XML_FILL:
+            {
+                const State& rParent( maParentStates.back() );
+                parsePaint( sValue,
+                            aValueUtf8.getStr(),
+                            maCurrState.meFillType,
+                            maCurrState.maFillColor,
+                            maCurrState.maFillGradient,
+                            rParent.meFillType,
+                            rParent.maFillColor,
+                            rParent.maFillGradient );
+                break;
+            }
+            case XML_STROKE:
+            {
+                const State& rParent( maParentStates.back() );
+                parsePaint( sValue,
+                            aValueUtf8.getStr(),
+                            maCurrState.meStrokeType,
+                            maCurrState.maStrokeColor,
+                            maCurrState.maStrokeGradient,
+                            rParent.meStrokeType,
+                            rParent.maStrokeColor,
+                            rParent.maStrokeGradient );
+                break;
+            }
+            case XML_TRANSFORM:
+            {
+                basegfx::B2DHomMatrix aTransform;
+                parseTransform(aValueUtf8.getStr(),aTransform);
+                maCurrState.maTransform = maCurrState.maTransform*aTransform;
+                break;
+            }
+            case XML_FONT_FAMILY:
+                maCurrState.maFontFamily=sValue;
+                break;
+            case XML_FONT_SIZE:
+                maCurrState.mnFontSize=convLength(sValue,maCurrState,'v');
+                break;
+            case XML_FONT_STYLE:
+                parseFontStyle(maCurrState,sValue,aValueUtf8.getStr());
+                break;
+            case XML_FONT_WEIGHT:
+                maCurrState.mnFontWeight=sValue.toDouble();
+                break;
+            case XML_FONT_VARIANT:
+                parseFontVariant(maCurrState,sValue,aValueUtf8.getStr());
+                break;
+            case XML_TEXT_ANCHOR:
+                parseTextAlign(maCurrState,aValueUtf8.getStr());
+                break;
+			case XML_STOP_COLOR:
+                if( maGradientVector.empty() ||
+                    maGradientVector.back().maStops.empty() )
+                    break;
+				parseColor( aValueUtf8, 
+                            maGradientStopVector[
+                                maGradientVector.back().maStops.back()].maStopColor );
+				break;
+			case XML_STOP_OPACITY:
+                if( maGradientVector.empty() ||
+                    maGradientVector.back().maStops.empty() )
+                    break;
+				parseOpacity( aValueUtf8, 
+                              maGradientStopVector[
+                                  maGradientVector.back().maStops.back()].maStopColor );
+				break;
+            default:
+                OSL_TRACE("unhandled token %s", getTokenName(nTokenId));
+                break;
+        }
+    }
+
+    void parseStyle( const rtl::OUString& sValue )
+    {
+        // split individual style attributes
+        sal_Int32 nIndex=0, nDummyIndex=0;
+        rtl::OUString aCurrToken;
+        do 
+        {
+            aCurrToken=sValue.getToken(0,';',nIndex);
+            
+            if( aCurrToken.getLength() )
+            {
+                // split attrib & value
+                nDummyIndex=0;
+                rtl::OUString aCurrAttrib(
+                    aCurrToken.getToken(0,':',nDummyIndex).trim());
+                OSL_ASSERT(nDummyIndex!=-1);
+                nDummyIndex=0;
+                rtl::OUString aCurrValue(
+                    aCurrToken.getToken(1,':',nDummyIndex).trim());
+                OSL_ASSERT(nDummyIndex==-1);
+
+                // recurse into normal attribute parsing
+                parseAttribute( getTokenId(aCurrAttrib),
+                                aCurrValue );
+            }
+        }
+        while( nIndex != -1 );
+    }
+
+    void parseFontStyle( State&               io_rInitialState,
+                         const rtl::OUString& rValue,
+                         const char*          sValue )
+    {
+        if( strcmp(sValue,"inherit") != 0 )
+            io_rInitialState.maFontStyle = rValue;
+    }
+
+    void parseFontVariant( State&               io_rInitialState,
+                           const rtl::OUString& rValue,
+                           const char*          sValue )
+    {
+        if( strcmp(sValue,"inherit") != 0 )
+            io_rInitialState.maFontVariant = rValue;
+    }
+
+    void parseTextAlign( State&      io_rInitialState,
+                         const char* sValue )
+    {
+        if( strcmp(sValue,"start") == 0 )
+            io_rInitialState.meTextAnchor = BEFORE;
+        else if( strcmp(sValue,"middle") == 0 )
+            io_rInitialState.meTextAnchor = CENTER;
+        else if( strcmp(sValue,"end") == 0 )
+            io_rInitialState.meTextAnchor = AFTER;
+        // keep current val for sValue == "inherit"
+    }
+
+    void parsePaint( const rtl::OUString& rValue,
+                     const char*      sValue, 
+                     PaintType&       rType,
+                     ARGBColor&       rColor,
+                     Gradient&        rGradient,
+                     const PaintType& rInheritType,
+                     const ARGBColor& rInheritColor,
+                     const Gradient&  rInheritGradient )
+    {
+        std::pair<const char*,const char*> aPaintUri(NULL,NULL);
+        std::pair<ARGBColor,bool>          aColor(maCurrState.maCurrentColor,
+                                                  false);
+        if( strcmp(sValue,"none") == 0 )
+            rType = NONE;
+        else if( strcmp(sValue,"currentColor") == 0 )
+        {
+            rType = SOLID;
+            rColor = maCurrState.maCurrentColor;
+        }
+        else if( strcmp(sValue,"inherit") == 0)
+        {
+            rType = rInheritType;
+            rColor = rInheritColor;
+            rGradient = rInheritGradient;
+        }
+		else if( parsePaintUri(aPaintUri,aColor,sValue) )
+		{
+            if( aPaintUri.first != aPaintUri.second )
+            {
+                // assuming gradient. assumption does not hold generally    
+                const char* pClosingBracket;
+                if( (pClosingBracket=strstr(sValue,")")) && rValue.getLength() > 5 )
+                {
+                    ElementRefMapType::iterator aRes;
+                    if( (aRes=maGradientIdMap.find(
+                             rValue.copy(aPaintUri.first-sValue,
+                                         aPaintUri.second-aPaintUri.first))) != maGradientIdMap.end() )
+                    {
+                        rGradient = maGradientVector[aRes->second];
+                        rType = GRADIENT;
+                    }
+                }
+            }
+            else if( aColor.second )
+            {
+                rType = SOLID;
+                rColor = aColor.first;
+            }
+            else
+            {
+                rType = NONE;
+            }
+		}
+        else
+        { 
+            rType = SOLID;
+            parseColor(sValue,rColor);
+        }
+    }
+
+    sal_Int32                                  mnCurrStateId;
+    State                                      maCurrState;
+    std::vector<State>                         maParentStates;
+    StatePool&                                 mrStates;
+    StateMap&                                  mrStateMap;
+    uno::Reference<xml::sax::XDocumentHandler> mxDocumentHandler;
+    std::vector< Gradient >                    maGradientVector;
+    std::vector< GradientStop >                maGradientStopVector;
+    ElementRefMapType                          maGradientIdMap;
+    ElementRefMapType                          maStopIdMap;
+};
+
+/// Annotate svg styles with unique references to state pool
+static void annotateStyles( StatePool&                                        rStatePool,
+                            StateMap&                                         rStateMap,
+                            const State&                                       rInitialState,
+                            const uno::Reference<xml::dom::XElement>          xElem,
+                            const uno::Reference<xml::sax::XDocumentHandler>& xDocHdl )
+{
+    AnnotatingVisitor aVisitor(rStatePool,rStateMap,rInitialState,xDocHdl);
+    visitElements(aVisitor, xElem);
+}
+
+struct ShapeWritingVisitor
+{
+    ShapeWritingVisitor(StatePool&                                        /*rStatePool*/,
+                        StateMap&                                         rStateMap,
+                        const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler) :
+        mrStateMap(rStateMap),
+        mxDocumentHandler(xDocumentHandler),
+        mnShapeNum(0)
+    {}
+
+    void operator()( const uno::Reference<xml::dom::XElement>& )
+    {
+    }
+
+    void operator()( const uno::Reference<xml::dom::XElement>&      xElem,
+                     const uno::Reference<xml::dom::XNamedNodeMap>& xAttributes )
+    {
+        rtl::Reference<SvXMLAttributeList> xAttrs( new SvXMLAttributeList() );
+        uno::Reference<xml::sax::XAttributeList> xUnoAttrs( xAttrs.get() );
+        
+        sal_Int32 nDummyIndex(0);
+        rtl::OUString sStyleId(
+            xElem->getAttribute(
+                USTR("internal-style-ref")).getToken(
+                    0,'$',nDummyIndex));
+        StateMap::iterator pOrigState=mrStateMap.find(
+            sStyleId.toInt32());
+
+        if( pOrigState == mrStateMap.end() )
+            return; // non-exportable element, e.g. linearGradient
+
+        maCurrState = pOrigState->second;
+
+        const sal_Int32 nTokenId(getTokenId(xElem->getNodeName()));
+        switch(nTokenId)
+        {
+		    case XML_LINE:
+			{
+                // collect attributes
+                const sal_Int32 nNumAttrs( xAttributes->getLength() );
+                rtl::OUString sAttributeValue;
+                double x1=0.0,y1=0.0,x2=0.0,y2=0.0;
+                for( sal_Int32 i=0; i<nNumAttrs; ++i )
+                {
+                    sAttributeValue = xAttributes->item(i)->getNodeValue();
+                    const sal_Int32 nAttribId( 
+                        getTokenId(xAttributes->item(i)->getNodeName()));
+                    switch(nAttribId)
+                    {
+                        case XML_X1:
+                            x1= convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_X2:
+                            x2 = convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_Y1:
+                            y1 = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        case XML_Y2:
+                            y2 = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        default:
+                            // skip
+                            break;
+                    }
+                }
+
+				rtl::OUString sLinePath = USTR("M")+rtl::OUString::valueOf(x1)+USTR(",")
+					+rtl::OUString::valueOf(y1)+USTR("L")+rtl::OUString::valueOf(x2)+USTR(",")
+					+rtl::OUString::valueOf(y2);
+                basegfx::B2DPolyPolygon aPoly;
+                basegfx::tools::importFromSvgD(aPoly, sLinePath);
+
+                writePathShape(xAttrs,
+                               xUnoAttrs,
+                               xElem,
+                               sStyleId,
+                               basegfx::B2DPolyPolygon(aPoly));                
+                break;
+			}
+            case XML_POLYGON:
+            case XML_POLYLINE:
+            {
+                rtl::OUString sPoints = xElem->hasAttribute(USTR("points")) ? xElem->getAttribute(USTR("points")) : USTR("");
+                basegfx::B2DPolygon aPoly;
+                basegfx::tools::importFromSvgPoints(aPoly, sPoints);
+                if( nTokenId == XML_POLYGON || maCurrState.meFillType != NONE )
+                    aPoly.setClosed(true);
+
+                writePathShape(xAttrs,
+                               xUnoAttrs,
+                               xElem,
+                               sStyleId,
+                               basegfx::B2DPolyPolygon(aPoly));
+                break;
+            }
+            case XML_RECT:
+            {
+                // collect attributes
+                const sal_Int32 nNumAttrs( xAttributes->getLength() );
+                rtl::OUString sAttributeValue;
+                bool bRxSeen=false, bRySeen=false;
+                double x=0.0,y=0.0,width=0.0,height=0.0,rx=0.0,ry=0.0;
+                for( sal_Int32 i=0; i<nNumAttrs; ++i )
+                {
+                    sAttributeValue = xAttributes->item(i)->getNodeValue();
+                    const sal_Int32 nAttribId( 
+                        getTokenId(xAttributes->item(i)->getNodeName()));
+                    switch(nAttribId)
+                    {
+                        case XML_X:
+                            x = convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_Y:
+                            y = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        case XML_WIDTH:
+                            width = convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_HEIGHT:
+                            height = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        case XML_RX:
+                            rx = convLength(sAttributeValue,maCurrState,'h');
+                            bRxSeen=true;
+                            break;
+                        case XML_RY:
+                            ry = convLength(sAttributeValue,maCurrState,'v');
+                            bRySeen=true;
+                            break;
+                        default:
+                            // skip
+                            break;
+                    }
+                }
+
+                if( bRxSeen && !bRySeen )
+                    ry = rx;
+                else if( bRySeen && !bRxSeen )
+                    rx = ry;
+
+                basegfx::B2DPolygon aPoly;
+                aPoly = basegfx::tools::createPolygonFromRect(
+                    basegfx::B2DRange(x,y,x+width,y+height),
+                    rx/width, ry/height );
+
+                writePathShape(xAttrs,
+                               xUnoAttrs,
+                               xElem,
+                               sStyleId,
+                               basegfx::B2DPolyPolygon(aPoly));                
+                break;
+            }
+            case XML_PATH:
+            {
+                rtl::OUString sPath = xElem->hasAttribute(USTR("d")) ? xElem->getAttribute(USTR("d")) : USTR("");
+                basegfx::B2DPolyPolygon aPoly;
+                basegfx::tools::importFromSvgD(aPoly, sPath);
+
+                writePathShape(xAttrs,
+                               xUnoAttrs,
+                               xElem,
+                               sStyleId,
+                               aPoly);
+                break;
+            }
+			case XML_CIRCLE:
+			{
+                // collect attributes
+                const sal_Int32 nNumAttrs( xAttributes->getLength() );
+                rtl::OUString sAttributeValue;
+                double cx=0.0,cy=0.0,r=0.0;
+                for( sal_Int32 i=0; i<nNumAttrs; ++i )
+                {
+                    sAttributeValue = xAttributes->item(i)->getNodeValue();
+                    const sal_Int32 nAttribId( 
+                        getTokenId(xAttributes->item(i)->getNodeName()));
+                    switch(nAttribId)
+                    {
+                        case XML_CX:
+                            cx = convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_CY:
+                            cy = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        case XML_R:
+                            r = convLength(sAttributeValue,maCurrState,'r');
+                        default:
+                            // skip
+                            break;
+                    }
+                }
+
+                writeEllipseShape(xAttrs,
+                               xUnoAttrs,
+                               xElem,
+                               sStyleId,
+                               basegfx::B2DEllipse(basegfx::B2DPoint(cx, cy), basegfx::B2DTuple(r,r)));                
+				break;
+			}
+			case XML_ELLIPSE:
+			{
+                // collect attributes
+                const sal_Int32 nNumAttrs( xAttributes->getLength() );
+                rtl::OUString sAttributeValue;
+                double cx=0.0,cy=0.0,rx=0.0, ry=0.0;
+                for( sal_Int32 i=0; i<nNumAttrs; ++i )
+                {
+                    sAttributeValue = xAttributes->item(i)->getNodeValue();
+                    const sal_Int32 nAttribId( 
+                        getTokenId(xAttributes->item(i)->getNodeName()));
+                    switch(nAttribId)
+                    {
+                        case XML_CX:
+                            cx = convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_CY:
+                            cy = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        case XML_RX:
+                            rx = convLength(sAttributeValue,maCurrState,'h');
+							break;
+						case XML_RY:
+							ry = convLength(sAttributeValue,maCurrState,'v');
+                        default:
+                            // skip
+                            break;
+                    }
+                }
+
+                writeEllipseShape(xAttrs,
+                               xUnoAttrs,
+                               xElem,
+                               sStyleId,
+                               basegfx::B2DEllipse(basegfx::B2DPoint(cx, cy), basegfx::B2DTuple(rx,ry)));                
+				break;
+			}
+            case XML_IMAGE:
+            {
+                // collect attributes
+                const sal_Int32 nNumAttrs( xAttributes->getLength() );
+                rtl::OUString sAttributeValue;
+                double x=0.0,y=0.0,width=0.0,height=0.0;
+                for( sal_Int32 i=0; i<nNumAttrs; ++i )
+                {
+                    sAttributeValue = xAttributes->item(i)->getNodeValue();
+                    const sal_Int32 nAttribId( 
+                        getTokenId(xAttributes->item(i)->getNodeName()));
+                    switch(nAttribId)
+                    {
+                        case XML_X:
+                            x = convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_Y:
+                            y = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        case XML_WIDTH:
+                            width = convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_HEIGHT:
+                            height = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        default:
+                            // skip
+                            break;
+                    }
+                }
+
+                rtl::OUString sValue = xElem->hasAttribute(USTR("href")) ? xElem->getAttribute(USTR("href")) : USTR("");
+        		rtl::OString aValueUtf8( sValue.getStr(), sValue.getLength(), RTL_TEXTENCODING_UTF8 );
+				std::string sLinkValue;
+				parseXlinkHref(aValueUtf8.getStr(), sLinkValue);
+
+				if (!sLinkValue.empty())
+					writeBinaryData(xAttrs, xUnoAttrs, xElem, basegfx::B2DRange(x,y,x+width,y+height), sLinkValue);
+                break;
+            }
+            case XML_TEXT:
+            {
+                // collect text from all TEXT_NODE children into sText
+                rtl::OUStringBuffer sText;
+                visitChildren(boost::bind(
+                                  (rtl::OUStringBuffer& (rtl::OUStringBuffer::*)(const sal_Unicode* str))&rtl::OUStringBuffer::append,
+                                  boost::ref(sText),
+                                  boost::bind(&xml::dom::XNode::getNodeValue,
+                                              _1)),
+                              xElem,
+                              xml::dom::NodeType_TEXT_NODE);
+
+                // collect attributes
+                const sal_Int32 nNumAttrs( xAttributes->getLength() );
+                rtl::OUString sAttributeValue;
+                double x=0.0,y=0.0,width=0.0,height=0.0;
+                for( sal_Int32 i=0; i<nNumAttrs; ++i )
+                {
+                    sAttributeValue = xAttributes->item(i)->getNodeValue();
+                    const sal_Int32 nAttribId( 
+                        getTokenId(xAttributes->item(i)->getNodeName()));
+                    switch(nAttribId)
+                    {
+                        case XML_X:
+                            x = convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_Y:
+                            y = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        case XML_WIDTH:
+                            width = convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_HEIGHT:
+                            height = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        default:
+                            // skip
+                            break;
+                    }
+                }
+
+                // actually export text
+                xAttrs->Clear();
+
+                // some heuristic attempts to have text output
+                // baseline-relative
+                y -= 2.0*maCurrState.mnFontSize/3.0;
+
+                // extract basic transformations out of CTM
+                basegfx::B2DTuple aScale, aTranslate;
+                double fRotate, fShearX;
+                ::rtl::OUString sTransformValue;
+                if (maCurrState.maCTM.decompose(aScale, aTranslate, fRotate, fShearX))
+                {
+                    rtl::OUString sTransform;
+                    x += aTranslate.getX();
+                    y += aTranslate.getY();
+
+                    sTransform += 
+                        USTR("scale(") + 
+                        rtl::OUString::valueOf(aScale.getX()) + 
+                        USTR(", ") +
+                        rtl::OUString::valueOf(aScale.getX()) + 
+                        USTR(")");
+
+                    if( fRotate )
+                        sTransform += USTR(" rotate(") + rtl::OUString::valueOf(fRotate*180.0/M_PI) + USTR(")");
+
+                    if( fShearX )
+                        sTransform += USTR(" skewX(") + rtl::OUString::valueOf(fShearX*180.0/M_PI) + USTR(")");
+                }
+
+                xAttrs->AddAttribute( USTR( "svg:x" ), rtl::OUString::valueOf(pt2mm(x))+USTR("mm"));
+                xAttrs->AddAttribute( USTR( "svg:y" ), rtl::OUString::valueOf(pt2mm(y))+USTR("mm"));
+                xAttrs->AddAttribute( USTR( "draw:style-name" ), USTR("svggraphicstyle")+sStyleId );
+
+                mxDocumentHandler->startElement(USTR("draw:frame"),xUnoAttrs);
+
+                xAttrs->Clear();
+                mxDocumentHandler->startElement(USTR("draw:text-box"),xUnoAttrs);
+                xAttrs->AddAttribute( USTR( "text:style-name" ), USTR("svgparagraphstyle")+sStyleId);
+                mxDocumentHandler->startElement(USTR("text:p"),xUnoAttrs);
+
+                xAttrs->Clear();
+                xAttrs->AddAttribute( USTR( "text:style-name" ), USTR("svgtextstyle")+sStyleId);
+                mxDocumentHandler->startElement(USTR("text:span"),xUnoAttrs);
+
+                xAttrs->Clear();
+                mxDocumentHandler->characters(sText.makeStringAndClear());
+                mxDocumentHandler->endElement(USTR("text:span"));
+                mxDocumentHandler->endElement(USTR("text:p"));
+                mxDocumentHandler->endElement(USTR("draw:text-box"));
+                mxDocumentHandler->endElement(USTR("draw:frame"));
+                break;
+            }
+        }
+    }
+
+    void push()
+    {}
+
+    void pop()
+    {}
+	
+	void writeBinaryData( rtl::Reference<SvXMLAttributeList>&           xAttrs,
+						const uno::Reference<xml::sax::XAttributeList>& xUnoAttrs,
+						const uno::Reference<xml::dom::XElement>&       /* xElem */,
+						const basegfx::B2DRange&                        rShapeBounds,
+						const std::string&                              data)
+	{
+		xAttrs->Clear();
+        xAttrs->AddAttribute( USTR( "svg:x" ), rtl::OUString::valueOf(pt2mm(rShapeBounds.getMinX()))+USTR("mm"));
+        xAttrs->AddAttribute( USTR( "svg:y" ), rtl::OUString::valueOf(pt2mm(rShapeBounds.getMinY()))+USTR("mm"));
+        xAttrs->AddAttribute( USTR( "svg:width" ), rtl::OUString::valueOf(pt2mm(rShapeBounds.getWidth()))+USTR("mm"));
+        xAttrs->AddAttribute( USTR( "svg:height" ), rtl::OUString::valueOf(pt2mm(rShapeBounds.getHeight()))+USTR("mm"));
+
+		mxDocumentHandler->startElement(USTR("draw:frame"),xUnoAttrs);
+
+		xAttrs->Clear();
+		mxDocumentHandler->startElement(USTR("draw:image"),xUnoAttrs);
+
+		mxDocumentHandler->startElement(USTR("office:binary-data"),xUnoAttrs);
+
+		mxDocumentHandler->characters(rtl::OUString::createFromAscii(data.c_str()));
+
+        mxDocumentHandler->endElement(USTR("office:binary-data"));
+
+        mxDocumentHandler->endElement(USTR("draw:image"));
+
+        mxDocumentHandler->endElement(USTR("draw:frame"));
+	}
+						  
+
+	void writeTransformAttribute(const basegfx::B2DHomMatrix rMatrix, rtl::Reference<SvXMLAttributeList>& xAttrs)
+	{
+		basegfx::B2DTuple rScale, rTranslate;
+		double rRotate, rShearX;
+		::rtl::OUString sTransformValue;
+		if (!rMatrix.decompose(rScale, rTranslate, rRotate, rShearX))
+			return;
+		if (rScale.getX() != 1.0 || rScale.getY() != 1.0)
+			sTransformValue += USTR("scale(")+::rtl::OUString::valueOf(rScale.getX())+USTR(" ")
+			     +::rtl::OUString::valueOf(rScale.getY())+USTR(") ");
+		if (rTranslate.getX() != 0.0f || rTranslate.getY() != 0.0f)
+			sTransformValue += USTR("translate(")+::rtl::OUString::valueOf(rTranslate.getX()/100.0f)+USTR("mm ")
+			     +::rtl::OUString::valueOf(rTranslate.getY()/100.0f)+USTR("mm) ");
+		if (rRotate != 0.0f)
+			sTransformValue += USTR("rotate(")+::rtl::OUString::valueOf(rRotate)+USTR(") ");
+
+		if (rShearX != 0.0f)
+			sTransformValue += USTR("skewX(")+::rtl::OUString::valueOf(rShearX)+USTR(") ");
+		if (!sTransformValue.getLength())
+			return;
+		xAttrs->AddAttribute( USTR("draw:transform"), sTransformValue);
+	}
+
+    void writeEllipseShape( rtl::Reference<SvXMLAttributeList>&          xAttrs,
+                         const uno::Reference<xml::sax::XAttributeList>& xUnoAttrs,
+                         const uno::Reference<xml::dom::XElement>&       xElem,
+                         const rtl::OUString&                            rStyleId,
+                         const basegfx::B2DEllipse&                      rEllipse)
+    {
+        State aState = maCurrState;
+        rtl::OUString aStyleId(rStyleId);
+		
+		xAttrs->Clear();
+
+		basegfx::B2DPolygon aPoly = basegfx::tools::createPolygonFromEllipse(rEllipse.getB2DEllipseCenter(),
+			rEllipse.getB2DEllipseRadius().getX(), rEllipse.getB2DEllipseRadius().getY());
+		writePathShape(xAttrs, xUnoAttrs, xElem, rStyleId, basegfx::B2DPolyPolygon(aPoly));
+		
+    }
+
+    void writePathShape( rtl::Reference<SvXMLAttributeList>&             xAttrs,
+                         const uno::Reference<xml::sax::XAttributeList>& xUnoAttrs,
+                         const uno::Reference<xml::dom::XElement>&       xElem,
+                         const rtl::OUString&                            rStyleId,
+                         const basegfx::B2DPolyPolygon&                  rPoly )
+    {
+        // we might need to split up polypolygon into multiple path
+        // shapes (e.g. when emulating line stroking)
+        std::vector<basegfx::B2DPolyPolygon> aPolys(1,rPoly);
+        State aState = maCurrState;
+        rtl::OUString aStyleId(rStyleId);
+		
+		xAttrs->Clear();
+
+        OSL_TRACE("writePath - the CTM is: %f %f %f %f %f %f", 
+                  maCurrState.maCTM.get(0,0),
+                  maCurrState.maCTM.get(0,1),
+                  maCurrState.maCTM.get(0,2),
+                  maCurrState.maCTM.get(1,0),
+                  maCurrState.maCTM.get(1,1),
+                  maCurrState.maCTM.get(1,2));
+        
+        if( aState.maDashArray.size() && 
+            aState.meStrokeType != NONE )
+        {
+            // ODF dashing is severly borked - generate filled polygon instead
+            aPolys.clear();
+            for( sal_uInt32 i=0; i<rPoly.count(); ++i )
+            {                
+                aPolys.push_back(
+                    basegfx::tools::stripNeutralPolygons(
+                        basegfx::tools::prepareForPolygonOperation(
+                            basegfx::tools::createAreaGeometry(
+                                rPoly.getB2DPolygon(i),
+                                aState.mnStrokeWidth/2.0,
+                                aState.meLineJoin))));
+                // TODO(F2): line ends
+            }
+
+            sal_Int32 nDummyIndex(0);
+            aStyleId = xElem->getAttribute(
+                USTR("internal-style-ref")).getToken(1,'$',nDummyIndex);
+            StateMap::iterator pAlternateState=mrStateMap.find(aStyleId.toInt32());
+            OSL_ASSERT(pAlternateState != mrStateMap.end());
+            aState = pAlternateState->second;
+            OSL_ENSURE( pAlternateState == mrStateMap.end(),
+                        "Doh - where's my alternate style entry?!" );
+        }
+
+        // TODO(F2): separate out shear, rotate etc.
+        // apply transformation to polygon, to keep draw
+        // import in 100th mm
+        std::for_each(aPolys.begin(),aPolys.end(),
+                      boost::bind(&basegfx::B2DPolyPolygon::transform,
+                                  _1,boost::cref(aState.maCTM)));
+
+        for( sal_uInt32 i=0; i<aPolys.size(); ++i )
+        {
+            const basegfx::B2DRange aBounds(
+                aPolys[i].areControlPointsUsed() ?
+                basegfx::tools::getRange(
+                    basegfx::tools::adaptiveSubdivideByAngle(aPolys[i])) :
+                basegfx::tools::getRange(aPolys[i]));
+            fillShapeProperties(xAttrs,
+                                xElem,
+                                aBounds,
+                                USTR("svggraphicstyle")+aStyleId);
+            
+            // force path coordinates to 100th millimeter, after
+            // putting polygon data at origin (odf viewbox
+            // calculations largely untested codepaths, as OOo always
+            // writes "0 0 w h" viewboxes)
+            basegfx::B2DHomMatrix aNormalize;
+            aNormalize.translate(-aBounds.getMinX(),-aBounds.getMinY());
+            aNormalize.scale(2540.0/72.0,2540.0/72.0);
+            aPolys[i].transform(aNormalize);
+
+            xAttrs->AddAttribute( USTR( "svg:d" ), basegfx::tools::exportToSvgD(
+                aPolys[i],
+                false,   // no relative coords. causes rounding errors      
+                false )); // no quad bezier detection. crashes older versions.   
+            mxDocumentHandler->startElement(USTR("draw:path"), 
+                                            xUnoAttrs);
+            mxDocumentHandler->endElement(USTR("draw:path"));
+        }
+    }
+
+    void fillShapeProperties( rtl::Reference<SvXMLAttributeList>&       xAttrs, 
+                              const uno::Reference<xml::dom::XElement>& /* xElem */,
+                              const basegfx::B2DRange&                  rShapeBounds,
+                              const rtl::OUString&                      rStyleName )
+    {
+        xAttrs->AddAttribute( USTR( "draw:z-index" ), rtl::OUString::valueOf( mnShapeNum++ ));
+        xAttrs->AddAttribute( USTR( "draw:style-name" ), rStyleName);
+        xAttrs->AddAttribute( USTR( "svg:width" ), rtl::OUString::valueOf(pt2mm(rShapeBounds.getWidth()))+USTR("mm"));
+        xAttrs->AddAttribute( USTR( "svg:height" ), rtl::OUString::valueOf(pt2mm(rShapeBounds.getHeight()))+USTR("mm"));
+
+        // OOo expects the viewbox to be in 100th of mm
+        xAttrs->AddAttribute( USTR( "svg:viewBox" ), 
+            USTR("0 0 ")
+            + rtl::OUString::valueOf( 
+                basegfx::fround(pt100thmm(rShapeBounds.getWidth())) )
+            + USTR(" ")
+            + rtl::OUString::valueOf(
+                basegfx::fround(pt100thmm(rShapeBounds.getHeight())) ));
+
+        // TODO(F1): decompose transformation in calling code, and use
+        // transform attribute here
+		// writeTranslate(maCurrState.maCTM, xAttrs);
+        xAttrs->AddAttribute( USTR( "svg:x" ), rtl::OUString::valueOf(pt2mm(rShapeBounds.getMinX()))+USTR("mm"));
+        xAttrs->AddAttribute( USTR( "svg:y" ), rtl::OUString::valueOf(pt2mm(rShapeBounds.getMinY()))+USTR("mm"));
+    }
+
+    State                                      maCurrState;
+    StateMap&                                  mrStateMap;
+    uno::Reference<xml::sax::XDocumentHandler> mxDocumentHandler;
+    sal_Int32                                  mnShapeNum;
+};
+
+/// Write out shapes from DOM tree
+static void writeShapes( StatePool&                                        rStatePool,
+                         StateMap&                                         rStateMap,
+                         const uno::Reference<xml::dom::XElement>          xElem,
+                         const uno::Reference<xml::sax::XDocumentHandler>& xDocHdl )
+{
+    ShapeWritingVisitor aVisitor(rStatePool,rStateMap,xDocHdl);
+    visitElements(aVisitor, xElem);
+}
+
+#ifdef VERBOSE
+struct DumpingVisitor
+{
+    void operator()( const uno::Reference<xml::dom::XElement>& xElem )
+    {
+        OSL_TRACE("name: %s", 
+                  rtl::OUStringToOString(
+                      xElem->getTagName(),
+                      RTL_TEXTENCODING_UTF8 ).getStr());
+    }
+
+    void operator()( const uno::Reference<xml::dom::XElement>&      xElem,
+                     const uno::Reference<xml::dom::XNamedNodeMap>& xAttributes )
+    {
+        OSL_TRACE("name: %s", 
+                  rtl::OUStringToOString(
+                      xElem->getTagName(),
+                      RTL_TEXTENCODING_UTF8 ).getStr());
+        const sal_Int32 nNumAttrs( xAttributes->getLength() );
+        for( sal_Int32 i=0; i<nNumAttrs; ++i )
+        {
+            OSL_TRACE(" %s=%s", 
+                      rtl::OUStringToOString(
+                          xAttributes->item(i)->getNodeName(),
+                          RTL_TEXTENCODING_UTF8 ).getStr(),
+                      rtl::OUStringToOString(
+                          xAttributes->item(i)->getNodeValue(),
+                          RTL_TEXTENCODING_UTF8 ).getStr());
+        }
+    }
+
+    void push() {}
+    void pop()  {}
+};
+
+static void dumpTree( const uno::Reference<xml::dom::XElement> xElem )
+{
+    DumpingVisitor aVisitor;
+    visitElements(aVisitor, xElem);
+}
+#endif
+
+} // namespace 
+
+
+SVGReader::SVGReader(const uno::Reference<lang::XMultiServiceFactory>&     xServiceFactory,
+                     const uno::Reference<io::XInputStream>&           xInputStream, 
+                     const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler) :
+	m_xServiceFactory( xServiceFactory ),
+	m_xInputStream( xInputStream ),
+	m_xDocumentHandler( xDocumentHandler )
+{
+}
+
+sal_Bool SVGReader::parseAndConvert()
+{
+	uno::Reference<xml::dom::XDocumentBuilder> xDomBuilder( 
+        m_xServiceFactory->createInstance( 
+            rtl::OUString::createFromAscii("com.sun.star.xml.dom.DocumentBuilder")), uno::UNO_QUERY );
+
+    uno::Reference<xml::dom::XDocument> xDom(
+        xDomBuilder->parse(m_xInputStream),
+        uno::UNO_QUERY_THROW );
+
+    uno::Reference<xml::dom::XElement> xDocElem( xDom->getDocumentElement(),
+                                                 uno::UNO_QUERY_THROW );
+
+    // the root state for svg document
+    State aInitialState;
+
+    /////////////////////////////////////////////////////////////////
+    // doc boilerplate    
+    /////////////////////////////////////////////////////////////////
+
+    m_xDocumentHandler->startDocument();
+    
+    // get the document dimensions
+
+    // if the "width" and "height" attributes are missing, inkscape fakes
+    // A4 portrait for. Let's do the same.
+	if (!xDocElem->hasAttribute(USTR("width")))
+		xDocElem->setAttribute(USTR("width"), USTR("210mm"));
+	if (!xDocElem->hasAttribute(USTR("height")))
+		xDocElem->setAttribute(USTR("height"), USTR("297mm"));
+		
+    double fViewPortWidth( pt2mm(convLength(xDocElem->getAttribute(USTR("width")),aInitialState,'h')) );
+    double fViewPortHeight( pt2mm(convLength(xDocElem->getAttribute(USTR("height")),aInitialState,'v')) );
+
+    // document prolog
+    rtl::Reference<SvXMLAttributeList> xAttrs( new SvXMLAttributeList() );
+    uno::Reference<xml::sax::XAttributeList> xUnoAttrs( xAttrs.get() );
+	
+    xAttrs->AddAttribute( USTR( "xmlns:office" ), USTR( OASIS_STR "office:1.0" ));
+    xAttrs->AddAttribute( USTR( "xmlns:style" ), USTR( OASIS_STR "style:1.0" ));
+    xAttrs->AddAttribute( USTR( "xmlns:text" ), USTR( OASIS_STR "text:1.0" ));
+    xAttrs->AddAttribute( USTR( "xmlns:svg" ), USTR( OASIS_STR "svg-compatible:1.0" ));
+    xAttrs->AddAttribute( USTR( "xmlns:table" ), USTR( OASIS_STR "table:1.0" ));
+    xAttrs->AddAttribute( USTR( "xmlns:draw" ), USTR( OASIS_STR "drawing:1.0" ));
+    xAttrs->AddAttribute( USTR( "xmlns:fo" ), USTR( OASIS_STR "xsl-fo-compatible:1.0" ));
+    xAttrs->AddAttribute( USTR( "xmlns:xlink" ), USTR( "http://www.w3.org/1999/xlink" ));
+    xAttrs->AddAttribute( USTR( "xmlns:dc" ), USTR( "http://purl.org/dc/elements/1.1/" ));
+    xAttrs->AddAttribute( USTR( "xmlns:number" ), USTR( OASIS_STR "datastyle:1.0" ));
+    xAttrs->AddAttribute( USTR( "xmlns:presentation" ), USTR( OASIS_STR "presentation:1.0" ));
+    xAttrs->AddAttribute( USTR( "xmlns:math" ), USTR( "http://www.w3.org/1998/Math/MathML" ));
+    xAttrs->AddAttribute( USTR( "xmlns:form" ), USTR( OASIS_STR "form:1.0" ));
+    xAttrs->AddAttribute( USTR( "xmlns:script" ), USTR( OASIS_STR "script:1.0" ));
+    xAttrs->AddAttribute( USTR( "xmlns:dom" ), USTR( "http://www.w3.org/2001/xml-events" ));
+    xAttrs->AddAttribute( USTR( "xmlns:xforms" ), USTR( "http://www.w3.org/2002/xforms" ));
+    xAttrs->AddAttribute( USTR( "xmlns:xsd" ), USTR( "http://www.w3.org/2001/XMLSchema" ));
+    xAttrs->AddAttribute( USTR( "xmlns:xsi" ), USTR( "http://www.w3.org/2001/XMLSchema-instance" ));
+    xAttrs->AddAttribute( USTR( "office:version" ), USTR( "1.0" ));
+	xAttrs->AddAttribute( USTR( "office:mimetype" ), USTR( "application/vnd.oasis.opendocument.graphics" ));
+
+    m_xDocumentHandler->startElement( USTR("office:document"), xUnoAttrs );
+
+    xAttrs->Clear();
+
+	m_xDocumentHandler->startElement( USTR("office:settings"), xUnoAttrs);
+	
+	xAttrs->AddAttribute( USTR( "config:name" ), USTR( "ooo:view-settings" ));
+	m_xDocumentHandler->startElement( USTR("config:config-item-set"), xUnoAttrs);
+	
+	xAttrs->Clear();
+	
+	xAttrs->AddAttribute( USTR( "config:name" ), USTR( "VisibleAreaTop" ));
+	xAttrs->AddAttribute( USTR( "config:type" ), USTR( "int" ));
+	m_xDocumentHandler->startElement( USTR( "config:config-item" ), xUnoAttrs);
+
+	m_xDocumentHandler->characters( USTR( "0" ));
+
+	m_xDocumentHandler->endElement( USTR( "config:config-item" ));
+	
+	xAttrs->Clear();
+	
+	xAttrs->AddAttribute( USTR( "config:name" ), USTR( "VisibleAreaLeft" ));
+	xAttrs->AddAttribute( USTR( "config:type" ), USTR( "int" ));
+	m_xDocumentHandler->startElement( USTR( "config:config-item" ), xUnoAttrs);
+
+	m_xDocumentHandler->characters( USTR( "0" ));
+
+	m_xDocumentHandler->endElement( USTR( "config:config-item" ));
+	
+	xAttrs->Clear();
+	
+	xAttrs->AddAttribute( USTR( "config:name" ), USTR( "VisibleAreaWidth" ));
+	xAttrs->AddAttribute( USTR( "config:type" ), USTR( "int" ));
+	m_xDocumentHandler->startElement( USTR( "config:config-item" ), xUnoAttrs);
+
+	sal_Int64 iWidth = sal_Int64(fViewPortWidth);
+	m_xDocumentHandler->characters( ::rtl::OUString::valueOf(iWidth) );
+
+	m_xDocumentHandler->endElement( USTR( "config:config-item" ));
+	
+	xAttrs->Clear();
+	
+	xAttrs->AddAttribute( USTR( "config:name" ), USTR( "VisibleAreaHeight" ));
+	xAttrs->AddAttribute( USTR( "config:type" ), USTR( "int" ));
+	m_xDocumentHandler->startElement( USTR( "config:config-item" ), xUnoAttrs);
+
+	sal_Int64 iHeight = sal_Int64(fViewPortHeight);
+	m_xDocumentHandler->characters( ::rtl::OUString::valueOf(iHeight) );
+
+	m_xDocumentHandler->endElement( USTR( "config:config-item" ));
+	
+	m_xDocumentHandler->endElement( USTR( "config:config-item-set" ));
+	
+	m_xDocumentHandler->endElement( USTR( "office:settings" ));
+
+	xAttrs->Clear();
+	
+    m_xDocumentHandler->startElement( USTR("office:automatic-styles"), 
+                                      xUnoAttrs );
+ 
+    xAttrs->AddAttribute( USTR( "style:name" ), USTR("pagelayout1"));
+    m_xDocumentHandler->startElement( USTR("style:page-layout"), 
+                                      xUnoAttrs );
+    // TODO(Q3): this is super-ugly. In-place container come to mind.
+    xAttrs->Clear();
+
+    // make page viewport-width times viewport-height mm large - add
+    // 5% border at every side
+    xAttrs->AddAttribute( USTR( "fo:margin-top" ), USTR("0mm"));
+    xAttrs->AddAttribute( USTR( "fo:margin-bottom" ), USTR("0mm"));
+    xAttrs->AddAttribute( USTR( "fo:margin-left" ), USTR("0mm"));
+    xAttrs->AddAttribute( USTR( "fo:margin-right" ), USTR("0mm"));
+    xAttrs->AddAttribute( USTR( "fo:page-width" ), rtl::OUString::valueOf(fViewPortWidth)+USTR("mm"));
+    xAttrs->AddAttribute( USTR( "fo:page-height" ), rtl::OUString::valueOf(fViewPortHeight)+USTR("mm"));
+    xAttrs->AddAttribute( USTR( "style:print-orientation" ), 
+        fViewPortWidth > fViewPortHeight ? 
+        USTR("landscape") :
+        USTR("portrait"));
+    m_xDocumentHandler->startElement( USTR("style:page-layout-properties"), 
+                                      xUnoAttrs );
+    m_xDocumentHandler->endElement( USTR("style:page-layout-properties") );
+    m_xDocumentHandler->endElement( USTR("style:page-layout") );
+
+    xAttrs->Clear();
+    xAttrs->AddAttribute( USTR( "style:name" ), USTR("pagestyle1"));
+    xAttrs->AddAttribute( USTR( "style:family" ), USTR("drawing-page"));
+    m_xDocumentHandler->startElement( USTR("style:style"), 
+                                      xUnoAttrs );
+
+    xAttrs->Clear();
+    xAttrs->AddAttribute( USTR( "draw:background-size" ), USTR("border"));
+    xAttrs->AddAttribute( USTR( "draw:fill" ), USTR("none"));
+    m_xDocumentHandler->startElement( USTR("style:drawing-page-properties"), 
+                                      xUnoAttrs );
+    m_xDocumentHandler->endElement( USTR("style:drawing-page-properties") );
+    m_xDocumentHandler->endElement( USTR("style:style") );
+
+    StatePool aStatePool;
+    StateMap  aStateMap;
+    annotateStyles(aStatePool,aStateMap,aInitialState,
+                   xDocElem,m_xDocumentHandler);
+
+#ifdef VERBOSE
+    dumpTree(xDocElem);
+#endif
+
+    m_xDocumentHandler->endElement( USTR("office:automatic-styles") );
+
+    ////////////////////////////////////////////////////////////////////
+
+    xAttrs->Clear();
+    m_xDocumentHandler->startElement( USTR("office:styles"), 
+                                      xUnoAttrs);
+    m_xDocumentHandler->endElement( USTR("office:styles") );
+
+    ////////////////////////////////////////////////////////////////////
+
+    m_xDocumentHandler->startElement( USTR("office:master-styles"), 
+                                      xUnoAttrs );
+    xAttrs->Clear();
+    xAttrs->AddAttribute( USTR( "style:name" ), USTR("Default"));
+    xAttrs->AddAttribute( USTR( "style:page-layout-name" ), USTR("pagelayout1"));
+    xAttrs->AddAttribute( USTR( "draw:style-name" ), USTR("pagestyle1"));
+    m_xDocumentHandler->startElement( USTR("style:master-page"), 
+                                      xUnoAttrs );
+    m_xDocumentHandler->endElement( USTR("style:master-page") );
+
+    m_xDocumentHandler->endElement( USTR("office:master-styles") );
+
+    ////////////////////////////////////////////////////////////////////
+
+    xAttrs->Clear();
+    m_xDocumentHandler->startElement( USTR("office:body"), 
+                                      xUnoAttrs );
+    m_xDocumentHandler->startElement( USTR("office:drawing"), 
+                                      xUnoAttrs );
+
+    xAttrs->Clear();
+    xAttrs->AddAttribute( USTR( "draw:master-page-name" ), USTR("Default"));
+    xAttrs->AddAttribute( USTR( "draw:style-name" ), USTR("pagestyle1"));
+    m_xDocumentHandler->startElement(USTR("draw:page"), 
+                                     xUnoAttrs);
+
+    // write out all shapes
+    writeShapes(aStatePool,
+                aStateMap,
+                xDocElem,
+                m_xDocumentHandler);
+
+    m_xDocumentHandler->endElement( USTR("draw:page") );
+    m_xDocumentHandler->endElement( USTR("office:drawing") );
+    m_xDocumentHandler->endElement( USTR("office:body") );
+    m_xDocumentHandler->endElement( USTR("office:document") );
+    m_xDocumentHandler->endDocument();
+
+    return sal_True;
+}
+
+///////////////////////////////////////////////////////////////
+
+struct ShapeRenderingVisitor
+{
+    ShapeRenderingVisitor(StatePool&    /*rStatePool*/,
+                          StateMap&     rStateMap,
+                          OutputDevice& rOutDev,
+                          const std::vector< Gradient >& rGradientVector,
+                          const std::vector< GradientStop >& rGradientStopVector) :
+        mrStateMap(rStateMap),
+        mrOutDev(rOutDev),
+        mrGradientVector(rGradientVector),
+        mrGradientStopVector(rGradientStopVector)
+    {}
+
+    void operator()( const uno::Reference<xml::dom::XElement>& )
+    {
+    }
+
+    void operator()( const uno::Reference<xml::dom::XElement>&      xElem,
+                     const uno::Reference<xml::dom::XNamedNodeMap>& xAttributes )
+    {
+        sal_Int32 nDummyIndex(0);
+        rtl::OUString sStyleId(
+            xElem->getAttribute(
+                USTR("internal-style-ref")).getToken(
+                    0,'$',nDummyIndex));
+        StateMap::iterator pOrigState=mrStateMap.find(
+            sStyleId.toInt32());
+
+        if( pOrigState == mrStateMap.end() )
+            return; // non-exportable element, e.g. linearGradient
+
+        maCurrState = pOrigState->second;
+
+        const sal_Int32 nTokenId(getTokenId(xElem->getNodeName()));
+        switch(nTokenId)
+        {
+		    case XML_LINE:
+			{
+                // collect attributes
+                const sal_Int32 nNumAttrs( xAttributes->getLength() );
+                rtl::OUString sAttributeValue;
+                double x1=0.0,y1=0.0,x2=0.0,y2=0.0;
+                for( sal_Int32 i=0; i<nNumAttrs; ++i )
+                {
+                    sAttributeValue = xAttributes->item(i)->getNodeValue();
+                    const sal_Int32 nAttribId( 
+                        getTokenId(xAttributes->item(i)->getNodeName()));
+                    switch(nAttribId)
+                    {
+                        case XML_X1:
+                            x1= convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_X2:
+                            x2 = convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_Y1:
+                            y1 = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        case XML_Y2:
+                            y2 = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        default:
+                            // skip
+                            break;
+                    }
+                }
+
+                basegfx::B2DPolygon aPoly;
+                aPoly.append(basegfx::B2DPoint(x1,y1));
+                aPoly.append(basegfx::B2DPoint(x2,y2));
+
+                renderPathShape(basegfx::B2DPolyPolygon(aPoly));
+                break;
+			}
+            case XML_POLYGON:
+            case XML_POLYLINE:
+            {
+                rtl::OUString sPoints = xElem->hasAttribute(USTR("points")) ? xElem->getAttribute(USTR("points")) : USTR("");
+                basegfx::B2DPolygon aPoly;
+                basegfx::tools::importFromSvgPoints(aPoly, sPoints);
+                if( nTokenId == XML_POLYGON || maCurrState.meFillType != NONE )
+                    aPoly.setClosed(true);
+
+                renderPathShape(basegfx::B2DPolyPolygon(aPoly));
+                break;
+            }
+            case XML_RECT:
+            {
+                // collect attributes
+                const sal_Int32 nNumAttrs( xAttributes->getLength() );
+                rtl::OUString sAttributeValue;
+                bool bRxSeen=false, bRySeen=false;
+                double x=0.0,y=0.0,width=0.0,height=0.0,rx=0.0,ry=0.0;
+                for( sal_Int32 i=0; i<nNumAttrs; ++i )
+                {
+                    sAttributeValue = xAttributes->item(i)->getNodeValue();
+                    const sal_Int32 nAttribId( 
+                        getTokenId(xAttributes->item(i)->getNodeName()));
+                    switch(nAttribId)
+                    {
+                        case XML_X:
+                            x = convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_Y:
+                            y = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        case XML_WIDTH:
+                            width = convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_HEIGHT:
+                            height = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        case XML_RX:
+                            rx = convLength(sAttributeValue,maCurrState,'h');
+                            bRxSeen=true;
+                            break;
+                        case XML_RY:
+                            ry = convLength(sAttributeValue,maCurrState,'v');
+                            bRySeen=true;
+                            break;
+                        default:
+                            // skip
+                            break;
+                    }
+                }
+
+                if( bRxSeen && !bRySeen )
+                    ry = rx;
+                else if( bRySeen && !bRxSeen )
+                    rx = ry;
+
+                basegfx::B2DPolygon aPoly;
+                aPoly = basegfx::tools::createPolygonFromRect(
+                    basegfx::B2DRange(x,y,x+width,y+height),
+                    rx, ry );
+
+                renderPathShape(basegfx::B2DPolyPolygon(aPoly));
+                break;
+            }
+            case XML_PATH:
+            {
+                rtl::OUString sPath = xElem->hasAttribute(USTR("d")) ? xElem->getAttribute(USTR("d")) : USTR("");
+                basegfx::B2DPolyPolygon aPoly;
+                basegfx::tools::importFromSvgD(aPoly, sPath);
+
+                renderPathShape(aPoly);
+                break;
+            }
+			case XML_CIRCLE:
+			{
+                // collect attributes
+                const sal_Int32 nNumAttrs( xAttributes->getLength() );
+                rtl::OUString sAttributeValue;
+                double cx=0.0,cy=0.0,r=0.0;
+                for( sal_Int32 i=0; i<nNumAttrs; ++i )
+                {
+                    sAttributeValue = xAttributes->item(i)->getNodeValue();
+                    const sal_Int32 nAttribId( 
+                        getTokenId(xAttributes->item(i)->getNodeName()));
+                    switch(nAttribId)
+                    {
+                        case XML_CX:
+                            cx = convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_CY:
+                            cy = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        case XML_R:
+                            r = convLength(sAttributeValue,maCurrState,'o');
+                        default:
+                            // skip
+                            break;
+                    }
+                }
+
+                basegfx::B2DEllipse aEllipse(basegfx::B2DPoint(cx, cy), basegfx::B2DTuple(r,r));
+                basegfx::B2DPolygon aPoly = basegfx::tools::createPolygonFromEllipse(
+                    aEllipse.getB2DEllipseCenter(),
+                    aEllipse.getB2DEllipseRadius().getX(), 
+                    aEllipse.getB2DEllipseRadius().getY());
+
+                renderPathShape(basegfx::B2DPolyPolygon(aPoly));
+				break;
+			}
+			case XML_ELLIPSE:
+			{
+                // collect attributes
+                const sal_Int32 nNumAttrs( xAttributes->getLength() );
+                rtl::OUString sAttributeValue;
+                double cx=0.0,cy=0.0,rx=0.0, ry=0.0;
+                for( sal_Int32 i=0; i<nNumAttrs; ++i )
+                {
+                    sAttributeValue = xAttributes->item(i)->getNodeValue();
+                    const sal_Int32 nAttribId( 
+                        getTokenId(xAttributes->item(i)->getNodeName()));
+                    switch(nAttribId)
+                    {
+                        case XML_CX:
+                            cx = convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_CY:
+                            cy = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        case XML_RX:
+                            rx = convLength(sAttributeValue,maCurrState,'h');
+							break;
+						case XML_RY:
+							ry = convLength(sAttributeValue,maCurrState,'v');
+                        default:
+                            // skip
+                            break;
+                    }
+                }
+
+                basegfx::B2DEllipse aEllipse(basegfx::B2DPoint(cx, cy), basegfx::B2DTuple(rx,ry));
+                basegfx::B2DPolygon aPoly = basegfx::tools::createPolygonFromEllipse(
+                    aEllipse.getB2DEllipseCenter(),
+                    aEllipse.getB2DEllipseRadius().getX(), 
+                    aEllipse.getB2DEllipseRadius().getY());
+
+                renderPathShape(basegfx::B2DPolyPolygon(aPoly));
+				break;
+			}
+            case XML_IMAGE:
+            {
+                // collect attributes
+                const sal_Int32 nNumAttrs( xAttributes->getLength() );
+                rtl::OUString sAttributeValue;
+                double x=0.0,y=0.0,width=0.0,height=0.0;
+                for( sal_Int32 i=0; i<nNumAttrs; ++i )
+                {
+                    sAttributeValue = xAttributes->item(i)->getNodeValue();
+                    const sal_Int32 nAttribId( 
+                        getTokenId(xAttributes->item(i)->getNodeName()));
+                    switch(nAttribId)
+                    {
+                        case XML_X:
+                            x = convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_Y:
+                            y = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        case XML_WIDTH:
+                            width = convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_HEIGHT:
+                            height = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        default:
+                            // skip
+                            break;
+                    }
+                }
+
+                rtl::OUString sValue = xElem->hasAttribute(USTR("href")) ? xElem->getAttribute(USTR("href")) : USTR("");
+        		rtl::OString aValueUtf8( sValue.getStr(), sValue.getLength(), RTL_TEXTENCODING_UTF8 );
+				std::string sLinkValue;
+				parseXlinkHref(aValueUtf8.getStr(), sLinkValue);
+
+				if (!sLinkValue.empty())
+                {
+                    // <- blatant copy from svx/source/xml/xmlgrhlp.cxx
+                    Graphic aGraphic;
+
+                    uno::Sequence<sal_Int8> aData;
+                    SvXMLUnitConverter::decodeBase64(aData, 
+                                                     rtl::OUString::createFromAscii(sLinkValue.c_str()));
+                    SvMemoryStream aSrc(aData.getArray(), 
+                                        aData.getLength(), 
+                                        STREAM_READ);
+                    USHORT nFormat = GRFILTER_FORMAT_DONTKNOW;
+                    USHORT pDeterminedFormat = GRFILTER_FORMAT_DONTKNOW;
+                    GetGrfFilter()->ImportGraphic( aGraphic, String(), aSrc ,nFormat,&pDeterminedFormat );
+
+                    if (pDeterminedFormat == GRFILTER_FORMAT_DONTKNOW)
+                    {
+                        //Read the first two byte to check whether it is a gzipped stream, is so it may be in wmz or emz format 
+                        //unzip them and try again
+
+                        BYTE    sFirstBytes[ 2 ];
+
+                        aSrc.Seek( STREAM_SEEK_TO_END );
+                        ULONG nStreamLen = aSrc.Tell();
+                        aSrc.Seek( 0 );
+
+                        if ( !nStreamLen )
+                        {
+                            SvLockBytes* pLockBytes = aSrc.GetLockBytes();
+                            if ( pLockBytes  )
+                                pLockBytes->SetSynchronMode( TRUE );
+
+                            aSrc.Seek( STREAM_SEEK_TO_END );
+                            nStreamLen = aSrc.Tell();
+                            aSrc.Seek( 0 );
+                        }
+                        if( nStreamLen >= 2 )
+                        {
+                            //read two byte
+                            aSrc.Read( sFirstBytes, 2 );
+
+                            if( sFirstBytes[0] == 0x1f && sFirstBytes[1] == 0x8b )
+                            {
+                                SvMemoryStream* pDest = new SvMemoryStream;
+                                ZCodec aZCodec( 0x8000, 0x8000 );
+                                aZCodec.BeginCompression(ZCODEC_GZ_LIB);
+                                aSrc.Seek( 0 );
+                                aZCodec.Decompress( aSrc, *pDest );
+					
+                                if (aZCodec.EndCompression() && pDest )
+                                {
+                                    pDest->Seek( STREAM_SEEK_TO_END );
+                                    ULONG nStreamLen_ = pDest->Tell();
+                                    if (nStreamLen_)
+                                    {
+                                        pDest->Seek(0L);
+                                        GetGrfFilter()->ImportGraphic( aGraphic, String(), *pDest ,nFormat,&pDeterminedFormat );
+                                    }
+                                }
+                                delete pDest;
+                            }
+                        }
+                    }
+                    // -> blatant copy from svx/source/xml/xmlgrhlp.cxx
+
+                    const Rectangle aBounds(
+                        Point(basegfx::fround(pt100thmm(x)),
+                              basegfx::fround(pt100thmm(y))),
+                        Size(basegfx::fround(pt100thmm(width)),
+                             basegfx::fround(pt100thmm(height))));
+                    aGraphic.Draw(&mrOutDev,
+                                  aBounds.TopLeft(),
+                                  aBounds.GetSize());
+                    maBounds.Union(aBounds);
+                }
+                break;
+            }
+            case XML_TEXT:
+            {
+                // collect text from all TEXT_NODE children into sText
+                rtl::OUStringBuffer sText;
+                visitChildren(boost::bind(
+                                  (rtl::OUStringBuffer& (rtl::OUStringBuffer::*)(const sal_Unicode* str))&rtl::OUStringBuffer::append,
+                                  boost::ref(sText),
+                                  boost::bind(&xml::dom::XNode::getNodeValue,
+                                              _1)),
+                              xElem,
+                              xml::dom::NodeType_TEXT_NODE);
+
+                // collect attributes
+                const sal_Int32 nNumAttrs( xAttributes->getLength() );
+                rtl::OUString sAttributeValue;
+                double x=0.0,y=0.0,width=0.0,height=0.0;
+                for( sal_Int32 i=0; i<nNumAttrs; ++i )
+                {
+                    sAttributeValue = xAttributes->item(i)->getNodeValue();
+                    const sal_Int32 nAttribId( 
+                        getTokenId(xAttributes->item(i)->getNodeName()));
+                    switch(nAttribId)
+                    {
+                        case XML_X:
+                            x = convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_Y:
+                            y = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        case XML_WIDTH:
+                            width = convLength(sAttributeValue,maCurrState,'h');
+                            break;
+                        case XML_HEIGHT:
+                            height = convLength(sAttributeValue,maCurrState,'v');
+                            break;
+                        default:
+                            // skip
+                            break;
+                    }
+                }
+
+                // actually export text
+                Font aFont(maCurrState.maFontFamily, 
+                           Size(0,
+                                basegfx::fround(pt100thmm(maCurrState.mnFontSize))));
+                aFont.SetAlign(ALIGN_BASELINE);
+                aFont.SetColor(getVclColor(maCurrState.maFillColor)); 
+                aFont.SetFillColor(getVclColor(maCurrState.maFillColor));
+
+                if( !maCurrState.maFontStyle.equalsAscii("normal") )
+                    aFont.SetItalic(ITALIC_NORMAL); // TODO: discriminate
+                if( !maCurrState.mnFontWeight != 400.0 )
+                    aFont.SetWeight(WEIGHT_BOLD); // TODO: discriminate
+
+                // extract basic transformations out of CTM
+                basegfx::B2DTuple aScale, aTranslate;
+                double fRotate, fShearX;
+                ::rtl::OUString sTransformValue;
+                if (maCurrState.maCTM.decompose(aScale, aTranslate, fRotate, fShearX))
+                {
+                    rtl::OUString sTransform;
+                    x += aTranslate.getX();
+                    y += aTranslate.getY();
+
+                    aFont.SetSize(
+                        Size(basegfx::fround(aFont.GetWidth()*aScale.getX()),
+                             basegfx::fround(aFont.GetHeight()*aScale.getY())));
+
+                    if( fRotate )
+                        aFont.SetOrientation(basegfx::fround(fRotate*1800.0/M_PI));
+                }
+
+                // TODO(F2): update bounds
+                mrOutDev.SetFont(aFont);
+                const ::rtl::OUString aText( sText.makeStringAndClear() );
+                switch( maCurrState.meTextAnchor )
+                {
+                    default:
+                    case BEFORE:
+                        break;
+
+                    case CENTER:
+                    {
+                        const long nWidth=mrOutDev.GetTextWidth(aText);
+                        x -= nWidth/2;
+                    }
+                    break;
+
+                    case AFTER:
+                        x -= mrOutDev.GetTextWidth(aText);
+                        break;
+                }
+                mrOutDev.DrawText(Point(basegfx::fround(pt100thmm(x)),
+                                        basegfx::fround(pt100thmm(y))),
+                                  aText);
+                break;
+            }
+        }
+    }
+
+    void push()
+    {
+    }
+
+    void pop()
+    {
+    }
+	
+    bool hasGradientOpacity( const Gradient& rGradient )
+    {
+        return 
+            mrGradientStopVector[
+                rGradient.maStops[0]].maStopColor.a != 1.0 ||
+            mrGradientStopVector[
+                rGradient.maStops[1]].maStopColor.a != 1.0;
+    }
+
+    sal_Int8 toByteColor( double val )
+    {
+        // TODO(Q3): duplicated from vcl::unotools
+        return sal::static_int_cast<sal_Int8>(
+            basegfx::fround(val*255.0));
+    }
+
+    ::Color getVclColor( const ARGBColor& rColor )
+    {
+        const sal_uInt8 nRed  ( toByteColor(rColor.r)   );
+        const sal_uInt8 nGreen( toByteColor(rColor.g) );
+        const sal_uInt8 nBlue ( toByteColor(rColor.b)  );
+
+        return ::Color(nRed,nGreen,nBlue);
+    }
+
+    void renderPathShape(const basegfx::B2DPolyPolygon& rPoly)
+    {
+        // we might need to split up polypolygon into multiple path
+        // shapes (e.g. when emulating line stroking)
+        State aState = maCurrState;
+		
+        // bring polygon from pt coordinate system to 100th millimeter
+        aState.maCTM.scale(2540.0/72.0,2540.0/72.0);
+
+        basegfx::B2DPolyPolygon aPoly(rPoly);
+        aPoly.transform(aState.maCTM);
+
+        const basegfx::B2DRange aBounds=basegfx::tools::getRange(aPoly);
+        maBounds.Union(
+            Rectangle(
+                basegfx::fround(aBounds.getMinX()),
+                basegfx::fround(aBounds.getMinY()),
+                basegfx::fround(aBounds.getMaxX()),
+                basegfx::fround(aBounds.getMaxY())));
+
+        // fill first
+        mrOutDev.SetLineColor();
+
+        // do we have a gradient fill?
+        if( aState.meFillType == GRADIENT && aState.maFillGradient.maStops.size() > 1 )
+        {
+            ::Gradient aGradient;
+
+            if( aState.maFillGradient.meType == Gradient::LINEAR )
+            {
+                // should the optimizeGradientStops method decide that
+                // this is a three-color gradient, it prolly wanted us
+                // to take axial instead
+                aGradient = ::Gradient( aState.maFillGradient.maStops.size() == 3 ?
+                                        GRADIENT_AXIAL :
+                                        GRADIENT_LINEAR );
+            }
+            else
+            {
+                aGradient = ::Gradient( GRADIENT_ELLIPTICAL );
+            }
+
+            basegfx::B2DTuple rScale, rTranslate;
+            double rRotate, rShearX;
+            if( aState.maFillGradient.maTransform.decompose(rScale, rTranslate, rRotate, rShearX) )
+                aGradient.SetAngle( basegfx::fround(rRotate*1800.0/M_PI) );
+            aGradient.SetStartColor( getVclColor(
+                                         mrGradientStopVector[
+                                             aState.maFillGradient.maStops[0]].maStopColor) );
+            aGradient.SetEndColor( getVclColor(
+                                       mrGradientStopVector[
+                                           aState.maFillGradient.maStops[1]].maStopColor) );
+
+            if( hasGradientOpacity(aState.maFillGradient) )
+            {
+                ::Gradient aTransparencyGradient=aGradient;
+
+                const BYTE	cTransStart( 255-
+                    basegfx::fround(mrGradientStopVector[
+                                        aState.maFillGradient.maStops[1]].maStopColor.a*
+                                    aState.mnFillOpacity*255.0));
+                const Color aTransStart( cTransStart, cTransStart, cTransStart );
+
+                const BYTE	cTransEnd( 255-
+                    basegfx::fround(mrGradientStopVector[
+                                        aState.maFillGradient.maStops[0]].maStopColor.a*
+                                    aState.mnFillOpacity*255.0));
+                const Color aTransEnd( cTransEnd, cTransEnd, cTransEnd );
+
+                // modulate gradient opacity with overall fill opacity
+                aTransparencyGradient.SetStartColor(aTransStart);
+                aTransparencyGradient.SetEndColor(aTransEnd);
+
+                VirtualDevice	aVDev;
+                GDIMetaFile		aMtf;
+
+                aVDev.EnableOutput( FALSE );
+                aVDev.SetMapMode( mrOutDev.GetMapMode() );
+                aMtf.Record( &aVDev );
+
+                aVDev.SetLineColor();
+                aVDev.SetFillColor();
+                aVDev.DrawGradient(::PolyPolygon(aPoly),aGradient);
+
+                const Rectangle aMtfBounds(
+                    basegfx::fround(aBounds.getMinX()),
+                    basegfx::fround(aBounds.getMinY()),
+                    basegfx::fround(aBounds.getMaxX()),
+                    basegfx::fround(aBounds.getMaxY()));
+
+                MapMode aMap(mrOutDev.GetMapMode());
+                aMtf.Stop();
+                aMtf.WindStart();
+                aMap.SetOrigin( aMtfBounds.TopLeft() );
+                aMtf.SetPrefMapMode( aMap );
+                aMtf.SetPrefSize( aMtfBounds.GetSize() );
+
+                mrOutDev.DrawTransparent(aMtf,
+                                         aMtfBounds.TopLeft(),
+                                         aMtfBounds.GetSize(),
+                                         aTransparencyGradient);
+            }
+            else
+            {
+                mrOutDev.DrawGradient(::PolyPolygon(aPoly),aGradient);
+            }
+        }
+        else
+        {
+            if( aState.meFillType == NONE )
+                mrOutDev.SetFillColor();
+            else
+                mrOutDev.SetFillColor(getVclColor(aState.maFillColor));
+
+            if( aState.mnFillOpacity != 1.0 )
+                mrOutDev.DrawTransparent(::PolyPolygon(aPoly),
+                                         basegfx::fround(
+                                             (1.0-aState.mnFillOpacity)*100.0));
+            else
+                mrOutDev.DrawPolyPolygon(::PolyPolygon(aPoly));
+        }
+
+        // Stroking now
+        mrOutDev.SetFillColor();
+
+        if( aState.meStrokeType != NONE &&
+            (aState.maDashArray.size() ||
+             aState.mnStrokeWidth != 1.0) )
+        {
+            // vcl thick lines are severly borked - generate filled
+            // polygon instead
+            std::vector<basegfx::B2DPolyPolygon> aPolys;
+            aPoly = rPoly;
+            if( !aState.maDashArray.empty() )
+            {
+                aPoly.clear();
+                basegfx::B2DPolyPolygon aSegment;
+                for( sal_uInt32 i=0; i<rPoly.count(); ++i )
+                {
+                    basegfx::tools::applyLineDashing(rPoly,
+                                                     aState.maDashArray,
+                                                     &aSegment);
+                    aPoly.append(aSegment);
+                }
+            }
+
+            // applied line dashing to original rPoly above, to get
+            // correctly transformed lengths - need to transform
+            // again, now
+            aPoly.transform(aState.maCTM);
+
+            for( sal_uInt32 i=0; i<aPoly.count(); ++i )
+            {                
+                // ugly. convert to integer-based tools polygon
+                // first, and only _then_ remove intersections (we
+                // might get new ones from the rounding)
+                aPolys.push_back(
+                    basegfx::tools::stripNeutralPolygons(
+                        basegfx::tools::prepareForPolygonOperation(
+                            ::PolyPolygon(
+                                basegfx::tools::createAreaGeometry(
+                                    aPoly.getB2DPolygon(i),
+                                    pt100thmm(aState.mnStrokeWidth/2.0),
+                                    aState.meLineJoin)).getB2DPolyPolygon())));
+                // TODO(F2): line ends
+            }
+
+            mrOutDev.SetLineColor();
+            mrOutDev.SetFillColor(getVclColor(aState.maStrokeColor));
+
+            for( sal_uInt32 i=0; i<aPolys.size(); ++i )
+            {
+                if( aState.mnStrokeOpacity != 1.0 )
+                    mrOutDev.DrawTransparent(::PolyPolygon(aPolys[i]),
+                                             basegfx::fround(
+                                                 (1.0-aState.mnStrokeOpacity)*100.0));
+                else
+                    mrOutDev.DrawPolyPolygon(::PolyPolygon(aPolys[i]));
+
+                const basegfx::B2DRange aStrokeBounds=basegfx::tools::getRange(aPolys[i]);
+                maBounds.Union(
+                    Rectangle(
+                        basegfx::fround(aStrokeBounds.getMinX()),
+                        basegfx::fround(aStrokeBounds.getMinY()),
+                        basegfx::fround(aStrokeBounds.getMaxX()),
+                        basegfx::fround(aStrokeBounds.getMaxY())));
+            }
+        }
+        else
+        {
+            if( aState.meStrokeType == NONE )
+                mrOutDev.SetLineColor();
+            else
+                mrOutDev.SetLineColor(getVclColor(aState.maStrokeColor));
+
+            if( aState.mnStrokeOpacity != 1.0 )
+                mrOutDev.DrawTransparent(::PolyPolygon(aPoly),
+                                         basegfx::fround(
+                                             (1.0-aState.mnStrokeOpacity)*100.0));
+            else
+                mrOutDev.DrawPolyPolygon(::PolyPolygon(aPoly));
+        }
+    }
+
+    State                                      maCurrState;
+    StateMap&                                  mrStateMap;
+    OutputDevice&                               mrOutDev;
+    const std::vector< Gradient >&             mrGradientVector;
+    const std::vector< GradientStop >&         mrGradientStopVector;
+    Rectangle                                   maBounds;
+};
+
+} // namespace svgi
+
+bool importSvg(SvStream & rStream, Graphic & rGraphic )
+{
+    const uno::Reference<lang::XMultiServiceFactory> xServiceFactory(
+        ::comphelper::getProcessServiceFactory());    
+
+	uno::Reference<xml::dom::XDocumentBuilder> xDomBuilder( 
+        xServiceFactory->createInstance( 
+            rtl::OUString::createFromAscii("com.sun.star.xml.dom.DocumentBuilder")), 
+        uno::UNO_QUERY );
+
+    uno::Reference<io::XInputStream> xStream(
+        new utl::OInputStreamWrapper(rStream) );
+
+    uno::Reference<xml::dom::XDocument> xDom(
+        xDomBuilder->parse(xStream),
+        uno::UNO_QUERY_THROW );
+
+    uno::Reference<xml::dom::XElement> xDocElem( xDom->getDocumentElement(),
+                                                 uno::UNO_QUERY_THROW );
+    
+    VirtualDevice	aVDev;
+    GDIMetaFile		aMtf;
+
+    aVDev.EnableOutput( FALSE );
+    aMtf.Record( &aVDev );
+    aVDev.SetTextAlign(ALIGN_BASELINE);
+
+    // parse styles and fill state stack
+    svgi::State      aInitialState;
+    svgi::StatePool aStatePool;
+    svgi::StateMap  aStateMap;
+    svgi::AnnotatingVisitor aVisitor(aStatePool,
+                                     aStateMap,
+                                     aInitialState,
+                                     uno::Reference<xml::sax::XDocumentHandler>());
+    svgi::visitElements(aVisitor, xDocElem);
+
+#ifdef VERBOSE
+    dumpTree(xDocElem);
+#endif
+
+    // render all shapes to mtf
+    svgi::ShapeRenderingVisitor aRenderer(aStatePool,aStateMap,aVDev,
+                                         aVisitor.maGradientVector,
+                                         aVisitor.maGradientStopVector);
+    svgi::visitElements(aRenderer, xDocElem);
+
+    aMtf.Stop();
+
+    aMtf.WindStart();
+    aMtf.SetPrefMapMode( MAP_100TH_MM );
+
+    // get the document dimensions
+
+    // if the "width" and "height" attributes are missing, inkscape fakes
+    // A4 portrait for. Let's do the same.
+	if (!xDocElem->hasAttribute(USTR("width")))
+		xDocElem->setAttribute(USTR("width"), USTR("210mm"));
+	if (!xDocElem->hasAttribute(USTR("height")))
+		xDocElem->setAttribute(USTR("height"), USTR("297mm"));
+		
+    aMtf.SetPrefSize( 
+        Size( 
+            std::max(
+                sal_Int32(aRenderer.maBounds.Right()),
+                basegfx::fround( svgi::pt100thmm(svgi::convLength(xDocElem->getAttribute(USTR("width")),aInitialState,'h')) )), 
+            std::max(
+                sal_Int32(aRenderer.maBounds.Bottom()),
+                basegfx::fround( svgi::pt100thmm(svgi::convLength(xDocElem->getAttribute(USTR("height")),aInitialState,'v')) ))));
+
+    rGraphic = aMtf;
+    
+    return sal_True;
+}
+
+
diff -ruN OOO310_m6.orig/filter/source/svg/svgreader.hxx OOO310_m6/filter/source/svg/svgreader.hxx
--- OOO310_m6.orig/filter/source/svg/svgreader.hxx	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/svgreader.hxx	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,43 @@
+/*************************************************************************
+ *
+ *    OpenOffice.org - a multi-platform office productivity suite
+ *
+ *    Author:
+ *      Fridrich Strba  <fridrich.strba@bluewin.ch>
+ *      Thorsten Behrens <tbehrens@novell.com>	   	
+ *
+ *      Copyright (C) 2008, Novell Inc.
+ *
+ *   The Contents of this file are made available subject to
+ *   the terms of GNU Lesser General Public License Version 2.1.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SVGREADER_HXX
+#define INCLUDED_SVGREADER_HXX
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+
+namespace svgi
+{
+
+class SVGReader
+{
+    const ::com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >      m_xServiceFactory;    
+    const ::com::sun::star::uno::Reference< com::sun::star::io::XInputStream >              m_xInputStream;
+	const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler >  m_xDocumentHandler;
+
+public:
+    SVGReader( const com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory>&           xServiceFactory,
+               const com::sun::star::uno::Reference< com::sun::star::io::XInputStream >&               xInputStream,
+               const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler >& xDocumentHandler );
+
+	sal_Bool parseAndConvert();
+};
+
+} // namespace svgi
+
+#endif
diff -ruN OOO310_m6.orig/filter/source/svg/test/makefile.mk OOO310_m6/filter/source/svg/test/makefile.mk
--- OOO310_m6.orig/filter/source/svg/test/makefile.mk	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/test/makefile.mk	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,115 @@
+#*************************************************************************
+#
+#    OpenOffice.org - a multi-platform office productivity suite
+#
+#    Author:
+#      Fridrich Strba  <fridrich.strba@bluewin.ch>
+#      Thorsten Behrens <tbehrens@novell.com>	   	
+#
+#      Copyright (C) 2008, Novell Inc.
+#      Parts copyright 2005 by Sun Microsystems, Inc.
+#
+#   The Contents of this file are made available subject to
+#   the terms of GNU Lesser General Public License Version 2.1.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+PRJNAME=filter
+TARGET=tests
+TARGETTYPE=CUI
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE: settings.mk
+
+# --- unit tests ---------------------------------------------------
+
+SHL1OBJS=  \
+	$(SLO)$/parsertest.obj
+
+SHL1TARGET= tests
+SHL1LIBS= $(SLB)$/svgfilter.lib
+SHL1STDLIBS= 	        \
+	$(BASEGFXLIB)		\
+	$(SVXLIB)			\
+	$(SVTOOLLIB)	    \
+	$(XMLOFFLIB)		\
+	$(BASEGFXLIB)		\
+	$(VCLLIB)			\
+	$(UNOTOOLSLIB)		\
+	$(TOOLSLIB)			\
+	$(COMPHELPERLIB)	\
+	$(SVTOOLLIB)	    \
+	$(CPPUHELPERLIB)	\
+	$(CPPULIB)			\
+	$(SALLIB)			\
+	$(LIBXML)			\
+	$(CPPUNITLIB)
+
+# --- svg2xml binary ------------------------------------------------------
+
+TARGET2=svg2odf
+
+APP1TARGET=$(TARGET2)
+APP1LIBSALCPPRT=
+APP1OBJS= \
+	$(SLO)$/odfserializer.obj	\
+    $(SLO)$/svg2odf.obj
+
+APP1LIBS=\
+	$(SLB)$/svgfilter.lib
+
+APP1STDLIBS=\
+	$(BASEGFXLIB)		\
+	$(SVXLIB)			\
+	$(XMLOFFLIB)		\
+	$(BASEGFXLIB)		\
+	$(VCLLIB)			\
+	$(UNOTOOLSLIB)		\
+	$(TOOLSLIB)			\
+	$(COMPHELPERLIB)	\
+	$(CPPUHELPERLIB)	\
+	$(CPPULIB)			\
+	$(SALLIB)			\
+	$(LIBXML)
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+.INCLUDE : _cppunit.mk 
+
+# --- Special ------------------------------------------------------
+
+TESTFILES=\
+	anarchist.svg \
+	anarchist2.svg \
+	Nested.svg
+
+$(MISC)$/%_svgi_unittest_succeeded : $(BIN)$/svg2odf
+    rm -f $(MISC)$/$(@:s/_succeeded/.xml/:f)
+	$(BIN)$/svg2odf $(@:s/_svgi_unittest_succeeded/.svg/:f) $(MISC)$/$(@:s/_succeeded/.xml/:f) $(BIN)$/svgi_unittest_test.ini
+	$(TOUCH) $@
+
+.IF "$(GUI)" == "WNT"
+SAXPARSERLIB=$(SOLARBINDIR)$/sax.uno$(DLLPOST)
+UNOXMLLIB=$(SOLARBINDIR)$/$(DLLPRE)unoxml$(OFFICEUPD)$(DLLPOSTFIX)$(DLLPOST)
+.ELSE
+SAXPARSERLIB=$(SOLARLIBDIR)$/sax.uno$(DLLPOST)
+UNOXMLLIB=$(SOLARLIBDIR)$/$(DLLPRE)unoxml$(OFFICEUPD)$(DLLPOSTFIX)$(DLLPOST)
+.ENDIF
+
+$(BIN)$/unittestservices.rdb : makefile.mk $(SAXPARSERLIB) $(UNOXMLLIB)
+    rm -f $@
+	$(REGCOMP) -register -r $@ -c $(SAXPARSERLIB)
+	$(REGCOMP) -register -r $@ -c $(UNOXMLLIB)
+
+$(BIN)$/svgi_unittest_test.ini : makefile.mk
+	rm -f $@
+	@echo UNO_SERVICES=$(BIN)$/unittestservices.rdb > $@
+	@echo UNO_TYPES=$(UNOUCRRDB:s/\/\\/) >> $@
+
+ALLTAR : $(BIN)$/svgi_unittest_test.ini \
+		 $(BIN)$/unittestservices.rdb \
+         $(foreach,i,$(TESTFILES:s/.svg/_svgi_unittest_succeeded/:f) $(MISC)$/$i)
diff -ruN OOO310_m6.orig/filter/source/svg/test/odfserializer.cxx OOO310_m6/filter/source/svg/test/odfserializer.cxx
--- OOO310_m6.orig/filter/source/svg/test/odfserializer.cxx	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/test/odfserializer.cxx	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,140 @@
+/*************************************************************************
+ *
+ *    OpenOffice.org - a multi-platform office productivity suite
+ *
+ *    Author:
+ *      Fridrich Strba  <fridrich.strba@bluewin.ch>
+ *      Thorsten Behrens <tbehrens@novell.com>	   	
+ *
+ *      Copyright (C) 2008, Novell Inc.
+ *      Parts copyright 2005 by Sun Microsystems, Inc.
+ *
+ *   The Contents of this file are made available subject to
+ *   the terms of GNU Lesser General Public License Version 2.1.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_filter.hxx"
+
+#include "odfserializer.hxx"
+#include <osl/diagnose.h>
+#include <rtl/ustrbuf.hxx>
+#include <cppuhelper/compbase1.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <boost/noncopyable.hpp>
+
+using namespace ::com::sun::star;
+
+namespace svgi
+{
+
+typedef ::cppu::WeakComponentImplHelper1< 
+    com::sun::star::xml::sax::XDocumentHandler> ODFSerializerBase;
+
+class ODFSerializer : private cppu::BaseMutex,
+                public ODFSerializerBase,
+                boost::noncopyable
+{
+public:
+    explicit ODFSerializer(const uno::Reference<io::XOutputStream>& xOut) :
+        ODFSerializerBase(m_aMutex),
+        m_xOutStream(xOut),
+        m_aLineFeed(1),
+        m_aBuf()
+    {
+        m_aLineFeed[0] = '\n';
+    }
+
+    virtual void SAL_CALL startDocument(  ) throw (xml::sax::SAXException, uno::RuntimeException);
+    virtual void SAL_CALL endDocument(  ) throw (xml::sax::SAXException, uno::RuntimeException);
+    virtual void SAL_CALL startElement( const ::rtl::OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs ) throw (xml::sax::SAXException, uno::RuntimeException);
+    virtual void SAL_CALL endElement( const ::rtl::OUString& aName ) throw (xml::sax::SAXException, uno::RuntimeException);
+    virtual void SAL_CALL characters( const ::rtl::OUString& aChars ) throw (xml::sax::SAXException, uno::RuntimeException);
+    virtual void SAL_CALL ignorableWhitespace( const ::rtl::OUString& aWhitespaces ) throw (xml::sax::SAXException, uno::RuntimeException);
+    virtual void SAL_CALL processingInstruction( const ::rtl::OUString& aTarget, const ::rtl::OUString& aData ) throw (xml::sax::SAXException, uno::RuntimeException);
+    virtual void SAL_CALL setDocumentLocator( const uno::Reference< xml::sax::XLocator >& xLocator ) throw (xml::sax::SAXException, uno::RuntimeException);
+
+private:
+    uno::Reference<io::XOutputStream> m_xOutStream;
+    uno::Sequence<sal_Int8>           m_aLineFeed;
+    uno::Sequence<sal_Int8>           m_aBuf;
+};
+
+void SAL_CALL ODFSerializer::startDocument(  ) throw (xml::sax::SAXException, uno::RuntimeException)
+{
+    OSL_PRECOND(m_xOutStream.is(), "ODFSerializer(): invalid output stream");
+
+    rtl::OUStringBuffer aElement;
+    aElement.appendAscii("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+    characters(aElement.makeStringAndClear());
+}
+
+void SAL_CALL ODFSerializer::endDocument() throw (xml::sax::SAXException, uno::RuntimeException)
+{}
+
+void SAL_CALL ODFSerializer::startElement( const ::rtl::OUString& aName, 
+                                           const uno::Reference< xml::sax::XAttributeList >& xAttribs ) throw (xml::sax::SAXException, uno::RuntimeException)
+{
+    rtl::OUStringBuffer aElement;
+    aElement.appendAscii("<");
+    aElement.append(aName);
+    aElement.appendAscii(" ");
+
+    const sal_Int16 nLen=xAttribs->getLength();
+    for( sal_Int16 i=0; i<nLen; ++i )
+    {
+        rtl::OUStringBuffer aAttribute;
+        aElement.append(xAttribs->getNameByIndex(i));
+        aElement.appendAscii("=\"");
+        aElement.append(xAttribs->getValueByIndex(i));
+        aElement.appendAscii("\" ");
+    }
+
+    aElement.appendAscii(">");
+    characters(aElement.makeStringAndClear());
+}
+
+void SAL_CALL ODFSerializer::endElement( const ::rtl::OUString& aName ) throw (xml::sax::SAXException, uno::RuntimeException)
+{
+    rtl::OUStringBuffer aElement;
+    aElement.appendAscii("</");
+    aElement.append(aName);
+    aElement.appendAscii(">");
+    characters(aElement.makeStringAndClear());
+}
+
+void SAL_CALL ODFSerializer::characters( const ::rtl::OUString& aChars ) throw (xml::sax::SAXException, uno::RuntimeException)
+{
+    const rtl::OString aStr = rtl::OUStringToOString(aChars,
+                                                     RTL_TEXTENCODING_UTF8);
+    const sal_Int32 nLen( aStr.getLength() );
+    m_aBuf.realloc( nLen );
+    const sal_Char* pStr = aStr.getStr();
+    std::copy(pStr,pStr+nLen,m_aBuf.getArray());
+
+    m_xOutStream->writeBytes(m_aBuf);
+    // TODO(F1): Make pretty printing configurable
+    m_xOutStream->writeBytes(m_aLineFeed);
+}
+
+void SAL_CALL ODFSerializer::ignorableWhitespace( const ::rtl::OUString& aWhitespaces ) throw (xml::sax::SAXException, uno::RuntimeException)
+{
+    // TODO(F1): Make pretty printing configurable
+    characters(aWhitespaces);
+}
+
+void SAL_CALL ODFSerializer::processingInstruction( const ::rtl::OUString&, 
+                                                    const ::rtl::OUString& ) throw (xml::sax::SAXException, uno::RuntimeException)
+{}
+
+void SAL_CALL ODFSerializer::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& ) throw (xml::sax::SAXException, uno::RuntimeException)
+{}
+
+uno::Reference< xml::sax::XDocumentHandler> createSerializer(const uno::Reference<io::XOutputStream>& xOut )
+{
+    return uno::Reference<xml::sax::XDocumentHandler>(new ODFSerializer(xOut));
+}
+
+}
diff -ruN OOO310_m6.orig/filter/source/svg/test/odfserializer.hxx OOO310_m6/filter/source/svg/test/odfserializer.hxx
--- OOO310_m6.orig/filter/source/svg/test/odfserializer.hxx	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/test/odfserializer.hxx	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,31 @@
+/*************************************************************************
+ *
+ *    OpenOffice.org - a multi-platform office productivity suite
+ *
+ *    Author:
+ *      Fridrich Strba  <fridrich.strba@bluewin.ch>
+ *      Thorsten Behrens <tbehrens@novell.com>	   	
+ *
+ *      Copyright (C) 2008, Novell Inc.
+ *      Parts copyright 2005 by Sun Microsystems, Inc.
+ *
+ *   The Contents of this file are made available subject to
+ *   the terms of GNU Lesser General Public License Version 2.1.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_SVG_ODFSERIALIZER_HXX
+#define INCLUDED_SVG_ODFSERIALIZER_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+
+namespace svgi
+{
+    /// Creates a XDocumentHandler that serializes directly to an XOutputStream
+    ::com::sun::star::uno::Reference< com::sun::star::xml::sax::XDocumentHandler>
+        createSerializer(const ::com::sun::star::uno::Reference<com::sun::star::io::XOutputStream>& );
+}
+
+#endif // _COM_SUN_STAR_XML_SAX_XDOCUMENTHANDLER_HDL_
diff -ruN OOO310_m6.orig/filter/source/svg/test/parsertest.cxx OOO310_m6/filter/source/svg/test/parsertest.cxx
--- OOO310_m6.orig/filter/source/svg/test/parsertest.cxx	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/test/parsertest.cxx	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,210 @@
+/*************************************************************************
+ *
+ *    OpenOffice.org - a multi-platform office productivity suite
+ *
+ *    Author:
+ *      Fridrich Strba  <fridrich.strba@bluewin.ch>
+ *      Thorsten Behrens <tbehrens@novell.com>	   	
+ *
+ *      Copyright (C) 2008, Novell Inc.
+ *
+ *   The Contents of this file are made available subject to
+ *   the terms of GNU Lesser General Public License Version 2.1.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_filter.hxx"
+
+#include <cppunit/simpleheader.hxx>
+
+#include "../gfxtypes.hxx"
+#include "../parserfragments.hxx"
+
+using namespace svgi;
+
+class TestParser : public CppUnit::TestFixture
+{
+public:
+    void setUp()
+    {}
+
+    void tearDown()
+    {}
+
+    void testParseColor()
+    {
+        ARGBColor aTmp;
+
+        const char* sIn="#102030  ";
+        ARGBColor aOut(16, 32, 48);
+        CPPUNIT_ASSERT_MESSAGE( "Consuming color #112233",
+                                parseColor( sIn, aTmp ) );
+        OSL_TRACE("color is: a:%f r:%f g:%f b:%f", aTmp.a, aTmp.r, aTmp.g, aTmp.b);
+        CPPUNIT_ASSERT_MESSAGE( "Parsing color #112233",
+                                aOut==aTmp );
+
+        sIn="  #321";
+        aOut=ARGBColor(51, 34, 17);
+        CPPUNIT_ASSERT_MESSAGE( "Consuming color #321",
+                                parseColor( sIn, aTmp ) );
+        OSL_TRACE("color is: a:%f r:%f g:%f b:%f", aTmp.a, aTmp.r, aTmp.g, aTmp.b);
+        CPPUNIT_ASSERT_MESSAGE( "Parsing color #321",
+                                aOut==aTmp );
+
+        sIn="rgb(100,200,\t 50)";
+        aOut=ARGBColor(100, 200, 50);
+        CPPUNIT_ASSERT_MESSAGE( "Consuming color rgb(100,200,50)",
+                                parseColor( sIn, aTmp ) );
+        OSL_TRACE("color is: a:%f r:%f g:%f b:%f", aTmp.a, aTmp.r, aTmp.g, aTmp.b);
+        CPPUNIT_ASSERT_MESSAGE( "Parsing color rgb(100,200,50)",
+                                aOut==aTmp );
+
+        sIn="rgb(0.1, \t0.2,0.9)";
+        aOut=ARGBColor(0.1, 0.2, 0.9);
+        CPPUNIT_ASSERT_MESSAGE( "Consuming color rgb(0.1,0.2,0.9)",
+                                parseColor( sIn, aTmp ) );
+        OSL_TRACE("color is: a:%f r:%f g:%f b:%f", aTmp.a, aTmp.r, aTmp.g, aTmp.b);
+        CPPUNIT_ASSERT_MESSAGE( "Parsing color rgb(0.1,0.2,0.9)",
+                                aOut==aTmp );
+
+        sIn=" burlywood ";
+        aOut=ARGBColor(222,184,135);
+        CPPUNIT_ASSERT_MESSAGE( "Consuming color burlywood",
+                                parseColor( sIn, aTmp ) );
+        OSL_TRACE("color is: a:%f r:%f g:%f b:%f", aTmp.a, aTmp.r, aTmp.g, aTmp.b);
+        CPPUNIT_ASSERT_MESSAGE( "Parsing color burlywood",
+                                aOut==aTmp );
+    }
+
+    void testParseOpacity()
+    {
+        ARGBColor aTmp;
+
+        const char* sIn=" 0.123  ";
+        ARGBColor aOut(0.123, 0.0, 0.0, 0.0);
+        CPPUNIT_ASSERT_MESSAGE( "Consuming opacity 0.123",
+                                parseOpacity( sIn, aTmp ) );
+        OSL_TRACE("color is: a:%f r:%f g:%f b:%f", aTmp.a, aTmp.r, aTmp.g, aTmp.b);
+        CPPUNIT_ASSERT_MESSAGE( "Parsing opacity 0.123",
+                                aOut==aTmp );
+    }
+
+    void testParseTransform()
+    {
+        basegfx::B2DHomMatrix aOut;
+
+        const char* sIn=" none  ";
+        basegfx::B2DHomMatrix aTmp;
+        CPPUNIT_ASSERT_MESSAGE( "Consuming transformation none",
+                                parseTransform( sIn, aTmp ) );
+        OSL_TRACE("transformation is: m00:%f m01:%f m02:%f m10:%f m11:%f m12:%f", 
+                  aTmp.get(0,0), aTmp.get(0,1), aTmp.get(0,2), aTmp.get(1,0), aTmp.get(1,1), aTmp.get(1,2) );
+        CPPUNIT_ASSERT_MESSAGE( "Parsing transformation none",
+                                aOut==aTmp );
+
+        sIn=" scale( 10 )  ";
+        aOut.identity();
+        aOut.scale(10.0,10.0);
+        CPPUNIT_ASSERT_MESSAGE( "Consuming transformation scale(10)",
+                                parseTransform( sIn, aTmp ) );
+        OSL_TRACE("transformation is: m00:%f m01:%f m02:%f m10:%f m11:%f m12:%f", 
+                  aTmp.get(0,0), aTmp.get(0,1), aTmp.get(0,2), aTmp.get(1,0), aTmp.get(1,1), aTmp.get(1,2) );
+        CPPUNIT_ASSERT_MESSAGE( "Parsing transformation scale(10)",
+                                aOut==aTmp );
+
+        sIn=" scale( 10 20.12 )  ";
+        aOut.identity();
+        aOut.scale(10.0,20.12);
+        CPPUNIT_ASSERT_MESSAGE( "Consuming transformation scale(10 20.12)",
+                                parseTransform( sIn, aTmp ) );
+        OSL_TRACE("transformation is: m00:%f m01:%f m02:%f m10:%f m11:%f m12:%f", 
+                  aTmp.get(0,0), aTmp.get(0,1), aTmp.get(0,2), aTmp.get(1,0), aTmp.get(1,1), aTmp.get(1,2) );
+        CPPUNIT_ASSERT_MESSAGE( "Parsing transformation scale(10 20.12)",
+                                aOut==aTmp );
+
+        sIn="matrix( 1,2 3,4,5 6 )";
+        aOut.identity();
+        aOut.set(0,0,1.0); aOut.set(1,0,2.0); aOut.set(0,1,3.0); aOut.set(1,1,4.0); aOut.set(0,2,5.0); aOut.set(1,2,6.0);
+        CPPUNIT_ASSERT_MESSAGE( "Consuming transformation matrix(1,2,3,4,5,6)",
+                                parseTransform( sIn, aTmp ) );
+        OSL_TRACE("transformation is: m00:%f m01:%f m02:%f m10:%f m11:%f m12:%f", 
+                  aTmp.get(0,0), aTmp.get(0,1), aTmp.get(0,2), aTmp.get(1,0), aTmp.get(1,1), aTmp.get(1,2) );
+        CPPUNIT_ASSERT_MESSAGE( "Parsing transformation matrix(1,2,3,4,5,6)",
+                                aOut==aTmp );
+
+        sIn="matrix( 1 0 0 1 -10 -10 ) translate(10) scale(10), rotate(90)";
+        aOut.identity();
+        aOut.set(0,0,0.0); aOut.set(1,0,10.0); aOut.set(0,1,-10.0); aOut.set(1,1,0.0); aOut.set(0,2,0.0); aOut.set(1,2,0.0);
+        CPPUNIT_ASSERT_MESSAGE( "Consuming transformation matrix(1,2,3,4,5,6)",
+                                parseTransform( sIn, aTmp ) );
+        OSL_TRACE("transformation is: m00:%f m01:%f m02:%f m10:%f m11:%f m12:%f", 
+                  aTmp.get(0,0), aTmp.get(0,1), aTmp.get(0,2), aTmp.get(1,0), aTmp.get(1,1), aTmp.get(1,2) );
+        CPPUNIT_ASSERT_MESSAGE( "Parsing transformation matrix(1,2,3,4,5,6)",
+                                aOut==aTmp );
+
+        sIn="skewX(45)";
+        aOut.identity();
+        aOut.set(0,0,1.0); aOut.set(1,0,1.0); aOut.set(0,1,0.0); aOut.set(1,1,1.0); aOut.set(0,2,0.0); aOut.set(1,2,0.0);
+        CPPUNIT_ASSERT_MESSAGE( "Consuming transformation skewX(45)",
+                                parseTransform( sIn, aTmp ) );
+        OSL_TRACE("transformation is: m00:%f m01:%f m02:%f m10:%f m11:%f m12:%f", 
+                  aTmp.get(0,0), aTmp.get(0,1), aTmp.get(0,2), aTmp.get(1,0), aTmp.get(1,1), aTmp.get(1,2) );
+        CPPUNIT_ASSERT_MESSAGE( "Parsing transformation skewX(45)",
+                                aOut==aTmp );
+
+        sIn="skewY(45)";
+        aOut.identity();
+        aOut.set(0,0,1.0); aOut.set(1,0,0.0); aOut.set(0,1,1.0); aOut.set(1,1,1.0); aOut.set(0,2,0.0); aOut.set(1,2,0.0);
+        CPPUNIT_ASSERT_MESSAGE( "Consuming transformation skewY(45)",
+                                parseTransform( sIn, aTmp ) );
+        OSL_TRACE("transformation is: m00:%f m01:%f m02:%f m10:%f m11:%f m12:%f", 
+                  aTmp.get(0,0), aTmp.get(0,1), aTmp.get(0,2), aTmp.get(1,0), aTmp.get(1,1), aTmp.get(1,2) );
+        CPPUNIT_ASSERT_MESSAGE( "Parsing transformation skewY(45)",
+                                aOut==aTmp );
+    }
+
+    void testParseViewBox()
+    {
+        basegfx::B2DRange aTmp;
+
+        const char* sIn=" 10 20, 30.5,5  ";
+        basegfx::B2DRange aOut(10,20,40.5,25);
+        CPPUNIT_ASSERT_MESSAGE( "Consuming 10,20,30.5,5",
+                                parseViewBox( sIn, aTmp ) );
+        OSL_TRACE("viewbox is: x1:%f y1:%f x2:%f y2:%f", aTmp.getMinX(), aTmp.getMinY(), aTmp.getMaxX(), aTmp.getMaxY());
+        CPPUNIT_ASSERT_MESSAGE( "Parsing 10,20,30.5,5",
+                                aOut==aTmp );
+    }
+
+    void testParseDashArray()
+    {
+        std::vector<double> aTmp;
+
+        const char* sIn=" 10,20, -10.00  ";
+        std::vector<double> aOut; aOut.push_back(10.0); aOut.push_back(20.0); aOut.push_back(-10.0);
+        CPPUNIT_ASSERT_MESSAGE( "Consuming 10,20,-10.00",
+                                parseDashArray( sIn, aTmp ) );
+        OSL_TRACE("dash array is: len %d, %f %f %f", aTmp.size(), aTmp[0], aTmp[1], aTmp[2] );
+        CPPUNIT_ASSERT_MESSAGE( "Parsing 10,20,-10.00",
+                                aOut==aTmp );
+    }
+
+    CPPUNIT_TEST_SUITE(TestParser);
+    CPPUNIT_TEST(testParseColor);
+    CPPUNIT_TEST(testParseOpacity);
+    CPPUNIT_TEST(testParseTransform);
+    CPPUNIT_TEST(testParseViewBox);
+    CPPUNIT_TEST(testParseDashArray);
+    // TODO: CPPUNIT_TEST(testParseXlinkHref);
+    CPPUNIT_TEST_SUITE_END();
+};
+
+// -----------------------------------------------------------------------------
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(TestParser, "test svg parser fragments");
+
+// this macro creates an empty function, which will called by the RegisterAllFunctions()
+// to let the user the possibility to also register some functions by hand.
+NOADDITIONAL;
+
diff -ruN OOO310_m6.orig/filter/source/svg/test/svg2odf.cxx OOO310_m6/filter/source/svg/test/svg2odf.cxx
--- OOO310_m6.orig/filter/source/svg/test/svg2odf.cxx	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/test/svg2odf.cxx	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,124 @@
+/*************************************************************************
+ *
+ *    OpenOffice.org - a multi-platform office productivity suite
+ *
+ *    Author:
+ *      Fridrich Strba  <fridrich.strba@bluewin.ch>
+ *      Thorsten Behrens <tbehrens@novell.com>	   	
+ *
+ *      Copyright (C) 2008, Novell Inc.
+ *      Parts copyright 2005 by Sun Microsystems, Inc.
+ *
+ *   The Contents of this file are made available subject to
+ *   the terms of GNU Lesser General Public License Version 2.1.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_filter.hxx"
+
+#include "../svgreader.hxx" 
+#include "odfserializer.hxx" 
+
+#include <sal/main.h>
+#include <osl/file.hxx>
+#include <osl/process.h>
+#include <rtl/bootstrap.hxx>
+
+#include <cppuhelper/implbase1.hxx>
+#include <cppuhelper/bootstrap.hxx>
+#include <cppuhelper/servicefactory.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/oslfile2streamwrap.hxx>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+    class OutputWrap : public cppu::WeakImplHelper1<
+        io::XOutputStream>
+    {
+        osl::File maFile;
+
+    public:
+
+        explicit OutputWrap( const rtl::OUString& rURL ) : maFile(rURL) 
+        {
+            maFile.open(osl_File_OpenFlag_Create|OpenFlag_Write);
+        }
+
+		virtual void SAL_CALL writeBytes( const com::sun::star::uno::Sequence< ::sal_Int8 >& aData ) throw (com::sun::star::io::NotConnectedException,com::sun::star::io::BufferSizeExceededException, com::sun::star::io::IOException, com::sun::star::uno::RuntimeException)
+
+        {
+            sal_uInt64 nBytesWritten(0);
+            maFile.write(aData.getConstArray(),aData.getLength(),nBytesWritten);
+        }
+
+        virtual void SAL_CALL flush() throw (com::sun::star::io::NotConnectedException, com::sun::star::io::BufferSizeExceededException, com::sun::star::io::IOException, com::sun::star::uno::RuntimeException)
+        {
+        }
+
+        virtual void SAL_CALL closeOutput() throw (com::sun::star::io::NotConnectedException, com::sun::star::io::BufferSizeExceededException, com::sun::star::io::IOException, com::sun::star::uno::RuntimeException)
+        {
+            maFile.close();
+        }
+    };
+}
+
+SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv)
+{
+	if( argc != 4 )
+    {
+        OSL_TRACE( "Invocation: svg2odf <base_url> <dst_url> <ini_file>. Exiting" );
+		return 1;
+    }
+
+	::rtl::OUString aBaseURL, aTmpURL, aSrcURL, aDstURL, aIniUrl;
+    
+    osl_getProcessWorkingDir(&aBaseURL.pData);
+    osl_getFileURLFromSystemPath( rtl::OUString::createFromAscii(argv[1]).pData,
+                                  &aTmpURL.pData );
+    osl_getAbsoluteFileURL(aBaseURL.pData,aTmpURL.pData,&aSrcURL.pData);
+
+    osl_getFileURLFromSystemPath( rtl::OUString::createFromAscii(argv[2]).pData,
+                                  &aTmpURL.pData );
+    osl_getAbsoluteFileURL(aBaseURL.pData,aTmpURL.pData,&aDstURL.pData);
+
+	osl_getFileURLFromSystemPath( rtl::OUString::createFromAscii(argv[3]).pData, 
+								&aTmpURL.pData );
+    osl_getAbsoluteFileURL(aBaseURL.pData,aTmpURL.pData,&aIniUrl.pData);
+
+    // bootstrap UNO
+    uno::Reference< lang::XMultiServiceFactory > xFactory;
+    uno::Reference< uno::XComponentContext > xCtx;
+    try
+    {
+        xCtx = ::cppu::defaultBootstrap_InitialComponentContext(aIniUrl);
+        xFactory = uno::Reference< lang::XMultiServiceFactory >(xCtx->getServiceManager(), 
+                                                                uno::UNO_QUERY);
+        if( xFactory.is() )
+            ::comphelper::setProcessServiceFactory( xFactory );
+    }
+    catch( uno::Exception& )
+    {
+    }
+
+    if( !xFactory.is() )
+    {
+        OSL_TRACE( "Could not bootstrap UNO, installation must be in disorder. Exiting." );
+        return 1;
+    }
+
+    osl::File aInputFile(aSrcURL);
+    if( osl::FileBase::E_None!=aInputFile.open(OpenFlag_Read) )
+    {
+        OSL_TRACE( "Cannot open input file" );
+        return 1;
+    }
+
+    svgi::SVGReader aReader(xFactory, 
+                            uno::Reference<io::XInputStream>(
+                                new comphelper::OSLInputStreamWrapper(aInputFile)),
+                            svgi::createSerializer(new OutputWrap(aDstURL)));
+    return aReader.parseAndConvert() ? 0 : 1;
+}
diff -ruN OOO310_m6.orig/filter/source/svg/tokenmap.cxx OOO310_m6/filter/source/svg/tokenmap.cxx
--- OOO310_m6.orig/filter/source/svg/tokenmap.cxx	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/tokenmap.cxx	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,62 @@
+/*************************************************************************
+ *
+ *    OpenOffice.org - a multi-platform office productivity suite
+ *
+ *    Author:
+ *      Fridrich Strba  <fridrich.strba@bluewin.ch>
+ *      Thorsten Behrens <tbehrens@novell.com>	   	
+ *
+ *      Copyright (C) 2008, Novell Inc.
+ *      Parts copyright 2005 by Sun Microsystems, Inc.
+ *
+ *   The Contents of this file are made available subject to
+ *   the terms of GNU Lesser General Public License Version 2.1.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_filter.hxx"
+
+#include "tokenmap.hxx"
+#include <string.h>
+
+namespace svgi 
+{
+
+#include "tokens.cxx"
+
+sal_Int32 getTokenId( const char* sIdent, sal_Int32 nLen )
+{
+	const struct xmltoken* t = Perfect_Hash::in_word_set( sIdent, nLen );
+	if( t )
+		return t->nToken;
+	else
+		return XML_TOKEN_INVALID;
+}
+
+sal_Int32 getTokenId( const rtl::OUString& sIdent )
+{
+	rtl::OString aUTF8( sIdent.getStr(), 
+                        sIdent.getLength(), 
+                        RTL_TEXTENCODING_UTF8 );
+    return getTokenId( aUTF8.getStr(), aUTF8.getLength() );
+}
+
+const char* getTokenName( sal_Int32 nTokenId )
+{
+	if( nTokenId >= XML_TOKEN_COUNT )
+		return NULL;
+
+    const xmltoken* pCurr=wordlist;
+    const xmltoken* pEnd=wordlist+sizeof(wordlist)/sizeof(*wordlist);
+    while( pCurr != pEnd )
+    {
+        if(pCurr->nToken == nTokenId)
+            return pCurr->name;
+        ++pCurr;
+    }
+
+    return NULL;
+}
+
+} // namespace svgi
diff -ruN OOO310_m6.orig/filter/source/svg/tokenmap.hxx OOO310_m6/filter/source/svg/tokenmap.hxx
--- OOO310_m6.orig/filter/source/svg/tokenmap.hxx	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/tokenmap.hxx	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,32 @@
+/*************************************************************************
+ *
+ *    OpenOffice.org - a multi-platform office productivity suite
+ *
+ *    Author:
+ *      Fridrich Strba  <fridrich.strba@bluewin.ch>
+ *      Thorsten Behrens <tbehrens@novell.com>	   	
+ *
+ *      Copyright (C) 2008, Novell Inc.
+ *
+ *   The Contents of this file are made available subject to
+ *   the terms of GNU Lesser General Public License Version 2.1.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_TOKENMAP_HXX
+#define INCLUDED_TOKENMAP_HXX
+
+#include "tokens.hxx"
+
+#include <rtl/string.hxx>
+#include <rtl/ustring.hxx>
+
+namespace svgi
+{
+    sal_Int32   getTokenId( const char* sIdent, sal_Int32 nLen );
+    sal_Int32   getTokenId( const rtl::OUString& sIdent );
+    const char* getTokenName( sal_Int32 nTokenId );
+
+} // namespace svgi
+
+#endif
diff -ruN OOO310_m6.orig/filter/source/svg/tokens.txt OOO310_m6/filter/source/svg/tokens.txt
--- OOO310_m6.orig/filter/source/svg/tokens.txt	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/tokens.txt	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,403 @@
+#######################################
+#
+# elements (SVG Tiny 1.2)
+#
+#######################################
+a
+animate
+animateColor
+animateMotion
+animateTransform
+animation
+audio
+circle
+defs
+desc
+discard
+ellipse
+font
+font-face
+font-face-src
+font-face-uri
+foreignObject
+g
+glyph
+handler
+hkern
+image
+line
+linearGradient
+listener
+metadata
+missing-glyph
+mpath
+path
+polygon
+polyline
+prefetch
+radialGradient
+rect
+script
+set
+solidColor
+stop
+svg
+switch
+tbreak
+text
+textArea
+title
+tspan
+use
+video
+#######################################
+#
+# properties (SVG Tiny 1.2)
+#
+#######################################
+audio-level
+color
+color-rendering
+display
+display-align
+fill
+fill-opacity
+fill-rule
+font-family
+font-size
+font-style
+font-variant
+font-weight
+image-rendering
+line-increment
+opacity
+pointer-events
+shape-rendering
+solid-color
+solid-opacity
+stop-color
+stop-opacity
+stroke
+stroke-dasharray
+stroke-dashoffset
+stroke-linecap
+stroke-linejoin
+stroke-miterlimit
+stroke-opacity
+stroke-width
+text-align
+text-anchor
+text-rendering
+vector-effect
+viewport-fill
+viewport-fill-opacity
+visibility
+#######################################
+#
+# attributes (SVG Tiny 1.2)
+#
+#######################################
+accent-height
+accumulate
+additive
+alphabetic
+arabic-form
+ascent
+attributeName
+attributeType
+bandwidth
+baseProfile
+bbox
+begin
+by
+calcMode
+cap-height
+class
+contentScriptType
+cx
+cy
+d
+defaultAction
+descent
+dur
+editable
+end
+event
+externalResourcesRequired
+fill
+focusHighlight
+focusable
+font-family
+font-stretch
+font-style
+font-variant
+font-weight
+from
+fx
+fy
+g1
+g2
+glyph-name
+gradientTransform
+gradientUnits
+handler
+hanging
+height
+height
+horiz-adv-x
+horiz-origin-x
+id
+ideographic
+initialVisibility
+k
+keyPoints
+keySplines
+keyTimes
+lang
+mathematical
+max
+mediaCharacterEncoding
+mediaContentEncodings
+mediaSize
+mediaTime
+min
+nav-down
+nav-down-left
+nav-down-right
+nav-left
+nav-next
+nav-prev
+nav-right
+nav-up
+nav-up-left
+nav-up-right
+observer
+offset
+origin
+overlay
+overline-position
+overline-thickness
+panose-1
+path
+pathLength
+phase
+playbackOrder
+points
+preserveAspectRatio
+propagate
+r
+repeatCount
+repeatDur
+requiredExtensions
+requiredFeatures
+requiredFonts
+requiredFormats
+restart
+rotate
+rx
+ry
+slope
+snapshotTime
+stemh
+stemv
+strikethrough-position
+strikethrough-thickness
+style
+syncBehavior
+syncBehaviorDefault
+syncMaster
+syncTolerance
+syncToleranceDefault
+systemLanguage
+target
+timelineBegin
+to
+transform
+transformBehavior
+type
+u1
+u2
+underline-position
+underline-thickness
+unicode
+unicode-range
+units-per-em
+values
+version
+viewBox
+width
+widths
+x
+x-height
+x1
+x2
+actuate
+arcrole
+href
+role
+show
+base
+space
+y
+y1
+y2
+zoomAndPan
+#######################################
+#
+# colour values
+#
+#######################################
+aliceblue
+antiquewhite
+aqua
+aquamarine
+azure
+beige
+bisque
+black
+blanchedalmond
+blue
+blueviolet
+brown
+burlywood
+cadetblue
+chartreuse
+chocolate
+coral
+cornflowerblue
+cornsilk
+crimson
+cyan
+darkblue
+darkcyan
+darkgoldenrod
+darkgray
+darkgreen
+darkgrey
+darkkhaki
+darkmagenta
+darkolivegreen
+darkorange
+darkorchid
+darkred
+darksalmon
+darkseagreen
+darkslateblue
+darkslategray
+darkslategrey
+darkturquoise
+darkviolet
+deeppink
+deepskyblue
+dimgray
+dimgrey
+dodgerblue
+firebrick
+floralwhite
+forestgreen
+fuchsia
+gainsboro
+ghostwhite
+gold
+goldenrod
+gray
+grey
+green
+greenyellow
+honeydew
+hotpink
+indianred
+indigo
+ivory
+khaki
+lavender
+lavenderblush
+lawngreen
+lemonchiffon
+lightblue
+lightcoral
+lightcyan
+lightgoldenrodyellow
+lightgray
+lightgreen
+lightgrey
+lightpink
+lightsalmon
+lightseagreen
+lightskyblue
+lightslategray
+lightslategrey
+lightsteelblue
+lightyellow
+lime
+limegreen
+linen
+magenta
+maroon
+mediumaquamarine
+mediumblue
+mediumorchid
+mediumpurple
+mediumseagreen
+mediumslateblue
+mediumspringgreen
+mediumturquoise
+mediumvioletred
+midnightblue
+mintcream
+mistyrose
+moccasin
+navajowhite
+navy
+oldlace
+olive
+olivedrab
+orange
+orangered
+orchid
+palegoldenrod
+palegreen
+paleturquoise
+palevioletred
+papayawhip
+peachpuff
+peru
+pink
+plum
+powderblue
+purple
+red
+rosybrown
+royalblue
+saddlebrown
+salmon
+sandybrown
+seagreen
+seashell
+sienna
+silver
+skyblue
+slateblue
+slategray
+slategrey
+snow
+springgreen
+steelblue
+tan
+teal
+thistle
+tomato
+turquoise
+violet
+wheat
+white
+whitesmoke
+yellow
+yellowgreen
+#######################################
+#
+# Gradient units values
+#
+#######################################
+userSpaceOnUse
+objectBoundingBox
diff -ruN OOO310_m6.orig/filter/source/svg/units.cxx OOO310_m6/filter/source/svg/units.cxx
--- OOO310_m6.orig/filter/source/svg/units.cxx	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/units.cxx	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,99 @@
+/*************************************************************************
+ *
+ *    OpenOffice.org - a multi-platform office productivity suite
+ *
+ *    Author:
+ *      Jan Holesovsky   <kendy@suse.cz>
+ *      Fridrich Strba   <fridrich.strba@bluewin.ch>
+ *      Thorsten Behrens <tbehrens@novell.com>	   	
+ *
+ *      Copyright (C) 2008, Novell Inc.
+ *
+ *   The Contents of this file are made available subject to
+ *   the terms of GNU Lesser General Public License Version 2.1.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_filter.hxx"
+
+#include "units.hxx"
+#include "gfxtypes.hxx"
+#include "spirit_supplements.hxx"
+
+#include <string.h>
+#include <rtl/ustring.hxx>
+
+#include <boost/bind.hpp>
+// workaround. spirit uses INT_MAX.
+#include <limits.h>
+#include <boost/spirit.hpp>
+
+
+namespace svgi
+{
+
+double convLength( double value, SvgUnit unit, const State& rState, char dir )
+{
+    const double fBoxLen( dir=='h' ? rState.maViewBox.getWidth() : 
+                          (dir=='v' ? rState.maViewBox.getHeight() : 
+                           rState.maViewBox.getRange().getLength()));
+
+    // convert svg unit to internal coordinates ("pixel"). Since the
+    // OOo drawing layer is still largely integer-based, the initial
+    // viewport transformation includes a certain scale factor
+    double fRet(value);
+    switch ( unit )
+    {
+        case SVG_LENGTH_UNIT_CM: fRet *= 72.0/2.54; break;
+        case SVG_LENGTH_UNIT_IN: fRet *= 72.0; break;
+        case SVG_LENGTH_UNIT_MM: fRet *= 72.0/25.4; break;
+        case SVG_LENGTH_UNIT_PC: fRet *= 72.0/6.0; break;
+		case SVG_LENGTH_UNIT_USER:
+        case SVG_LENGTH_UNIT_PX: // no unit defaults to PX in svg,
+                                 // assume display to have 72DPI
+        case SVG_LENGTH_UNIT_PT: break;
+        case SVG_LENGTH_UNIT_EM: fRet *= rState.mnFontSize; break;
+        case SVG_LENGTH_UNIT_EX: fRet *= rState.mnFontSize / 2.0; break;
+        case SVG_LENGTH_UNIT_PERCENTAGE: fRet *= fBoxLen; break;
+        default: OSL_TRACE( "Unknown length type" ); break;
+    }
+
+    return fRet;
+}
+
+double convLength( const rtl::OUString& sValue, const State& rState, char dir )
+{
+    using namespace ::boost::spirit;
+
+    rtl::OString aUTF8 = rtl::OUStringToOString( sValue, 
+                                                 RTL_TEXTENCODING_UTF8 );  
+
+    double  nVal=0.0;
+    SvgUnit eUnit=SVG_LENGTH_UNIT_PX;
+    const bool bRes = parse(aUTF8.getStr(),
+        //  Begin grammar
+        (
+            real_p[assign_a(nVal)] 
+            >> (  str_p("cm") [assign_a(eUnit,SVG_LENGTH_UNIT_CM)]
+                | str_p("em") [assign_a(eUnit,SVG_LENGTH_UNIT_EM)]
+                | str_p("ex") [assign_a(eUnit,SVG_LENGTH_UNIT_EX)]
+                | str_p("in") [assign_a(eUnit,SVG_LENGTH_UNIT_IN)]
+                | str_p("mm") [assign_a(eUnit,SVG_LENGTH_UNIT_MM)]
+                | str_p("pc") [assign_a(eUnit,SVG_LENGTH_UNIT_PC)]
+                | str_p("pt") [assign_a(eUnit,SVG_LENGTH_UNIT_PT)]
+                | str_p("px") [assign_a(eUnit,SVG_LENGTH_UNIT_PX)]
+                | str_p("%") [assign_a(eUnit,SVG_LENGTH_UNIT_PERCENTAGE)]
+                | str_p("") [assign_a(eUnit,SVG_LENGTH_UNIT_USER)]
+                | end_p)
+        ),
+        //  End grammar
+        space_p).full;
+
+    if( !bRes )
+        return 0.0;
+
+    return convLength(nVal,eUnit,rState,dir);
+}
+
+} // namespace svgi
diff -ruN OOO310_m6.orig/filter/source/svg/units.hxx OOO310_m6/filter/source/svg/units.hxx
--- OOO310_m6.orig/filter/source/svg/units.hxx	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/units.hxx	2009-03-17 14:59:37.000000000 +0000
@@ -0,0 +1,60 @@
+/*************************************************************************
+ *
+ *    OpenOffice.org - a multi-platform office productivity suite
+ *
+ *    Author:
+ *      Jan Holesovsky   <kendy@suse.cz>
+ *      Fridrich Strba   <fridrich.strba@bluewin.ch>
+ *      Thorsten Behrens <tbehrens@novell.com>	   	
+ *
+ *      Copyright (C) 2008, Novell Inc.
+ *
+ *   The Contents of this file are made available subject to
+ *   the terms of GNU Lesser General Public License Version 2.1.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_UNITS_HXX
+#define INCLUDED_UNITS_HXX
+
+#include <sal/config.h>
+
+namespace rtl{ class OUString; }
+namespace svgi
+{
+    struct State;
+    enum SvgUnit
+    {
+        SVG_LENGTH_UNIT_CM,
+        SVG_LENGTH_UNIT_EM,
+        SVG_LENGTH_UNIT_EX,
+        SVG_LENGTH_UNIT_IN,
+        SVG_LENGTH_UNIT_MM,
+        SVG_LENGTH_UNIT_PC,
+        SVG_LENGTH_UNIT_PT,
+        SVG_LENGTH_UNIT_PX,
+        SVG_LENGTH_UNIT_PERCENTAGE,
+		SVG_LENGTH_UNIT_USER
+    };
+
+    /** return svg_length_t in 100th's of mm
+         @param fVal value to convert
+         @param unit unit the value is in
+         @param rState current state (needed for viewport dimensions etc.)
+         @param dir direction - either 'h' or 'v' for horizonal or vertical, resp.
+     */
+    double convLength( double fVal, SvgUnit unit, const State& rState, char dir );
+
+    /** return svg_length_t in 100th's of mm
+         @param sValue value to convert
+         @param rState current state (needed for viewport dimensions etc.)
+         @param dir direction - either 'h' or 'v' for horizonal or vertical, resp.
+     */
+    double convLength( const rtl::OUString& sValue, const State& rState, char dir );
+
+    inline double pt2mm(double fVal) { return fVal*25.4/72.0; }
+    inline double pt100thmm(double fVal) { return fVal*2540.0/72.0; }
+
+} // namespace svgi
+
+#endif
diff -ruN OOO310_m6.orig/filter/source/svg/units.cxx OOO310_m6/filter/source/svg/units.hxx
--- OOO310_m6.orig/filter/source/svg/units.cxx	1970-01-01 01:00:00.000000000 +0100
+++ OOO310_m6/filter/source/svg/units.cxx	2009-03-17 14:59:37.000000000 +0000
@@ -35,10 +35,6 @@
 
 double convLength( double value, SvgUnit unit, const State& rState, char dir )
 {
-    const double fBoxLen( dir=='h' ? rState.maViewBox.getWidth() : 
-                          (dir=='v' ? rState.maViewBox.getHeight() : 
-                           rState.maViewBox.getRange().getLength()));
-
     // convert svg unit to internal coordinates ("pixel"). Since the
     // OOo drawing layer is still largely integer-based, the initial
     // viewport transformation includes a certain scale factor
@@ -55,7 +51,28 @@
         case SVG_LENGTH_UNIT_PT: break;
         case SVG_LENGTH_UNIT_EM: fRet *= rState.mnFontSize; break;
         case SVG_LENGTH_UNIT_EX: fRet *= rState.mnFontSize / 2.0; break;
-        case SVG_LENGTH_UNIT_PERCENTAGE: fRet *= fBoxLen; break;
+        case SVG_LENGTH_UNIT_PERCENTAGE:
+        {
+            double fBoxLen;
+            if (rState.maViewBox.isEmpty())
+            {
+                basegfx::B2DRange aDefaultBox(0, 0,
+                  convLength(210, SVG_LENGTH_UNIT_MM, rState, 'h'), 
+                  convLength(297, SVG_LENGTH_UNIT_MM, rState, 'v'));
+                fBoxLen = (dir=='h' ? aDefaultBox.getWidth() : 
+                          (dir=='v' ? aDefaultBox.getHeight() : 
+                           aDefaultBox.getRange().getLength()));
+            }
+            else
+            {
+                fBoxLen = (dir=='h' ? rState.maViewBox.getWidth() : 
+                          (dir=='v' ? rState.maViewBox.getHeight() : 
+                           rState.maViewBox.getRange().getLength()));
+            }
+
+            fRet *= fBoxLen/100.0;
+        }
+        break;
         default: OSL_TRACE( "Unknown length type" ); break;
     }