From cbf10a85ee07cf370a5547e725cce5f193c9362c Mon Sep 17 00:00:00 2001
From: Jens-Heiner Rechtien <hr@openoffice.org>
Date: Mon, 27 Jul 2009 16:24:52 +0000
Subject: CWS-TOOLING: integrate CWS aw073 2009-07-16 11:21:19 +0200 aw 
 r274036 : corrections after resync 2009-07-15 13:34:18 +0200 aw  r274009 :
 CWS-TOOLING: rebase CWS aw073 to trunk@273858 (milestone: DEV300:m52)
 2009-07-01 20:04:27 +0200 aw  r273613 : CWS-TOOLING: rebase CWS aw073 to
 trunk@273468 (milestone: DEV300:m51) 2009-06-24 11:51:03 +0200 aw  r273324 :
 #i102062# added using statement for solaris compiler 2009-06-23 12:53:50
 +0200 aw  r273278 : #i100158# force filled polygons to closed state
 2009-06-23 12:28:33 +0200 aw  r273276 : #i100158#, #i102371# corrected all
 (mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) shortcuts to support line/fill
 and to be not used when FillMode is not overpaint 2009-06-23 12:15:14 +0200
 aw  r273274 : #i100158# added PolyPolygon support for
 snapPointsOfHorizontalOrVerticalEdges helper 2009-06-22 17:28:33 +0200 aw 
 r273244 : #i101508# added taking care of cell's distance-to-border values for
 cell text primitive creation 2009-06-22 12:59:10 +0200 aw  r273218 :
 #i102253# applied patch from OD (see task) 2009-06-18 17:00:52 +0200 aw 
 r273125 : #i102251# added EE_CNTRL_ONLINESPELLING switch off at DrawOutliner
 during GraphicExporter::GetGraphic 2009-06-18 14:35:57 +0200 aw  r273120 :
 #i102241# added mergeToSinglePolyPolygon usage to
 SdrObject::ImpConvertToContourObj 2009-06-18 14:35:20 +0200 aw  r273119 :
 #i102241# improved PolygonStrokePrimitive2D::createLocalDecomposition
 2009-06-18 14:34:49 +0200 aw  r273118 : #i102241# Made
 B2DCubicBezier::testAndSolveTrivialBezier() numerically more stable
 2009-06-17 16:11:21 +0200 aw  r273078 : #i102062# added compare support for
 OutlireParaObject's WrongList in an extra method; using in primitive
 comparators 2009-06-16 19:10:18 +0200 aw  r273037 : #i101957# corrected:
 offset needs to be added before rotation and shear 2009-06-16 18:58:43 +0200
 aw  r273035 : #i101957# added needed offset by object width to
 SdrTextObj::impDecomposeStretchTextPrimitive for vertical texts 2009-06-16
 18:35:55 +0200 aw  r273034 : #i101941# corrected object initialisation for 3D
 Scenes on Clone operator 2009-06-16 16:07:30 +0200 aw  r273024 : #i101811#
 extended renderChartPrimitive2D to create a correct embedding in a new
 MapMode 2009-06-12 19:38:07 +0200 aw  r272940 : #i101734# added test code to
 experiment on demand with more complex transformations for virtual objects
 than only translations 2009-06-12 19:37:07 +0200 aw  r272939 : #i101734#
 corrected SvtGraphicStroke preparation in MetaFile renderer (AFAP) 2009-06-12
 16:31:55 +0200 aw  r272931 : #i101648# re-enabled object creation with
 objecttype OBJ_NONE for SW Frame creation 2009-06-12 13:59:05 +0200 aw 
 r272917 : #i101598# supported AAed single line paint in VCL 2009-06-12
 11:34:25 +0200 aw  r272907 : #i101598# adapted Graphic::GetBitmap() usage
 2009-06-10 16:34:19 +0200 aw  r272830 : #i101598# added VCL_DLLPUBLIC to
 parameter class 2009-06-10 16:30:27 +0200 aw  r272829 : #i101598# extended
 calls to Graphic::GetBitmap/Ex where conversions to Bitmap objects is needed
 to user defined parameters like AntiAlisasing 2009-06-10 16:28:44 +0200 aw 
 r272828 : #i101598# extended Graphic::GetBitmap/Ex interfaces to transport
 raster conversion parameters since these calls potentially need to
 rasterconvert a contained MetaFile 2009-06-09 16:26:40 +0200 aw  r272781 :
 #i100945# checked in proposed patch for now 2009-06-08 18:01:42 +0200 aw 
 r272742 : #i101239# teached BinTextObject to register at EditEngineItemPool
 sub-pool, not on given pool directly

