emfio/qa/cppunit/emf/EmfImportTest.cxx     |   89 ++++++++++--------------
 emfio/qa/cppunit/emf/data/TestAngleArc.emf |binary
 emfio/source/reader/emfreader.cxx          |   38 +++++++++-
 include/tools/poly.hxx                     |    3 
 tools/inc/poly.h                           |    3 
 tools/source/generic/poly.cxx              |  104 ++++++++++++++++++++++-------
 6 files changed, 154 insertions(+), 83 deletions(-)

New commits:
commit 5b32c63c6569996acc39216f81520291f15c7659
Author:     Bartosz Kosiorek <gan...@poczta.onet.pl>
AuthorDate: Wed Aug 6 18:03:05 2025 +0200
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Fri Aug 8 20:03:18 2025 +0200

    tdf#103859 EMF Fix quality of EMR_ROUNDRECT by using Bazier curve for 
drawing
    
    As WMF and EMF is using integers and previous EMR_ROUNDRECT implementation
    used many small lines to display curves, it produces low quality curves.
    With this implementation using Bezier curves,
    EMR_ROUNDRECT images are scalable without any loss of quality.
    
    Change-Id: I3ef7f15ed9e3835065030bdf196b9bfa044d84a3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189016
    Tested-by: Jenkins
    Reviewed-by: Bartosz Kosiorek <gan...@poczta.onet.pl>
    (cherry picked from commit 05fd7ddeb2f7d506b6c94dfcdef12b9bdbf9e4e5)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189090
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/emfio/qa/cppunit/emf/EmfImportTest.cxx 
b/emfio/qa/cppunit/emf/EmfImportTest.cxx
index 6ef45e866f19..a644d46b2b73 100644
--- a/emfio/qa/cppunit/emf/EmfImportTest.cxx
+++ b/emfio/qa/cppunit/emf/EmfImportTest.cxx
@@ -1504,33 +1504,8 @@ CPPUNIT_TEST_FIXTURE(Test, testRoundrectWMF)
 
     assertXPath(pDocument, aXPathPrefix + "polypolygoncolor", "color", 
u"#ffffff");
 
