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

Stephan Bergmann sbergman at redhat.com
Wed Feb 21 19:08:11 UTC 2018


 filter/source/msfilter/escherex.cxx |    6 
 include/svx/xpoly.hxx               |    9 
 include/tools/poly.hxx              |    1 
 svx/inc/xpolyimp.hxx                |   27 +-
 svx/source/svdraw/svdoedge.cxx      |   21 -
 svx/source/xoutdev/_xpoly.cxx       |  409 +++++++++++++++++++++++++++---------
 tools/inc/poly.h                    |    1 
 tools/source/generic/poly.cxx       |   22 -
 8 files changed, 340 insertions(+), 156 deletions(-)

New commits:
commit e07d741b61ddc8b13046ce6ea0c0921ce046a0cf
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Tue Feb 20 18:54:13 2018 +0100

    Revert "simplify ImpXPolygon"
    
    This reverts commit f9c2bcc8b761f5e21354c0fb7bca6aa432d11ec2.  Drawing all sorts
    of curves and polygons in Draw causes various crashes in
    svx/source/svdraw/svdopath.cxx, apparently because in the past ImpXPolygon's
    pPointAry had a "buffer" of more elements (nSize) than it had nPoints, and the
    code heavily relied on that, assigning to such excess elements of pPointAry past
    nPoints (and presumably calling XPolygon::SetPointCount later?).
    
    Conflicts:
            svx/source/xoutdev/_xpoly.cxx
    (Reverted the mostly, if not completely, automatic changes there done by
    924c0e34fdc36cd44100dafc2c68656ce32374e6 "loplugin:changetoolsgen in svx"; they
    will need to be re-done.)
    
    Change-Id: I6cb41fd218c3bdd0b3bbeb45f5b3d68649901a48
    Reviewed-on: https://gerrit.libreoffice.org/50057
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Stephan Bergmann <sbergman at redhat.com>