---
 .../inc/basegfx/polygon/b2dpolypolygoncutter.hxx   |   9 +
 .../inc/basegfx/polygon/b2dpolypolygontools.hxx    |  14 ++
 basegfx/source/curve/b2dcubicbezier.cxx            |  36 ++--
 basegfx/source/polygon/b2dpolypolygoncutter.cxx    |  79 +++++++++
 basegfx/source/polygon/b2dpolypolygontools.cxx     |  12 ++
 vcl/inc/vcl/graph.hxx                              |  44 ++++-
 vcl/inc/vcl/impgraph.hxx                           |   5 +-
 vcl/source/gdi/graph.cxx                           |  38 +---
 vcl/source/gdi/impgraph.cxx                        |  38 ++--
 vcl/source/gdi/outdev.cxx                          | 195 +++++++++++++++++----
 vcl/source/gdi/outdev6.cxx                         |  14 +-
 11 files changed, 380 insertions(+), 104 deletions(-)

diff --git a/basegfx/inc/basegfx/polygon/b2dpolypolygoncutter.hxx b/basegfx/inc/basegfx/polygon/b2dpolypolygoncutter.hxx
index 9474e51e3904..12532ff078f3 100644
--- a/basegfx/inc/basegfx/polygon/b2dpolypolygoncutter.hxx
+++ b/basegfx/inc/basegfx/polygon/b2dpolypolygoncutter.hxx
@@ -104,6 +104,15 @@ namespace basegfx
         // DIFF: Return all areas where CandidateA is not covered by CandidateB (cut B out of A)
         B2DPolyPolygon solvePolygonOperationDiff(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB);
 
+        /** merge all single PolyPolygons to a single, OR-ed PolyPolygon
+
+            @param rInput
+            The source PolyPolygons
+
+            @return A single PolyPolygon containing the Or-merged result
+        */
+        B2DPolyPolygon mergeToSinglePolyPolygon(const std::vector< basegfx::B2DPolyPolygon >& rInput);
+
     } // end of namespace tools
 } // end of namespace basegfx
 
diff --git a/basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx b/basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx
index 5c75edd7f262..c4687b3cfc5f 100644
--- a/basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx
+++ b/basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx
@@ -262,6 +262,20 @@ namespace basegfx
         bool equal(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB, const double& rfSmallValue);
         bool equal(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB);
 
+        /** snap some polygon coordinates to discrete coordinates
+
+            This method allows to snap some polygon points to discrete (integer) values
+            which equals e.g. a snap to discrete coordinates. It will snap points of
+            horizontal and vertical edges
+
+            @param rCandidate
+            The source polygon
+
+            @return
+            The modified version of the source polygon
+        */
+        B2DPolyPolygon snapPointsOfHorizontalOrVerticalEdges(const B2DPolyPolygon& rCandidate);
+
     } // end of namespace tools
 } // end of namespace basegfx
 
diff --git a/basegfx/source/curve/b2dcubicbezier.cxx b/basegfx/source/curve/b2dcubicbezier.cxx
index 76d1b74ddbca..e7247a95333b 100644
--- a/basegfx/source/curve/b2dcubicbezier.cxx
+++ b/basegfx/source/curve/b2dcubicbezier.cxx
@@ -443,21 +443,32 @@ namespace basegfx
                 bool bAIsTrivial(aVecA.equalZero());
                 bool bBIsTrivial(aVecB.equalZero());
 
+                // #i102241# prepare inverse edge length to normalize cross values;
+                // else the small compare value used in fTools::equalZero
+                // will be length dependent and this detection will work as less
+                // precise as longer the edge is. In principle, the length of the control
+                // vector would need to be used too, but to be trivial it is assumed to
+                // be of roughly equal length to the edge, so edge length can be used
+                // for both. Only needed when one of both is not trivial per se.
+                const double fInverseEdgeLength(bAIsTrivial && bBIsTrivial
+                    ? 1.0
+                    : 1.0 / aEdge.getLength());
+
                 // if A is not zero, check if it could be
                 if(!bAIsTrivial)
                 {
-                    // parallel to edge? Check aVecA, aEdge
-                    // B2DVector::areParallel is too correct, uses differences in the e15 region,
-                    // thus do own test here
-                    const double fValA(aVecA.getX() * aEdge.getY());
-                    const double fValB(aVecA.getY() * aEdge.getX());
+                    // #i102241# parallel to edge? Check aVecA, aEdge. Use cross() which does what
+                    // we need here with the precision we need
+                    const double fCross(aVecA.cross(aEdge) * fInverseEdgeLength);
 
-                    if(fTools::equalZero(fabs(fValA) - fabs(fValB)))
+                    if(fTools::equalZero(fCross))
                     {
                         // get scale to edge. Use bigger distance for numeric quality
-                        const double fScale(fabs(aEdge.getX()) > fabs(aEdge.getY()) ? aVecA.getX() / aEdge.getX() : aVecA.getY() / aEdge.getY());
+                        const double fScale(fabs(aEdge.getX()) > fabs(aEdge.getY())
+                            ? aVecA.getX() / aEdge.getX()
+                            : aVecA.getY() / aEdge.getY());
 
-                        // end point of vector in edge range?
+                        // relative end point of vector in edge range?
                         if(fTools::moreOrEqual(fScale, 0.0) && fTools::lessOrEqual(fScale, 1.0))
                         {
                             bAIsTrivial = true;
@@ -470,13 +481,14 @@ namespace basegfx
                 if(bAIsTrivial && !bBIsTrivial)
                 {
                     // parallel to edge? Check aVecB, aEdge
-                    const double fValA(aVecB.getX() * aEdge.getY());
-                    const double fValB(aVecB.getY() * aEdge.getX());
+                    const double fCross(aVecB.cross(aEdge) * fInverseEdgeLength);
 
-                    if(fTools::equalZero(fabs(fValA) - fabs(fValB)))
+                    if(fTools::equalZero(fCross))
                     {
                         // get scale to edge. Use bigger distance for numeric quality
-                        const double fScale(fabs(aEdge.getX()) > fabs(aEdge.getY()) ? aVecB.getX() / aEdge.getX() : aVecB.getY() / aEdge.getY());
+                        const double fScale(fabs(aEdge.getX()) > fabs(aEdge.getY())
+                            ? aVecB.getX() / aEdge.getX()
+                            : aVecB.getY() / aEdge.getY());
 
                         // end point of vector in edge range? Caution: controlB is directed AGAINST edge
                         if(fTools::lessOrEqual(fScale, 0.0) && fTools::moreOrEqual(fScale, -1.0))
diff --git a/basegfx/source/polygon/b2dpolypolygoncutter.cxx b/basegfx/source/polygon/b2dpolypolygoncutter.cxx
index b06e6fbafff7..0674bfe3953e 100644
--- a/basegfx/source/polygon/b2dpolypolygoncutter.cxx
+++ b/basegfx/source/polygon/b2dpolypolygoncutter.cxx
@@ -929,6 +929,85 @@ namespace basegfx
             }
         }
 
+        B2DPolyPolygon mergeToSinglePolyPolygon(const std::vector< basegfx::B2DPolyPolygon >& rInput)
+        {
+            std::vector< basegfx::B2DPolyPolygon > aInput(rInput);
+
+            // first step: prepareForPolygonOperation and simple merge of non-overlapping
+            // PolyPolygons for speedup; this is possible for the wanted OR-operation
+            if(aInput.size())
+            {
+                std::vector< basegfx::B2DPolyPolygon > aResult;
+                aResult.reserve(aInput.size());
+
+                for(sal_uInt32 a(0); a < aInput.size(); a++)
+                {
+                    const basegfx::B2DPolyPolygon aCandidate(prepareForPolygonOperation(aInput[a]));
+
+                    if(aResult.size())
+                    {
+                        const B2DRange aCandidateRange(aCandidate.getB2DRange());
+                        bool bCouldMergeSimple(false);
+
+                        for(sal_uInt32 b(0); !bCouldMergeSimple && b < aResult.size(); b++)
+                        {
+                            basegfx::B2DPolyPolygon aTarget(aResult[b]);
+                            const B2DRange aTargetRange(aTarget.getB2DRange());
+
+                            if(!aCandidateRange.overlaps(aTargetRange))
+                            {
+                                aTarget.append(aCandidate);
+                                aResult[b] = aTarget;
+                                bCouldMergeSimple = true;
+                            }
+                        }
+
+                        if(!bCouldMergeSimple)
+                        {
+                            aResult.push_back(aCandidate);
+                        }
+                    }
+                    else
+                    {
+                        aResult.push_back(aCandidate);
+                    }
+                }
+
+                aInput = aResult;
+            }
+
+            // second step: melt pairwise to a single PolyPolygon
+            while(aInput.size() > 1)
+            {
+                std::vector< basegfx::B2DPolyPolygon > aResult;
+                aResult.reserve((aInput.size() / 2) + 1);
+
+                for(sal_uInt32 a(0); a < aInput.size(); a += 2)
+                {
+                    if(a + 1 < aInput.size())
+                    {
+                        // a pair for processing
+                        aResult.push_back(solvePolygonOperationOr(aInput[a], aInput[a + 1]));
+                    }
+                    else
+                    {
+                        // last single PolyPolygon; copy to target to not lose it
+                        aResult.push_back(aInput[a]);
+                    }
+                }
+
+                aInput = aResult;
+            }
+
+            // third step: get result
+            if(1 == aInput.size())
+            {
+                return aInput[0];
+            }
+
+            return B2DPolyPolygon();
+        }
+
         //////////////////////////////////////////////////////////////////////////////
 
     } // end of namespace tools
diff --git a/basegfx/source/polygon/b2dpolypolygontools.cxx b/basegfx/source/polygon/b2dpolypolygontools.cxx
index c92f2f29147b..e6b3a448530d 100644
--- a/basegfx/source/polygon/b2dpolypolygontools.cxx
+++ b/basegfx/source/polygon/b2dpolypolygontools.cxx
@@ -569,6 +569,18 @@ namespace basegfx
             return equal(rCandidateA, rCandidateB, fSmallValue);
         }
 
+        B2DPolyPolygon snapPointsOfHorizontalOrVerticalEdges(const B2DPolyPolygon& rCandidate)
+        {
+            B2DPolyPolygon aRetval;
+
+            for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
+            {
+                aRetval.append(snapPointsOfHorizontalOrVerticalEdges(rCandidate.getB2DPolygon(a)));
+            }
+
+            return aRetval;
+        }
+
     } // end of namespace tools
 } // end of namespace basegfx
 
