You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openoffice.apache.org by al...@apache.org on 2012/01/24 18:13:46 UTC

svn commit: r1235361 - in /incubator/ooo/trunk/main/drawinglayer: inc/drawinglayer/primitive2d/ inc/drawinglayer/processor2d/ source/primitive2d/ source/processor2d/

Author: alg
Date: Tue Jan 24 17:13:46 2012
New Revision: 1235361

URL: http://svn.apache.org/viewvc?rev=1235361&view=rev
Log:
#118829# enhanced Svg gradient quality, obstacles avoided

Modified:
    incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/primitive2d/svggradientprimitive2d.hxx
    incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx
    incubator/ooo/trunk/main/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx
    incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
    incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclprocessor2d.cxx

Modified: incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/primitive2d/svggradientprimitive2d.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/primitive2d/svggradientprimitive2d.hxx?rev=1235361&r1=1235360&r2=1235361&view=diff
==============================================================================
--- incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/primitive2d/svggradientprimitive2d.hxx (original)
+++ incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/primitive2d/svggradientprimitive2d.hxx Tue Jan 24 17:13:46 2012
@@ -35,8 +35,8 @@
 
 namespace drawinglayer
 {
-	namespace primitive2d
-	{
+    namespace primitive2d
+    {
         /// a single GradientStop defining a color and opacity at a distance
         class SvgGradientEntry
         {
@@ -77,7 +77,6 @@ namespace drawinglayer
 
 //////////////////////////////////////////////////////////////////////////////
 // SvgGradientHelper class
-#define DEFAULT_OVERLAPPING_VALUE (1.0/512.0)
 
 namespace drawinglayer
 {
@@ -93,11 +92,11 @@ namespace drawinglayer
         /*  helper for linear and radial gradient, both get derived from this
             to share common definitions and functionality
          **/
-		class SvgGradientHelper
-		{
-		private:
+        class SvgGradientHelper
+        {
+        private:
             /// geometric definition, the geometry to be filled
-			basegfx::B2DPolyPolygon		maPolyPolygon;
+            basegfx::B2DPolyPolygon		maPolyPolygon;
 
             /// the gradient definition
             SvgGradientEntryVector      maGradientEntries;
@@ -108,23 +107,6 @@ namespace drawinglayer
             /// how to spread
             SpreadMethod                maSpreadMethod;
 
-            /*  allows to set an overlapping value to be able to create
-                slightly overlapping PolyPolygons/Polygons for the decomposition.
-                This is needed since when creating geometrically correct decompositions
-                many visualisations will show artefacts at the borders, even when these 
-                borders are absolutely correctly defined. It is possible to define a 
-                useful value for this since the coordinate system we are working in is 
-                in unit coordinates so that the whole gradient is from [0.0 .. 1.0] range.
-                This explains the default value which is 1/512 by a maximum possible
-                color count of 255 steps per GradientStop.
-                Give a 0.0 here to go to geometrically correct gradient decompositions if 
-                needed.
-                An alternative would be to create no PolyPolygons from outside to inside 
-                (example for radial), but this leads to up to 255 filled polygons per 
-                GradientStop and thus to enormous rendering costs.
-             **/
-            double                      mfOverlapping;
-
             /// bitfield
             bool                        mbPreconditionsChecked : 1;
             bool                        mbCreatesContent : 1;
@@ -133,7 +115,7 @@ namespace drawinglayer
 
         protected:
             /// local helpers
-    		Primitive2DSequence createSingleGradientEntryFill() const;
+            Primitive2DSequence createSingleGradientEntryFill() const;
             virtual void createAtom(
                 Primitive2DVector& rTargetColor,
                 Primitive2DVector& rTargetOpacity, 
@@ -161,24 +143,22 @@ namespace drawinglayer
 
         public:
             /// constructor
-			SvgGradientHelper(
-				const basegfx::B2DPolyPolygon& rPolyPolygon,
+            SvgGradientHelper(
+                const basegfx::B2DPolyPolygon& rPolyPolygon,
                 const SvgGradientEntryVector& rGradientEntries,
                 const basegfx::B2DPoint& rStart,
-                SpreadMethod aSpreadMethod = Spread_pad,
-                double fOverlapping = DEFAULT_OVERLAPPING_VALUE);
+                SpreadMethod aSpreadMethod = Spread_pad);
 
-			/// data read access
+            /// data read access
             const basegfx::B2DPolyPolygon& getPolyPolygon() const { return maPolyPolygon; }
             const SvgGradientEntryVector& getGradientEntries() const { return maGradientEntries; }
             const basegfx::B2DPoint& getStart() const { return maStart; }
             SpreadMethod getSpreadMethod() const { return maSpreadMethod; }
-            double getOverlapping() const { return mfOverlapping; }
 
             /// compare operator
-			virtual bool operator==(const SvgGradientHelper& rSvgGradientHelper) const;
-		};
-	} // end of namespace primitive2d
+            virtual bool operator==(const SvgGradientHelper& rSvgGradientHelper) const;
+        };
+    } // end of namespace primitive2d
 } // end of namespace drawinglayer
 
 //////////////////////////////////////////////////////////////////////////////
@@ -186,22 +166,15 @@ namespace drawinglayer
 
 namespace drawinglayer
 {
-	namespace primitive2d
-	{
+    namespace primitive2d
+    {
         /// the basic linear gradient primitive
-		class DRAWINGLAYER_DLLPUBLIC SvgLinearGradientPrimitive2D : public BufferedDecompositionPrimitive2D, public SvgGradientHelper
-		{
-		private:
+        class DRAWINGLAYER_DLLPUBLIC SvgLinearGradientPrimitive2D : public BufferedDecompositionPrimitive2D, public SvgGradientHelper
+        {
+        private:
             /// the end point for linear gradient
             basegfx::B2DPoint                       maEnd;
 
-            /// local helpers
-            void ensureGeometry(
-                basegfx::B2DPolyPolygon& rPolyPolygon,
-                const SvgGradientEntry& rFrom, 
-                const SvgGradientEntry& rTo,
-                sal_Int32 nOffset) const;
-
         protected:
             /// local helpers
             virtual void createAtom(
@@ -213,31 +186,30 @@ namespace drawinglayer
             virtual void checkPreconditions();
 
             /// local decomposition.
-			virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;
+            virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;
 
-		public:
+        public:
             /// constructor
-			SvgLinearGradientPrimitive2D(
-				const basegfx::B2DPolyPolygon& rPolyPolygon,
+            SvgLinearGradientPrimitive2D(
+                const basegfx::B2DPolyPolygon& rPolyPolygon,
                 const SvgGradientEntryVector& rGradientEntries,
                 const basegfx::B2DPoint& rStart,
                 const basegfx::B2DPoint& rEnd,
-                SpreadMethod aSpreadMethod = Spread_pad,
-                double fOverlapping = DEFAULT_OVERLAPPING_VALUE);
+                SpreadMethod aSpreadMethod = Spread_pad);
 
-			/// data read access
+            /// data read access
             const basegfx::B2DPoint& getEnd() const { return maEnd; }
 
             /// compare operator
-			virtual bool operator==(const BasePrimitive2D& rPrimitive) const;
+            virtual bool operator==(const BasePrimitive2D& rPrimitive) const;
 
-			/// get range
-			virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const;
+            /// get range
+            virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const;
 
-			/// provide unique ID
-			DeclPrimitrive2DIDBlock()
-		};
-	} // end of namespace primitive2d
+            /// provide unique ID
+            DeclPrimitrive2DIDBlock()
+        };
+} // end of namespace primitive2d
 } // end of namespace drawinglayer
 
 //////////////////////////////////////////////////////////////////////////////
@@ -245,12 +217,12 @@ namespace drawinglayer
 
 namespace drawinglayer
 {
-	namespace primitive2d
-	{
+    namespace primitive2d
+    {
         /// the basic radial gradient primitive
-		class DRAWINGLAYER_DLLPUBLIC SvgRadialGradientPrimitive2D : public BufferedDecompositionPrimitive2D, public SvgGradientHelper
-		{
-		private:
+        class DRAWINGLAYER_DLLPUBLIC SvgRadialGradientPrimitive2D : public BufferedDecompositionPrimitive2D, public SvgGradientHelper
+        {
+        private:
             /// the geometric definition
             double                                  mfRadius;
 
@@ -268,11 +240,6 @@ namespace drawinglayer
             /// local helpers
             const SvgGradientEntryVector& getMirroredGradientEntries() const;
             void createMirroredGradientEntries();
-            void ensureGeometry(
-                basegfx::B2DPolyPolygon& rPolyPolygon,
-                const SvgGradientEntry& rFrom, 
-                const SvgGradientEntry& rTo,
-                sal_Int32 nOffset) const;
 
         protected:
             /// local helpers
@@ -285,34 +252,33 @@ namespace drawinglayer
             virtual void checkPreconditions();
 
             /// local decomposition.
-			virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;
+            virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;
 
-		public:
+        public:
             /// constructor
-			SvgRadialGradientPrimitive2D(
-				const basegfx::B2DPolyPolygon& rPolyPolygon,
+            SvgRadialGradientPrimitive2D(
+                const basegfx::B2DPolyPolygon& rPolyPolygon,
                 const SvgGradientEntryVector& rGradientEntries,
                 const basegfx::B2DPoint& rStart,
                 double fRadius,
                 SpreadMethod aSpreadMethod = Spread_pad,
-                const basegfx::B2DPoint* pFocal = 0,
-                double fOverlapping = DEFAULT_OVERLAPPING_VALUE);
+                const basegfx::B2DPoint* pFocal = 0);
 
-			/// data read access
+            /// data read access
             double getRadius() const { return mfRadius; }
             const basegfx::B2DPoint& getFocal() const { return maFocal; }
             bool isFocalSet() const { return mbFocalSet; }
 
             /// compare operator
-			virtual bool operator==(const BasePrimitive2D& rPrimitive) const;
+            virtual bool operator==(const BasePrimitive2D& rPrimitive) const;
 
-			/// get range
-			virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const;
+            /// get range
+            virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const;
 
-			/// provide unique ID
-			DeclPrimitrive2DIDBlock()
-		};
-	} // end of namespace primitive2d
+            /// provide unique ID
+            DeclPrimitrive2DIDBlock()
+        };
+    } // end of namespace primitive2d
 } // end of namespace drawinglayer
 
 //////////////////////////////////////////////////////////////////////////////
@@ -320,56 +286,45 @@ namespace drawinglayer
 
 namespace drawinglayer
 {
-	namespace primitive2d
-	{
+    namespace primitive2d
+    {
         /*  basic primitive for a single linear GradientRun in unit coordiantes.
             It's derived from DiscreteMetricDependentPrimitive2D to allow view-dependent
             decompositions allowing reduced color steps
          **/
-		class DRAWINGLAYER_DLLPUBLIC SvgLinearAtomPrimitive2D : public DiscreteMetricDependentPrimitive2D
-		{
-		private:
+        class DRAWINGLAYER_DLLPUBLIC SvgLinearAtomPrimitive2D : public DiscreteMetricDependentPrimitive2D
+        {
+        private:
             /// the geometric definition in unit coordiantes
             basegfx::BColor             maColorA;
             basegfx::BColor             maColorB;
             double                      mfOffsetA;
             double                      mfOffsetB;
-            double                      mfOverlapping;
 
         protected:
 
             /// local decomposition.
-			virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;
+            virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;
 
-		public:
+        public:
             /// constructor
-			SvgLinearAtomPrimitive2D(
+            SvgLinearAtomPrimitive2D(
                 const basegfx::BColor& aColorA, double fOffsetA,
-                const basegfx::BColor& aColorB, double fOffsetB,
-                double fOverlapping = DEFAULT_OVERLAPPING_VALUE)
-            :   DiscreteMetricDependentPrimitive2D(),
-                maColorA(aColorA),
-                maColorB(aColorB),
-                mfOffsetA(fOffsetA),
-                mfOffsetB(fOffsetB),
-                mfOverlapping(fOverlapping)
-            {
-            }
+                const basegfx::BColor& aColorB, double fOffsetB);
 
-			/// data read access
+            /// data read access
             const basegfx::BColor& getColorA() const { return maColorA; }
             const basegfx::BColor& getColorB() const { return maColorB; }
             double getOffsetA() const { return mfOffsetA; }
             double getOffsetB() const { return mfOffsetB; }
-            double getOverlapping() const { return mfOverlapping; }
 
             /// compare operator
-			virtual bool operator==(const BasePrimitive2D& rPrimitive) const;
+            virtual bool operator==(const BasePrimitive2D& rPrimitive) const;
 
-			/// provide unique ID
-			DeclPrimitrive2DIDBlock()
-		};
-	} // end of namespace primitive2d
+            /// provide unique ID
+            DeclPrimitrive2DIDBlock()
+        };
+    } // end of namespace primitive2d
 } // end of namespace drawinglayer
 
 //////////////////////////////////////////////////////////////////////////////
@@ -377,87 +332,68 @@ namespace drawinglayer
 
 namespace drawinglayer
 {
-	namespace primitive2d
-	{
+    namespace primitive2d
+    {
         /*  basic primitive for a single radial GradientRun in unit coordiantes.
             It's derived from DiscreteMetricDependentPrimitive2D to allow view-dependent
             decompositions allowing reduced color steps
          **/
-		class DRAWINGLAYER_DLLPUBLIC SvgRadialAtomPrimitive2D : public DiscreteMetricDependentPrimitive2D
-		{
-		private:
+        class DRAWINGLAYER_DLLPUBLIC SvgRadialAtomPrimitive2D : public DiscreteMetricDependentPrimitive2D
+        {
+        private:
             /// the geometric definition in unit coordiantes
             basegfx::BColor             maColorA;
             basegfx::BColor             maColorB;
             double                      mfScaleA;
             double                      mfScaleB;
 
-            /// Only used when focal is set
-            basegfx::B2DVector          maTranslateA;
-            basegfx::B2DVector          maTranslateB;
+            // helper to hold translation vectors when given (for focal)
+            struct VectorPair
+            {
+                basegfx::B2DVector          maTranslateA;
+                basegfx::B2DVector          maTranslateB;
 
-            double                      mfOverlapping;
+                VectorPair(const basegfx::B2DVector& rTranslateA, const basegfx::B2DVector& rTranslateB)
+                :   maTranslateA(rTranslateA),
+                    maTranslateB(rTranslateB)
+                {
+                }
+            };
 
-            /// bitfield
-            bool                        mbTranslateSet : 1;
+            /// Only used when focal is set
+            VectorPair*                 mpTranslate;
 
         protected:
 
             /// local decomposition.
-			virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;
+            virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;
 
-		public:
+        public:
             /// constructor
-			SvgRadialAtomPrimitive2D(
+            SvgRadialAtomPrimitive2D(
                 const basegfx::BColor& aColorA, double fScaleA, const basegfx::B2DVector& rTranslateA,
-                const basegfx::BColor& aColorB, double fScaleB, const basegfx::B2DVector& rTranslateB,
-                double fOverlapping = DEFAULT_OVERLAPPING_VALUE)
-            :   DiscreteMetricDependentPrimitive2D(),
-                maColorA(aColorA),
-                maColorB(aColorB),
-                mfScaleA(fScaleA),
-                mfScaleB(fScaleB),
-                maTranslateA(rTranslateA),
-                maTranslateB(rTranslateB),
-                mfOverlapping(fOverlapping),
-                mbTranslateSet(true)
-            {
-                mbTranslateSet = !maTranslateA.equal(maTranslateB);
-            }
-
+                const basegfx::BColor& aColorB, double fScaleB, const basegfx::B2DVector& rTranslateB);
             SvgRadialAtomPrimitive2D(
                 const basegfx::BColor& aColorA, double fScaleA,
-                const basegfx::BColor& aColorB, double fScaleB,
-                double fOverlapping = DEFAULT_OVERLAPPING_VALUE)
-            :   DiscreteMetricDependentPrimitive2D(),
-                maColorA(aColorA),
-                maColorB(aColorB),
-                mfScaleA(fScaleA),
-                mfScaleB(fScaleB),
-                maTranslateA(),
-                maTranslateB(),
-                mfOverlapping(fOverlapping),
-                mbTranslateSet(false)
-            {
-            }
+                const basegfx::BColor& aColorB, double fScaleB);
+            virtual ~SvgRadialAtomPrimitive2D();
 
-			/// data read access
+            /// data read access
             const basegfx::BColor& getColorA() const { return maColorA; }
             const basegfx::BColor& getColorB() const { return maColorB; }
             double getScaleA() const { return mfScaleA; }
             double getScaleB() const { return mfScaleB; }
-            const basegfx::B2DVector& getTranslateA() const { return maTranslateA; }
-            const basegfx::B2DVector& getTranslateB() const { return maTranslateB; }
-            double getOverlapping() const { return mfOverlapping; }
-            bool getTranslateSet() const { return mbTranslateSet; }
+            bool isTranslateSet() const { return (0 != mpTranslate); }
+            basegfx::B2DVector getTranslateA() const { if(mpTranslate) return mpTranslate->maTranslateA; return basegfx::B2DVector(); }
+            basegfx::B2DVector getTranslateB() const { if(mpTranslate) return mpTranslate->maTranslateB; return basegfx::B2DVector(); }
 
             /// compare operator
-			virtual bool operator==(const BasePrimitive2D& rPrimitive) const;
+            virtual bool operator==(const BasePrimitive2D& rPrimitive) const;
 
-			/// provide unique ID
-			DeclPrimitrive2DIDBlock()
-		};
-	} // end of namespace primitive2d
+            /// provide unique ID
+            DeclPrimitrive2DIDBlock()
+        };
+    } // end of namespace primitive2d
 } // end of namespace drawinglayer
 
 //////////////////////////////////////////////////////////////////////////////

Modified: incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx?rev=1235361&r1=1235360&r2=1235361&view=diff
==============================================================================
--- incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx (original)
+++ incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx Tue Jan 24 17:13:46 2012
@@ -54,6 +54,8 @@ namespace drawinglayer { namespace primi
 	class ControlPrimitive2D;
 	class PagePreviewPrimitive2D;
     class EpsPrimitive2D;
+    class SvgLinearAtomPrimitive2D;
+    class SvgRadialAtomPrimitive2D;
 }}
 
 //////////////////////////////////////////////////////////////////////////////
@@ -109,6 +111,8 @@ namespace drawinglayer
 			void RenderPointArrayPrimitive2D(const primitive2d::PointArrayPrimitive2D& rPointArrayCandidate);
 			void RenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokeCandidate);
             void RenderEpsPrimitive2D(const primitive2d::EpsPrimitive2D& rEpsPrimitive2D);
+            void RenderSvgLinearAtomPrimitive2D(const primitive2d::SvgLinearAtomPrimitive2D& rCandidate);
+            void RenderSvgRadialAtomPrimitive2D(const primitive2d::SvgRadialAtomPrimitive2D& rCandidate);
 
 			/////////////////////////////////////////////////////////////////////////////
 			// DrawMode adaption support

Modified: incubator/ooo/trunk/main/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx?rev=1235361&r1=1235360&r2=1235361&view=diff
==============================================================================
--- incubator/ooo/trunk/main/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx (original)
+++ incubator/ooo/trunk/main/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx Tue Jan 24 17:13:46 2012
@@ -41,12 +41,37 @@ using namespace com::sun::star;
 
 //////////////////////////////////////////////////////////////////////////////
 
+namespace
+{
+    sal_uInt32 calculateStepsForSvgGradient(const basegfx::BColor& rColorA, const basegfx::BColor& rColorB, double fDelta, double fDiscreteUnit)
+    {
+        // use color distance, assume to do every color step (full quality)
+        sal_uInt32 nSteps(basegfx::fround(rColorA.getDistance(rColorB) * 255.0));
+
+        if(nSteps)
+        {
+            // calc discrete length to change color all 1.5 disctete units (pixels)
+            const sal_uInt32 nDistSteps(basegfx::fround(fDelta / (fDiscreteUnit * 1.5)));
+
+            nSteps = std::min(nSteps, nDistSteps);
+        }
+
+        // roughly cut when too big or too small
+        nSteps = std::min(nSteps, sal_uInt32(255));
+        nSteps = std::max(nSteps, sal_uInt32(1));
+
+        return nSteps;
+    }
+} // end of anonymous namespace
+
+//////////////////////////////////////////////////////////////////////////////
+
 namespace drawinglayer
 {
-	namespace primitive2d
-	{
-		Primitive2DSequence SvgGradientHelper::createSingleGradientEntryFill() const
-		{
+    namespace primitive2d
+    {
+        Primitive2DSequence SvgGradientHelper::createSingleGradientEntryFill() const
+        {
             const SvgGradientEntryVector& rEntries = getGradientEntries();
             const sal_uInt32 nCount(rEntries.size());
             Primitive2DSequence xRetval;
@@ -58,15 +83,15 @@ namespace drawinglayer
 
                 if(fOpacity > 0.0)
                 {
-    			    Primitive2DReference xRef(
+                    Primitive2DReference xRef(
                         new PolyPolygonColorPrimitive2D(
                             getPolyPolygon(), 
                             rSingleEntry.getColor()));
 
                     if(fOpacity < 1.0)
                     {
-            		    const Primitive2DSequence aContent(&xRef, 1);
-    				    
+                        const Primitive2DSequence aContent(&xRef, 1);
+
                         xRef = Primitive2DReference(
                             new UnifiedTransparencePrimitive2D(
                                 aContent, 
@@ -230,11 +255,11 @@ namespace drawinglayer
 
             if(aTargetColorEntries.hasElements())
             {
-    			Primitive2DReference xRefContent;
+                Primitive2DReference xRefContent;
                     
                 if(aTargetOpacityEntries.hasElements())
                 {
-        			const Primitive2DReference xRefOpacity = new TransparencePrimitive2D(
+                    const Primitive2DReference xRefOpacity = new TransparencePrimitive2D(
                         aTargetColorEntries, 
                         aTargetOpacityEntries);
                         
@@ -259,34 +284,31 @@ namespace drawinglayer
             return xRetval;
         }
 
-		SvgGradientHelper::SvgGradientHelper(
-			const basegfx::B2DPolyPolygon& rPolyPolygon,
+        SvgGradientHelper::SvgGradientHelper(
+            const basegfx::B2DPolyPolygon& rPolyPolygon,
             const SvgGradientEntryVector& rGradientEntries,
             const basegfx::B2DPoint& rStart,
-            SpreadMethod aSpreadMethod,
-            double fOverlapping)
-		:	maPolyPolygon(rPolyPolygon),
+            SpreadMethod aSpreadMethod)
+        :   maPolyPolygon(rPolyPolygon),
             maGradientEntries(rGradientEntries),
             maStart(rStart),
             maSpreadMethod(aSpreadMethod),
-            mfOverlapping(fOverlapping),
             mbPreconditionsChecked(false),
             mbCreatesContent(false),
             mbSingleEntry(false),
             mbFullyOpaque(true)
-		{
-		}
+        {
+        }
 
-		bool SvgGradientHelper::operator==(const SvgGradientHelper& rSvgGradientHelper) const
-		{
-			const SvgGradientHelper& rCompare = static_cast< const SvgGradientHelper& >(rSvgGradientHelper);
+        bool SvgGradientHelper::operator==(const SvgGradientHelper& rSvgGradientHelper) const
+        {
+            const SvgGradientHelper& rCompare = static_cast< const SvgGradientHelper& >(rSvgGradientHelper);
 
-			return (getPolyPolygon() == rCompare.getPolyPolygon()
+            return (getPolyPolygon() == rCompare.getPolyPolygon()
                 && getGradientEntries() == rCompare.getGradientEntries()
                 && getStart() == rCompare.getStart()
-                && getSpreadMethod() == rCompare.getSpreadMethod()
-                && getOverlapping() == rCompare.getOverlapping());
-		}
+                && getSpreadMethod() == rCompare.getSpreadMethod());
+        }
 
     } // end of namespace primitive2d
 } // end of namespace drawinglayer
@@ -296,7 +318,7 @@ namespace drawinglayer
 namespace drawinglayer
 {
 	namespace primitive2d
-	{
+    {
         void SvgLinearGradientPrimitive2D::checkPreconditions()
         {
             // call parent
@@ -315,24 +337,6 @@ namespace drawinglayer
             }
         }
 
-        void SvgLinearGradientPrimitive2D::ensureGeometry(
-            basegfx::B2DPolyPolygon& rPolyPolygon,
-            const SvgGradientEntry& rFrom, 
-            const SvgGradientEntry& rTo,
-            sal_Int32 nOffset) const
-        {
-            if(!rPolyPolygon.count())
-            {
-                rPolyPolygon.append(
-                    basegfx::tools::createPolygonFromRect(
-                        basegfx::B2DRange(
-                            rFrom.getOffset() - getOverlapping() + nOffset, 
-                            0.0, 
-                            rTo.getOffset() + getOverlapping() + nOffset, 
-                            1.0)));
-            }
-        }
-
         void SvgLinearGradientPrimitive2D::createAtom(
             Primitive2DVector& rTargetColor,
             Primitive2DVector& rTargetOpacity, 
@@ -347,53 +351,23 @@ namespace drawinglayer
             }
             else
             {
-                const bool bColorChange(rFrom.getColor() != rTo.getColor());
-                const bool bOpacityChange(rFrom.getOpacity() != rTo.getOpacity());
-                basegfx::B2DPolyPolygon aPolyPolygon;
-                                            
-                if(bColorChange)
-                {
-    		        rTargetColor.push_back(
-                        new SvgLinearAtomPrimitive2D(
-                            rFrom.getColor(), rFrom.getOffset() + nOffset,
-                            rTo.getColor(), rTo.getOffset() + nOffset,
-                            getOverlapping()));
-                }
-                else
-                {
-                    ensureGeometry(aPolyPolygon, rFrom, rTo, nOffset);
-                    rTargetColor.push_back(
-                        new PolyPolygonColorPrimitive2D(
-                            aPolyPolygon, 
-                            rFrom.getColor()));
-                }
-
-                if(bOpacityChange)
-                {
-                    const double fTransFrom(1.0 - rFrom.getOpacity());
-                    const double fTransTo(1.0 - rTo.getOpacity());
-
-                    rTargetOpacity.push_back(
-                        new SvgLinearAtomPrimitive2D(
-                            basegfx::BColor(fTransFrom, fTransFrom, fTransFrom), rFrom.getOffset() + nOffset,
-                            basegfx::BColor(fTransTo,fTransTo, fTransTo), rTo.getOffset() + nOffset,
-                            getOverlapping()));
-                }
-                else if(!getFullyOpaque())
-                {
-                    const double fTransparence(1.0 - rFrom.getOpacity());
-
-                    ensureGeometry(aPolyPolygon, rFrom, rTo, nOffset);
-                    rTargetOpacity.push_back(
-                        new PolyPolygonColorPrimitive2D(
-                            aPolyPolygon, 
-                            basegfx::BColor(fTransparence, fTransparence, fTransparence)));
-                }
+                rTargetColor.push_back(
+                    new SvgLinearAtomPrimitive2D(
+                        rFrom.getColor(), rFrom.getOffset() + nOffset,
+                        rTo.getColor(), rTo.getOffset() + nOffset));
+
+                const double fTransFrom(1.0 - rFrom.getOpacity());
+                const double fTransTo(1.0 - rTo.getOpacity());
+
+                rTargetOpacity.push_back(
+                    new SvgLinearAtomPrimitive2D(
+                        basegfx::BColor(fTransFrom, fTransFrom, fTransFrom), rFrom.getOffset() + nOffset,
+                        basegfx::BColor(fTransTo,fTransTo, fTransTo), rTo.getOffset() + nOffset));
             }
         }
 
-		Primitive2DSequence SvgLinearGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
-		{
+        Primitive2DSequence SvgLinearGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
+        {
             Primitive2DSequence xRetval;
 
             if(!getPreconditionsChecked())
@@ -549,53 +523,52 @@ namespace drawinglayer
             }
 
             return xRetval;
-		}
+        }
 
-		SvgLinearGradientPrimitive2D::SvgLinearGradientPrimitive2D(
-			const basegfx::B2DPolyPolygon& rPolyPolygon,
+        SvgLinearGradientPrimitive2D::SvgLinearGradientPrimitive2D(
+            const basegfx::B2DPolyPolygon& rPolyPolygon,
             const SvgGradientEntryVector& rGradientEntries,
             const basegfx::B2DPoint& rStart,
             const basegfx::B2DPoint& rEnd,
-            SpreadMethod aSpreadMethod,
-            double fOverlapping)
-		:	BufferedDecompositionPrimitive2D(),
-            SvgGradientHelper(rPolyPolygon, rGradientEntries, rStart, aSpreadMethod, fOverlapping),
+            SpreadMethod aSpreadMethod)
+        :   BufferedDecompositionPrimitive2D(),
+            SvgGradientHelper(rPolyPolygon, rGradientEntries, rStart, aSpreadMethod),
             maEnd(rEnd)
-		{
-		}
+        {
+        }
 
-		bool SvgLinearGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
-		{
+        bool SvgLinearGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+        {
             const SvgGradientHelper* pSvgGradientHelper = dynamic_cast< const SvgGradientHelper* >(&rPrimitive);
 
             if(pSvgGradientHelper && SvgGradientHelper::operator==(*pSvgGradientHelper))
-			{
-				const SvgLinearGradientPrimitive2D& rCompare = static_cast< const SvgLinearGradientPrimitive2D& >(rPrimitive);
+            {
+                const SvgLinearGradientPrimitive2D& rCompare = static_cast< const SvgLinearGradientPrimitive2D& >(rPrimitive);
 
-				return (getEnd() == rCompare.getEnd());
-			}
+                return (getEnd() == rCompare.getEnd());
+            }
 
-			return false;
-		}
+            return false;
+        }
 
-		basegfx::B2DRange SvgLinearGradientPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
-		{
-			// return ObjectRange
-			return getPolyPolygon().getB2DRange();
-		}
+        basegfx::B2DRange SvgLinearGradientPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
+        {
+            // return ObjectRange
+            return getPolyPolygon().getB2DRange();
+        }
 
-		// provide unique ID
-		ImplPrimitrive2DIDBlock(SvgLinearGradientPrimitive2D, PRIMITIVE2D_ID_SVGLINEARGRADIENTPRIMITIVE2D)
+        // provide unique ID
+        ImplPrimitrive2DIDBlock(SvgLinearGradientPrimitive2D, PRIMITIVE2D_ID_SVGLINEARGRADIENTPRIMITIVE2D)
 
-	} // end of namespace primitive2d
+    } // end of namespace primitive2d
 } // end of namespace drawinglayer
 
 //////////////////////////////////////////////////////////////////////////////
 
 namespace drawinglayer
 {
-	namespace primitive2d
-	{
+    namespace primitive2d
+    {
         void SvgRadialGradientPrimitive2D::checkPreconditions()
         {
             // call parent
@@ -612,60 +585,6 @@ namespace drawinglayer
             }
         }
 
-        void SvgRadialGradientPrimitive2D::ensureGeometry(
-            basegfx::B2DPolyPolygon& rPolyPolygon,
-            const SvgGradientEntry& rFrom, 
-            const SvgGradientEntry& rTo,
-            sal_Int32 nOffset) const
-        {
-            if(!rPolyPolygon.count())
-            {
-                basegfx::B2DPolygon aPolygonA(basegfx::tools::createPolygonFromUnitCircle());
-                basegfx::B2DPolygon aPolygonB(basegfx::tools::createPolygonFromUnitCircle());
-                double fScaleFrom(rFrom.getOffset() + nOffset);
-                const double fScaleTo(rTo.getOffset() + nOffset);
-
-                if(fScaleFrom > getOverlapping())
-                {
-                    fScaleFrom -= getOverlapping();
-                }
-
-                if(isFocalSet())
-                {
-                    const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom));
-                    const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo));
-
-                    aPolygonA.transform(
-                        basegfx::tools::createScaleTranslateB2DHomMatrix(
-                            fScaleFrom,
-                            fScaleFrom,
-                            aTranslateFrom.getX(),
-                            aTranslateFrom.getY()));
-                    aPolygonB.transform(
-                        basegfx::tools::createScaleTranslateB2DHomMatrix(
-                            fScaleTo,
-                            fScaleTo,
-                            aTranslateTo.getX(),
-                            aTranslateTo.getY()));
-                }
-                else
-                {
-                    aPolygonA.transform(
-                        basegfx::tools::createScaleB2DHomMatrix(
-                            fScaleFrom,
-                            fScaleFrom));
-                    aPolygonB.transform(
-                        basegfx::tools::createScaleB2DHomMatrix(
-                            fScaleTo,
-                            fScaleTo));
-                }
-
-                // add the outer polygon first
-                rPolyPolygon.append(aPolygonB);
-                rPolyPolygon.append(aPolygonA);
-            }
-        }
-
         void SvgRadialGradientPrimitive2D::createAtom(
             Primitive2DVector& rTargetColor,
             Primitive2DVector& rTargetOpacity, 
@@ -680,82 +599,48 @@ namespace drawinglayer
             }
             else
             {
-                const bool bColorChange(rFrom.getColor() != rTo.getColor());
-                const bool bOpacityChange(rFrom.getOpacity() != rTo.getOpacity());
-                basegfx::B2DPolyPolygon aPolyPolygon;
+                const double fScaleFrom(rFrom.getOffset() + nOffset);
+                const double fScaleTo(rTo.getOffset() + nOffset);
 
-                if(bColorChange)
+                if(isFocalSet())
                 {
-                    const double fScaleFrom(rFrom.getOffset() + nOffset);
-                    const double fScaleTo(rTo.getOffset() + nOffset);
-
-                    if(isFocalSet())
-                    {
-                        const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom));
-                        const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo));
+                    const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom));
+                    const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo));
                         
-                        rTargetColor.push_back(
-                            new SvgRadialAtomPrimitive2D(
-                                rFrom.getColor(), fScaleFrom, aTranslateFrom,
-                                rTo.getColor(), fScaleTo, aTranslateTo,
-                                getOverlapping()));
-                    }
-                    else
-                    {
-                        rTargetColor.push_back(
-                            new SvgRadialAtomPrimitive2D(
-                                rFrom.getColor(), fScaleFrom,
-                                rTo.getColor(), fScaleTo,
-                                getOverlapping()));
-                    }
+                    rTargetColor.push_back(
+                        new SvgRadialAtomPrimitive2D(
+                            rFrom.getColor(), fScaleFrom, aTranslateFrom,
+                            rTo.getColor(), fScaleTo, aTranslateTo));
                 }
                 else
                 {
-                    ensureGeometry(aPolyPolygon, rFrom, rTo, nOffset);
                     rTargetColor.push_back(
-                        new PolyPolygonColorPrimitive2D(
-                            aPolyPolygon, 
-                            rFrom.getColor()));
+                        new SvgRadialAtomPrimitive2D(
+                            rFrom.getColor(), fScaleFrom,
+                            rTo.getColor(), fScaleTo));
                 }
 