-    assertXPathContent(
-        pDocument, aXPathPrefix + "polygonstroke/polygon",
-        u"2858,659 2858,651 2858,643 2858,635 2858,619 2858,611 2858,603 
2850,595 2850,587 "
-        u"2850,580 "
-        "2850,564 2850,556 2842,548 2842,540 2842,532 2834,524 2834,516 
2834,508 2826,500 2826,492 "
-        "2818,484 2818,476 2810,468 2810,460 2802,452 2802,445 2794,437 
2794,429 2786,421 2786,421 "
-        "2778,413 2770,405 2770,397 2762,389 2754,389 2754,381 2746,373 
2738,373 2731,365 2731,365 "
-        "2723,357 2715,349 2707,349 2707,341 2699,341 2691,341 2683,333 
2675,333 2675,333 2667,325 "
-        "2659,325 2651,325 2643,325 2635,318 2627,318 2627,318 2619,318 
2611,318 2604,318 572,318 "
-        "564,318 556,318 548,318 548,318 540,318 532,325 524,325 516,325 
508,325 500,333 500,333 "
-        "492,333 484,341 476,341 468,341 468,349 460,349 452,357 445,365 
445,365 437,373 429,373 "
-        "421,381 421,389 413,389 405,397 405,405 397,413 389,421 389,421 
381,429 381,437 373,445 "
-        "373,452 365,460 365,468 357,476 357,484 349,492 349,500 341,508 
341,516 341,524 333,532 "
-        "333,540 333,548 325,556 325,564 325,580 325,587 325,595 318,603 
318,611 318,619 318,635 "
-        "318,643 318,651 318,659 318,1667 318,1675 318,1683 318,1691 318,1707 
318,1715 318,1723 "
-        "325,1731 325,1739 325,1746 325,1762 325,1770 333,1778 333,1786 
333,1794 341,1802 341,1810 "
-        "341,1818 349,1826 349,1834 357,1842 357,1850 365,1858 365,1866 
373,1874 373,1881 381,1889 "
-        "381,1897 389,1905 389,1905 397,1913 405,1921 405,1929 413,1937 
421,1937 421,1945 429,1953 "
-        "437,1953 445,1961 445,1961 452,1969 460,1977 468,1977 468,1985 
476,1985 484,1985 492,1993 "
-        "500,1993 500,1993 508,2001 516,2001 524,2001 532,2001 540,2008 
548,2008 548,2008 556,2008 "
-        "564,2008 572,2008 2604,2008 2611,2008 2619,2008 2627,2008 2627,2008 
2635,2008 2643,2001 "
-        "2651,2001 2659,2001 2667,2001 2675,1993 2675,1993 2683,1993 2691,1985 
2699,1985 2707,1985 "
-        "2707,1977 2715,1977 2723,1969 2731,1961 2731,1961 2738,1953 2746,1953 
2754,1945 2754,1937 "
-        "2762,1937 2770,1929 2770,1921 2778,1913 2786,1905 2786,1905 2794,1897 
2794,1889 2802,1881 "
-        "2802,1874 2810,1866 2810,1858 2818,1850 2818,1842 2826,1834 2826,1826 
2834,1818 2834,1810 "
-        "2834,1802 2842,1794 2842,1786 2842,1778 2850,1770 2850,1762 2850,1746 
2850,1739 2850,1731 "
-        "2858,1723 2858,1715 2858,1707 2858,1691 2858,1683 2858,1675 
2858,1667");
+    assertXPathContent(pDocument, aXPathPrefix + "polygonstroke/polygon",
+                       u"318,659 572,318 2604,318 2858,659 2858,1667 2604,2008 
572,2008 318,1667");
     assertXPath(pDocument, aXPathPrefix + "polygonstroke/line", "color", 
u"#000000");
     assertXPath(pDocument, aXPathPrefix + "polygonstroke/line", "width", 
u"143");
 }
@@ -1632,36 +1607,14 @@ CPPUNIT_TEST_FIXTURE(Test, testRoundRect)
                        u"100,100 4100,100 4100,2100 100,2100");
     assertXPath(pDocument, aXPathPrefix + "polygonstroke[1]/line", "color", 
u"#ff0000");
 