diff --git a/vcl/inc/vcl/graph.hxx b/vcl/inc/vcl/graph.hxx
index f56c55b7db42..9d70c67d3e55 100644
--- a/vcl/inc/vcl/graph.hxx
+++ b/vcl/inc/vcl/graph.hxx
@@ -53,6 +53,36 @@ class   OutputDevice;
 class   Font;
 class   GfxLink;
 
+class VCL_DLLPUBLIC GraphicConversionParameters
+{
+private:
+    Size            maSizePixel;            // default is (0,0)
+
+    // bitfield
+    unsigned        mbUnlimitedSize : 1;    // default is false
+    unsigned        mbAntiAliase : 1;       // default is false
+    unsigned        mbSnapHorVerLines : 1;  // default is false
+
+public:
+    GraphicConversionParameters(
+        const Size& rSizePixel = Size(),
+        bool bUnlimitedSize = false,
+        bool bAntiAliase = false,
+        bool bSnapHorVerLines = false)
+    :   maSizePixel(rSizePixel),
+        mbUnlimitedSize(bUnlimitedSize),
+        mbAntiAliase(bAntiAliase),
+        mbSnapHorVerLines(bSnapHorVerLines)
+    {
+    }
+
+    // data read access
+    const Size getSizePixel() const { return maSizePixel; }
+    bool getUnlimitedSize() const { return mbUnlimitedSize; }
+    bool getAntiAliase() const { return mbAntiAliase; }
+    bool getSnapHorVerLines() const { return mbSnapHorVerLines; }
+};
+
 class VCL_DLLPUBLIC Graphic : public SvDataCopyStream
 {
 private:
@@ -96,12 +126,14 @@ public:
     BOOL                IsAlpha() const;
     BOOL                IsAnimated() const;
 
-    Bitmap              GetBitmap() const;
-    Bitmap              GetBitmap( const Size* pSizePixel ) const;
-    BitmapEx            GetBitmapEx() const;
-    BitmapEx            GetBitmapEx( const Size* pSizePixel ) const;
-    Bitmap              GetUnlimitedBitmap( const Size* pSizePixel ) const;
-    BitmapEx            GetUnlimitedBitmapEx( const Size* pSizePixel ) const;
+    // #i102089# Access of Bitmap potentially will have to rasterconvert the Graphic
+    // if it is a MetaFile. To be able to control this conversion it is necessary to
+    // allow giving parameters which control AntiAliasing and LineSnapping of the
+    // MetaFile when played. Defaults will use a no-AAed, not snapped conversion as
+    // before.
+    Bitmap              GetBitmap(const GraphicConversionParameters& rParameters = GraphicConversionParameters()) const;
+    BitmapEx            GetBitmapEx(const GraphicConversionParameters& rParameters = GraphicConversionParameters()) const;
+
     Animation           GetAnimation() const;
     const GDIMetaFile&  GetGDIMetaFile() const;
 
diff --git a/vcl/inc/vcl/impgraph.hxx b/vcl/inc/vcl/impgraph.hxx
index 34b61a5fe21c..3b36173891ae 100644
--- a/vcl/inc/vcl/impgraph.hxx
+++ b/vcl/inc/vcl/impgraph.hxx
@@ -55,6 +55,7 @@ struct ImpSwapInfo
 class   OutputDevice;
 class   GfxLink;
 struct  ImpSwapFile;
+class GraphicConversionParameters;
 
 class ImpGraphic
 {
@@ -102,8 +103,8 @@ private:
     BOOL                ImplIsAlpha() const;
     BOOL                ImplIsAnimated() const;
 
-    Bitmap              ImplGetBitmap( const Size* pSizePixel, BOOL bUnlimited ) const;
-    BitmapEx            ImplGetBitmapEx( const Size* pSizePixel, BOOL bUnlimited ) const;
+    Bitmap              ImplGetBitmap(const GraphicConversionParameters& rParameters) const;
+    BitmapEx            ImplGetBitmapEx(const GraphicConversionParameters& rParameters) const;
     Animation           ImplGetAnimation() const;
     const GDIMetaFile&  ImplGetGDIMetaFile() const;
 
diff --git a/vcl/source/gdi/graph.cxx b/vcl/source/gdi/graph.cxx
index dfa155e29eae..77f065912e5d 100644
--- a/vcl/source/gdi/graph.cxx
+++ b/vcl/source/gdi/graph.cxx
@@ -430,44 +430,16 @@ BOOL Graphic::IsAnimated() const
 
 // ------------------------------------------------------------------------
 
-Bitmap Graphic::GetBitmap() const
+Bitmap Graphic::GetBitmap(const GraphicConversionParameters& rParameters) const
 {
-    return GetBitmap( NULL );
+    return mpImpGraphic->ImplGetBitmap(rParameters);
 }
 
 // ------------------------------------------------------------------------
 
-BitmapEx Graphic::GetBitmapEx() const
+BitmapEx Graphic::GetBitmapEx(const GraphicConversionParameters& rParameters) const
 {
-    return GetBitmapEx( NULL );
-}
-
-// ------------------------------------------------------------------------
-
-Bitmap Graphic::GetBitmap( const Size* pSizePixel ) const
-{
-    return mpImpGraphic->ImplGetBitmap( pSizePixel, FALSE );
-}
-
-// ------------------------------------------------------------------------
-
-BitmapEx Graphic::GetBitmapEx( const Size* pSizePixel ) const
-{
-    return mpImpGraphic->ImplGetBitmapEx( pSizePixel, FALSE );
-}
-
-// ------------------------------------------------------------------------
-
-Bitmap Graphic::GetUnlimitedBitmap( const Size* pSizePixel ) const
-{
-    return mpImpGraphic->ImplGetBitmap( pSizePixel, TRUE ) ;
-}
-
-// ------------------------------------------------------------------------
-
-BitmapEx Graphic::GetUnlimitedBitmapEx( const Size* pSizePixel ) const
-{
-    return mpImpGraphic->ImplGetBitmapEx( pSizePixel, TRUE ) ;
+    return mpImpGraphic->ImplGetBitmapEx(rParameters);
 }
 
 // ------------------------------------------------------------------------
@@ -553,7 +525,7 @@ Size Graphic::GetSizePixel( const OutputDevice* pRefDevice ) const
     Size aRet;
 
     if( GRAPHIC_BITMAP == mpImpGraphic->ImplGetType() )
-        aRet = mpImpGraphic->ImplGetBitmapEx( NULL, FALSE ).GetSizePixel();
+        aRet = mpImpGraphic->ImplGetBitmapEx(GraphicConversionParameters()).GetSizePixel();
     else
         aRet = ( pRefDevice ? pRefDevice : Application::GetDefaultDevice() )->LogicToPixel( GetPrefSize(), GetPrefMapMode() );
 
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index a67d6fa7feac..d73f35bef962 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -483,7 +483,7 @@ BOOL ImpGraphic::ImplIsAnimated() const
 
 // ------------------------------------------------------------------------
 
-Bitmap ImpGraphic::ImplGetBitmap( const Size* pSizePixel, BOOL bUnlimited ) const
+Bitmap ImpGraphic::ImplGetBitmap(const GraphicConversionParameters& rParameters) const
 {
     Bitmap aRetBmp;
 
@@ -494,8 +494,8 @@ Bitmap ImpGraphic::ImplGetBitmap( const Size* pSizePixel, BOOL bUnlimited ) cons
 
         aRetBmp = rRetBmpEx.GetBitmap( &aReplaceColor );
 
-        if( pSizePixel )
-            aRetBmp.Scale( *pSizePixel );
+        if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height())
+            aRetBmp.Scale(rParameters.getSizePixel());
     }
     else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() )
     {
@@ -508,16 +508,18 @@ Bitmap ImpGraphic::ImplGetBitmap( const Size* pSizePixel, BOOL bUnlimited ) cons
         Size            aDrawSize( aVDev.LogicToPixel( maMetaFile.GetPrefSize(), maMetaFile.GetPrefMapMode() ) );
         Size            aSizePix( labs( aBRPix.X() - aTLPix.X() ) + 1, labs( aBRPix.Y() - aTLPix.Y() ) + 1 );
 
-        if( pSizePixel && aSizePix.Width() && aSizePix.Height() )
+        if(rParameters.getSizePixel().Width() && rParameters.getSizePixel().Height())
         {
-            aDrawSize.Width() = FRound( (double) pSizePixel->Width() * (double) aDrawSize.Width() / (double) aSizePix.Width() );
-            aDrawSize.Height() = FRound( (double) pSizePixel->Height() * (double) aDrawSize.Height() / (double) aSizePix.Height() );
+            aDrawSize.Width() = FRound((double)rParameters.getSizePixel().Width() *
+                (double)aDrawSize.Width() / (double)aSizePix.Width());
+            aDrawSize.Height() = FRound((double)rParameters.getSizePixel().Height() *
+                (double)aDrawSize.Height() / (double)aSizePix.Height());
 
-            aSizePix = *pSizePixel;
+            aSizePix = rParameters.getSizePixel();
         }
 
-        if( aSizePix.Width() && aSizePix.Height() && !bUnlimited &&
-            ( aSizePix.Width() > GRAPHIC_MTFTOBMP_MAXEXT || aSizePix.Height() > GRAPHIC_MTFTOBMP_MAXEXT ) )
+        if( aSizePix.Width() && aSizePix.Height() && !rParameters.getUnlimitedSize()
+            && (aSizePix.Width() > GRAPHIC_MTFTOBMP_MAXEXT || aSizePix.Height() > GRAPHIC_MTFTOBMP_MAXEXT))
         {
             const Size  aOldSizePix( aSizePix );
             double      fWH = (double) aSizePix.Width() / aSizePix.Height();
@@ -533,6 +535,16 @@ Bitmap ImpGraphic::ImplGetBitmap( const Size* pSizePixel, BOOL bUnlimited ) cons
 
         if( aVDev.SetOutputSizePixel( aSizePix ) )
         {
+            if(rParameters.getAntiAliase())
+            {
+                aVDev.SetAntialiasing(aVDev.GetAntialiasing() | ANTIALIASING_ENABLE_B2DDRAW);
+            }
+
+            if(rParameters.getSnapHorVerLines())
+            {
+                aVDev.SetAntialiasing(aVDev.GetAntialiasing() | ANTIALIASING_PIXELSNAPHAIRLINE);
+            }
+
             ImplDraw( &aVDev, aNullPt, aDrawSize );
             aRetBmp =  aVDev.GetBitmap( aNullPt, aVDev.GetOutputSizePixel() );
         }
@@ -549,7 +561,7 @@ Bitmap ImpGraphic::ImplGetBitmap( const Size* pSizePixel, BOOL bUnlimited ) cons
 
 // ------------------------------------------------------------------------
 
-BitmapEx ImpGraphic::ImplGetBitmapEx( const Size* pSizePixel, BOOL bUnlimited ) const
+BitmapEx ImpGraphic::ImplGetBitmapEx(const GraphicConversionParameters& rParameters) const
 {
     BitmapEx aRetBmpEx;
 
@@ -557,13 +569,13 @@ BitmapEx ImpGraphic::ImplGetBitmapEx( const Size* pSizePixel, BOOL bUnlimited )
     {
         aRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx );
 
-        if( pSizePixel )
-            aRetBmpEx.Scale( *pSizePixel );
+        if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height())
+            aRetBmpEx.Scale(rParameters.getSizePixel());
     }
     else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() )
     {
         const ImpGraphic aMonoMask( maMetaFile.GetMonochromeMtf( COL_BLACK ) );
-        aRetBmpEx = BitmapEx( ImplGetBitmap( pSizePixel, bUnlimited ), aMonoMask.ImplGetBitmap( pSizePixel, bUnlimited ) );
+        aRetBmpEx = BitmapEx(ImplGetBitmap(rParameters), aMonoMask.ImplGetBitmap(rParameters));
     }
 
     return aRetBmpEx;