-                if(bOpacityChange)
-                {
-                    const double fTransFrom(1.0 - rFrom.getOpacity());
-                    const double fTransTo(1.0 - rTo.getOpacity());
-                    const basegfx::BColor aColorFrom(fTransFrom, fTransFrom, fTransFrom);
-                    const basegfx::BColor aColorTo(fTransTo, fTransTo, fTransTo);
-                    const double fScaleFrom(rFrom.getOffset() + nOffset);
-                    const double fScaleTo(rTo.getOffset() + nOffset);
+                const double fTransFrom(1.0 - rFrom.getOpacity());
+                const double fTransTo(1.0 - rTo.getOpacity());
+                const basegfx::BColor aColorFrom(fTransFrom, fTransFrom, fTransFrom);
+                const basegfx::BColor aColorTo(fTransTo, fTransTo, fTransTo);
 
-                    if(isFocalSet())
-                    {
-                        const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom));
-                        const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo));
+                if(isFocalSet())
+                {
+                    const basegfx::B2DVector aTranslateFrom(maFocalVector * (maFocalLength - fScaleFrom));
+                    const basegfx::B2DVector aTranslateTo(maFocalVector * (maFocalLength - fScaleTo));
                         
-                        rTargetOpacity.push_back(
-                            new SvgRadialAtomPrimitive2D(
-                                aColorFrom, fScaleFrom, aTranslateFrom,
-                                aColorTo, fScaleTo, aTranslateTo,
-                                getOverlapping()));
-                    }
-                    else
-                    {
-                        rTargetOpacity.push_back(
-                            new SvgRadialAtomPrimitive2D(
-                                aColorFrom, fScaleFrom,
-                                aColorTo, fScaleTo,
-                                getOverlapping()));
-                    }
+                    rTargetOpacity.push_back(
+                        new SvgRadialAtomPrimitive2D(
+                            aColorFrom, fScaleFrom, aTranslateFrom,
+                            aColorTo, fScaleTo, aTranslateTo));
                 }