-    assertXPath(
-        pDocument, aXPathPrefix + "polypolygoncolor[2]/polypolygon", "path",
-        u"m4090 "
-        
"2700v-30-20l-10-30v-20l-10-30-10-20-10-20-20-30-10-20-20-20-20-20-20-30-20-20-20-20-20-10-"
-        
"30-20-20-20-30-20-30-10-30-10-30-20-30-10-30-10-40-10-30-10h-30l-40-10h-30l-40-10h-30-40-"
-        "2590-40-30l-40 10h-30l-40 10h-30l-30 10-40 10-30 10-30 10-30 20-30 
10-30 10-30 20-20 "
-        "20-30 20-20 10-20 20-20 20-20 30-20 20-20 20-10 20-20 30-10 20-10 
20-10 30v20l-10 30v20 "
-        "30 990 30 20l10 30v20l10 30 10 20 10 20 20 30 10 20 20 20 20 20 20 30 
20 20 20 20 20 10 "
-        "30 20 20 20 30 20 30 10 30 10 30 20 30 10 30 10 40 10 30 10h30l40 
10h30l40 10h30 40 2590 "
-        "40 30l40-10h30l40-10h30l30-10 40-10 30-10 30-10 30-20 30-10 30-10 
30-20 20-20 30-20 20-10 "
-        "20-20 20-20 20-30 20-20 20-20 10-20 20-30 10-20 10-20 
10-30v-20l10-30v-20-30z");
+    assertXPath(pDocument, aXPathPrefix + "polypolygoncolor[2]/polypolygon", 
"path",
+                u"m100 2700c0-250 350-500 700-500h2590c350 0 700 250 700 
500v990c0 250-350 500-700 "
+                u"500h-2590c-350 0-700-250-700-500z");
     assertXPath(pDocument, aXPathPrefix + "polypolygoncolor[2]", "color", 
u"#ffffff");
 
     assertXPathContent(
         pDocument, aXPathPrefix + "polygonstroke[2]/polygon",
-        u"4090,2700 4090,2670 4090,2650 4080,2620 4080,2600 4070,2570 
4060,2550 4050,2530 "
-        u"4030,2500 "
-        "4020,2480 4000,2460 3980,2440 3960,2410 3940,2390 3920,2370 3900,2360 
3870,2340 3850,2320 "
-        "3820,2300 3790,2290 3760,2280 3730,2260 3700,2250 3670,2240 3630,2230 
3600,2220 3570,2220 "
-        "3530,2210 3500,2210 3460,2200 3430,2200 3390,2200 800,2200 760,2200 
730,2200 690,2210 "
-        "660,2210 620,2220 590,2220 560,2230 520,2240 490,2250 460,2260 
430,2280 400,2290 370,2300 "
-        "340,2320 320,2340 290,2360 270,2370 250,2390 230,2410 210,2440 
190,2460 170,2480 160,2500 "
-        "140,2530 130,2550 120,2570 110,2600 110,2620 100,2650 100,2670 
100,2700 100,3690 100,3720 "
-        "100,3740 110,3770 110,3790 120,3820 130,3840 140,3860 160,3890 
170,3910 190,3930 210,3950 "
-        "230,3980 250,4000 270,4020 290,4030 320,4050 340,4070 370,4090 
400,4100 430,4110 460,4130 "
-        "490,4140 520,4150 560,4160 590,4170 620,4170 660,4180 690,4180 
730,4190 760,4190 800,4190 "
-        "3390,4190 3430,4190 3460,4190 3500,4180 3530,4180 3570,4170 3600,4170 
3630,4160 3670,4150 "
-        "3700,4140 3730,4130 3760,4110 3790,4100 3820,4090 3850,4070 3870,4050 
3900,4030 3920,4020 "
-        "3940,4000 3960,3980 3980,3950 4000,3930 4020,3910 4030,3890 4050,3860 
4060,3840 4070,3820 "
-        "4080,3790 4080,3770 4090,3740 4090,3720 4090,3690");
+        u"100,2700 800,2200 3390,2200 4090,2700 4090,3690 3390,4190 800,4190 
100,3690");
     assertXPath(pDocument, aXPathPrefix + "polygonstroke[2]/line", "color", 
u"#ff0000");
 }
 
diff --git a/emfio/source/reader/emfreader.cxx 
b/emfio/source/reader/emfreader.cxx
index 13961baab645..e281e4f009ee 100644
--- a/emfio/source/reader/emfreader.cxx
+++ b/emfio/source/reader/emfreader.cxx
@@ -1347,11 +1347,13 @@ namespace emfio
                     }
                     break;
 
-                    case EMR_ROUNDRECT :
+                    case EMR_ROUNDRECT:
                     {
-                        mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 
).ReadInt32( nx32 ).ReadInt32( ny32 ).ReadUInt32( nW ).ReadUInt32( nH );
-                        tools::Polygon aRoundRectPoly( ReadRectangle( nX32, 
nY32, nx32, ny32 ), nW, nH );
-                        DrawPolygon( std::move(aRoundRectPoly), mbRecordPath );
+                        
mpInputStream->ReadInt32(nX32).ReadInt32(nY32).ReadInt32(nx32).ReadInt32(ny32).ReadUInt32(nW).ReadUInt32(nH);
+                        SAL_INFO("emfio", "             Rectangle position: " 
<< nX32 << ":" << nY32 << ", " << nx32 << ":" << ny32);
+                        SAL_INFO("emfio", "             Ellipse Width: " << nW 
<< ", Height" << nH);
+                        tools::Polygon aRoundRectPoly(ReadRectangle(nX32, 
nY32, nx32, ny32), nW, nH);
+                        DrawPolygon(std::move(aRoundRectPoly), mbRecordPath);
                     }
                     break;
 
diff --git a/tools/source/generic/poly.cxx b/tools/source/generic/poly.cxx
index b68cb92425a7..028b2925c2b2 100644
--- a/tools/source/generic/poly.cxx
+++ b/tools/source/generic/poly.cxx
@@ -123,17 +123,19 @@ ImplPolygon::ImplPolygon( const tools::Rectangle& rRect )
         mnPoints = 0;
 }
 
-ImplPolygon::ImplPolygon( const tools::Rectangle& rRect, sal_uInt32 
nHorzRound, sal_uInt32 nVertRound )
+ImplPolygon::ImplPolygon(const tools::Rectangle& rRect, sal_uInt32 nHorzRound,
+                         sal_uInt32 nVertRound)
 {
-    if ( !rRect.IsEmpty() )
+    if (!rRect.IsEmpty())
     {
-        tools::Rectangle aRect( rRect );
-        aRect.Normalize();            // SJ: i9140
+        tools::Rectangle aRect(rRect);
+        aRect.Normalize(); // SJ: i9140
 
-        nHorzRound = std::min( nHorzRound, static_cast<sal_uInt32>(std::abs( 
aRect.GetWidth() >> 1 )) );
-        nVertRound = std::min( nVertRound, static_cast<sal_uInt32>(std::abs( 
aRect.GetHeight() >> 1 )) );
+        nHorzRound = std::min(nHorzRound, 
static_cast<sal_uInt32>(std::abs(aRect.GetWidth() >> 1)));
+        nVertRound
+            = std::min(nVertRound, 
static_cast<sal_uInt32>(std::abs(aRect.GetHeight() >> 1)));
 
-        if( !nHorzRound && !nVertRound )
+        if (!nHorzRound || !nVertRound)
         {
             ImplInitSize(5);
             mxPointAry[0] = aRect.TopLeft();
@@ -144,31 +146,49 @@ ImplPolygon::ImplPolygon( const tools::Rectangle& rRect, 
sal_uInt32 nHorzRound,
         }
         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 );
-            tools::Polygon aEllipsePoly( Point(), nHorzRound, nVertRound );
-            sal_uInt16 i, nEnd, nSize4 = aEllipsePoly.GetSize() >> 2;
+            ImplInitSize(17, true);
+
+            mxPointAry[0] = Point(aRect.Left(), aRect.Top() + nVertRound);
+
+            mxPointAry[1] = Point(aRect.Left(), aRect.Top() + 0.5 * 
nVertRound);
+            mxFlagAry[1] = PolyFlags::Control;
+
+            mxPointAry[2] = Point(aRect.Left() + 0.5 * nHorzRound, 
aRect.Top());
+            mxFlagAry[2] = PolyFlags::Control;
+
+            mxPointAry[3] = Point(aRect.Left() + nHorzRound, aRect.Top());
+
+            mxPointAry[4] = Point(aRect.Right() - nHorzRound, aRect.Top());
+
+            mxPointAry[5] = Point(aRect.Right() - 0.5 * nHorzRound, 
aRect.Top());
+            mxFlagAry[5] = PolyFlags::Control;
+
+            mxPointAry[6] = Point(aRect.Right(), aRect.Top() + 0.5 * 
nVertRound);
+            mxFlagAry[6] = PolyFlags::Control;
+
+            mxPointAry[7] = Point(aRect.Right(), aRect.Top() + nVertRound);
+
+            mxPointAry[8] = Point(aRect.Right(), aRect.Bottom() - nVertRound);
+
+            mxPointAry[9] = Point(aRect.Right(), aRect.Bottom() - 0.5 * 
nVertRound);
+            mxFlagAry[9] = PolyFlags::Control;
 
-            ImplInitSize(aEllipsePoly.GetSize() + 1);
+            mxPointAry[10] = Point(aRect.Right() - 0.5 * nHorzRound, 
aRect.Bottom());
+            mxFlagAry[10] = PolyFlags::Control;
 
-            const Point* pSrcAry = aEllipsePoly.GetConstPointAry();
-            Point* pDstAry = mxPointAry.get();
+            mxPointAry[11] = Point(aRect.Right() - nHorzRound, aRect.Bottom());
 
-            for( i = 0, nEnd = nSize4; i < nEnd; i++ )
-                pDstAry[ i ] = pSrcAry[ i ] + aTR;
+            mxPointAry[12] = Point(aRect.Left() + nHorzRound, aRect.Bottom());
 
-            for( nEnd = nEnd + nSize4; i < nEnd; i++ )
-                pDstAry[ i ] = pSrcAry[ i ] + aTL;
+            mxPointAry[13] = Point(aRect.Left() + 0.5 * nHorzRound, 
aRect.Bottom());
+            mxFlagAry[13] = PolyFlags::Control;
 
-            for( nEnd = nEnd + nSize4; i < nEnd; i++ )
-                pDstAry[ i ] = pSrcAry[ i ] + aBL;
+            mxPointAry[14] = Point(aRect.Left(), aRect.Bottom() - 0.5 * 
nVertRound);
+            mxFlagAry[14] = PolyFlags::Control;
 
-            for( nEnd = nEnd + nSize4; i < nEnd; i++ )
-                pDstAry[ i ] = pSrcAry[ i ] + aBR;
+            mxPointAry[15] = Point(aRect.Left(), aRect.Bottom() - nVertRound);
 
-            pDstAry[ nEnd ] = pDstAry[ 0 ];
+            mxPointAry[16] = mxPointAry[0];
         }
     }
     else
commit 6f1769122be69e31ce8a67c91a1d90430150fe47
Author:     Bartosz Kosiorek <gan...@poczta.onet.pl>
AuthorDate: Sun Aug 3 01:01:38 2025 +0200
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Fri Aug 8 20:03:14 2025 +0200

    tdf#167616 EMF Add support for EMR_ANGLEARC record
    
    Change-Id: Ic872f80b2a318ac7c0f3b0cbdb4ad285795989c8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188865
    Tested-by: Jenkins
    Reviewed-by: Bartosz Kosiorek <gan...@poczta.onet.pl>
    (cherry picked from commit 1b68f859034ecc2342a772685d6563fa1ad71f7f)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189091
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/emfio/qa/cppunit/emf/EmfImportTest.cxx 
b/emfio/qa/cppunit/emf/EmfImportTest.cxx
index 1c4378c7bc42..6ef45e866f19 100644
--- a/emfio/qa/cppunit/emf/EmfImportTest.cxx
+++ b/emfio/qa/cppunit/emf/EmfImportTest.cxx
@@ -607,6 +607,36 @@ CPPUNIT_TEST_FIXTURE(Test, 
testChordWithModifyWorldTransform)
                        "575,716 608,704 654,725 720,700 753,688 819,664 
853,652 919,628");
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testAngleArc)
+{
+    // tdf167616 EMF import test of displaying AngleArc which draw a line 
segment and an arc in a single operation
+    // Records: EMR_ANGLEARC, EMR_SETARCDIRECTION
+    Primitive2DSequence aSequence = 
parseEmf(u"/emfio/qa/cppunit/emf/data/TestAngleArc.emf");
+    CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aSequence.getLength()));
+    drawinglayer::Primitive2dXmlDump dumper;
+    xmlDocUniquePtr pDocument = 
dumper.dumpAndParse(Primitive2DContainer(aSequence));
+    CPPUNIT_ASSERT(pDocument);
+    assertXPath(pDocument, aXPathPrefix + "mask/polygonhairline", 20);
+    assertXPath(pDocument, aXPathPrefix + "mask/polygonhairline[1]", "color", 
u"#000000");
+
+    assertXPathContent(pDocument, aXPathPrefix + 
"mask/polygonhairline[5]/polygon",
+                       u"2350,990 4000,640");
+    assertXPathContent(pDocument, aXPathPrefix + 
"mask/polygonhairline[7]/polygon",
+                       u"4000,640 1140,2000");
+    assertXPathContent(pDocument, aXPathPrefix + 
"mask/polygonhairline[9]/polygon",
+                       u"640,2500 2350,2350");
+    assertXPathContent(pDocument, aXPathPrefix + 
"mask/polygonhairline[11]/polygon",
+                       u"2350,1650 4000,2000");
+    assertXPathContent(pDocument, aXPathPrefix + 
"mask/polygonhairline[13]/polygon",
+                       u"4000,2000 640,3000");
+    assertXPathContent(pDocument, aXPathPrefix + 
"mask/polygonhairline[15]/polygon",
+                       u"1140,3500 2350,3850");
+    assertXPathContent(pDocument, aXPathPrefix + 
"mask/polygonhairline[17]/polygon",
+                       u"1650,3850 3500,3000");
+    assertXPathContent(pDocument, aXPathPrefix + 
"mask/polygonhairline[19]/polygon",
+                       u"3500,4000 1280,4250");
+}
+
 CPPUNIT_TEST_FIXTURE(Test, testArcStartPointEqualEndPoint)
 {
     // i73608 EMF import test where StartPoint == EndPoint. It should draw 
full circle
diff --git a/emfio/qa/cppunit/emf/data/TestAngleArc.emf 
b/emfio/qa/cppunit/emf/data/TestAngleArc.emf
new file mode 100644
index 000000000000..dce3c8442fa1
Binary files /dev/null and b/emfio/qa/cppunit/emf/data/TestAngleArc.emf differ
diff --git a/emfio/source/reader/emfreader.cxx 
b/emfio/source/reader/emfreader.cxx
index 31903c4ce10f..13961baab645 100644
--- a/emfio/source/reader/emfreader.cxx
+++ b/emfio/source/reader/emfreader.cxx
@@ -1355,6 +1355,33 @@ namespace emfio
                     }
                     break;
 