diff --git a/filter/source/msfilter/escherex.cxx b/filter/source/msfilter/escherex.cxx
index e585b787b866..9039c367fa7e 100644
--- a/filter/source/msfilter/escherex.cxx
+++ b/filter/source/msfilter/escherex.cxx
@@ -2094,7 +2094,7 @@ when save as MS file, the connector must be convert to corresponding type.
 sal_Int32 lcl_GetAdjustValueCount( const XPolygon& rPoly )
 {
     int nRet = 0;
-    switch (  rPoly.GetPointCount() )
+    switch (  rPoly.GetSize() )
     {
     case 2 :
     case 3:
@@ -2107,7 +2107,7 @@ sal_Int32 lcl_GetAdjustValueCount( const XPolygon& rPoly )
         nRet = 2;
         break;
     default:
-        if ( rPoly.GetPointCount()>=6 )
+        if ( rPoly.GetSize()>=6 )
             nRet = 3;
         break;
     }
@@ -2117,7 +2117,7 @@ sal_Int32 lcl_GetAdjustValueCount( const XPolygon& rPoly )
 // Adjust value decide the position which connector should turn a corner
 sal_Int32 lcl_GetConnectorAdjustValue ( const XPolygon& rPoly, sal_uInt16 nIndex )
 {
-    sal_uInt16 k =  rPoly.GetPointCount();
+    sal_uInt16 k =  rPoly.GetSize();
     OSL_ASSERT ( k >= ( 3 + nIndex ) );
 
     Point aPt;
diff --git a/include/svx/xpoly.hxx b/include/svx/xpoly.hxx
index ffc95ab3f4d0..2c6f848d00be 100644
--- a/include/svx/xpoly.hxx
+++ b/include/svx/xpoly.hxx
@@ -53,8 +53,7 @@ class SVX_DLLPUBLIC XPolygon final
     static bool CheckAngles(sal_uInt16& nStart, sal_uInt16 nEnd, sal_uInt16& nA1, sal_uInt16& nA2);
 
 public:
-    XPolygon();
-    XPolygon( sal_uInt16 nSize );
+    XPolygon( sal_uInt16 nSize=16 );
     XPolygon( const XPolygon& rXPoly );
     XPolygon( XPolygon&& rXPoly );
     XPolygon( const tools::Polygon& rPoly );
@@ -65,8 +64,10 @@ public:
 
     ~XPolygon();
 
+    sal_uInt16      GetSize() const;
+
+    void        SetPointCount( sal_uInt16 nPoints );
     sal_uInt16      GetPointCount() const;
-    void            SetPointCount( sal_uInt16 nPoints );
 
     void        Insert( sal_uInt16 nPos, const Point& rPt, PolyFlags eFlags );
     void        Insert( sal_uInt16 nPos, const XPolygon& rXPoly );
@@ -80,7 +81,7 @@ public:
     XPolygon&       operator=( XPolygon&& rXPoly );
     bool            operator==( const XPolygon& rXPoly ) const;
 
-    PolyFlags   GetFlags( sal_uInt16 nPos ) const;
+    PolyFlags  GetFlags( sal_uInt16 nPos ) const;
     void        SetFlags( sal_uInt16 nPos, PolyFlags eFlags );
     bool        IsControl(sal_uInt16 nPos) const;
     bool        IsSmooth(sal_uInt16 nPos) const;
diff --git a/include/tools/poly.hxx b/include/tools/poly.hxx
index 259aeac21b9c..1a0926ecfff3 100644
--- a/include/tools/poly.hxx
+++ b/include/tools/poly.hxx
@@ -88,7 +88,6 @@ public:
                         Polygon( sal_uInt16 nSize );
                         Polygon( sal_uInt16 nPoints, const Point* pPtAry,
                                  const PolyFlags* pFlagAry = nullptr );
-                        Polygon( std::vector< std::pair<Point, PolyFlags> > const & );
                         Polygon( const tools::Rectangle& rRect );
                         Polygon( const tools::Rectangle& rRect,
                                  sal_uInt32 nHorzRound, sal_uInt32 nVertRound );
diff --git a/svx/inc/xpolyimp.hxx b/svx/inc/xpolyimp.hxx
index 76f4ae24c87f..fd0fe2905d8b 100644
--- a/svx/inc/xpolyimp.hxx
+++ b/svx/inc/xpolyimp.hxx
@@ -29,13 +29,26 @@ class Point;
 class ImpXPolygon
 {
 public:
-    std::vector<std::pair<Point, PolyFlags>> mvPointsAndFlags;
-    ImpXPolygon() = default;
-    ImpXPolygon(sal_uInt16 nSize)
-    {
-        mvPointsAndFlags.resize(nSize);
-    }
-    bool operator==(ImpXPolygon const & rOther) const { return mvPointsAndFlags == rOther.mvPointsAndFlags; }
+    Point*              pPointAry;
+    std::unique_ptr<PolyFlags[]>
+                        pFlagAry;
+    Point*              pOldPointAry;
+    bool                bDeleteOldPoints;
+    sal_uInt16          nSize;
+    sal_uInt16          nResize;
+    sal_uInt16          nPoints;
+
+    ImpXPolygon( sal_uInt16 nInitSize, sal_uInt16 nResize=16 );
+    ImpXPolygon( const ImpXPolygon& rImpXPoly );
+    ~ImpXPolygon();
+
+    bool operator==(const ImpXPolygon& rImpXPoly) const;
+
+    void CheckPointDelete() const;
+
+    void Resize( sal_uInt16 nNewSize, bool bDeletePoints = true );
+    void InsertSpace( sal_uInt16 nPos, sal_uInt16 nCount );
+    void Remove( sal_uInt16 nPos, sal_uInt16 nCount );
 };
 
 class ImpXPolyPolygon
diff --git a/svx/source/svdraw/svdoedge.cxx b/svx/source/svdraw/svdoedge.cxx
index 7aeb6bf17a04..45203c3d63cf 100644
--- a/svx/source/svdraw/svdoedge.cxx
+++ b/svx/source/svdraw/svdoedge.cxx
@@ -505,23 +505,14 @@ void SdrEdgeObj::ImpSetTailPoint(bool bTail1, const Point& rPt)
 {
     sal_uInt16 nPointCount=pEdgeTrack->GetPointCount();
     if (nPointCount==0) {
-        pEdgeTrack->SetPointCount(2);
         (*pEdgeTrack)[0]=rPt;
         (*pEdgeTrack)[1]=rPt;
     } else if (nPointCount==1) {
-        pEdgeTrack->SetPointCount(2);
-        if (!bTail1)
-            (*pEdgeTrack)[1]=rPt;
-        else
-        {
-            (*pEdgeTrack)[1]=(*pEdgeTrack)[0];
-            (*pEdgeTrack)[0]=rPt;
-        }
+        if (!bTail1) (*pEdgeTrack)[1]=rPt;
+        else { (*pEdgeTrack)[1]=(*pEdgeTrack)[0]; (*pEdgeTrack)[0]=rPt; }
     } else {
-        if (!bTail1)
-            (*pEdgeTrack)[sal_uInt16(nPointCount-1)]=rPt;
-        else
-            (*pEdgeTrack)[0]=rPt;
+        if (!bTail1) (*pEdgeTrack)[sal_uInt16(nPointCount-1)]=rPt;
+        else (*pEdgeTrack)[0]=rPt;
     }
     ImpRecalcEdgeTrack();
     SetRectsDirty();
@@ -2411,11 +2402,9 @@ void SdrEdgeObj::NbcSetPoint(const Point& rPnt, sal_uInt32 i)
     // TODO: Need an implementation to connect differently.
     ImpUndirtyEdgeTrack();
     sal_uInt16 nCount=pEdgeTrack->GetPointCount();
-    if (nCount == 0)
-        pEdgeTrack->SetPointCount(1);
     if (0 == i)
         (*pEdgeTrack)[0]=rPnt;
-    else if (1 == i)
+    if (1 == i)
         (*pEdgeTrack)[nCount-1]=rPnt;
     SetEdgeTrackDirty();
     SetRectsDirty();
diff --git a/svx/source/xoutdev/_xpoly.cxx b/svx/source/xoutdev/_xpoly.cxx
index b4b65449ebf1..9f98aa2df29d 100644
--- a/svx/source/xoutdev/_xpoly.cxx
+++ b/svx/source/xoutdev/_xpoly.cxx
@@ -38,14 +38,174 @@
 #include <basegfx/numeric/ftools.hxx>
 
 
+ImpXPolygon::ImpXPolygon(sal_uInt16 nInitSize, sal_uInt16 _nResize)
+    : pPointAry(nullptr)
+    , pFlagAry(nullptr)
+    , pOldPointAry(nullptr)
+    , bDeleteOldPoints(false)
+    , nSize(0)
+    , nResize(_nResize)
+    , nPoints(0)
+{
+    Resize(nInitSize);
+}
+
+ImpXPolygon::ImpXPolygon( const ImpXPolygon& rImpXPoly )
+    : pPointAry(nullptr)
+    , pFlagAry(nullptr)
+    , pOldPointAry(nullptr)
+    , bDeleteOldPoints(false)
+    , nSize(0)
+    , nResize(rImpXPoly.nResize)
+    , nPoints(0)
+{
+    rImpXPoly.CheckPointDelete();
+
+    Resize( rImpXPoly.nSize );
+
+    // copy
+    nPoints = rImpXPoly.nPoints;
+    memcpy( pPointAry, rImpXPoly.pPointAry, nSize*sizeof( Point ) );
+    memcpy( pFlagAry.get(), rImpXPoly.pFlagAry.get(), nSize );
+}
+
+ImpXPolygon::~ImpXPolygon()
+{
+    delete[] pPointAry;
+    if ( bDeleteOldPoints )
+    {
+        delete[] pOldPointAry;
+        pOldPointAry = nullptr;
+    }
+}
+
+bool ImpXPolygon::operator==(const ImpXPolygon& rImpXPoly) const
+{
+    return nPoints==rImpXPoly.nPoints &&
+           (nPoints==0 ||
+            (memcmp(pPointAry, rImpXPoly.pPointAry, nPoints*sizeof(Point))==0 &&
+             memcmp(pFlagAry.get(), rImpXPoly.pFlagAry.get(), nPoints)==0));
+}
+
+/** Change polygon size
+ *
+ * @param nNewSize      the new size of the polygon
+ * @param bDeletePoints if FALSE, do not delete the point array directly but
+ *                      wait for the next call before doing so. This prevents
+ *                      errors with XPoly[n] = XPoly[0] where a resize might
+ *                      destroy the right side point array too early.
+ */
+void ImpXPolygon::Resize( sal_uInt16 nNewSize, bool bDeletePoints )
+{
+    if( nNewSize == nSize )
+        return;
+
+    PolyFlags*  pOldFlagAry  = pFlagAry.release();
+    sal_uInt16  nOldSize     = nSize;
+
+    CheckPointDelete();
+    pOldPointAry = pPointAry;
+
+    // Round the new size to a multiple of nResize, if
+    // the object was not newly created (nSize != 0)
+    if ( nSize != 0 && nNewSize > nSize )
+    {
+        DBG_ASSERT(nResize, "Trying to resize but nResize = 0 !");
+        nNewSize = nSize + ((nNewSize-nSize-1) / nResize + 1) * nResize;
+    }
+    // create point array
+    nSize     = nNewSize;
+    pPointAry = new Point[ nSize ];
+
+    // create flag array
+    pFlagAry.reset( new PolyFlags[ nSize ] );
+    memset( pFlagAry.get(), 0, nSize );
+
+    // copy if needed
+    if( nOldSize )
+    {
+        if( nOldSize < nSize )
+        {
+            memcpy( pPointAry, pOldPointAry, nOldSize*sizeof( Point ) );
+            memcpy( pFlagAry.get(),  pOldFlagAry, nOldSize );
+        }
+        else
+        {
+            memcpy( pPointAry, pOldPointAry, nSize*sizeof( Point ) );
+            memcpy( pFlagAry.get(), pOldFlagAry, nSize );
+
+            // adjust number of valid points
+            if( nPoints > nSize )
+                nPoints = nSize;
+        }
+        if ( bDeletePoints )
+        {
+            delete[] pOldPointAry;
+            pOldPointAry = nullptr;
+        }
+        else
+            bDeleteOldPoints = true;
+        delete[] pOldFlagAry;
+    }
+}
 
-XPolygon::XPolygon()
-    : pImpXPolygon( ImpXPolygon() )
+void ImpXPolygon::InsertSpace( sal_uInt16 nPos, sal_uInt16 nCount )
 {
+    CheckPointDelete();
+
+    if ( nPos > nPoints )
+        nPos = nPoints;
+
+    // if the polygon is too small than enlarge it
+    if( (nPoints + nCount) > nSize )
+        Resize( nPoints + nCount );
+
+    // If the insert is not at the last position, move everything after backwards
+    if( nPos < nPoints )
+    {
+        sal_uInt16 nMove = nPoints - nPos;
+        memmove( &pPointAry[nPos+nCount], &pPointAry[nPos],
+                 nMove * sizeof(Point) );
+        memmove( &pFlagAry[nPos+nCount], &pFlagAry[nPos], nMove );
+    }
+    std::fill(pPointAry + nPos, pPointAry + nPos + nCount, Point());
+    memset( &pFlagAry [nPos], 0, nCount );
+
+    nPoints = nPoints + nCount;
+}
+
+void ImpXPolygon::Remove( sal_uInt16 nPos, sal_uInt16 nCount )
+{
+    CheckPointDelete();
+
+    if( (nPos + nCount) <= nPoints )
+    {
+        sal_uInt16 nMove = nPoints - nPos - nCount;
+
+        if( nMove )
+        {
+            memmove( &pPointAry[nPos], &pPointAry[nPos+nCount],
+                     nMove * sizeof(Point) );
+            memmove( &pFlagAry[nPos], &pFlagAry[nPos+nCount], nMove );
+        }
+        std::fill(pPointAry + (nPoints - nCount), pPointAry + nPoints, Point());
+        memset( &pFlagAry [nPoints - nCount], 0, nCount );
+        nPoints = nPoints - nCount;
+    }
+}
+
+void ImpXPolygon::CheckPointDelete() const
+{
+    if ( bDeleteOldPoints )
+    {
+        delete[] pOldPointAry;
+        const_cast< ImpXPolygon* >(this)->pOldPointAry = nullptr;
+        const_cast< ImpXPolygon* >(this)->bDeleteOldPoints = false;
+    }
 }
 
 XPolygon::XPolygon( sal_uInt16 nSize )
-    : pImpXPolygon( ImpXPolygon( nSize ) )
+    : pImpXPolygon( ImpXPolygon( nSize, 16 ) )
 {
 }
 
@@ -64,12 +224,12 @@ XPolygon::XPolygon( const tools::Polygon& rPoly )
     : pImpXPolygon( rPoly.GetSize() )
 {
     sal_uInt16 nSize = rPoly.GetSize();
-    pImpXPolygon->mvPointsAndFlags.resize(nSize);
+    pImpXPolygon->nPoints = nSize;
 
     for( sal_uInt16 i = 0; i < nSize;  i++ )
     {
-        pImpXPolygon->mvPointsAndFlags[i].first = rPoly[i];
-        pImpXPolygon->mvPointsAndFlags[i].second = rPoly.GetFlags( i );
+        pImpXPolygon->pPointAry[i] = rPoly[i];
+        pImpXPolygon->pFlagAry[i] = rPoly.GetFlags( i );
     }
 }
 
@@ -91,8 +251,6 @@ XPolygon::XPolygon(const tools::Rectangle& rRect, long nRx, long nRy)
     long    nYHdl = static_cast<long>(0.552284749 * nRy);
     sal_uInt16  nPos = 0;
 
-    pImpXPolygon->mvPointsAndFlags.resize(17);
-
     if ( nRx && nRy )
     {
         Point aCenter;
@@ -119,20 +277,20 @@ XPolygon::XPolygon(const tools::Rectangle& rRect, long nRx, long nRy)
                         break;
             }
             GenBezArc(aCenter, nRx, nRy, nXHdl, nYHdl, 0, 900, nQuad, nPos);
-            pImpXPolygon->mvPointsAndFlags[nPos  ].second = PolyFlags::Smooth;
-            pImpXPolygon->mvPointsAndFlags[nPos+3].second = PolyFlags::Smooth;
+            pImpXPolygon->pFlagAry[nPos  ] = PolyFlags::Smooth;
+            pImpXPolygon->pFlagAry[nPos+3] = PolyFlags::Smooth;
             nPos += 4;
         }
     }
     else
     {
-        pImpXPolygon->mvPointsAndFlags[nPos++].first = rRect.TopLeft();
-        pImpXPolygon->mvPointsAndFlags[nPos++].first = rRect.TopRight();
-        pImpXPolygon->mvPointsAndFlags[nPos++].first = rRect.BottomRight();
-        pImpXPolygon->mvPointsAndFlags[nPos++].first = rRect.BottomLeft();
+        pImpXPolygon->pPointAry[nPos++] = rRect.TopLeft();
+        pImpXPolygon->pPointAry[nPos++] = rRect.TopRight();
+        pImpXPolygon->pPointAry[nPos++] = rRect.BottomRight();
+        pImpXPolygon->pPointAry[nPos++] = rRect.BottomLeft();
     }
-    pImpXPolygon->mvPointsAndFlags[nPos].first = pImpXPolygon->mvPointsAndFlags[0].first;
-    pImpXPolygon->mvPointsAndFlags.resize(nPos + 1);
+    pImpXPolygon->pPointAry[nPos] = pImpXPolygon->pPointAry[0];
+    pImpXPolygon->nPoints = nPos + 1;
 }
 
 /// create a ellipse (curve) as Bézier polygon