diff --git a/vcl/source/gdi/outdev.cxx b/vcl/source/gdi/outdev.cxx
index 0e9da9f81136..ebcf31199364 100644
--- a/vcl/source/gdi/outdev.cxx
+++ b/vcl/source/gdi/outdev.cxx
@@ -68,6 +68,7 @@
 #include <basegfx/polygon/b2dpolypolygon.hxx>
 #include <basegfx/matrix/b2dhommatrix.hxx>
 #include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
 
 #include <com/sun/star/awt/XGraphics.hpp>
 #include <com/sun/star/uno/Sequence.hxx>
@@ -2285,8 +2286,35 @@ void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt )
     if ( mbInitLineColor )
         ImplInitLineColor();
 
-    Point aStartPt = ImplLogicToDevicePixel( rStartPt );
-    Point aEndPt = ImplLogicToDevicePixel( rEndPt );
+    // #i101598# support AA and snap for lines, too
+    if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
+        && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
+        && ROP_OVERPAINT == GetRasterOp()
+        && IsLineColor())
+    {
+        // at least transform with double precision to device coordinates; this will
+        // avoid pixel snap of single, appended lines
+        const basegfx::B2DHomMatrix aTransform(ImplGetDeviceTransformation());
+        const basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
+        basegfx::B2DPolygon aB2DPolyLine;
+
+        aB2DPolyLine.append(basegfx::B2DPoint(rStartPt.X(), rStartPt.Y()));
+        aB2DPolyLine.append(basegfx::B2DPoint(rEndPt.X(), rEndPt.Y()));
+        aB2DPolyLine.transform( aTransform );
+
+        if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
+        {
+            aB2DPolyLine = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyLine);
+        }
+
+        if(mpGraphics->DrawPolyLine(aB2DPolyLine, aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, this))
+        {
+            return;
+        }
+    }
+
+    const Point aStartPt(ImplLogicToDevicePixel(rStartPt));
+    const Point aEndPt(ImplLogicToDevicePixel(rEndPt));
 
     mpGraphics->DrawLine( aStartPt.X(), aStartPt.Y(), aEndPt.X(), aEndPt.Y(), this );
 