+                    case EMR_ANGLEARC:
+                    {
+                        sal_Int32 nCenterX, nCenterY;
+                        sal_uInt32 nRadius;
+                        float fStartAngle, fSweepAngle;
+                        
mpInputStream->ReadInt32(nCenterX).ReadInt32(nCenterY).ReadUInt32(nRadius);
+                        
mpInputStream->ReadFloat(fStartAngle).ReadFloat(fSweepAngle);
+                        SAL_INFO("emfio", "             Center: " << nCenterX 
<< ":" << nCenterY << ", Radius: " << nRadius);
+                        SAL_INFO("emfio", "             Start Angle: " << 
fStartAngle << ", Sweep Angle: " << fSweepAngle);
+
+                        if (!mpInputStream->good())
+                            bStatus = false;
+                        else
+                        {
+                            // Convert from degrees to radians and start angle 
to draw from x-axis
+                            fStartAngle = basegfx::deg2rad(fStartAngle);
+                            fSweepAngle = basegfx::deg2rad(fSweepAngle);
+
+                            tools::Polygon aPoly(Point(nCenterX, nCenterY), 
nRadius, fStartAngle, fSweepAngle, IsArcDirectionClockWise());
+
+                            // Before drawing the arc, AngleArc draws the line 
segment from the current position to the beginning of the arc
+                            LineTo(aPoly[0], mbRecordPath);
+                            DrawPolyLine(std::move(aPoly), true, mbRecordPath);
+                        }
+                    }
+                    break;
+
                     case EMR_ARC :
                     case EMR_ARCTO :
                     case EMR_CHORD :
@@ -2173,7 +2200,6 @@ namespace emfio
                     case EMR_SETPALETTEENTRIES :
                     case EMR_RESIZEPALETTE :
                     case EMR_EXTFLOODFILL :
-                    case EMR_ANGLEARC :
                     case EMR_SETCOLORADJUSTMENT :
                     case EMR_POLYDRAW16 :
                     case EMR_SETCOLORSPACE :
diff --git a/include/tools/poly.hxx b/include/tools/poly.hxx
index 95d39d8df5ab..8d9fbeea8e8c 100644
--- a/include/tools/poly.hxx
+++ b/include/tools/poly.hxx
@@ -95,6 +95,9 @@ public:
                                  const Point& rStart, const Point& rEnd,
                                  PolyStyle ePolyStyle = PolyStyle::Arc,
                                  const bool bClockWiseArcDirection = false);
+                        Polygon( const Point& aCenter, const sal_uInt32 
nRadius,
+                                 const float fStartAngle, const float 
fSweepAngle,
+                                 const bool bClockWiseArcDirection);
                         Polygon( const Point& rBezPt1, const Point& rCtrlPt1,
                                  const Point& rBezPt2, const Point& rCtrlPt2,
                                  sal_uInt16 nPoints );
diff --git a/tools/inc/poly.h b/tools/inc/poly.h
index 6576beecaf97..f61850b352a3 100644
--- a/tools/inc/poly.h
+++ b/tools/inc/poly.h
@@ -40,6 +40,9 @@ public:
                     ImplPolygon( const Point& rCenter, tools::Long nRadX, 
tools::Long nRadY );
                     ImplPolygon( const tools::Rectangle& rBound, const Point& 
rStart, const Point& rEnd,
                                     PolyStyle eStyle, bool 
bClockWiseArcDirection );
+                    ImplPolygon( const Point& aCenter, const sal_uInt32 
nRadius,
+                                    const float fStartAngle, const float 
fSweepAngle,
+                                    const bool bClockWiseArcDirection );
                     ImplPolygon( const Point& rBezPt1, const Point& rCtrlPt1, 
const Point& rBezPt2,
                                     const Point& rCtrlPt2, sal_uInt16 nPoints 
);
                     ImplPolygon(const basegfx::B2DPolygon& rPolygon);
diff --git a/tools/source/generic/poly.cxx b/tools/source/generic/poly.cxx
index 0b8350bd8638..b68cb92425a7 100644
--- a/tools/source/generic/poly.cxx
+++ b/tools/source/generic/poly.cxx
@@ -306,6 +306,34 @@ ImplPolygon::ImplPolygon(const tools::Rectangle& rBound, 
const Point& rStart, co
         mnPoints = 0;
 }
 
+ImplPolygon::ImplPolygon(const Point& aCenter, const sal_uInt32 nRadius, const 
float fStartAngle,
+                         const float fSweepAngle, const bool 
bClockWiseArcDirection)
+{
+    float fStart = fStartAngle;
+    float fEnd = fStartAngle + fSweepAngle;
+
+    if (bClockWiseArcDirection)
+        std::swap(fStart, fEnd);
+    float fDiff = fEnd - fStart;
+    float fStep = static_cast<float>(M_PI / 128.0);
+
+    if ((fSweepAngle < 0.0) || bClockWiseArcDirection)
+        fStep = -fStep;
+
+    const sal_uInt16 nPoints = static_cast<sal_uInt16>(fDiff / fStep) + 1;
+
+    ImplInitSize(nPoints);
+
+    for (sal_uInt16 i = 0; i < nPoints; i++, fStart += fStep)
+    {
+        Point& rPt = mxPointAry[i];
+        rPt.setX(basegfx::fround<tools::Long>(aCenter.X() + nRadius * 
cos(fStart)));
+        rPt.setY(basegfx::fround<tools::Long>(aCenter.Y() - nRadius * 
sin(fStart)));
+    }
+    mxPointAry[nPoints - 1].setX(basegfx::fround<tools::Long>(aCenter.X() + 
nRadius * cos(fEnd)));
+    mxPointAry[nPoints - 1].setY(basegfx::fround<tools::Long>(aCenter.Y() - 
nRadius * sin(fEnd)));
+}
+
 ImplPolygon::ImplPolygon( const Point& rBezPt1, const Point& rCtrlPt1,
     const Point& rBezPt2, const Point& rCtrlPt2, sal_uInt16 nPoints )
 {
@@ -911,6 +939,12 @@ Polygon::Polygon(const tools::Rectangle& rBound, const 
Point& rStart, const Poin
 {
 }
 
+Polygon::Polygon(const Point& aCenter, const sal_uInt32 nRadius, const float 
fStartAngle,
+                 const float fSweepAngle, const bool bClockWiseArcDirection)
+    : mpImplPolygon(ImplPolygon(aCenter, nRadius, fStartAngle, fSweepAngle, 
bClockWiseArcDirection))
+{
+}
+
 Polygon::Polygon( const Point& rBezPt1, const Point& rCtrlPt1,
                   const Point& rBezPt2, const Point& rCtrlPt2,
                   sal_uInt16 nPoints ) : mpImplPolygon(ImplPolygon(rBezPt1, 
rCtrlPt1, rBezPt2, rCtrlPt2, nPoints))

Reply via email to