[Libreoffice-commits] core.git: include/tools tools/inc tools/source

Andreas Brandner Andreas.Brandner at cib.de
Sun Dec 10 22:25:48 UTC 2017


 include/tools/poly.hxx        |    8 
 tools/inc/poly.h              |   14 
 tools/source/generic/poly.cxx | 1128 ++++++++++++++++++++----------------------
 3 files changed, 558 insertions(+), 592 deletions(-)

New commits:
commit 225115af05cba9a603130914b49c5b28ed451108
Author: Andreas Brandner <Andreas.Brandner at cib.de>
Date:   Fri Sep 15 09:17:17 2017 +0200

    tdf#62525 tools: use cow_wrapper class for Polygon
    
    Change-Id: I78f141762f593b36d32eb3eb2cda8fdae54b7277
    Reviewed-on: https://gerrit.libreoffice.org/42309
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/include/tools/poly.hxx b/include/tools/poly.hxx
index 223f2c1e6731..a1351aa299a2 100644
--- a/include/tools/poly.hxx
+++ b/include/tools/poly.hxx
@@ -23,6 +23,7 @@
 #include <tools/gen.hxx>
 #include <tools/debug.hxx>
 #include <o3tl/typed_flags_set.hxx>
+#include <o3tl/cow_wrapper.hxx>
 
 #include <vector>
 
@@ -72,10 +73,10 @@ namespace tools {
 
 class SAL_WARN_UNUSED TOOLS_DLLPUBLIC Polygon
 {
+public:
+    typedef             o3tl::cow_wrapper<ImplPolygon> ImplType;
 private:
-    ImplPolygon*        mpImplPolygon;
-
-    TOOLS_DLLPRIVATE inline void ImplMakeUnique();
+    ImplType            mpImplPolygon;
 
 public:
     static void         ImplReduceEdges( tools::Polygon& rPoly, const double& rArea, sal_uInt16 nPercent );
@@ -101,6 +102,7 @@ public:
                                  sal_uInt16 nPoints );
 
                         Polygon( const tools::Polygon& rPoly );
+                        Polygon( tools::Polygon&& rPoly);
                         ~Polygon();
 
     void                SetPoint( const Point& rPt, sal_uInt16 nPos );
diff --git a/tools/inc/poly.h b/tools/inc/poly.h
index 835beb8bcffe..4adb7184708e 100644
--- a/tools/inc/poly.h
+++ b/tools/inc/poly.h
@@ -30,17 +30,29 @@ public:
     Point*          mpPointAry;
     PolyFlags*      mpFlagAry;
     sal_uInt16      mnPoints;
-    sal_uInt32      mnRefCount;
 };
 
 class SAL_WARN_UNUSED ImplPolygon  : public ImplPolygonData
 {
 public:
+                    ImplPolygon() { mpPointAry = nullptr; mpFlagAry = nullptr; mnPoints = 0;};
                     ImplPolygon( sal_uInt16 nInitSize, bool bFlags = false );
                     ImplPolygon( sal_uInt16 nPoints, const Point* pPtAry, const PolyFlags* pInitFlags );
                     ImplPolygon( const ImplPolygon& rImplPoly );
+                    ImplPolygon( const tools::Rectangle& rRect );
+                    ImplPolygon( const tools::Rectangle& rRect, sal_uInt32 nHorzRound, sal_uInt32 nVertRound);
+                    ImplPolygon( const Point& rCenter, long nRadX, long nRadY );
+                    ImplPolygon( const tools::Rectangle& rBound, const Point& rStart, const Point& rEnd,
+                                    PolyStyle eStyle, bool bFullCircle );
+                    ImplPolygon( const Point& rBezPt1, const Point& rCtrlPt1, const Point& rBezPt2,
+                                    const Point& rCtrlPt2, sal_uInt16 nPoints );
+                    ImplPolygon(const basegfx::B2DPolygon& rPolygon);
                     ~ImplPolygon();
 
+    bool            operator==( const ImplPolygon& rCandidate ) const;
+
+    void            ImplInitDefault();
+    void            ImplInitSize(sal_uInt16 nInitSize, bool bFlags = false);
     void            ImplSetSize( sal_uInt16 nSize, bool bResize = true );
     void            ImplCreateFlagArray();
     bool            ImplSplit( sal_uInt16 nPos, sal_uInt16 nSpace, ImplPolygon const * pInitPoly = nullptr );
diff --git a/tools/source/generic/poly.cxx b/tools/source/generic/poly.cxx
index 1904d85d5a9d..664428426352 100644
--- a/tools/source/generic/poly.cxx
+++ b/tools/source/generic/poly.cxx
@@ -53,95 +53,504 @@
 #define SMALL_DVALUE    0.0000001
 #define FSQRT2          1.4142135623730950488016887242097
 
-static ImplPolygonData aStaticImplPolygon =
+inline double ImplGetParameter( const Point& rCenter, const Point& rPt, double fWR, double fHR )
 {
-    nullptr, nullptr, 0, 0
-};
+    const long nDX = rPt.X() - rCenter.X();
+    double fAngle = atan2( -rPt.Y() + rCenter.Y(), ( ( nDX == 0 ) ? 0.000000001 : nDX ) );
+
+    return atan2(fWR*sin(fAngle), fHR*cos(fAngle));
+}
+
+ImplPolygon::ImplPolygon( sal_uInt16 nInitSize, bool bFlags  )
+{
+    ImplInitSize(nInitSize, bFlags);
+}
+
+ImplPolygon::ImplPolygon( const ImplPolygon& rImpPoly )
+{
+    if ( rImpPoly.mnPoints )
+    {
+        mpPointAry = new Point[ rImpPoly.mnPoints ];
+        memcpy( mpPointAry,
+                rImpPoly.mpPointAry,
+                static_cast<std::size_t>(rImpPoly.mnPoints)*sizeof(Point) );
+
+        if( rImpPoly.mpFlagAry )
+        {
+            mpFlagAry = new PolyFlags[ rImpPoly.mnPoints ];
+            memcpy( mpFlagAry, rImpPoly.mpFlagAry, rImpPoly.mnPoints );
+        }
+        else
+            mpFlagAry = nullptr;
+    }
+    else
+    {
+        mpPointAry = nullptr;
+        mpFlagAry = nullptr;
+    }
+
+    mnPoints   = rImpPoly.mnPoints;
+}
+
+ImplPolygon::ImplPolygon( sal_uInt16 nInitSize, const Point* pInitAry, const PolyFlags* pInitFlags )
+{
+    if ( nInitSize )
+    {
+        mpPointAry = new Point[ nInitSize ];
+        memcpy( mpPointAry,
+                pInitAry,
+                static_cast<std::size_t>(nInitSize)*sizeof(Point) );
+
+        if( pInitFlags )
+        {
+            mpFlagAry = new PolyFlags[ nInitSize ];
+            memcpy( mpFlagAry, pInitFlags, nInitSize );
+        }
+        else
+            mpFlagAry = nullptr;
+    }
+    else
+    {
+        mpPointAry = nullptr;
+        mpFlagAry  = nullptr;
+    }
+
+    mnPoints   = nInitSize;
+}
+
+ImplPolygon::ImplPolygon( const tools::Rectangle& rRect )
+{
+    if ( !rRect.IsEmpty() )
+    {
+         ImplInitSize(5);
+         mpPointAry[0] = rRect.TopLeft();
+         mpPointAry[1] = rRect.TopRight();
+         mpPointAry[2] = rRect.BottomRight();
+         mpPointAry[3] = rRect.BottomLeft();
+         mpPointAry[4] = rRect.TopLeft();
+     }
+     else
+        ImplInitDefault();
+}
+
+ImplPolygon::ImplPolygon( const tools::Rectangle& rRect, sal_uInt32 nHorzRound, sal_uInt32 nVertRound )
+{
+    if ( !rRect.IsEmpty() )
+    {
+        tools::Rectangle aRect( rRect );
+        aRect.Justify();            // SJ: i9140
+
+        nHorzRound = std::min( nHorzRound, static_cast<sal_uInt32>(labs( aRect.GetWidth() >> 1 )) );
+        nVertRound = std::min( nVertRound, static_cast<sal_uInt32>(labs( aRect.GetHeight() >> 1 )) );
+
+        if( !nHorzRound && !nVertRound )
+        {
+            ImplInitSize(5);
+            mpPointAry[0] = aRect.TopLeft();
+            mpPointAry[1] = aRect.TopRight();
+            mpPointAry[2] = aRect.BottomRight();
+            mpPointAry[3] = aRect.BottomLeft();
+            mpPointAry[4] = aRect.TopLeft();
+        }
+        else
+        {
+            const Point     aTL( aRect.Left() + nHorzRound, aRect.Top() + nVertRound );
+            const Point     aTR( aRect.Right() - nHorzRound, aRect.Top() + nVertRound );
+            const Point     aBR( aRect.Right() - nHorzRound, aRect.Bottom() - nVertRound );
+            const Point     aBL( aRect.Left() + nHorzRound, aRect.Bottom() - nVertRound );
+            std::unique_ptr<tools::Polygon> pEllipsePoly( new tools::Polygon( Point(), nHorzRound, nVertRound ) );
+            sal_uInt16 i, nEnd, nSize4 = pEllipsePoly->GetSize() >> 2;
+
+            ImplInitSize((pEllipsePoly->GetSize() + 1));
+
+            const Point* pSrcAry = pEllipsePoly->GetConstPointAry();
+            Point* pDstAry = mpPointAry;
+
+            for( i = 0, nEnd = nSize4; i < nEnd; i++ )
+                ( pDstAry[ i ] = pSrcAry[ i ] ) += aTR;
+
+            for( nEnd = nEnd + nSize4; i < nEnd; i++ )
+                ( pDstAry[ i ] = pSrcAry[ i ] ) += aTL;
+
+            for( nEnd = nEnd + nSize4; i < nEnd; i++ )
+                ( pDstAry[ i ] = pSrcAry[ i ] ) += aBL;
+
+            for( nEnd = nEnd + nSize4; i < nEnd; i++ )
+                ( pDstAry[ i ] = pSrcAry[ i ] ) += aBR;
+
+            pDstAry[ nEnd ] = pDstAry[ 0 ];
+        }
+    }
+    else
+        ImplInitDefault();
+}
+
+ImplPolygon::ImplPolygon( const Point& rCenter, long nRadX, long nRadY )
+{
+    if( nRadX && nRadY )
+    {
+        sal_uInt16 nPoints;
+        // Compute default (depends on size)
+        long nRadXY;
+        const bool bOverflow = o3tl::checked_multiply(nRadX, nRadY, nRadXY);
+        if (!bOverflow)
+        {
+            nPoints = (sal_uInt16) MinMax(
+                ( F_PI * ( 1.5 * ( nRadX + nRadY ) -
+                           sqrt( (double) labs(nRadXY) ) ) ),
+                32, 256 );
+        }
+        else
+        {
+           nPoints = 256;
+        }
+
+        if( ( nRadX > 32 ) && ( nRadY > 32 ) && ( nRadX + nRadY ) < 8192 )
+            nPoints >>= 1;
+
+        // Ceil number of points until divisible by four
+        nPoints = (nPoints + 3) & ~3;
+        ImplInitSize(nPoints);
+
+        sal_uInt16 i;
+        sal_uInt16 nPoints2 = nPoints >> 1;
+        sal_uInt16 nPoints4 = nPoints >> 2;
+        double nAngle;
+        double nAngleStep = F_PI2 / ( nPoints4 - 1 );
+
+        for( i=0, nAngle = 0.0; i < nPoints4; i++, nAngle += nAngleStep )
+        {
+            long nX = FRound( nRadX * cos( nAngle ) );
+            long nY = FRound( -nRadY * sin( nAngle ) );
+
+            Point* pPt = &(mpPointAry[i]);
+            pPt->X() =  nX + rCenter.X();
+            pPt->Y() =  nY + rCenter.Y();
+            pPt = &(mpPointAry[nPoints2-i-1]);
+            pPt->X() = -nX + rCenter.X();
+            pPt->Y() =  nY + rCenter.Y();
+            pPt = &(mpPointAry[i+nPoints2]);
+            pPt->X() = -nX + rCenter.X();
+            pPt->Y() = -nY + rCenter.Y();
+            pPt = &(mpPointAry[nPoints-i-1]);
+            pPt->X() =  nX + rCenter.X();
+            pPt->Y() = -nY + rCenter.Y();
+        }
+    }
+    else
+        ImplInitDefault();
+}
+
+ImplPolygon::ImplPolygon( const tools::Rectangle& rBound, const Point& rStart, const Point& rEnd,
+    PolyStyle eStyle, bool bFullCircle )
+{
+    const long  nWidth = rBound.GetWidth();
+    const long  nHeight = rBound.GetHeight();
+
+    if( ( nWidth > 1 ) && ( nHeight > 1 ) )
+    {
+        const Point aCenter( rBound.Center() );
+        const long  nRadX = aCenter.X() - rBound.Left();
+        const long  nRadY = aCenter.Y() - rBound.Top();
+        sal_uInt16  nPoints;
+
+        long nRadXY;
+        const bool bOverflow = o3tl::checked_multiply(nRadX, nRadY, nRadXY);
+        if (!bOverflow)
+        {
+            nPoints = (sal_uInt16) MinMax(
+                ( F_PI * ( 1.5 * ( nRadX + nRadY ) -
+                           sqrt( (double) labs(nRadXY) ) ) ),
+                32, 256 );
+        }
+        else
+        {
+            nPoints = 256;
+        }
+
+
+        if( ( nRadX > 32 ) && ( nRadY > 32 ) && ( nRadX + nRadY ) < 8192 )
+            nPoints >>= 1;
+
+        // compute threshold
+        const double    fRadX = nRadX;
+        const double    fRadY = nRadY;
+        const double    fCenterX = aCenter.X();
+        const double    fCenterY = aCenter.Y();
+        double          fStart = ImplGetParameter( aCenter, rStart, fRadX, fRadY );
+        double          fEnd = ImplGetParameter( aCenter, rEnd, fRadX, fRadY );
+        double          fDiff = fEnd - fStart;
+        double          fStep;
+        sal_uInt16      nStart;
+        sal_uInt16      nEnd;
+
+        if( fDiff < 0. )
+            fDiff += F_2PI;
+
+        if ( bFullCircle )
+            fDiff = F_2PI;
+
+        // Proportionally shrink number of points( fDiff / (2PI) );
+        nPoints = std::max( (sal_uInt16) ( ( fDiff * 0.1591549 ) * nPoints ), (sal_uInt16) 16 );
+        fStep = fDiff / ( nPoints - 1 );
+
+        if( PolyStyle::Pie == eStyle )
+        {
+            const Point aCenter2( FRound( fCenterX ), FRound( fCenterY ) );
+
+            nStart = 1;
+            nEnd = nPoints + 1;
+            ImplInitSize((nPoints + 2));
+            mpPointAry[ 0 ] = aCenter2;
+            mpPointAry[ nEnd ] = aCenter2;
+        }
+        else
+        {
+            ImplInitSize( ( PolyStyle::Chord == eStyle ) ? ( nPoints + 1 ) : nPoints );
+            nStart = 0;
+            nEnd = nPoints;
+        }
+
+        for(; nStart < nEnd; nStart++, fStart += fStep )
+        {
+            Point& rPt = mpPointAry[ nStart ];
+
+            rPt.X() = FRound( fCenterX + fRadX * cos( fStart ) );
+            rPt.Y() = FRound( fCenterY - fRadY * sin( fStart ) );
+        }
+
+        if( PolyStyle::Chord == eStyle )
+            mpPointAry[ nPoints ] = mpPointAry[ 0 ];
+    }
+    else
+        ImplInitDefault();
+}
+
+ImplPolygon::ImplPolygon( const Point& rBezPt1, const Point& rCtrlPt1,
+    const Point& rBezPt2, const Point& rCtrlPt2, sal_uInt16 nPoints )
+{
+    nPoints = ( 0 == nPoints ) ? 25 : ( ( nPoints < 2 ) ? 2 : nPoints );
+
+    const double    fInc = 1.0 / ( nPoints - 1 );
+    double          fK_1 = 0.0, fK1_1 = 1.0;
+    double          fK_2, fK_3, fK1_2, fK1_3;
+    const double    fX0 = rBezPt1.X();
+    const double    fY0 = rBezPt1.Y();
+    const double    fX1 = 3.0 * rCtrlPt1.X();
+    const double    fY1 = 3.0 * rCtrlPt1.Y();
+    const double    fX2 = 3.0 * rCtrlPt2.X();
+    const double    fY2 = 3.0 * rCtrlPt2.Y();
+    const double    fX3 = rBezPt2.X();
+    const double    fY3 = rBezPt2.Y();
+
+    ImplInitSize(nPoints);
+
+    for( sal_uInt16 i = 0; i < nPoints; i++, fK_1 += fInc, fK1_1 -= fInc )
+    {
+        Point& rPt = mpPointAry[ i ];
+
+        fK_2 = fK_1;
+        fK_3 = ( fK_2 *= fK_1 );
+        fK_3 *= fK_1;
+        fK1_2 = fK1_1;
+        fK1_3 = ( fK1_2 *= fK1_1 );
+        fK1_3 *= fK1_1;
+        double fK12 = fK_1 * fK1_2;
+        double fK21 = fK_2 * fK1_1;
+
+        rPt.X() = FRound( fK1_3 * fX0 + fK12 * fX1 + fK21 * fX2 + fK_3 * fX3 );
+        rPt.Y() = FRound( fK1_3 * fY0 + fK12 * fY1 + fK21 * fY2 + fK_3 * fY3 );
+    }
+}
+
+// constructor to convert from basegfx::B2DPolygon
+// #i76891# Needed to change from adding all control points (even for unused
+// edges) and creating a fixed-size Polygon in the first run to creating the
+// minimal Polygon. This requires a temporary Point- and Flag-Array for curves
+// and a memcopy at ImplPolygon creation, but contains no zero-controlpoints
+// for straight edges.
+ImplPolygon::ImplPolygon(const basegfx::B2DPolygon& rPolygon)
+{
+    const bool bCurve(rPolygon.areControlPointsUsed());
+    const bool bClosed(rPolygon.isClosed());
+    sal_uInt32 nB2DLocalCount(rPolygon.count());
+
+    ImplInitDefault();
+
+    if(bCurve)
+    {
+        // #127979# Reduce source point count hard to the limit of the tools Polygon
+        if(nB2DLocalCount > ((0x0000ffff / 3) - 1))
+        {
+            OSL_FAIL("Polygon::Polygon: Too many points in given B2DPolygon, need to reduce hard to maximum of tools Polygon (!)");
+            nB2DLocalCount = ((0x0000ffff / 3) - 1);
+        }
+
+        // calculate target point count
+        const sal_uInt32 nLoopCount(bClosed ? nB2DLocalCount : (nB2DLocalCount ? nB2DLocalCount - 1 : 0 ));
+
+        if(nLoopCount)
+        {
+            // calculate maximum array size and allocate; prepare insert index
+            const sal_uInt32 nMaxTargetCount((nLoopCount * 3) + 1);
+            ImplInitSize(static_cast< sal_uInt16 >(nMaxTargetCount), true);
+
+            // prepare insert index and current point
+            sal_uInt32 nArrayInsert(0);
+            basegfx::B2DCubicBezier aBezier;
+            aBezier.setStartPoint(rPolygon.getB2DPoint(0));
+
+            for(sal_uInt32 a(0); a < nLoopCount; a++)
+            {
+                // add current point (always) and remember StartPointIndex for evtl. later corrections
+                const Point aStartPoint(FRound(aBezier.getStartPoint().getX()), FRound(aBezier.getStartPoint().getY()));
+                const sal_uInt32 nStartPointIndex(nArrayInsert);
+                mpPointAry[nStartPointIndex] = aStartPoint;
+                mpFlagAry[nStartPointIndex] = PolyFlags::Normal;
+                nArrayInsert++;
+
+                // prepare next segment
+                const sal_uInt32 nNextIndex((a + 1) % nB2DLocalCount);
+                aBezier.setEndPoint(rPolygon.getB2DPoint(nNextIndex));
+                aBezier.setControlPointA(rPolygon.getNextControlPoint(a));
+                aBezier.setControlPointB(rPolygon.getPrevControlPoint(nNextIndex));
+
+                if(aBezier.isBezier())
+                {
+                    // if one is used, add always two control points due to the old schema
+                    mpPointAry[nArrayInsert] = Point(FRound(aBezier.getControlPointA().getX()), FRound(aBezier.getControlPointA().getY()));
+                    mpFlagAry[nArrayInsert] = PolyFlags::Control;
+                    nArrayInsert++;
+
+                    mpPointAry[nArrayInsert] = Point(FRound(aBezier.getControlPointB().getX()), FRound(aBezier.getControlPointB().getY()));
+                    mpFlagAry[nArrayInsert] = PolyFlags::Control;
+                    nArrayInsert++;
+                }
+
+                // test continuity with previous control point to set flag value
+                if(aBezier.getControlPointA() != aBezier.getStartPoint() && (bClosed || a))
+                {
+                    const basegfx::B2VectorContinuity eCont(rPolygon.getContinuityInPoint(a));
+
+                    if(basegfx::B2VectorContinuity::C1 == eCont)
+                    {
+                        mpFlagAry[nStartPointIndex] = PolyFlags::Smooth;
+                    }
+                    else if(basegfx::B2VectorContinuity::C2 == eCont)
+                    {
+                        mpFlagAry[nStartPointIndex] = PolyFlags::Symmetric;
+                    }
+                }
+
+                // prepare next polygon step
+                aBezier.setStartPoint(aBezier.getEndPoint());
+            }
+
+            if(bClosed)
+            {
+                // add first point again as closing point due to old definition
+                mpPointAry[nArrayInsert] = mpPointAry[0];
+                mpFlagAry[nArrayInsert] = PolyFlags::Normal;
+                nArrayInsert++;
+            }
+            else
+            {
+                // add last point as closing point
+                const basegfx::B2DPoint aClosingPoint(rPolygon.getB2DPoint(nB2DLocalCount - 1));
+                const Point aEnd(FRound(aClosingPoint.getX()), FRound(aClosingPoint.getY()));
+                mpPointAry[nArrayInsert] = aEnd;
+                mpFlagAry[nArrayInsert] = PolyFlags::Normal;
+                nArrayInsert++;
+            }
+
+            DBG_ASSERT(nArrayInsert <= nMaxTargetCount, "Polygon::Polygon from basegfx::B2DPolygon: wrong max point count estimation (!)");
+
+            if(nArrayInsert != nMaxTargetCount)
+            {
+                ImplSetSize(static_cast< sal_uInt16 >(nArrayInsert));
+            }
+        }
+    }
+    else
+    {
+        // #127979# Reduce source point count hard to the limit of the tools Polygon
+        if(nB2DLocalCount > (0x0000ffff - 1))
+        {
+            OSL_FAIL("Polygon::Polygon: Too many points in given B2DPolygon, need to reduce hard to maximum of tools Polygon (!)");
+            nB2DLocalCount = (0x0000ffff - 1);
+        }
+
+        if(nB2DLocalCount)
+        {
+            // point list creation
+            const sal_uInt32 nTargetCount(nB2DLocalCount + (bClosed ? 1 : 0));
+            ImplInitSize(static_cast< sal_uInt16 >(nTargetCount));
+            sal_uInt16 nIndex(0);
+
+            for(sal_uInt32 a(0); a < nB2DLocalCount; a++)
+            {
+                basegfx::B2DPoint aB2DPoint(rPolygon.getB2DPoint(a));
+                Point aPoint(FRound(aB2DPoint.getX()), FRound(aB2DPoint.getY()));
+                mpPointAry[nIndex++] = aPoint;
+            }
 
-ImplPolygon::ImplPolygon( sal_uInt16 nInitSize, bool bFlags  )
-{
-    if ( nInitSize )
-    {
-        const std::size_t nSz(static_cast<std::size_t>(nInitSize)*sizeof(Point));
-        mpPointAry = reinterpret_cast<Point*>(new char[nSz]);
-        memset( mpPointAry, 0, nSz );
+            if(bClosed)
+            {
+                // add first point as closing point
+                mpPointAry[nIndex] = mpPointAry[0];
+            }
+        }
     }
-    else
-        mpPointAry = nullptr;
+}
 
-    if( bFlags )
+bool ImplPolygon::operator==( const ImplPolygon& rCandidate) const
+{
+    if(mnPoints == rCandidate.mnPoints)
     {
-        mpFlagAry = new PolyFlags[ nInitSize ];
-        memset( mpFlagAry, 0, nInitSize );
+        if (mpFlagAry == rCandidate.mpFlagAry && mpPointAry == rCandidate.mpPointAry)
+            return true;
     }
-    else
-        mpFlagAry = nullptr;
 
-    mnRefCount = 1;
-    mnPoints = nInitSize;
+    return false;
 }
 
-ImplPolygon::ImplPolygon( const ImplPolygon& rImpPoly )
+ImplPolygon::~ImplPolygon()
 {
-    if ( rImpPoly.mnPoints )
-    {
-        const std::size_t nSz(static_cast<std::size_t>(rImpPoly.mnPoints)*sizeof(Point));
-        mpPointAry = reinterpret_cast<Point*>(new char[nSz]);
-        memcpy( mpPointAry, rImpPoly.mpPointAry, nSz );
+    if ( mpPointAry )
+        delete[] mpPointAry;
 
-        if( rImpPoly.mpFlagAry )
-        {
-            mpFlagAry = new PolyFlags[ rImpPoly.mnPoints ];
-            memcpy( mpFlagAry, rImpPoly.mpFlagAry, rImpPoly.mnPoints );
-        }
-        else
-            mpFlagAry = nullptr;
-    }
-    else
-    {
-        mpPointAry = nullptr;
-        mpFlagAry = nullptr;
-    }
+    if( mpFlagAry )
+        delete[] mpFlagAry;
+}
 
-    mnRefCount = 1;
-    mnPoints   = rImpPoly.mnPoints;
+void ImplPolygon::ImplInitDefault()
+{
+    mpPointAry = nullptr;
+    mpFlagAry = nullptr;
+    mnPoints = 0;
 }
 
-ImplPolygon::ImplPolygon( sal_uInt16 nInitSize, const Point* pInitAry, const PolyFlags* pInitFlags )
+void ImplPolygon::ImplInitSize( sal_uInt16 nInitSize, bool bFlags)
 {
     if ( nInitSize )
     {
-        const std::size_t nSz(static_cast<std::size_t>(nInitSize)*sizeof(Point));
-        mpPointAry = reinterpret_cast<Point*>(new char[nSz]);
-        memcpy( mpPointAry, pInitAry, nSz );
-
-        if( pInitFlags )
-        {
-            mpFlagAry = new PolyFlags[ nInitSize ];
-            memcpy( mpFlagAry, pInitFlags, nInitSize );
-        }
-        else
-            mpFlagAry = nullptr;
+        mpPointAry = new Point[ nInitSize ];
+        memset( mpPointAry,
+                0,
+                static_cast<std::size_t>(nInitSize)*sizeof(Point) );
     }
     else
-    {
         mpPointAry = nullptr;
-        mpFlagAry  = nullptr;
-    }
-
-    mnRefCount = 1;
-    mnPoints   = nInitSize;
-}
 
-ImplPolygon::~ImplPolygon()
-{
-    if ( mpPointAry )
+    if( bFlags )
     {
-        delete[] reinterpret_cast<char*>(mpPointAry);
+        mpFlagAry = new PolyFlags[ nInitSize ];
+        memset( mpFlagAry, 0, nInitSize );
     }
+    else
+        mpFlagAry = nullptr;
 
-    if( mpFlagAry )
-        delete[] mpFlagAry;
+    mnPoints = nInitSize;
 }
 
 void ImplPolygon::ImplSetSize( sal_uInt16 nNewSize, bool bResize )
@@ -154,7 +563,7 @@ void ImplPolygon::ImplSetSize( sal_uInt16 nNewSize, bool bResize )
     if ( nNewSize )
     {
         const std::size_t nNewSz(static_cast<std::size_t>(nNewSize)*sizeof(Point));
-        pNewAry = reinterpret_cast<Point*>(new char[nNewSz]);
+        pNewAry = new Point[ nNewSize ];
 
         if ( bResize )
         {
@@ -178,7 +587,7 @@ void ImplPolygon::ImplSetSize( sal_uInt16 nNewSize, bool bResize )
         pNewAry = nullptr;
 
     if ( mpPointAry )
-        delete[] reinterpret_cast<char*>(mpPointAry);
+        delete[] mpPointAry;
 
     // take FlagArray into account, if applicable
     if( mpFlagAry )
@@ -244,8 +653,7 @@ bool ImplPolygon::ImplSplit( sal_uInt16 nPos, sal_uInt16 nSpace, ImplPolygon con
         const sal_uInt16    nSecPos = nPos + nSpace;
         const sal_uInt16    nRest = mnPoints - nPos;
 
-        Point* pNewAry = reinterpret_cast<Point*>(new char[ static_cast<std::size_t>(nNewSize) * sizeof(Point) ]);
-
+        Point* pNewAry = new Point[ nNewSize ];
         memcpy( pNewAry, mpPointAry, nPos * sizeof( Point ) );
 
         if( pInitPoly )
@@ -254,7 +662,7 @@ bool ImplPolygon::ImplSplit( sal_uInt16 nPos, sal_uInt16 nSpace, ImplPolygon con
             memset( pNewAry + nPos, 0, nSpaceSize );
 
         memcpy( pNewAry + nSecPos, mpPointAry + nPos, nRest * sizeof( Point ) );
-        delete[] reinterpret_cast<char*>(mpPointAry);
+        delete[] mpPointAry;
 
         // consider FlagArray
         if( mpFlagAry )
@@ -289,14 +697,6 @@ void ImplPolygon::ImplCreateFlagArray()
     }
 }
 
-inline double ImplGetParameter( const Point& rCenter, const Point& rPt, double fWR, double fHR )
-{
-    const long nDX = rPt.X() - rCenter.X();
-    double fAngle = atan2( -rPt.Y() + rCenter.Y(), ( ( nDX == 0 ) ? 0.000000001 : nDX ) );
-
-    return atan2(fWR*sin(fAngle), fHR*cos(fAngle));
-}
-
 class ImplPointFilter
 {
 public:
@@ -486,334 +886,82 @@ void ImplEdgePointFilter::Input( const Point& rPoint )
     }
 
     maLastPoint    = rPoint;
-    mnLastOutside  = nOutside;
-}
-
-void ImplEdgePointFilter::LastPoint()
-{
-    if ( !mbFirst )
-    {
-        int nOutside = VisibleSide( maFirstPoint );
-
-        if ( nOutside != mnLastOutside )
-            Input( maFirstPoint );
-        mrNextFilter.LastPoint();
-    }
-}
-
-namespace tools
-{
-
-tools::Polygon Polygon::SubdivideBezier( const tools::Polygon& rPoly )
-{
-    tools::Polygon aPoly;
-
-    // #100127# Use adaptive subdivide instead of fixed 25 segments
-    rPoly.AdaptiveSubdivide( aPoly );
-
-    return aPoly;
-}
-
-
-inline void Polygon::ImplMakeUnique()
-{
-    // copy references if any exist
-    if ( mpImplPolygon->mnRefCount != 1 )
-    {
-        if ( mpImplPolygon->mnRefCount )
-            mpImplPolygon->mnRefCount--;
-        mpImplPolygon = new ImplPolygon( *mpImplPolygon );
-    }
-}
-
-Polygon::Polygon()
-{
-    mpImplPolygon = static_cast<ImplPolygon*>(&aStaticImplPolygon);
-}
-
-Polygon::Polygon( sal_uInt16 nSize )
-{
-
-    if ( nSize )
-        mpImplPolygon = new ImplPolygon( nSize );
-    else
-        mpImplPolygon = static_cast<ImplPolygon*>(&aStaticImplPolygon);
-}
-
-Polygon::Polygon( sal_uInt16 nPoints, const Point* pPtAry, const PolyFlags* pFlagAry )
-{
-    if( nPoints )
-        mpImplPolygon = new ImplPolygon( nPoints, pPtAry, pFlagAry );
-    else
-        mpImplPolygon = static_cast<ImplPolygon*>(&aStaticImplPolygon);
-}
-
-Polygon::Polygon( const tools::Polygon& rPoly )
-{
-    DBG_ASSERT( rPoly.mpImplPolygon->mnRefCount < (SAL_MAX_UINT32-1), "Polygon: RefCount overflow" );
-
-    mpImplPolygon = rPoly.mpImplPolygon;
-    if ( mpImplPolygon->mnRefCount )
-        mpImplPolygon->mnRefCount++;
-}
-
-Polygon::Polygon( const tools::Rectangle& rRect )
-{
-
-    if ( rRect.IsEmpty() )
-        mpImplPolygon = static_cast<ImplPolygon*>(&aStaticImplPolygon);
-    else
-    {
-        mpImplPolygon = new ImplPolygon( 5 );
-        mpImplPolygon->mpPointAry[0] = rRect.TopLeft();
-        mpImplPolygon->mpPointAry[1] = rRect.TopRight();
-        mpImplPolygon->mpPointAry[2] = rRect.BottomRight();
-        mpImplPolygon->mpPointAry[3] = rRect.BottomLeft();
-        mpImplPolygon->mpPointAry[4] = rRect.TopLeft();
-    }
-}
-
-Polygon::Polygon( const tools::Rectangle& rRect, sal_uInt32 nHorzRound, sal_uInt32 nVertRound )
-{
-    if ( rRect.IsEmpty() )
-        mpImplPolygon = static_cast<ImplPolygon*>(&aStaticImplPolygon);
-    else
-    {
-        tools::Rectangle aRect( rRect );
-        aRect.Justify();            // SJ: i9140
-
-        nHorzRound = std::min( nHorzRound, static_cast<sal_uInt32>(labs( aRect.GetWidth() >> 1 )) );
-        nVertRound = std::min( nVertRound, static_cast<sal_uInt32>(labs( aRect.GetHeight() >> 1 )) );
-
-        if( !nHorzRound && !nVertRound )
-        {
-            mpImplPolygon = new ImplPolygon( 5 );
-            mpImplPolygon->mpPointAry[0] = aRect.TopLeft();
-            mpImplPolygon->mpPointAry[1] = aRect.TopRight();
-            mpImplPolygon->mpPointAry[2] = aRect.BottomRight();
-            mpImplPolygon->mpPointAry[3] = aRect.BottomLeft();
-            mpImplPolygon->mpPointAry[4] = aRect.TopLeft();
-        }
-        else
-        {
-            const Point     aTL( aRect.Left() + nHorzRound, aRect.Top() + nVertRound );
-            const Point     aTR( aRect.Right() - nHorzRound, aRect.Top() + nVertRound );
-            const Point     aBR( aRect.Right() - nHorzRound, aRect.Bottom() - nVertRound );
-            const Point     aBL( aRect.Left() + nHorzRound, aRect.Bottom() - nVertRound );
-            std::unique_ptr<tools::Polygon> pEllipsePoly( new tools::Polygon( Point(), nHorzRound, nVertRound ) );
-            sal_uInt16 i, nEnd, nSize4 = pEllipsePoly->GetSize() >> 2;
-
-            mpImplPolygon = new ImplPolygon( pEllipsePoly->GetSize() + 1 );
-
-            const Point* pSrcAry = pEllipsePoly->GetConstPointAry();
-            Point* pDstAry = mpImplPolygon->mpPointAry;
-
-            for( i = 0, nEnd = nSize4; i < nEnd; i++ )
-                ( pDstAry[ i ] = pSrcAry[ i ] ) += aTR;
-
-            for( nEnd = nEnd + nSize4; i < nEnd; i++ )
-                ( pDstAry[ i ] = pSrcAry[ i ] ) += aTL;
-
-            for( nEnd = nEnd + nSize4; i < nEnd; i++ )
-                ( pDstAry[ i ] = pSrcAry[ i ] ) += aBL;
-
-            for( nEnd = nEnd + nSize4; i < nEnd; i++ )
-                ( pDstAry[ i ] = pSrcAry[ i ] ) += aBR;
-
-            pDstAry[ nEnd ] = pDstAry[ 0 ];
-        }
-    }
-}
-
-Polygon::Polygon( const Point& rCenter, long nRadX, long nRadY )
-{
-    if( nRadX && nRadY )
-    {
-        sal_uInt16 nPoints;
-
-        // Compute default (depends on size)
-        long nRadXY;
-        const bool bOverflow = o3tl::checked_multiply(nRadX, nRadY, nRadXY);
-        if (!bOverflow)
-        {
-            nPoints = (sal_uInt16) MinMax(
-                ( F_PI * ( 1.5 * ( nRadX + nRadY ) -
-                           sqrt( (double) labs(nRadXY) ) ) ),
-                32, 256 );
-        }
-        else
-        {
-            nPoints = 256;
-        }
-
-        if( ( nRadX > 32 ) && ( nRadY > 32 ) && ( nRadX + nRadY ) < 8192 )
-            nPoints >>= 1;
-
-        // Ceil number of points until divisible by four
-        mpImplPolygon = new ImplPolygon( nPoints = (nPoints + 3) & ~3 );
-
-        sal_uInt16 i;
-        sal_uInt16 nPoints2 = nPoints >> 1;
-        sal_uInt16 nPoints4 = nPoints >> 2;
-        double nAngle;
-        double nAngleStep = F_PI2 / ( nPoints4 - 1 );
-
-        for( i=0, nAngle = 0.0; i < nPoints4; i++, nAngle += nAngleStep )
-        {
-            long nX = FRound( nRadX * cos( nAngle ) );
-            long nY = FRound( -nRadY * sin( nAngle ) );
-
-            Point* pPt = &(mpImplPolygon->mpPointAry[i]);
-            pPt->X() =  nX + rCenter.X();
-            pPt->Y() =  nY + rCenter.Y();
-            pPt = &(mpImplPolygon->mpPointAry[nPoints2-i-1]);
-            pPt->X() = -nX + rCenter.X();
-            pPt->Y() =  nY + rCenter.Y();
-            pPt = &(mpImplPolygon->mpPointAry[i+nPoints2]);
-            pPt->X() = -nX + rCenter.X();
-            pPt->Y() = -nY + rCenter.Y();
-            pPt = &(mpImplPolygon->mpPointAry[nPoints-i-1]);
-            pPt->X() =  nX + rCenter.X();
-            pPt->Y() = -nY + rCenter.Y();
-        }
-    }
-    else
-        mpImplPolygon = static_cast<ImplPolygon*>(&aStaticImplPolygon);
-}
-
-Polygon::Polygon( const tools::Rectangle& rBound, const Point& rStart, const Point& rEnd,
-                  PolyStyle eStyle, bool bFullCircle )
-{
-    const long  nWidth = rBound.GetWidth();
-    const long  nHeight = rBound.GetHeight();
-
-    if( ( nWidth > 1 ) && ( nHeight > 1 ) )
-    {
-        const Point aCenter( rBound.Center() );
-        const long  nRadX = aCenter.X() - rBound.Left();
-        const long  nRadY = aCenter.Y() - rBound.Top();
-        sal_uInt16  nPoints;
-
-        long nRadXY;
-        const bool bOverflow = o3tl::checked_multiply(nRadX, nRadY, nRadXY);
-        if (!bOverflow)
-        {
-            nPoints = (sal_uInt16) MinMax(
-                ( F_PI * ( 1.5 * ( nRadX + nRadY ) -
-                           sqrt( (double) labs(nRadXY) ) ) ),
-                32, 256 );
-        }
-        else
-        {
-            nPoints = 256;
-        }
+    mnLastOutside  = nOutside;
+}
 
-        if( ( nRadX > 32 ) && ( nRadY > 32 ) && ( nRadX + nRadY ) < 8192 )
-            nPoints >>= 1;
+void ImplEdgePointFilter::LastPoint()
+{
+    if ( !mbFirst )
+    {
+        int nOutside = VisibleSide( maFirstPoint );
 
-        // compute threshold
-        const double    fRadX = nRadX;
-        const double    fRadY = nRadY;
-        const double    fCenterX = aCenter.X();
-        const double    fCenterY = aCenter.Y();
-        double          fStart = ImplGetParameter( aCenter, rStart, fRadX, fRadY );
-        double          fEnd = ImplGetParameter( aCenter, rEnd, fRadX, fRadY );
-        double          fDiff = fEnd - fStart;
-        double          fStep;
-        sal_uInt16      nStart;
-        sal_uInt16      nEnd;
+        if ( nOutside != mnLastOutside )
+            Input( maFirstPoint );
+        mrNextFilter.LastPoint();
+    }
+}
 
-        if( fDiff < 0. )
-            fDiff += F_2PI;
+namespace tools
+{
 
-        if ( bFullCircle )
-            fDiff = F_2PI;
+tools::Polygon Polygon::SubdivideBezier( const tools::Polygon& rPoly )
+{
+    tools::Polygon aPoly;
 
-        // Proportionally shrink number of points( fDiff / (2PI) );
-        nPoints = std::max( (sal_uInt16) ( ( fDiff * 0.1591549 ) * nPoints ), (sal_uInt16) 16 );
-        fStep = fDiff / ( nPoints - 1 );
+    // #100127# Use adaptive subdivide instead of fixed 25 segments
+    rPoly.AdaptiveSubdivide( aPoly );
 
-        if( PolyStyle::Pie == eStyle )
-        {
-            const Point aCenter2( FRound( fCenterX ), FRound( fCenterY ) );
+    return aPoly;
+}
 
-            nStart = 1;
-            nEnd = nPoints + 1;
-            mpImplPolygon = new ImplPolygon( nPoints + 2 );
-            mpImplPolygon->mpPointAry[ 0 ] = aCenter2;
-            mpImplPolygon->mpPointAry[ nEnd ] = aCenter2;
-        }
-        else
-        {
-            mpImplPolygon = new ImplPolygon( ( PolyStyle::Chord == eStyle ) ? ( nPoints + 1 ) : nPoints );
-            nStart = 0;
-            nEnd = nPoints;
-        }
+Polygon::Polygon() : mpImplPolygon(ImplPolygon())
+{
+}
 
-        for(; nStart < nEnd; nStart++, fStart += fStep )
-        {
-            Point& rPt = mpImplPolygon->mpPointAry[ nStart ];
+Polygon::Polygon( sal_uInt16 nSize ) : mpImplPolygon(ImplPolygon(nSize))
+{
+}
 
-            rPt.X() = FRound( fCenterX + fRadX * cos( fStart ) );
-            rPt.Y() = FRound( fCenterY - fRadY * sin( fStart ) );
-        }
+Polygon::Polygon( sal_uInt16 nPoints, const Point* pPtAry, const PolyFlags* pFlagAry ) : mpImplPolygon(ImplPolygon(nPoints, pPtAry, pFlagAry))
+{
+}
 
-        if( PolyStyle::Chord == eStyle )
-            mpImplPolygon->mpPointAry[ nPoints ] = mpImplPolygon->mpPointAry[ 0 ];
-    }
-    else
-        mpImplPolygon = static_cast<ImplPolygon*>( &aStaticImplPolygon );
+Polygon::Polygon( const tools::Polygon& rPoly ) : mpImplPolygon(rPoly.mpImplPolygon)
+{
 }
 
-Polygon::Polygon( const Point& rBezPt1, const Point& rCtrlPt1,
-                  const Point& rBezPt2, const Point& rCtrlPt2,
-                  sal_uInt16 nPoints )
+Polygon::Polygon( tools::Polygon&& rPoly)
+    : mpImplPolygon(std::move(rPoly.mpImplPolygon))
 {
-    nPoints = ( 0 == nPoints ) ? 25 : ( ( nPoints < 2 ) ? 2 : nPoints );
+}
 
-    const double    fInc = 1.0 / ( nPoints - 1 );
-    double          fK_1 = 0.0, fK1_1 = 1.0;
-    double          fK_2, fK_3, fK1_2, fK1_3;
-    const double    fX0 = rBezPt1.X();
-    const double    fY0 = rBezPt1.Y();
-    const double    fX1 = 3.0 * rCtrlPt1.X();
-    const double    fY1 = 3.0 * rCtrlPt1.Y();
-    const double    fX2 = 3.0 * rCtrlPt2.X();
-    const double    fY2 = 3.0 * rCtrlPt2.Y();
-    const double    fX3 = rBezPt2.X();
-    const double    fY3 = rBezPt2.Y();
+Polygon::Polygon( const tools::Rectangle& rRect ) : mpImplPolygon(ImplPolygon(rRect))
+{
+}
 
-    mpImplPolygon = new ImplPolygon( nPoints );
+Polygon::Polygon( const tools::Rectangle& rRect, sal_uInt32 nHorzRound, sal_uInt32 nVertRound )
+    : mpImplPolygon(ImplPolygon(rRect, nHorzRound, nVertRound))
+{
+}
 
-    for( sal_uInt16 i = 0; i < nPoints; i++, fK_1 += fInc, fK1_1 -= fInc )
-    {
-        Point& rPt = mpImplPolygon->mpPointAry[ i ];
+Polygon::Polygon( const Point& rCenter, long nRadX, long nRadY )
+    : mpImplPolygon(ImplPolygon(rCenter, nRadX, nRadY))
+{
+}
 
-        fK_2 = fK_1;
-        fK_3 = ( fK_2 *= fK_1 );
-        fK_3 *= fK_1;
-        fK1_2 = fK1_1;
-        fK1_3 = ( fK1_2 *= fK1_1 );
-        fK1_3 *= fK1_1;
-        double fK12 = fK_1 * fK1_2;
-        double fK21 = fK_2 * fK1_1;
+Polygon::Polygon( const tools::Rectangle& rBound, const Point& rStart, const Point& rEnd,
+                  PolyStyle eStyle, bool bFullCircle ) : mpImplPolygon(ImplPolygon(rBound, rStart, rEnd, eStyle, bFullCircle))
+{
+}
 
-        rPt.X() = FRound( fK1_3 * fX0 + fK12 * fX1 + fK21 * fX2 + fK_3 * fX3 );
-        rPt.Y() = FRound( fK1_3 * fY0 + fK12 * fY1 + fK21 * fY2 + fK_3 * fY3 );
-    }
+Polygon::Polygon( const Point& rBezPt1, const Point& rCtrlPt1,
+                  const Point& rBezPt2, const Point& rCtrlPt2,
+                  sal_uInt16 nPoints ) : mpImplPolygon(ImplPolygon(rBezPt1, rCtrlPt1, rBezPt2, rCtrlPt2, nPoints))
+{
 }
 
 Polygon::~Polygon()
 {
-
-    // Remove if refcount == 0, otherwise decrement refcount
-    if ( mpImplPolygon->mnRefCount )
-    {
-        if ( mpImplPolygon->mnRefCount > 1 )
-            mpImplPolygon->mnRefCount--;
-        else
-            delete mpImplPolygon;
-    }
 }
 
 Point * Polygon::GetPointAry()
@@ -836,7 +984,6 @@ void Polygon::SetPoint( const Point& rPt, sal_uInt16 nPos )
     DBG_ASSERT( nPos < mpImplPolygon->mnPoints,
                 "Polygon::SetPoint(): nPos >= nPoints" );
 
-    ImplMakeUnique();
     mpImplPolygon->mpPointAry[nPos] = rPt;
 }
 
@@ -849,7 +996,6 @@ void Polygon::SetFlags( sal_uInt16 nPos, PolyFlags eFlags )
     // is at least one flag different to PolyFlags::Normal
     if ( eFlags != PolyFlags::Normal )
     {
-        ImplMakeUnique();
         mpImplPolygon->ImplCreateFlagArray();
         mpImplPolygon->mpFlagAry[ nPos ] = eFlags;
     }
@@ -899,7 +1045,6 @@ void Polygon::SetSize( sal_uInt16 nNewSize )
 {
     if( nNewSize != mpImplPolygon->mnPoints )
     {
-        ImplMakeUnique();
         mpImplPolygon->ImplSetSize( nNewSize );
     }
 }
@@ -911,15 +1056,7 @@ sal_uInt16 Polygon::GetSize() const
 
 void Polygon::Clear()
 {
-    if ( mpImplPolygon->mnRefCount )
-    {
-        if ( mpImplPolygon->mnRefCount > 1 )
-            mpImplPolygon->mnRefCount--;
-        else
-            delete mpImplPolygon;
-    }
-
-    mpImplPolygon = static_cast<ImplPolygon*>(&aStaticImplPolygon);
+    mpImplPolygon = ImplType(ImplPolygon());
 }
 
 double Polygon::CalcDistance( sal_uInt16 nP1, sal_uInt16 nP2 ) const
@@ -1284,8 +1421,6 @@ void Polygon::Move( long nHorzMove, long nVertMove )
     if ( !nHorzMove && !nVertMove )
         return;
 
-    ImplMakeUnique();
-
     // Move points
     sal_uInt16 nCount = mpImplPolygon->mnPoints;
     for ( sal_uInt16 i = 0; i < nCount; i++ )
@@ -1298,16 +1433,12 @@ void Polygon::Move( long nHorzMove, long nVertMove )
 
 void Polygon::Translate(const Point& rTrans)
 {
-    ImplMakeUnique();
-
     for ( sal_uInt16 i = 0, nCount = mpImplPolygon->mnPoints; i < nCount; i++ )
         mpImplPolygon->mpPointAry[ i ] += rTrans;
 }
 
 void Polygon::Scale( double fScaleX, double fScaleY )
 {
-    ImplMakeUnique();
-
     for ( sal_uInt16 i = 0, nCount = mpImplPolygon->mnPoints; i < nCount; i++ )
     {
         Point& rPnt = mpImplPolygon->mpPointAry[i];
@@ -1329,8 +1460,6 @@ void Polygon::Rotate( const Point& rCenter, sal_uInt16 nAngle10 )
 
 void Polygon::Rotate( const Point& rCenter, double fSin, double fCos )
 {
-    ImplMakeUnique();
-
     long nCenterX = rCenter.X();
     long nCenterY = rCenter.Y();
 
@@ -1351,7 +1480,7 @@ void Polygon::Clip( const tools::Rectangle& rRect )
     tools::Rectangle               aJustifiedRect( rRect );
     aJustifiedRect.Justify();
 
-    sal_uInt16                  nSourceSize = mpImplPolygon->mnPoints;
+    sal_uInt16              nSourceSize = mpImplPolygon->mnPoints;
     ImplPolygonPointFilter  aPolygon( nSourceSize );
     ImplEdgePointFilter     aHorzFilter( EDGE_HORZ, aJustifiedRect.Left(), aJustifiedRect.Right(),
                                          aPolygon );
@@ -1365,15 +1494,7 @@ void Polygon::Clip( const tools::Rectangle& rRect )
     else
         aPolygon.LastPoint();
 
-    // Delete old ImpPolygon-data and assign from ImpPolygonPointFilter
-    if ( mpImplPolygon->mnRefCount )
-    {
-        if ( mpImplPolygon->mnRefCount > 1 )
-            mpImplPolygon->mnRefCount--;
-        else
-            delete mpImplPolygon;
-    }
-    mpImplPolygon = aPolygon.release();
+    mpImplPolygon = ImplType(*aPolygon.release());
 }
 
 tools::Rectangle Polygon::GetBoundRect() const
@@ -1466,8 +1587,6 @@ bool Polygon::IsInside( const Point& rPoint ) const
 
 void Polygon::Insert( sal_uInt16 nPos, const Point& rPt )
 {
-    ImplMakeUnique();
-
     if( nPos >= mpImplPolygon->mnPoints )
         nPos = mpImplPolygon->mnPoints;
 
@@ -1481,15 +1600,13 @@ void Polygon::Insert( sal_uInt16 nPos, const tools::Polygon& rPoly )
 
     if( nInsertCount )
     {
-        ImplMakeUnique();
-
         if( nPos >= mpImplPolygon->mnPoints )
             nPos = mpImplPolygon->mnPoints;
 
         if( rPoly.mpImplPolygon->mpFlagAry )
             mpImplPolygon->ImplCreateFlagArray();
 
-        mpImplPolygon->ImplSplit( nPos, nInsertCount, rPoly.mpImplPolygon );
+        mpImplPolygon->ImplSplit( nPos, nInsertCount, rPoly.mpImplPolygon.get() );
     }
 }
 
@@ -1497,41 +1614,24 @@ Point& Polygon::operator[]( sal_uInt16 nPos )
 {
     DBG_ASSERT( nPos < mpImplPolygon->mnPoints, "Polygon::[]: nPos >= nPoints" );
 
-    ImplMakeUnique();
     return mpImplPolygon->mpPointAry[nPos];
 }
 
 tools::Polygon& Polygon::operator=( const tools::Polygon& rPoly )
 {
-    DBG_ASSERT( rPoly.mpImplPolygon->mnRefCount < 0xFFFFFFFE, "Polygon: RefCount overflow" );
-
-    // Increase refcounter before assigning
-    // Note: RefCount == 0 for static objects
-    if ( rPoly.mpImplPolygon->mnRefCount )
-        rPoly.mpImplPolygon->mnRefCount++;
-
-    // Delete if recount == 0, otherwise decrement
-    if ( mpImplPolygon->mnRefCount )
-    {
-        if ( mpImplPolygon->mnRefCount > 1 )
-            mpImplPolygon->mnRefCount--;
-        else
-            delete mpImplPolygon;
-    }
-
     mpImplPolygon = rPoly.mpImplPolygon;
     return *this;
 }
 
 tools::Polygon& Polygon::operator=( tools::Polygon&& rPoly )
 {
-    std::swap(mpImplPolygon, rPoly.mpImplPolygon);
+    mpImplPolygon = std::move(rPoly.mpImplPolygon);
     return *this;
 }
 
 bool Polygon::operator==( const tools::Polygon& rPoly ) const
 {
-    return rPoly.mpImplPolygon == mpImplPolygon;
+    return (mpImplPolygon == rPoly.mpImplPolygon);
 }
 
 bool Polygon::IsEqual( const tools::Polygon& rPoly ) const
@@ -1570,14 +1670,7 @@ SvStream& ReadPolygon( SvStream& rIStream, tools::Polygon& rPoly )
         nPoints = nMaxRecordsPossible;
     }
 
-    if ( rPoly.mpImplPolygon->mnRefCount != 1 )
-    {
-        if ( rPoly.mpImplPolygon->mnRefCount )
-            rPoly.mpImplPolygon->mnRefCount--;
-        rPoly.mpImplPolygon = new ImplPolygon( nPoints );
-    }
-    else
-        rPoly.mpImplPolygon->ImplSetSize( nPoints, false );
+    rPoly.mpImplPolygon->ImplSetSize( nPoints, false );
 
     // Determine whether we need to write through operators
 #if (SAL_TYPES_SIZEOFLONG) == 4
@@ -1821,149 +1914,8 @@ basegfx::B2DPolygon Polygon::getB2DPolygon() const
     return aRetval;
 }
 
-// constructor to convert from basegfx::B2DPolygon
-// #i76891# Needed to change from adding all control points (even for unused
-// edges) and creating a fixed-size Polygon in the first run to creating the
-// minimal Polygon. This requires a temporary Point- and Flag-Array for curves
-// and a memcopy at ImplPolygon creation, but contains no zero-controlpoints
-// for straight edges.
-Polygon::Polygon(const basegfx::B2DPolygon& rPolygon)
-:   mpImplPolygon(nullptr)
+Polygon::Polygon(const basegfx::B2DPolygon& rPolygon) :  mpImplPolygon(ImplPolygon(rPolygon))
 {
-    const bool bCurve(rPolygon.areControlPointsUsed());
-    const bool bClosed(rPolygon.isClosed());
-    sal_uInt32 nB2DLocalCount(rPolygon.count());
-
-    if(bCurve)
-    {
-        // #127979# Reduce source point count hard to the limit of the tools Polygon
-        if(nB2DLocalCount > ((0x0000ffff / 3) - 1))
-        {
-            OSL_FAIL("Polygon::Polygon: Too many points in given B2DPolygon, need to reduce hard to maximum of tools Polygon (!)");
-            nB2DLocalCount = ((0x0000ffff / 3) - 1);
-        }
-
-        // calculate target point count
-        const sal_uInt32 nLoopCount(bClosed ? nB2DLocalCount : (nB2DLocalCount ? nB2DLocalCount - 1 : 0 ));
-
-        if(nLoopCount)
-        {
-            // calculate maximum array size and allocate; prepare insert index
-            const sal_uInt32 nMaxTargetCount((nLoopCount * 3) + 1);
-            mpImplPolygon = new ImplPolygon(static_cast< sal_uInt16 >(nMaxTargetCount), true);
-
-            // prepare insert index and current point
-            sal_uInt32 nArrayInsert(0);
-            basegfx::B2DCubicBezier aBezier;
-            aBezier.setStartPoint(rPolygon.getB2DPoint(0));
-
-            for(sal_uInt32 a(0); a < nLoopCount; a++)
-            {
-                // add current point (always) and remember StartPointIndex for evtl. later corrections
-                const Point aStartPoint(FRound(aBezier.getStartPoint().getX()), FRound(aBezier.getStartPoint().getY()));
-                const sal_uInt32 nStartPointIndex(nArrayInsert);
-                mpImplPolygon->mpPointAry[nStartPointIndex] = aStartPoint;
-                mpImplPolygon->mpFlagAry[nStartPointIndex] = PolyFlags::Normal;
-                nArrayInsert++;
-
-                // prepare next segment
-                const sal_uInt32 nNextIndex((a + 1) % nB2DLocalCount);
-                aBezier.setEndPoint(rPolygon.getB2DPoint(nNextIndex));
-                aBezier.setControlPointA(rPolygon.getNextControlPoint(a));
-                aBezier.setControlPointB(rPolygon.getPrevControlPoint(nNextIndex));
-
-                if(aBezier.isBezier())
-                {
-                    // if one is used, add always two control points due to the old schema
-                    mpImplPolygon->mpPointAry[nArrayInsert] = Point(FRound(aBezier.getControlPointA().getX()), FRound(aBezier.getControlPointA().getY()));
-                    mpImplPolygon->mpFlagAry[nArrayInsert] = PolyFlags::Control;
-                    nArrayInsert++;
-
-                    mpImplPolygon->mpPointAry[nArrayInsert] = Point(FRound(aBezier.getControlPointB().getX()), FRound(aBezier.getControlPointB().getY()));
-                    mpImplPolygon->mpFlagAry[nArrayInsert] = PolyFlags::Control;
-                    nArrayInsert++;
-                }
-
-                // test continuity with previous control point to set flag value
-                if(aBezier.getControlPointA() != aBezier.getStartPoint() && (bClosed || a))
-                {
-                    const basegfx::B2VectorContinuity eCont(rPolygon.getContinuityInPoint(a));
-
-                    if(basegfx::B2VectorContinuity::C1 == eCont)
-                    {
-                        mpImplPolygon->mpFlagAry[nStartPointIndex] = PolyFlags::Smooth;
-                    }
-                    else if(basegfx::B2VectorContinuity::C2 == eCont)
-                    {
-                        mpImplPolygon->mpFlagAry[nStartPointIndex] = PolyFlags::Symmetric;
-                    }
-                }
-
-                // prepare next polygon step
-                aBezier.setStartPoint(aBezier.getEndPoint());
-            }
-
-            if(bClosed)
-            {
-                // add first point again as closing point due to old definition
-                mpImplPolygon->mpPointAry[nArrayInsert] = mpImplPolygon->mpPointAry[0];
-                mpImplPolygon->mpFlagAry[nArrayInsert] = PolyFlags::Normal;
-                nArrayInsert++;
-            }
-            else
-            {
-                // add last point as closing point
-                const basegfx::B2DPoint aClosingPoint(rPolygon.getB2DPoint(nB2DLocalCount - 1));
-                const Point aEnd(FRound(aClosingPoint.getX()), FRound(aClosingPoint.getY()));
-                mpImplPolygon->mpPointAry[nArrayInsert] = aEnd;
-                mpImplPolygon->mpFlagAry[nArrayInsert] = PolyFlags::Normal;
-                nArrayInsert++;
-            }
-
-            DBG_ASSERT(nArrayInsert <= nMaxTargetCount, "Polygon::Polygon from basegfx::B2DPolygon: wrong max point count estimation (!)");
-
-            if(nArrayInsert != nMaxTargetCount)
-            {
-                mpImplPolygon->ImplSetSize(static_cast< sal_uInt16 >(nArrayInsert));
-            }
-        }
-    }
-    else
-    {
-        // #127979# Reduce source point count hard to the limit of the tools Polygon
-        if(nB2DLocalCount > (0x0000ffff - 1))
-        {
-            OSL_FAIL("Polygon::Polygon: Too many points in given B2DPolygon, need to reduce hard to maximum of tools Polygon (!)");
-            nB2DLocalCount = (0x0000ffff - 1);
-        }
-
-        if(nB2DLocalCount)
-        {
-            // point list creation
-            const sal_uInt32 nTargetCount(nB2DLocalCount + (bClosed ? 1 : 0));
-            mpImplPolygon = new ImplPolygon( static_cast< sal_uInt16 >(nTargetCount) );
-            sal_uInt16 nIndex(0);
-
-            for(sal_uInt32 a(0); a < nB2DLocalCount; a++)
-            {
-                basegfx::B2DPoint aB2DPoint(rPolygon.getB2DPoint(a));
-                Point aPoint(FRound(aB2DPoint.getX()), FRound(aB2DPoint.getY()));
-                mpImplPolygon->mpPointAry[nIndex++] = aPoint;
-            }
-
-            if(bClosed)
-            {
-                // add first point as closing point
-                mpImplPolygon->mpPointAry[nIndex] = mpImplPolygon->mpPointAry[0];
-            }
-        }
-    }
-
-    if(!mpImplPolygon)
-    {
-        // no content yet, create empty polygon
-        mpImplPolygon = static_cast<ImplPolygon*>(&aStaticImplPolygon);
-    }
 }
 
 } // namespace tools


More information about the Libreoffice-commits mailing list