@@ -150,7 +308,6 @@ XPolygon::XPolygon(const Point& rCenter, long nRx, long nRy,
     sal_uInt16  nPos = 0;
     bool    bLoopEnd = false;
 
-    pImpXPolygon->mvPointsAndFlags.resize(17);
     do
     {
         sal_uInt16 nA1, nA2;
@@ -160,20 +317,20 @@ XPolygon::XPolygon(const Point& rCenter, long nRx, long nRy,
         GenBezArc(rCenter, nRx, nRy, nXHdl, nYHdl, nA1, nA2, nQuad, nPos);
         nPos += 3;
         if ( !bLoopEnd )
-            pImpXPolygon->mvPointsAndFlags[nPos].second = PolyFlags::Smooth;
+            pImpXPolygon->pFlagAry[nPos] = PolyFlags::Smooth;
 
     } while ( !bLoopEnd );
 
     // if not a full circle than connect edges with center point if necessary
     if ( !bFull && bClose )
-        pImpXPolygon->mvPointsAndFlags[++nPos].first = rCenter;
+        pImpXPolygon->pPointAry[++nPos] = rCenter;
 
     if ( bFull )
     {
-        pImpXPolygon->mvPointsAndFlags[0   ].second = PolyFlags::Smooth;
-        pImpXPolygon->mvPointsAndFlags[nPos].second = PolyFlags::Smooth;
+        pImpXPolygon->pFlagAry[0   ] = PolyFlags::Smooth;
+        pImpXPolygon->pFlagAry[nPos] = PolyFlags::Smooth;
     }
-    pImpXPolygon->mvPointsAndFlags.resize( nPos + 1 );
+    pImpXPolygon->nPoints = nPos + 1;
 }
 
 XPolygon::~XPolygon()
@@ -182,33 +339,60 @@ XPolygon::~XPolygon()
 
 void XPolygon::SetPointCount( sal_uInt16 nPoints )
 {
-    pImpXPolygon->mvPointsAndFlags.resize( nPoints );
+    pImpXPolygon->CheckPointDelete();
+
+    if( pImpXPolygon->nSize < nPoints )
+        pImpXPolygon->Resize( nPoints );
+
+    if ( nPoints < pImpXPolygon->nPoints )
+    {
+        sal_uInt16 nSize = pImpXPolygon->nPoints - nPoints;
+        std::fill(
+            pImpXPolygon->pPointAry + nPoints, pImpXPolygon->pPointAry + nPoints + nSize, Point());
+        memset( &pImpXPolygon->pFlagAry [nPoints], 0, nSize );
+    }
+    pImpXPolygon->nPoints = nPoints;
+}
+
+sal_uInt16 XPolygon::GetSize() const
+{
+    pImpXPolygon->CheckPointDelete();
+    return pImpXPolygon->nSize;
 }
 
 sal_uInt16 XPolygon::GetPointCount() const
 {
-    return pImpXPolygon->mvPointsAndFlags.size();
+    pImpXPolygon->CheckPointDelete();
+    return pImpXPolygon->nPoints;
 }
 
 void XPolygon::Insert( sal_uInt16 nPos, const Point& rPt, PolyFlags eFlags )
 {
-    if (nPos>pImpXPolygon->mvPointsAndFlags.size()) nPos=pImpXPolygon->mvPointsAndFlags.size();
-    pImpXPolygon->mvPointsAndFlags.emplace(pImpXPolygon->mvPointsAndFlags.begin() + nPos, rPt, eFlags);
+    if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
+    pImpXPolygon->InsertSpace( nPos, 1 );
+    pImpXPolygon->pPointAry[nPos] = rPt;
+    pImpXPolygon->pFlagAry[nPos]  = eFlags;
 }
 
 void XPolygon::Insert( sal_uInt16 nPos, const XPolygon& rXPoly )
 {
-    if (nPos>pImpXPolygon->mvPointsAndFlags.size()) nPos=pImpXPolygon->mvPointsAndFlags.size();
+    if (nPos>pImpXPolygon->nPoints) nPos=pImpXPolygon->nPoints;
 
-    std::copy( rXPoly.pImpXPolygon->mvPointsAndFlags.begin(),
-               rXPoly.pImpXPolygon->mvPointsAndFlags.end(),
-               pImpXPolygon->mvPointsAndFlags.begin() + nPos );
+    sal_uInt16 nPoints = rXPoly.GetPointCount();
+
+    pImpXPolygon->InsertSpace( nPos, nPoints );
+
+    memcpy( &(pImpXPolygon->pPointAry[nPos]),
+            rXPoly.pImpXPolygon->pPointAry,
+            nPoints*sizeof( Point ) );
+    memcpy( &(pImpXPolygon->pFlagAry[nPos]),
+            rXPoly.pImpXPolygon->pFlagAry.get(),
+            nPoints );
 }
 
 void XPolygon::Remove( sal_uInt16 nPos, sal_uInt16 nCount )
 {
-    pImpXPolygon->mvPointsAndFlags.erase( pImpXPolygon->mvPointsAndFlags.begin() + nPos,
-                                          pImpXPolygon->mvPointsAndFlags.begin() + nPos + nCount );
+    pImpXPolygon->Remove( nPos, nCount );
 }
 
 void XPolygon::Move( long nHorzMove, long nVertMove )
@@ -217,20 +401,21 @@ void XPolygon::Move( long nHorzMove, long nVertMove )
         return;
 
     // move points
-    sal_uInt16 nCount = pImpXPolygon->mvPointsAndFlags.size();
+    sal_uInt16 nCount = pImpXPolygon->nPoints;
     for ( sal_uInt16 i = 0; i < nCount; i++ )
     {
-        Point* pPt = &(pImpXPolygon->mvPointsAndFlags[i].first);
-        pPt->AdjustX(nHorzMove );
-        pPt->AdjustY(nVertMove );
+        Point* pPt = &(pImpXPolygon->pPointAry[i]);
+        pPt->X() += nHorzMove;
+        pPt->Y() += nVertMove;
     }
 }
 
 tools::Rectangle XPolygon::GetBoundRect() const
 {
+    pImpXPolygon->CheckPointDelete();
     tools::Rectangle aRetval;
 
-    if(pImpXPolygon->mvPointsAndFlags.size())
+    if(pImpXPolygon->nPoints)
     {
         // #i37709#
         // For historical reasons the control points are not part of the
@@ -249,12 +434,25 @@ tools::Rectangle XPolygon::GetBoundRect() const
 
 const Point& XPolygon::operator[]( sal_uInt16 nPos ) const
 {
-    return pImpXPolygon->mvPointsAndFlags[nPos].first;
+    DBG_ASSERT(nPos < pImpXPolygon->nPoints, "Invalid index at const array access to XPolygon");
+
+    pImpXPolygon->CheckPointDelete();
+    return pImpXPolygon->pPointAry[nPos];
 }
 
 Point& XPolygon::operator[]( sal_uInt16 nPos )
 {
-    return pImpXPolygon->mvPointsAndFlags[nPos].first;
+    pImpXPolygon->CheckPointDelete();
+
+    if( nPos >= pImpXPolygon->nSize )
+    {
+        DBG_ASSERT(pImpXPolygon->nResize, "Invalid index at array access to XPolygon");
+        pImpXPolygon->Resize(nPos + 1, false);
+    }
+    if( nPos >= pImpXPolygon->nPoints )
+        pImpXPolygon->nPoints = nPos + 1;
+
+    return pImpXPolygon->pPointAry[nPos];
 }
 
 XPolygon& XPolygon::operator=( const XPolygon& rXPoly )
@@ -271,31 +469,34 @@ XPolygon& XPolygon::operator=( XPolygon&& rXPoly )
 
 bool XPolygon::operator==( const XPolygon& rXPoly ) const
 {
+    pImpXPolygon->CheckPointDelete();
     return rXPoly.pImpXPolygon == pImpXPolygon;
 }
 
 /// get the flags for the point at the given position
 PolyFlags XPolygon::GetFlags( sal_uInt16 nPos ) const
 {
-    return pImpXPolygon->mvPointsAndFlags[nPos].second;
+    pImpXPolygon->CheckPointDelete();
+    return pImpXPolygon->pFlagAry[nPos];
 }
 
 /// set the flags for the point at the given position
 void XPolygon::SetFlags( sal_uInt16 nPos, PolyFlags eFlags )
 {
-    pImpXPolygon->mvPointsAndFlags[nPos].second = eFlags;
+    pImpXPolygon->CheckPointDelete();
+    pImpXPolygon->pFlagAry[nPos] = eFlags;
 }
 
 /// short path to read the CONTROL flag directly (TODO: better explain what the sense behind this flag is!)
 bool XPolygon::IsControl(sal_uInt16 nPos) const
 {
-    return pImpXPolygon->mvPointsAndFlags[nPos].second == PolyFlags::Control;
+    return pImpXPolygon->pFlagAry[nPos] == PolyFlags::Control;
 }
 
 /// short path to read the SMOOTH and SYMMTR flag directly (TODO: better explain what the sense behind these flags is!)
 bool XPolygon::IsSmooth(sal_uInt16 nPos) const
 {
-    PolyFlags eFlag = pImpXPolygon->mvPointsAndFlags[nPos].second;
+    PolyFlags eFlag = pImpXPolygon->pFlagAry[nPos];
     return ( eFlag == PolyFlags::Smooth || eFlag == PolyFlags::Symmetric );
 }
 
@@ -306,8 +507,8 @@ bool XPolygon::IsSmooth(sal_uInt16 nPos) const
  */
 double XPolygon::CalcDistance(sal_uInt16 nP1, sal_uInt16 nP2)
 {
-    const Point& rP1 = pImpXPolygon->mvPointsAndFlags[nP1].first;
-    const Point& rP2 = pImpXPolygon->mvPointsAndFlags[nP2].first;
+    const Point& rP1 = pImpXPolygon->pPointAry[nP1];
+    const Point& rP2 = pImpXPolygon->pPointAry[nP2];
     double fDx = rP2.X() - rP1.X();
     double fDy = rP2.Y() - rP1.Y();
     return sqrt(fDx * fDx + fDy * fDy);
@@ -315,7 +516,7 @@ double XPolygon::CalcDistance(sal_uInt16 nP1, sal_uInt16 nP2)
 
 void XPolygon::SubdivideBezier(sal_uInt16 nPos, bool bCalcFirst, double fT)
 {
-    auto &  rPoints = pImpXPolygon->mvPointsAndFlags;
+    Point*  pPoints = pImpXPolygon->pPointAry;
     double  fT2 = fT * fT;
     double  fT3 = fT * fT2;
     double  fU = 1.0 - fT;
@@ -335,28 +536,28 @@ void XPolygon::SubdivideBezier(sal_uInt16 nPos, bool bCalcFirst, double fT)
         nPosInc = 1;
         nIdxInc = 1;
     }
-    rPoints[nPos].first.setX( static_cast<long>(fU3 *       rPoints[nIdx  ].first.X() +
-                                fT  * fU2 * rPoints[nIdx+1].first.X() * 3 +
-                                fT2 * fU  * rPoints[nIdx+2].first.X() * 3 +
-                                fT3 *       rPoints[nIdx+3].first.X()) );
-    rPoints[nPos].first.setY( static_cast<long>(fU3 *       rPoints[nIdx  ].first.Y() +
-                                fT  * fU2 * rPoints[nIdx+1].first.Y() * 3 +
-                                fT2 * fU  * rPoints[nIdx+2].first.Y() * 3 +
-                                fT3 *       rPoints[nIdx+3].first.Y()) );
+    pPoints[nPos].X() = static_cast<long>(fU3 *       pPoints[nIdx  ].X() +
+                                fT  * fU2 * pPoints[nIdx+1].X() * 3 +
+                                fT2 * fU  * pPoints[nIdx+2].X() * 3 +
+                                fT3 *       pPoints[nIdx+3].X());
+    pPoints[nPos].Y() = static_cast<long>(fU3 *       pPoints[nIdx  ].Y() +
+                                fT  * fU2 * pPoints[nIdx+1].Y() * 3 +
+                                fT2 * fU  * pPoints[nIdx+2].Y() * 3 +
+                                fT3 *       pPoints[nIdx+3].Y());
     nPos = nPos + nPosInc;
     nIdx = nIdx + nIdxInc;
-    rPoints[nPos].first.setX( static_cast<long>(fU2 *       rPoints[nIdx  ].first.X() +
-                                fT  * fU *  rPoints[nIdx+1].first.X() * 2 +
-                                fT2 *       rPoints[nIdx+2].first.X()) );
-    rPoints[nPos].first.setY( static_cast<long>(fU2 *       rPoints[nIdx  ].first.Y() +
-                                fT  * fU *  rPoints[nIdx+1].first.Y() * 2 +
-                                fT2 *       rPoints[nIdx+2].first.Y()) );
+    pPoints[nPos].X() = static_cast<long>(fU2 *       pPoints[nIdx  ].X() +
+                                fT  * fU *  pPoints[nIdx+1].X() * 2 +
+                                fT2 *       pPoints[nIdx+2].X());
+    pPoints[nPos].Y() = static_cast<long>(fU2 *       pPoints[nIdx  ].Y() +
+                                fT  * fU *  pPoints[nIdx+1].Y() * 2 +
+                                fT2 *       pPoints[nIdx+2].Y());
     nPos = nPos + nPosInc;
     nIdx = nIdx + nIdxInc;
-    rPoints[nPos].first.setX( static_cast<long>(fU * rPoints[nIdx  ].first.X() +
-                                fT * rPoints[nIdx+1].first.X()) );
-    rPoints[nPos].first.setY( static_cast<long>(fU * rPoints[nIdx  ].first.Y() +
-                                fT * rPoints[nIdx+1].first.Y()) );
+    pPoints[nPos].X() = static_cast<long>(fU * pPoints[nIdx  ].X() +
+                                fT * pPoints[nIdx+1].X());
+    pPoints[nPos].Y() = static_cast<long>(fU * pPoints[nIdx  ].Y() +
+                                fT * pPoints[nIdx+1].Y());
 }
 
 /// Generate a Bézier arc
@@ -364,9 +565,9 @@ void XPolygon::GenBezArc(const Point& rCenter, long nRx, long nRy,
                          long nXHdl, long nYHdl, sal_uInt16 nStart, sal_uInt16 nEnd,
                          sal_uInt16 nQuad, sal_uInt16 nFirst)
 {
-    auto& rPoints = pImpXPolygon->mvPointsAndFlags;
-    rPoints[nFirst  ].first = rCenter;
-    rPoints[nFirst+3].first = rCenter;
+    Point* pPoints = pImpXPolygon->pPointAry;
+    pPoints[nFirst  ] = rCenter;
+    pPoints[nFirst+3] = rCenter;
 
     if ( nQuad == 1 || nQuad == 2 )
     {
@@ -379,22 +580,22 @@ void XPolygon::GenBezArc(const Point& rCenter, long nRx, long nRy,
 
     if ( nQuad == 0 || nQuad == 2 )
     {
-        rPoints[nFirst].first.AdjustX(nRx ); rPoints[nFirst+3].first.AdjustY(nRy );
+        pPoints[nFirst].X() += nRx; pPoints[nFirst+3].Y() += nRy;
     }
     else
     {
-        rPoints[nFirst].first.AdjustY(nRy ); rPoints[nFirst+3].first.AdjustX(nRx );
+        pPoints[nFirst].Y() += nRy; pPoints[nFirst+3].X() += nRx;
     }
-    rPoints[nFirst+1] = rPoints[nFirst];
-    rPoints[nFirst+2] = rPoints[nFirst+3];
+    pPoints[nFirst+1] = pPoints[nFirst];
+    pPoints[nFirst+2] = pPoints[nFirst+3];
 
     if ( nQuad == 0 || nQuad == 2 )
     {
-        rPoints[nFirst+1].first.AdjustY(nYHdl ); rPoints[nFirst+2].first.AdjustX(nXHdl );
+        pPoints[nFirst+1].Y() += nYHdl; pPoints[nFirst+2].X() += nXHdl;
     }
     else
     {
-        rPoints[nFirst+1].first.AdjustX(nXHdl ); rPoints[nFirst+2].first.AdjustY(nYHdl );
+        pPoints[nFirst+1].X() += nXHdl; pPoints[nFirst+2].Y() += nYHdl;
     }
     if ( nStart > 0 )
         SubdivideBezier(nFirst, false, static_cast<double>(nStart) / 900);
@@ -442,8 +643,8 @@ void XPolygon::CalcSmoothJoin(sal_uInt16 nCenter, sal_uInt16 nDrag, sal_uInt16 n
         nDrag = nPnt;
         nPnt = nTmp;
     }
-    auto&   rPoints = pImpXPolygon->mvPointsAndFlags;
-    Point   aDiff   = rPoints[nDrag].first - rPoints[nCenter].first;
+    Point*  pPoints = pImpXPolygon->pPointAry;
+    Point   aDiff   = pPoints[nDrag] - pPoints[nCenter];
     double  fDiv    = CalcDistance(nCenter, nDrag);
 
     if ( fDiv )
@@ -455,7 +656,7 @@ void XPolygon::CalcSmoothJoin(sal_uInt16 nCenter, sal_uInt16 nDrag, sal_uInt16 n
             aDiff.setX( static_cast<long>(fRatio * aDiff.X()) );
             aDiff.setY( static_cast<long>(fRatio * aDiff.Y()) );
         }
-        rPoints[nPnt].first = rPoints[nCenter].first - aDiff;
+        pPoints[nPnt] = pPoints[nCenter] - aDiff;
     }
 }
 
@@ -472,9 +673,9 @@ void XPolygon::CalcTangent(sal_uInt16 nCenter, sal_uInt16 nPrev, sal_uInt16 nNex
     if ( !fAbsLen )
         return;
 
-    const Point& rCenter = pImpXPolygon->mvPointsAndFlags[nCenter].first;
-    Point&  rNext = pImpXPolygon->mvPointsAndFlags[nNext].first;
-    Point&  rPrev = pImpXPolygon->mvPointsAndFlags[nPrev].first;
+    const Point& rCenter = pImpXPolygon->pPointAry[nCenter];
+    Point&  rNext = pImpXPolygon->pPointAry[nNext];
+    Point&  rPrev = pImpXPolygon->pPointAry[nPrev];
     Point   aDiff = rNext - rPrev;
     double  fNextLen = CalcDistance(nCenter, nNext) / fAbsLen;
     double  fPrevLen = CalcDistance(nCenter, nPrev) / fAbsLen;
@@ -498,20 +699,20 @@ void XPolygon::PointsToBezier(sal_uInt16 nFirst)
     double  fX0, fY0, fX1, fY1, fX2, fY2, fX3, fY3;
     double  fTx1, fTx2, fTy1, fTy2;
     double  fT1, fU1, fT2, fU2, fV;
-    auto&   rPoints = pImpXPolygon->mvPointsAndFlags;
+    Point*  pPoints = pImpXPolygon->pPointAry;
 
-    if ( nFirst > pImpXPolygon->mvPointsAndFlags.size() - 4 || IsControl(nFirst) ||
+    if ( nFirst > pImpXPolygon->nPoints - 4 || IsControl(nFirst) ||
          IsControl(nFirst+1) || IsControl(nFirst+2) || IsControl(nFirst+3) )
         return;
 
-    fTx1 = rPoints[nFirst+1].first.X();
-    fTy1 = rPoints[nFirst+1].first.Y();
-    fTx2 = rPoints[nFirst+2].first.X();
-    fTy2 = rPoints[nFirst+2].first.Y();
-    fX0  = rPoints[nFirst  ].first.X();
-    fY0  = rPoints[nFirst  ].first.Y();
-    fX3  = rPoints[nFirst+3].first.X();
-    fY3  = rPoints[nFirst+3].first.Y();
+    fTx1 = pPoints[nFirst+1].X();
+    fTy1 = pPoints[nFirst+1].Y();
+    fTx2 = pPoints[nFirst+2].X();
+    fTy2 = pPoints[nFirst+2].Y();
+    fX0  = pPoints[nFirst  ].X();
+    fY0  = pPoints[nFirst  ].Y();
+    fX3  = pPoints[nFirst+3].X();
+    fY3  = pPoints[nFirst+3].Y();
 
     nPart1Length = CalcDistance(nFirst, nFirst+1);
     nPart2Length = nPart1Length + CalcDistance(nFirst+1, nFirst+2);
@@ -552,8 +753,8 @@ void XPolygon::PointsToBezier(sal_uInt16 nFirst)
     fY2 -= fY1 * fU2 / fT2;
     fY2 -= fY3 * fT2 / (fU2 * 3);
 
-    rPoints[nFirst+1].first = Point(static_cast<long>(fX1), static_cast<long>(fY1));
-    rPoints[nFirst+2].first = Point(static_cast<long>(fX2), static_cast<long>(fY2));
+    pPoints[nFirst+1] = Point(static_cast<long>(fX1), static_cast<long>(fY1));
+    pPoints[nFirst+2] = Point(static_cast<long>(fX2), static_cast<long>(fY2));
     SetFlags(nFirst+1, PolyFlags::Control);
     SetFlags(nFirst+2, PolyFlags::Control);
 }
@@ -561,13 +762,15 @@ void XPolygon::PointsToBezier(sal_uInt16 nFirst)
 /// scale in X- and/or Y-direction
 void XPolygon::Scale(double fSx, double fSy)
 {
-    sal_uInt16 nPntCnt = pImpXPolygon->mvPointsAndFlags.size();
+    pImpXPolygon->CheckPointDelete();
+
+    sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
 
     for (sal_uInt16 i = 0; i < nPntCnt; i++)
     {
-        Point& rPnt = pImpXPolygon->mvPointsAndFlags[i].first;
-        rPnt.setX( static_cast<long>(fSx * rPnt.X()) );
-        rPnt.setY( static_cast<long>(fSy * rPnt.Y()) );
+        Point& rPnt = pImpXPolygon->pPointAry[i];
+        rPnt.X() = static_cast<long>(fSx * rPnt.X());
+        rPnt.Y() = static_cast<long>(fSy * rPnt.Y());
     }
 }
 
@@ -584,6 +787,8 @@ void XPolygon::Scale(double fSx, double fSy)
 void XPolygon::Distort(const tools::Rectangle& rRefRect,
                        const XPolygon& rDistortedRect)
 {
+    pImpXPolygon->CheckPointDelete();
+
     long    Xr, Wr;
     long    Yr, Hr;
 
@@ -597,7 +802,7 @@ void XPolygon::Distort(const tools::Rectangle& rRefRect,
 
     long    X1, X2, X3, X4;
     long    Y1, Y2, Y3, Y4;
-    DBG_ASSERT(rDistortedRect.pImpXPolygon->mvPointsAndFlags.size() >= 4,
+    DBG_ASSERT(rDistortedRect.pImpXPolygon->nPoints >= 4,
                "Distort: rectangle to small");
 
     X1 = rDistortedRect[0].X();
@@ -609,12 +814,12 @@ void XPolygon::Distort(const tools::Rectangle& rRefRect,
     X4 = rDistortedRect[2].X();
     Y4 = rDistortedRect[2].Y();
 
-    sal_uInt16 nPntCnt = pImpXPolygon->mvPointsAndFlags.size();
+    sal_uInt16 nPntCnt = pImpXPolygon->nPoints;
 
     for (sal_uInt16 i = 0; i < nPntCnt; i++)
     {
         double  fTx, fTy, fUx, fUy;
-        Point& rPnt = pImpXPolygon->mvPointsAndFlags[i].first;
+        Point& rPnt = pImpXPolygon->pPointAry[i];
 
         fTx = static_cast<double>(rPnt.X() - Xr) / Wr;
         fTy = static_cast<double>(rPnt.Y() - Yr) / Hr;
@@ -633,7 +838,7 @@ basegfx::B2DPolygon XPolygon::getB2DPolygon() const
     // #i74631# use tools Polygon class for conversion to not have the code doubled
     // here. This needs one more conversion but avoids different convertors in
     // the long run
-    const tools::Polygon aSource(pImpXPolygon->mvPointsAndFlags);
+    const tools::Polygon aSource(GetPointCount(), pImpXPolygon->pPointAry, pImpXPolygon->pFlagAry.get());
 
     return aSource.getB2DPolygon();
 }
@@ -647,12 +852,12 @@ XPolygon::XPolygon(const basegfx::B2DPolygon& rPolygon)
 
     const tools::Polygon aSource(rPolygon);
     sal_uInt16 nSize = aSource.GetSize();
-    pImpXPolygon->mvPointsAndFlags.resize(nSize);
+    pImpXPolygon->nPoints = nSize;
 
     for( sal_uInt16 i = 0; i < nSize;  i++ )
     {
-        pImpXPolygon->mvPointsAndFlags[i].first = aSource[i];
-        pImpXPolygon->mvPointsAndFlags[i].second = aSource.GetFlags( i );
+        pImpXPolygon->pPointAry[i] = aSource[i];
+        pImpXPolygon->pFlagAry[i] = aSource.GetFlags( i );
     }
 }
 
diff --git a/tools/inc/poly.h b/tools/inc/poly.h
index 3c7b0c923465..88da80ca1615 100644
--- a/tools/inc/poly.h
+++ b/tools/inc/poly.h
@@ -35,7 +35,6 @@ public:
                     ImplPolygon() : mnPoints(0) {}
                     ImplPolygon( sal_uInt16 nInitSize, bool bFlags = false );
                     ImplPolygon( sal_uInt16 nPoints, const Point* pPtAry, const PolyFlags* pInitFlags );
-                    ImplPolygon( std::vector< std::pair<Point, PolyFlags> > const & );
                     ImplPolygon( const ImplPolygon& rImplPoly );
                     ImplPolygon( const tools::Rectangle& rRect );
                     ImplPolygon( const tools::Rectangle& rRect, sal_uInt32 nHorzRound, sal_uInt32 nVertRound);
diff --git a/tools/source/generic/poly.cxx b/tools/source/generic/poly.cxx
index b88c411a927b..3c78b5a04bc8 100644
--- a/tools/source/generic/poly.cxx
+++ b/tools/source/generic/poly.cxx
@@ -100,24 +100,6 @@ ImplPolygon::ImplPolygon( sal_uInt16 nInitSize, const Point* pInitAry, const Pol
     mnPoints   = nInitSize;
 }
 
-ImplPolygon::ImplPolygon( std::vector< std::pair<Point, PolyFlags> > const & rPointsAndFlags )
-{
-    auto nInitSize = rPointsAndFlags.size();
-    if ( nInitSize )
-    {
-        mxPointAry.reset(new Point[nInitSize]);
-        mxFlagAry.reset(new PolyFlags[nInitSize]);
-        int i = 0;
-        for (auto const & rPair : rPointsAndFlags) {
-            mxPointAry[i] = rPair.first;
-            mxFlagAry[i] = rPair.second;
-            ++i;
-        }
-    }
-
-    mnPoints   = nInitSize;
-}
-
 ImplPolygon::ImplPolygon( const tools::Rectangle& rRect )
 {
     if ( !rRect.IsEmpty() )
@@ -886,10 +868,6 @@ Polygon::Polygon( sal_uInt16 nPoints, const Point* pPtAry, const PolyFlags* pFla
 {
 }
 
-Polygon::Polygon( std::vector< std::pair<Point, PolyFlags> > const & rPointsAndFlags ) : mpImplPolygon(ImplPolygon(rPointsAndFlags))
-{
-}
-
 Polygon::Polygon( const tools::Polygon& rPoly ) : mpImplPolygon(rPoly.mpImplPolygon)
 {
 }


More information about the Libreoffice-commits mailing list