@@ -2445,21 +2473,27 @@ void OutputDevice::DrawPolyLine( const Polygon& rPoly )
         ImplInitLineColor();
 
     // use b2dpolygon drawing if possible
-    if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) && mpGraphics->supportsOperation(OutDevSupport_B2DDraw))
+    if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
+        && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
+        && ROP_OVERPAINT == GetRasterOp()
+        && IsLineColor())
     {
-        ::basegfx::B2DPolygon aB2DPolyLine = rPoly.getB2DPolygon();
+        basegfx::B2DPolygon aB2DPolyLine(rPoly.getB2DPolygon());
         const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
-        aB2DPolyLine.transform( aTransform );
         const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
 
-        if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) && (mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE))
+        // transform the polygon
+        aB2DPolyLine.transform( aTransform );
+
+        if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
         {
-            // #i98289#
             aB2DPolyLine = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyLine);
         }
 
-        if( mpGraphics->DrawPolyLine( aB2DPolyLine, aB2DLineWidth, basegfx::B2DLINEJOIN_ROUND, this ) )
+        if(mpGraphics->DrawPolyLine(aB2DPolyLine, aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, this))
+        {
             return;
+        }
     }
 
     Polygon aPoly = ImplLogicToDevicePixel( rPoly );
@@ -2598,13 +2632,40 @@ void OutputDevice::DrawPolygon( const Polygon& rPoly )
         ImplInitFillColor();
 
     // use b2dpolygon drawing if possible
-    if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) && mpGraphics->supportsOperation(OutDevSupport_B2DDraw))
+    if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
+        && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
+        && ROP_OVERPAINT == GetRasterOp()
+        && (IsLineColor() || IsFillColor()))
     {
-        ::basegfx::B2DPolyPolygon aB2DPolyPolygon( rPoly.getB2DPolygon() );
         const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
-        aB2DPolyPolygon.transform( aTransform );
-        if( mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, 0.0, this ) )
+        basegfx::B2DPolygon aB2DPolygon(rPoly.getB2DPolygon());
+        bool bSuccess(true);
+
+        // transform the polygon and ensure closed
+        aB2DPolygon.transform(aTransform);
+        aB2DPolygon.setClosed(true);
+
+        if(IsFillColor())
+        {
+            bSuccess = mpGraphics->DrawPolyPolygon(basegfx::B2DPolyPolygon(aB2DPolygon), 0.0, this);
+        }
+
+        if(bSuccess && IsLineColor())
+        {
+            const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
+
+            if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
+            {
+                aB2DPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolygon);
+            }
+
+            bSuccess = mpGraphics->DrawPolyLine(aB2DPolygon, aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, this);
+        }
+
+        if(bSuccess)
+        {
             return;
+        }
     }
 
     Polygon aPoly = ImplLogicToDevicePixel( rPoly );
@@ -2661,13 +2722,43 @@ void OutputDevice::DrawPolyPolygon( const PolyPolygon& rPolyPoly )
         ImplInitFillColor();
 
     // use b2dpolygon drawing if possible
-    if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) && mpGraphics->supportsOperation(OutDevSupport_B2DDraw))
+    if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
+        && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
+        && ROP_OVERPAINT == GetRasterOp()
+        && (IsLineColor() || IsFillColor()))
     {
-        ::basegfx::B2DPolyPolygon aB2DPolyPolygon = rPolyPoly.getB2DPolyPolygon();
         const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
-        aB2DPolyPolygon.transform( aTransform );
-        if( mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, 0.0, this ) )
+        basegfx::B2DPolyPolygon aB2DPolyPolygon(rPolyPoly.getB2DPolyPolygon());
+        bool bSuccess(true);
+
+        // transform the polygon and ensure closed
+        aB2DPolyPolygon.transform(aTransform);
+        aB2DPolyPolygon.setClosed(true);
+
+        if(IsFillColor())
+        {
+            bSuccess = mpGraphics->DrawPolyPolygon(aB2DPolyPolygon, 0.0, this);
+        }
+
+        if(bSuccess && IsLineColor())
+        {
+            const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
+
+            if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
+            {
+                aB2DPolyPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyPolygon);
+            }
+
+            for(sal_uInt32 a(0); bSuccess && a < aB2DPolyPolygon.count(); a++)
+            {
+                bSuccess = mpGraphics->DrawPolyLine(aB2DPolyPolygon.getB2DPolygon(a), aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, this);
+            }
+        }
+
+        if(bSuccess)
+        {
             return;
+        }
     }
 
     if ( nPoly == 1 )
@@ -2748,13 +2839,43 @@ void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly
     if( mbInitFillColor )
         ImplInitFillColor();
 
-    if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) && mpGraphics->supportsOperation(OutDevSupport_B2DDraw))
+    if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
+        && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
+        && ROP_OVERPAINT == GetRasterOp()
+        && (IsLineColor() || IsFillColor()))
     {
-        const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
-        ::basegfx::B2DPolyPolygon aB2DPP = rB2DPolyPoly;
-        aB2DPP.transform( aTransform );
-        if( mpGraphics->DrawPolyPolygon( aB2DPP, 0.0, this ) )
+        const basegfx::B2DHomMatrix aTransform(ImplGetDeviceTransformation());
+        basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly);
+        bool bSuccess(true);
+
+        // transform the polygon and ensure closed
+        aB2DPolyPolygon.transform(aTransform);
+        aB2DPolyPolygon.setClosed(true);
+
+        if(IsFillColor())
+        {
+            bSuccess = mpGraphics->DrawPolyPolygon(aB2DPolyPolygon, 0.0, this);
+        }
+
+        if(bSuccess && IsLineColor())
+        {
+            const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
+
+            if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
+            {
+                aB2DPolyPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyPolygon);
+            }
+
+            for(sal_uInt32 a(0);bSuccess && a < aB2DPolyPolygon.count(); a++)
+            {
+                bSuccess = mpGraphics->DrawPolyLine(aB2DPolyPolygon.getB2DPolygon(a), aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, this);
+            }
+        }
+
+        if(bSuccess)
+        {
             return;
+        }
     }
 
     // fallback to old polygon drawing if needed
@@ -2809,28 +2930,34 @@ void OutputDevice::DrawPolyLine(
         ImplInitLineColor();
 
     // #i98289# use b2dpolygon drawing if possible
-    if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) && mpGraphics->supportsOperation(OutDevSupport_B2DDraw))
+    if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
+        && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
+        && ROP_OVERPAINT == GetRasterOp()
+        && IsLineColor())
     {
-        const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
-        ::basegfx::B2DVector aB2DLineWidth(1.0, 1.0);
-
-        // transform the line width if used
-        if( fLineWidth != 0.0 )
-            aB2DLineWidth = aTransform * ::basegfx::B2DVector( fLineWidth, fLineWidth );
+        const basegfx::B2DHomMatrix aTransform(ImplGetDeviceTransformation());
+        basegfx::B2DPolygon aB2DPolygon(rB2DPolygon);
+        basegfx::B2DVector aB2DLineWidth(1.0, 1.0);
 
         // transform the polygon
-        ::basegfx::B2DPolygon aB2DPL = rB2DPolygon;
-        aB2DPL.transform( aTransform );
+        aB2DPolygon.transform(aTransform);
 
-        if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) && (mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE))
+        // transform the line width if used
+        if(fLineWidth != 0.0)
         {
-            // #i98289#
-            aB2DPL = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPL);
+            aB2DLineWidth = aTransform * ::basegfx::B2DVector(fLineWidth, fLineWidth);
+        }
+
+        if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
+        {
+            aB2DPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolygon);
         }
 
         // draw the polyline
-        if( mpGraphics->DrawPolyLine( aB2DPL, aB2DLineWidth, eLineJoin, this ) )
+        if(mpGraphics->DrawPolyLine(aB2DPolygon, aB2DLineWidth, eLineJoin, this))
+        {
             return;
+        }
     }
 
     // fallback to old polygon drawing if needed
diff --git a/vcl/source/gdi/outdev6.cxx b/vcl/source/gdi/outdev6.cxx
index cee4f475a577..a11e276982f7 100644
--- a/vcl/source/gdi/outdev6.cxx
+++ b/vcl/source/gdi/outdev6.cxx
@@ -185,14 +185,20 @@ void OutputDevice::DrawTransparent( const basegfx::B2DPolyPolygon& rB2DPolyPoly,
     if( mbInitFillColor )
         ImplInitFillColor();
 
-    if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) && mpGraphics->supportsOperation(OutDevSupport_B2DDraw))
+    if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
+        && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
+        && ROP_OVERPAINT == GetRasterOp()
+        && IsFillColor())
     {
         // b2dpolygon support not implemented yet on non-UNX platforms
         const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
-        ::basegfx::B2DPolyPolygon aB2DPP = rB2DPolyPoly;
-        aB2DPP.transform( aTransform );
+        basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly);
 
-        if( mpGraphics->DrawPolyPolygon( aB2DPP, fTransparency, this ) )
+        // transform the polygon and ensure closed
+        aB2DPolyPolygon.transform(aTransform);
+        aB2DPolyPolygon.setClosed(true);
+
+        if(mpGraphics->DrawPolyPolygon(aB2DPolyPolygon, fTransparency, this))
         {
 #if 0
             // MetaB2DPolyPolygonAction is not implemented yet:
-- 
cgit