-                else if(!getFullyOpaque())
+                else
                 {
-                    const double fTransparence(1.0 - rFrom.getOpacity());
-
-                    ensureGeometry(aPolyPolygon, rFrom, rTo, nOffset);
                     rTargetOpacity.push_back(
-                        new PolyPolygonColorPrimitive2D(
-                            aPolyPolygon, 
-                            basegfx::BColor(fTransparence, fTransparence, fTransparence)));
+                        new SvgRadialAtomPrimitive2D(
+                            aColorFrom, fScaleFrom,
+                            aColorTo, fScaleTo));
                 }
             }
         }
@@ -791,8 +676,8 @@ namespace drawinglayer
             }
         }
 
-		Primitive2DSequence SvgRadialGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
-		{
+        Primitive2DSequence SvgRadialGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
+        {
             Primitive2DSequence xRetval;
 
             if(!getPreconditionsChecked())
@@ -893,42 +778,41 @@ namespace drawinglayer
             }
 
             return xRetval;
-		}
+        }
 
-		SvgRadialGradientPrimitive2D::SvgRadialGradientPrimitive2D(
-			const basegfx::B2DPolyPolygon& rPolyPolygon,
+        SvgRadialGradientPrimitive2D::SvgRadialGradientPrimitive2D(
+            const basegfx::B2DPolyPolygon& rPolyPolygon,
             const SvgGradientEntryVector& rGradientEntries,
             const basegfx::B2DPoint& rStart,
             double fRadius,
             SpreadMethod aSpreadMethod,
-            const basegfx::B2DPoint* pFocal,
-            double fOverlapping)
-		:	BufferedDecompositionPrimitive2D(),
-            SvgGradientHelper(rPolyPolygon, rGradientEntries, rStart, aSpreadMethod, fOverlapping),
+            const basegfx::B2DPoint* pFocal)
+        :   BufferedDecompositionPrimitive2D(),
+            SvgGradientHelper(rPolyPolygon, rGradientEntries, rStart, aSpreadMethod),
             mfRadius(fRadius),
             maFocal(rStart),
             maFocalVector(0.0, 0.0),
             maFocalLength(0.0),
             maMirroredGradientEntries(),
             mbFocalSet(false)
