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.brand...@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 <c...@libreoffice.org> Reviewed-by: Thorsten Behrens <thorsten.behr...@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 _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits