summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Brandner <Andreas.Brandner@cib.de>2017-09-15 09:17:17 +0200
committerThorsten Behrens <Thorsten.Behrens@CIB.de>2017-12-10 23:23:39 +0100
commit225115af05cba9a603130914b49c5b28ed451108 (patch)
treea721d68102896cec18d3d61f9a4fd11762ade8f2
parent456f943d2258164d35ec3522b1866302aa1f6e6b (diff)
tdf#62525 tools: use cow_wrapper class for Polygon
Change-Id: I78f141762f593b36d32eb3eb2cda8fdae54b7277 Reviewed-on: https://gerrit.libreoffice.org/42309 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
-rw-r--r--include/tools/poly.hxx8
-rw-r--r--tools/inc/poly.h14
-rw-r--r--tools/source/generic/poly.cxx978
3 files changed, 483 insertions, 517 deletions
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,41 +53,27 @@
#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 )
{
- 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 );
- }
- else
- mpPointAry = nullptr;
-
- if( bFlags )
- {
- mpFlagAry = new PolyFlags[ nInitSize ];
- memset( mpFlagAry, 0, nInitSize );
- }
- else
- mpFlagAry = nullptr;
-
- mnRefCount = 1;
- mnPoints = nInitSize;
+ ImplInitSize(nInitSize, bFlags);
}
ImplPolygon::ImplPolygon( const ImplPolygon& rImpPoly )
{
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 );
+ mpPointAry = new Point[ rImpPoly.mnPoints ];
+ memcpy( mpPointAry,
+ rImpPoly.mpPointAry,
+ static_cast<std::size_t>(rImpPoly.mnPoints)*sizeof(Point) );
if( rImpPoly.mpFlagAry )
{
@@ -103,7 +89,6 @@ ImplPolygon::ImplPolygon( const ImplPolygon& rImpPoly )
mpFlagAry = nullptr;
}
- mnRefCount = 1;
mnPoints = rImpPoly.mnPoints;
}
@@ -111,9 +96,10 @@ ImplPolygon::ImplPolygon( sal_uInt16 nInitSize, const Point* pInitAry, const Pol
{
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 );
+ mpPointAry = new Point[ nInitSize ];
+ memcpy( mpPointAry,
+ pInitAry,
+ static_cast<std::size_t>(nInitSize)*sizeof(Point) );
if( pInitFlags )
{
@@ -129,21 +115,444 @@ ImplPolygon::ImplPolygon( sal_uInt16 nInitSize, const Point* pInitAry, const Pol
mpFlagAry = nullptr;
}
- mnRefCount = 1;
mnPoints = nInitSize;
}
-ImplPolygon::~ImplPolygon()
+ImplPolygon::ImplPolygon( const tools::Rectangle& rRect )
{
- if ( mpPointAry )
+ 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
{
- delete[] reinterpret_cast<char*>(mpPointAry);
+ // #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;
+ }
+
+ if(bClosed)
+ {
+ // add first point as closing point
+ mpPointAry[nIndex] = mpPointAry[0];
+ }
+ }
}
+}
+
+bool ImplPolygon::operator==( const ImplPolygon& rCandidate) const
+{
+ if(mnPoints == rCandidate.mnPoints)
+ {
+ if (mpFlagAry == rCandidate.mpFlagAry && mpPointAry == rCandidate.mpPointAry)
+ return true;
+ }
+
+ return false;
+}
+
+ImplPolygon::~ImplPolygon()
+{
+ if ( mpPointAry )
+ delete[] mpPointAry;
if( mpFlagAry )
delete[] mpFlagAry;
}
+void ImplPolygon::ImplInitDefault()
+{
+ mpPointAry = nullptr;
+ mpFlagAry = nullptr;
+ mnPoints = 0;
+}
+
+void ImplPolygon::ImplInitSize( sal_uInt16 nInitSize, bool bFlags)
+{
+ if ( nInitSize )
+ {
+ mpPointAry = new Point[ nInitSize ];
+ memset( mpPointAry,
+ 0,
+ static_cast<std::size_t>(nInitSize)*sizeof(Point) );
+ }
+ else
+ mpPointAry = nullptr;
+
+ if( bFlags )
+ {
+ mpFlagAry = new PolyFlags[ nInitSize ];
+ memset( mpFlagAry, 0, nInitSize );
+ }
+ else
+ mpFlagAry = nullptr;
+
+ mnPoints = nInitSize;
+}
+
void ImplPolygon::ImplSetSize( sal_uInt16 nNewSize, bool bResize )
{
if( mnPoints == nNewSize )
@@ -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:
@@ -514,306 +914,54 @@ tools::Polygon Polygon::SubdivideBezier( const tools::Polygon& rPoly )
return aPoly;
}
-
-inline void Polygon::ImplMakeUnique()
+Polygon::Polygon() : mpImplPolygon(ImplPolygon())
{
- // copy references if any exist
- if ( mpImplPolygon->mnRefCount != 1 )
- {
- if ( mpImplPolygon->mnRefCount )
- mpImplPolygon->mnRefCount--;
- mpImplPolygon = new ImplPolygon( *mpImplPolygon );
- }
}
-Polygon::Polygon()
+Polygon::Polygon( sal_uInt16 nSize ) : mpImplPolygon(ImplPolygon(nSize))
{
- mpImplPolygon = static_cast<ImplPolygon*>(&aStaticImplPolygon);
}
-Polygon::Polygon( sal_uInt16 nSize )
+Polygon::Polygon( sal_uInt16 nPoints, const Point* pPtAry, const PolyFlags* pFlagAry ) : mpImplPolygon(ImplPolygon(nPoints, pPtAry, pFlagAry))
{
-
- if ( nSize )
- mpImplPolygon = new ImplPolygon( nSize );
- else
- mpImplPolygon = static_cast<ImplPolygon*>(&aStaticImplPolygon);
}
-Polygon::Polygon( sal_uInt16 nPoints, const Point* pPtAry, const PolyFlags* pFlagAry )
+Polygon::Polygon( const tools::Polygon& rPoly ) : mpImplPolygon(rPoly.mpImplPolygon)
{
- if( nPoints )
- mpImplPolygon = new ImplPolygon( nPoints, pPtAry, pFlagAry );
- else
- mpImplPolygon = static_cast<ImplPolygon*>(&aStaticImplPolygon);
}
-Polygon::Polygon( const tools::Polygon& rPoly )
+Polygon::Polygon( tools::Polygon&& rPoly)
+ : mpImplPolygon(std::move(rPoly.mpImplPolygon))
{
- 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 )
+Polygon::Polygon( const tools::Rectangle& rRect ) : mpImplPolygon(ImplPolygon(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 )
+ : mpImplPolygon(ImplPolygon(rRect, nHorzRound, 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 )
+ : mpImplPolygon(ImplPolygon(rCenter, nRadX, 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 )
+ PolyStyle eStyle, bool bFullCircle ) : mpImplPolygon(ImplPolygon(rBound, rStart, rEnd, eStyle, 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;
- 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;
- }
-
- for(; nStart < nEnd; nStart++, fStart += fStep )
- {
- Point& rPt = mpImplPolygon->mpPointAry[ nStart ];
-
- rPt.X() = FRound( fCenterX + fRadX * cos( fStart ) );
- rPt.Y() = FRound( fCenterY - fRadY * sin( fStart ) );
- }
-
- if( PolyStyle::Chord == eStyle )
- mpImplPolygon->mpPointAry[ nPoints ] = mpImplPolygon->mpPointAry[ 0 ];
- }
- else
- mpImplPolygon = static_cast<ImplPolygon*>( &aStaticImplPolygon );
}
Polygon::Polygon( const Point& rBezPt1, const Point& rCtrlPt1,
const Point& rBezPt2, const Point& rCtrlPt2,
- sal_uInt16 nPoints )
+ sal_uInt16 nPoints ) : mpImplPolygon(ImplPolygon(rBezPt1, rCtrlPt1, rBezPt2, rCtrlPt2, 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();
-
- mpImplPolygon = new ImplPolygon( nPoints );
-
- for( sal_uInt16 i = 0; i < nPoints; i++, fK_1 += fInc, fK1_1 -= fInc )
- {
- Point& rPt = mpImplPolygon->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 );
- }
}
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