-		{
+        {
             if(pFocal)
             {
                 maFocal = *pFocal;
                 maFocalVector = maFocal - getStart();
                 mbFocalSet = true;
             }
-		}
+        }
 
-		bool SvgRadialGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
-		{
+        bool SvgRadialGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+        {
             const SvgGradientHelper* pSvgGradientHelper = dynamic_cast< const SvgGradientHelper* >(&rPrimitive);
 
             if(pSvgGradientHelper && SvgGradientHelper::operator==(*pSvgGradientHelper))
-			{
-				const SvgRadialGradientPrimitive2D& rCompare = static_cast< const SvgRadialGradientPrimitive2D& >(rPrimitive);
+            {
+                const SvgRadialGradientPrimitive2D& rCompare = static_cast< const SvgRadialGradientPrimitive2D& >(rPrimitive);
 
-				if(getRadius() == rCompare.getRadius())
+                if(getRadius() == rCompare.getRadius())
                 {
                     if(isFocalSet() == rCompare.isFocalSet())
                     {
@@ -942,21 +826,21 @@ namespace drawinglayer
                         }
                     }
                 }
-			}
+            }
 
-			return false;
-		}
+            return false;
+        }
 
-		basegfx::B2DRange SvgRadialGradientPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
-		{
-			// return ObjectRange
-			return getPolyPolygon().getB2DRange();
-		}
+        basegfx::B2DRange SvgRadialGradientPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
+        {
+            // return ObjectRange
+            return getPolyPolygon().getB2DRange();
+        }
 
-		// provide unique ID
-		ImplPrimitrive2DIDBlock(SvgRadialGradientPrimitive2D, PRIMITIVE2D_ID_SVGRADIALGRADIENTPRIMITIVE2D)
+        // provide unique ID
+        ImplPrimitrive2DIDBlock(SvgRadialGradientPrimitive2D, PRIMITIVE2D_ID_SVGRADIALGRADIENTPRIMITIVE2D)
 
-	} // end of namespace primitive2d
+    } // end of namespace primitive2d
 } // end of namespace drawinglayer
 
 //////////////////////////////////////////////////////////////////////////////
@@ -964,8 +848,8 @@ namespace drawinglayer
 
 namespace drawinglayer
 {
-	namespace primitive2d
-	{
+    namespace primitive2d
+    {
         Primitive2DSequence SvgLinearAtomPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
         {
             Primitive2DSequence xRetval;
@@ -973,81 +857,73 @@ namespace drawinglayer
 
             if(!basegfx::fTools::equalZero(fDelta))
             {
-                if(getColorA() == getColorB())
-                {
-                    const basegfx::B2DPolygon aPolygon(
-                        basegfx::tools::createPolygonFromRect(
-                            basegfx::B2DRange(
-                                getOffsetA() - getOverlapping(), 
-                                0.0, 
-                                getOffsetB() + getOverlapping(), 
-                                1.0)));
-
-                    xRetval.realloc(1);
-                    xRetval[0] = new PolyPolygonColorPrimitive2D(
-                        basegfx::B2DPolyPolygon(aPolygon), 
-                        getColorA());
-                }
-                else
-                {
-                    // calc discrete length to change color all 2.5 pixels
-                    sal_uInt32 nSteps(basegfx::fround(fDelta / (getDiscreteUnit() * 2.5)));
+                // use one discrete unit for overlap (one pixel)
+                const double fDiscreteUnit(getDiscreteUnit());
 
-                    // use color distance, assume to do every 3rd
-                    const double fColorDistance(getColorA().getDistance(getColorB()));
-                    const sal_uInt32 nColorSteps(basegfx::fround(fColorDistance * (255.0 * 0.3)));
-                    nSteps = std::min(nSteps, nColorSteps);
+                // use color distance and discrete lengths to calculate step count
+                const sal_uInt32 nSteps(calculateStepsForSvgGradient(getColorA(), getColorB(), fDelta, fDiscreteUnit));
 
-                    // roughly cut when too big
-                    nSteps = std::min(nSteps, sal_uInt32(100));
-                    nSteps = std::max(nSteps, sal_uInt32(1));
+                // prepare loop and polygon (with overlap for linear gradients)
+                double fStart(0.0);
+                double fStep(fDelta / nSteps);
+                const basegfx::B2DPolygon aPolygon(
+                    basegfx::tools::createPolygonFromRect(
+                        basegfx::B2DRange(
+                            getOffsetA() - fDiscreteUnit, 
+                            0.0, 
+                            getOffsetA() + fStep + fDiscreteUnit, 
+                            1.0)));
 
-                    // preapare iteration
-                    double fStart(0.0);
-                    double fStep(fDelta / nSteps);
+                // loop and create primitives
+                xRetval.realloc(nSteps);
 
-                    xRetval.realloc(nSteps);
+                for(sal_uInt32 a(0); a < nSteps; a++, fStart += fStep)
+                {
+                    basegfx::B2DPolygon aNew(aPolygon);
 
-                    for(sal_uInt32 a(0); a < nSteps; a++, fStart += fStep)
-                    {
-                        const double fLeft(getOffsetA() + fStart);
-                        const double fRight(fLeft + fStep);
-                        const basegfx::B2DPolygon aPolygon(
-                            basegfx::tools::createPolygonFromRect(
-                                basegfx::B2DRange(
-                                    fLeft - getOverlapping(), 
-                                    0.0, 
-                                    fRight + getOverlapping(), 
-                                    1.0)));
-
-                        xRetval[a] = new PolyPolygonColorPrimitive2D(
-                            basegfx::B2DPolyPolygon(aPolygon), 
-                            basegfx::interpolate(getColorA(), getColorB(), fStart/fDelta));
-                    }
+                    aNew.transform(basegfx::tools::createTranslateB2DHomMatrix(fStart, 0.0));
+                    xRetval[a] = new PolyPolygonColorPrimitive2D(
+                        basegfx::B2DPolyPolygon(aNew), 
+                        basegfx::interpolate(getColorA(), getColorB(), fStart/fDelta));
                 }
             }
 
             return xRetval;
         }
 
+        SvgLinearAtomPrimitive2D::SvgLinearAtomPrimitive2D(
+            const basegfx::BColor& aColorA, double fOffsetA,
+            const basegfx::BColor& aColorB, double fOffsetB)
+        :   DiscreteMetricDependentPrimitive2D(),
+            maColorA(aColorA),
+            maColorB(aColorB),
+            mfOffsetA(fOffsetA),
+            mfOffsetB(fOffsetB)
+        {
+            if(mfOffsetA > mfOffsetB)
+            {
+                OSL_ENSURE(false, "Wrong offset order (!)");
+                ::std::swap(mfOffsetA, mfOffsetB);
+            }
+        }
+
         bool SvgLinearAtomPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
         {
-			if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
-			{
-				const SvgLinearAtomPrimitive2D& rCompare = static_cast< const SvgLinearAtomPrimitive2D& >(rPrimitive);
+            if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
+            {
+                const SvgLinearAtomPrimitive2D& rCompare = static_cast< const SvgLinearAtomPrimitive2D& >(rPrimitive);
 
-				return (getColorA() == rCompare.getColorA()
+                return (getColorA() == rCompare.getColorA()
                     && getColorB() == rCompare.getColorB()
                     && getOffsetA() == rCompare.getOffsetA()
-                    && getOffsetB() == rCompare.getOffsetB()
-                    && getOverlapping() == rCompare.getOverlapping());
-			}
+                    && getOffsetB() == rCompare.getOffsetB());
+            }
 
-			return false;
+            return false;
         }
 
-		// provide unique ID
-		ImplPrimitrive2DIDBlock(SvgLinearAtomPrimitive2D, PRIMITIVE2D_ID_SVGLINEARATOMPRIMITIVE2D)
+        // provide unique ID
+        ImplPrimitrive2DIDBlock(SvgLinearAtomPrimitive2D, PRIMITIVE2D_ID_SVGLINEARATOMPRIMITIVE2D)
 
     } // end of namespace primitive2d
 } // end of namespace drawinglayer
@@ -1057,8 +933,8 @@ namespace drawinglayer
 
 namespace drawinglayer
 {
-	namespace primitive2d
-	{
+    namespace primitive2d
+    {
         Primitive2DSequence SvgRadialAtomPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
         {
             Primitive2DSequence xRetval;
@@ -1066,182 +942,151 @@ namespace drawinglayer
 
             if(!basegfx::fTools::equalZero(fDeltaScale))
             {
-                if(getColorA() == getColorB())
-                {
-                    basegfx::B2DPolygon aPolygonA(basegfx::tools::createPolygonFromUnitCircle());
-                    basegfx::B2DPolygon aPolygonB(basegfx::tools::createPolygonFromUnitCircle());
-                    double fScaleA(getScaleA());
-                    const double fScaleB(getScaleB());
+                // use one discrete unit for overlap (one pixel)
+                const double fDiscreteUnit(getDiscreteUnit());
 
-                    if(fScaleA > getOverlapping())
-                    {
-                        fScaleA -= getOverlapping();
-                    }
+                // use color distance and discrete lengths to calculate step count
+                const sal_uInt32 nSteps(calculateStepsForSvgGradient(getColorA(), getColorB(), fDeltaScale, fDiscreteUnit));
 
-                    const bool bUseA(basegfx::fTools::equalZero(fScaleA));
+                // prepare loop (outside to inside, full polygons, no polypolygons with holes)
+                double fEndScale(getScaleB());
+                double fStepScale(fDeltaScale / nSteps);
 
-                    if(getTranslateSet())
-                    {
-                        if(bUseA)
-                        {
-                            aPolygonA.transform(
-                                basegfx::tools::createScaleTranslateB2DHomMatrix(
-                                    fScaleA,
-                                    fScaleA,
-                                    getTranslateA().getX(),
-                                    getTranslateA().getY()));
-                        }
+                // loop and create primitives
+                xRetval.realloc(nSteps);
+
+                for(sal_uInt32 a(0); a < nSteps; a++, fEndScale -= fStepScale)
+                {
+                    const double fUnitScale(fEndScale/fDeltaScale);
+                    basegfx::B2DHomMatrix aTransform;
 
-                        aPolygonB.transform(
-                            basegfx::tools::createScaleTranslateB2DHomMatrix(
-                                fScaleB,
-                                fScaleB,
-                                getTranslateB().getX(),
-                                getTranslateB().getY()));
+                    if(isTranslateSet())
+                    {
+                        const basegfx::B2DVector aTranslate(
+                            basegfx::interpolate(
+                                getTranslateA(), 
+                                getTranslateB(), 
+                                fUnitScale));
+
+                        aTransform = basegfx::tools::createScaleTranslateB2DHomMatrix(
+                            fEndScale,
+                            fEndScale,
+                            aTranslate.getX(),
+                            aTranslate.getY());
                     }
                     else
                     {
-                        if(bUseA)
-                        {
-                            aPolygonA.transform(
-                                basegfx::tools::createScaleB2DHomMatrix(
-                                    fScaleA,
-                                    fScaleA));
-                        }
-
-                        aPolygonB.transform(
-                            basegfx::tools::createScaleB2DHomMatrix(
-                                fScaleB,
-                                fScaleB));
+                        aTransform = basegfx::tools::createScaleB2DHomMatrix(
+                            fEndScale,
+                            fEndScale);
                     }
 
-                    basegfx::B2DPolyPolygon aPolyPolygon(aPolygonB);
-                    
-                    if(bUseA)
-                    {
-                        aPolyPolygon.append(aPolygonA);
-                    }
+                    basegfx::B2DPolygon aNew(basegfx::tools::createPolygonFromUnitCircle());
 
-                    xRetval.realloc(1);
-                    
-                    xRetval[0] = new PolyPolygonColorPrimitive2D(
-                        aPolyPolygon, 
-                        getColorA());
+                    aNew.transform(aTransform);
+                    xRetval[a] = new PolyPolygonColorPrimitive2D(
+                        basegfx::B2DPolyPolygon(aNew), 
+                        basegfx::interpolate(getColorA(), getColorB(), fUnitScale));
                 }
-                else
-                {
-                    // calc discrete length to change color all 2.5 pixels
-                    sal_uInt32 nSteps(basegfx::fround(fDeltaScale / (getDiscreteUnit() * 2.5)));
-
-                    // use color distance, assume to do every 3rd
-                    const double fColorDistance(getColorA().getDistance(getColorB()));
-                    const sal_uInt32 nColorSteps(basegfx::fround(fColorDistance * (255.0 * 0.3)));
-                    nSteps = std::min(nSteps, nColorSteps);
-
-                    // roughly cut when too big
-                    nSteps = std::min(nSteps, sal_uInt32(100));
-                    nSteps = std::max(nSteps, sal_uInt32(1));
-
-                    // preapare iteration
-                    double fStartScale(0.0);
-                    double fStepScale(fDeltaScale / nSteps);
-
-                    xRetval.realloc(nSteps);
-
-                    for(sal_uInt32 a(0); a < nSteps; a++, fStartScale += fStepScale)
-                    {
-                        double fScaleA(getScaleA() + fStartScale);
-                        const double fScaleB(fScaleA + fStepScale);
-                        const double fUnitScale(fStartScale/fDeltaScale);
-                        basegfx::B2DPolygon aPolygonA(basegfx::tools::createPolygonFromUnitCircle());
-                        basegfx::B2DPolygon aPolygonB(basegfx::tools::createPolygonFromUnitCircle());
+            }
 
-                        if(fScaleA > getOverlapping())
-                        {
-                            fScaleA -= getOverlapping();
-                        }
-                        
-                        const bool bUseA(basegfx::fTools::equalZero(fScaleA));
+            return xRetval;
+        }
 
-                        if(getTranslateSet())
-                        {
-                            const double fUnitScaleEnd((fStartScale + fStepScale)/fDeltaScale);
-                            const basegfx::B2DVector aTranslateB(basegfx::interpolate(getTranslateA(), getTranslateB(), fUnitScaleEnd));
+        SvgRadialAtomPrimitive2D::SvgRadialAtomPrimitive2D(
+            const basegfx::BColor& aColorA, double fScaleA, const basegfx::B2DVector& rTranslateA,
+            const basegfx::BColor& aColorB, double fScaleB, const basegfx::B2DVector& rTranslateB)
+        :   DiscreteMetricDependentPrimitive2D(),
+            maColorA(aColorA),
+            maColorB(aColorB),
+            mfScaleA(fScaleA),
+            mfScaleB(fScaleB),
+            mpTranslate(0)
+        {
+            // check and evtl. set translations
+            if(!rTranslateA.equal(rTranslateB))
+            {
+                mpTranslate = new VectorPair(rTranslateA, rTranslateB);
+            }
 
-                            if(bUseA)
-                            {
-                                const basegfx::B2DVector aTranslateA(basegfx::interpolate(getTranslateA(), getTranslateB(), fUnitScale));
-                                
-                                aPolygonA.transform(
-                                    basegfx::tools::createScaleTranslateB2DHomMatrix(
-                                        fScaleA,
-                                        fScaleA,
-                                        aTranslateA.getX(),
-                                        aTranslateA.getY()));
-                            }
+            // scale A and B have to be positive
+            mfScaleA = ::std::max(mfScaleA, 0.0);
+            mfScaleB = ::std::max(mfScaleB, 0.0);
 
-                            aPolygonB.transform(
-                                basegfx::tools::createScaleTranslateB2DHomMatrix(
-                                    fScaleB,
-                                    fScaleB,
-                                    aTranslateB.getX(),
-                                    aTranslateB.getY()));
-                        }
-                        else
-                        {
-                            if(bUseA)
-                            {
-                                aPolygonA.transform(
-                                    basegfx::tools::createScaleB2DHomMatrix(
-                                        fScaleA,
-                                        fScaleA));
-                            }
+            // scale B has to be bigger than scale A; swap if different
+            if(mfScaleA > mfScaleB)
+            {
+                OSL_ENSURE(false, "Wrong offset order (!)");
+                ::std::swap(mfScaleA, mfScaleB);
 
-                            aPolygonB.transform(
-                                basegfx::tools::createScaleB2DHomMatrix(
-                                    fScaleB,
-                                    fScaleB));
-                        }
+                if(mpTranslate)
+                {
+                    ::std::swap(mpTranslate->maTranslateA, mpTranslate->maTranslateB);
+                }
+            }
+        }
 
-                        basegfx::B2DPolyPolygon aPolyPolygon(aPolygonB);
-                        
-                        if(bUseA)
-                        {
-                            aPolyPolygon.append(aPolygonA);
-                        }
+        SvgRadialAtomPrimitive2D::SvgRadialAtomPrimitive2D(
+            const basegfx::BColor& aColorA, double fScaleA,
+            const basegfx::BColor& aColorB, double fScaleB)
+        :   DiscreteMetricDependentPrimitive2D(),
+            maColorA(aColorA),
+            maColorB(aColorB),
+            mfScaleA(fScaleA),
+            mfScaleB(fScaleB),
+            mpTranslate(0)
+        {
+            // scale A and B have to be positive
+            mfScaleA = ::std::max(mfScaleA, 0.0);
+            mfScaleB = ::std::max(mfScaleB, 0.0);
 
-                        xRetval[nSteps - 1 - a] = new PolyPolygonColorPrimitive2D(
-                            aPolyPolygon, 
-                            basegfx::interpolate(getColorA(), getColorB(), fUnitScale));
-                    }
-                }
+            // scale B has to be bigger than scale A; swap if different
+            if(mfScaleA > mfScaleB)
+            {
+                OSL_ENSURE(false, "Wrong offset order (!)");
+                ::std::swap(mfScaleA, mfScaleB);
             }
+        }
 
-            return xRetval;
+        SvgRadialAtomPrimitive2D::~SvgRadialAtomPrimitive2D()
+        {
+            if(mpTranslate)
+            {
+                delete mpTranslate;
+                mpTranslate = 0;
+            }
         }
 
         bool SvgRadialAtomPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
         {
-			if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
-			{
-				const SvgRadialAtomPrimitive2D& rCompare = static_cast< const SvgRadialAtomPrimitive2D& >(rPrimitive);
+            if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
+            {
+                const SvgRadialAtomPrimitive2D& rCompare = static_cast< const SvgRadialAtomPrimitive2D& >(rPrimitive);
 
-				return (getColorA() == rCompare.getColorA()
+                if(getColorA() == rCompare.getColorA()
                     && getColorB() == rCompare.getColorB()
                     && getScaleA() == rCompare.getScaleA()
-                    && getScaleB() == rCompare.getScaleB()
-                    && getTranslateA() == rCompare.getTranslateA()
-                    && getTranslateB() == rCompare.getTranslateB()
-                    && getOverlapping() == rCompare.getOverlapping());
-			}
+                    && getScaleB() == rCompare.getScaleB())
+                {
+                    if(isTranslateSet() && rCompare.isTranslateSet())
+                    {
+                        return (getTranslateA() == rCompare.getTranslateA()
+                            && getTranslateB() == rCompare.getTranslateB());
+                    }
+                    else if(!isTranslateSet() && !rCompare.isTranslateSet())
+                    {
+                        return true;
+                    }
+                }
+            }
 
-			return false;
+            return false;
         }
 
-		// provide unique ID
-		ImplPrimitrive2DIDBlock(SvgRadialAtomPrimitive2D, PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D)
+        // provide unique ID
+        ImplPrimitrive2DIDBlock(SvgRadialAtomPrimitive2D, PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D)
 
-	} // end of namespace primitive2d
+    } // end of namespace primitive2d
 } // end of namespace drawinglayer
 
 //////////////////////////////////////////////////////////////////////////////

Modified: incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx?rev=1235361&r1=1235360&r2=1235361&view=diff
==============================================================================
--- incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx (original)
+++ incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx Tue Jan 24 17:13:46 2012
@@ -55,7 +55,7 @@
 #include <drawinglayer/primitive2d/backgroundcolorprimitive2d.hxx>
 #include <basegfx/matrix/b2dhommatrixtools.hxx>
 #include <drawinglayer/primitive2d/epsprimitive2d.hxx>
-
+#include <drawinglayer/primitive2d/svggradientprimitive2d.hxx>
 #include <toolkit/helper/vclunohelper.hxx>
 #include <vcl/window.hxx>
 
@@ -573,6 +573,16 @@ namespace drawinglayer
 					RenderEpsPrimitive2D(static_cast< const primitive2d::EpsPrimitive2D& >(rCandidate));
                     break;
                 }
+                case PRIMITIVE2D_ID_SVGLINEARATOMPRIMITIVE2D:
+                {
+                    RenderSvgLinearAtomPrimitive2D(static_cast< const primitive2d::SvgLinearAtomPrimitive2D& >(rCandidate));
+                    break;
+                }
+                case PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D:
+                {
+                    RenderSvgRadialAtomPrimitive2D(static_cast< const primitive2d::SvgRadialAtomPrimitive2D& >(rCandidate));
+                    break;
+                }
 				default :
 				{
 					// process recursively

Modified: incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclprocessor2d.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclprocessor2d.cxx?rev=1235361&r1=1235360&r2=1235361&view=diff
==============================================================================
--- incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclprocessor2d.cxx (original)
+++ incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclprocessor2d.cxx Tue Jan 24 17:13:46 2012
@@ -56,6 +56,9 @@
 #include <vcl/metric.hxx>
 #include <drawinglayer/primitive2d/textenumsprimitive2d.hxx>
 #include <drawinglayer/primitive2d/epsprimitive2d.hxx>
+#include <drawinglayer/primitive2d/svggradientprimitive2d.hxx>
+#include <basegfx/color/bcolor.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
 
 //////////////////////////////////////////////////////////////////////////////
 // control support
@@ -78,6 +81,34 @@ using namespace com::sun::star;
 
 //////////////////////////////////////////////////////////////////////////////
 
+namespace
+{
+    sal_uInt32 calculateStepsForSvgGradient(const basegfx::BColor& rColorA, const basegfx::BColor& rColorB, double fDelta, double fDiscreteUnit)
+    {
+        // use color distance, assume to do every color step
+        sal_uInt32 nSteps(basegfx::fround(rColorA.getDistance(rColorB) * 255.0));
+
+        if(nSteps)
+        {
+            // calc discrete length to change color each disctete unit (pixel)
+            const sal_uInt32 nDistSteps(basegfx::fround(fDelta / fDiscreteUnit));
+
+            nSteps = std::min(nSteps, nDistSteps);
+        }
+
+        // reduce quality to 3 discrete units or every 3rd color step for rendering
+        nSteps /= 2;
+
+        // roughly cut when too big or too small (not full quality, reduce complexity)
+        nSteps = std::min(nSteps, sal_uInt32(255));
+        nSteps = std::max(nSteps, sal_uInt32(1));
+
+        return nSteps;
+    }
+} // end of anonymous namespace
+
+//////////////////////////////////////////////////////////////////////////////
+
 namespace drawinglayer
 {
 	namespace processor2d
@@ -1331,6 +1362,100 @@ namespace drawinglayer
             }
         }
 
+        void VclProcessor2D::RenderSvgLinearAtomPrimitive2D(const primitive2d::SvgLinearAtomPrimitive2D& rCandidate)
+        {
+            const double fDelta(rCandidate.getOffsetB() - rCandidate.getOffsetA());
+
+            if(basegfx::fTools::more(fDelta, 0.0))
+            {
+                const basegfx::BColor aColorA(maBColorModifierStack.getModifiedColor(rCandidate.getColorA()));
+                const basegfx::BColor aColorB(maBColorModifierStack.getModifiedColor(rCandidate.getColorB()));
+                const double fDiscreteUnit((getViewInformation2D().getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0)).getLength());
+
+                // use color distance and discrete lengths to calculate step count
+                const sal_uInt32 nSteps(calculateStepsForSvgGradient(aColorA, aColorB, fDelta, fDiscreteUnit));
+
+                // prepare loop and polygon
+                double fStart(0.0);
+                double fStep(fDelta / nSteps);
+                const basegfx::B2DPolygon aPolygon(
+                    basegfx::tools::createPolygonFromRect(
+                        basegfx::B2DRange(
+                            rCandidate.getOffsetA() - fDiscreteUnit, 
+                            0.0, 
+                            rCandidate.getOffsetA() + fStep + fDiscreteUnit, 
+                            1.0)));
+
+                // switch off line painting
+                mpOutputDevice->SetLineColor();
+
+                // loop and paint
+                for(sal_uInt32 a(0); a < nSteps; a++, fStart += fStep)
+                {
+                    basegfx::B2DPolygon aNew(aPolygon);
+
+                    aNew.transform(maCurrentTransformation * basegfx::tools::createTranslateB2DHomMatrix(fStart, 0.0));
+                    mpOutputDevice->SetFillColor(Color(basegfx::interpolate(aColorA, aColorB, fStart/fDelta)));
+                    mpOutputDevice->DrawPolyPolygon(basegfx::B2DPolyPolygon(aNew));
+                }
+            }
+        }
+
+        void VclProcessor2D::RenderSvgRadialAtomPrimitive2D(const primitive2d::SvgRadialAtomPrimitive2D& rCandidate)
+        {
+            const double fDeltaScale(rCandidate.getScaleB() - rCandidate.getScaleA());
+
+            if(basegfx::fTools::more(fDeltaScale, 0.0))
+            {
+                const basegfx::BColor aColorA(maBColorModifierStack.getModifiedColor(rCandidate.getColorA()));
+                const basegfx::BColor aColorB(maBColorModifierStack.getModifiedColor(rCandidate.getColorB()));
+                const double fDiscreteUnit((getViewInformation2D().getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0)).getLength());
+
+                // use color distance and discrete lengths to calculate step count
+                const sal_uInt32 nSteps(calculateStepsForSvgGradient(aColorA, aColorB, fDeltaScale, fDiscreteUnit));
+
+                // switch off line painting
+                mpOutputDevice->SetLineColor();
+
+                // prepare loop (outside to inside)
+                double fEndScale(rCandidate.getScaleB());
+                double fStepScale(fDeltaScale / nSteps);
+
+                for(sal_uInt32 a(0); a < nSteps; a++, fEndScale -= fStepScale)
+                {
+                    const double fUnitScale(fEndScale/fDeltaScale);
+                    basegfx::B2DHomMatrix aTransform;
+
+                    if(rCandidate.isTranslateSet())
+                    {
+                        const basegfx::B2DVector aTranslate(
+                            basegfx::interpolate(
+                                rCandidate.getTranslateA(), 
+                                rCandidate.getTranslateB(), 
+                                fUnitScale));
+
+                        aTransform = basegfx::tools::createScaleTranslateB2DHomMatrix(
+                            fEndScale,
+                            fEndScale,
+                            aTranslate.getX(),
+                            aTranslate.getY());
+                    }
+                    else
+                    {
+                        aTransform = basegfx::tools::createScaleB2DHomMatrix(
+                            fEndScale,
+                            fEndScale);
+                    }
+
+                    basegfx::B2DPolygon aNew(basegfx::tools::createPolygonFromUnitCircle());
+                    
+                    aNew.transform(maCurrentTransformation * aTransform);
+                    mpOutputDevice->SetFillColor(Color(basegfx::interpolate(aColorA, aColorB, fUnitScale)));
+                    mpOutputDevice->DrawPolyPolygon(basegfx::B2DPolyPolygon(aNew));
+                }
+            }
+        }
+
 		void VclProcessor2D::adaptLineToFillDrawMode() const
 		{
 			const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode());