emfio/qa/cppunit/emf/EmfImportTest.cxx                          |   61 +-------
 emfio/qa/cppunit/emf/data/TestEllipseWithSelectClipPath.emf     |binary
 emfio/qa/cppunit/emf/data/TestEllipseXformIntersectClipRect.emf |binary
 emfio/source/reader/emfreader.cxx                               |   10 -
 tools/source/generic/poly.cxx                                   |   71 
+++++-----
 5 files changed, 51 insertions(+), 91 deletions(-)

New commits:
commit ccf1476f70d39797f968444ac585c19b0edbff36
Author:     Bartosz Kosiorek <gan...@poczta.onet.pl>
AuthorDate: Wed Aug 6 21:23:28 2025 +0200
Commit:     Bartosz Kosiorek <gan...@poczta.onet.pl>
CommitDate: Fri Aug 8 17:46:09 2025 +0200

    tdf#103859 EMF Fix quality of EMR_ELLIPSE by using Bazier curve for drawing
    
    Change-Id: I7eaca22dac921229b4a88e07739d379948730bd9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189024
    Reviewed-by: Bartosz Kosiorek <gan...@poczta.onet.pl>
    Tested-by: Jenkins

diff --git a/emfio/qa/cppunit/emf/EmfImportTest.cxx 
b/emfio/qa/cppunit/emf/EmfImportTest.cxx
index e3f7f07f7f83..a32db251df92 100644
--- a/emfio/qa/cppunit/emf/EmfImportTest.cxx
+++ b/emfio/qa/cppunit/emf/EmfImportTest.cxx
@@ -726,17 +726,11 @@ CPPUNIT_TEST_FIXTURE(Test, testEllipseWithSelectClipPath)
 
     assertXPath(pDocument, aXPathPrefix + "group/mask/polypolygon", 1);
     assertXPath(pDocument, aXPathPrefix + "group/mask/polypolygon[1]", "path",
-                u"m2790 "
-                
"776v-36-35h-36v-35l-35-35-35-36h-36l-35-35-35-35h-35-36l-35-35h-35-36l-35-36h-35-"
-                
"36l-35-35h-35-71-35l-36-35h-70-35-36-70l-36-35h-35-71-35-71-35-71-35-35-71-35-71-"
-                "35-71-35l-35 35h-71-35-36-70l-35 35h-36-70-36l-35 
35h-35-36l-35 36h-35-36l-35 "
-                "35h-35-36l-35 35-35 35h-35l-36 36-35 35v35h-35v35 36 35 
35h35v35l35 36 36 "
-                "35h35l35 35 35 35h36 35l35 36h36 35l35 35h36 35l35 35h36 70 
36l35 35h70 36 35 "
-                "71l35 36h35 71 35 71 35 71 35 35 71 35 71 35 71 35l36-36h70 
36 35 70l36-35h35 71 "
-                "35l35-35h36 35l35-35h36 35l35-36h36 35l35-35 35-35h36l35-35 
35-36v-35h36v-35z");
+                u"m177 776c0 211 565 423 1306 423 706 0 1307-212 1307-423 "
+                u"0-247-601-423-1307-423-741 0-1306 176-1306 423z");
 
     assertXPath(pDocument, aXPathPrefix + "group/mask/polypolygoncolor", 1);
-    assertXPath(pDocument, aXPathPrefix + "group/mask/polypolygoncolor[1]", 
"color", u"#ffff00");
+    assertXPath(pDocument, aXPathPrefix + "group/mask/polypolygoncolor[1]", 
"color", u"#ff1100");
     assertXPath(pDocument, aXPathPrefix + 
"group/mask/polypolygoncolor[1]/polypolygon[1]", "path",
                 u"m353 353h2472v1057h-2472z");
 
@@ -758,49 +752,12 @@ CPPUNIT_TEST_FIXTURE(Test, 
testEllipseXformIntersectClipRect)
     assertXPath(pDocument, aXPathPrefix + "mask/polypolygon", "path", u"m0 
0h3000v2000h-3000z");
     assertXPath(pDocument, aXPathPrefix + "mask/group/mask/polypolygon", 
"path",
                 u"m370 152 1128-409 592 1623-1128 410z");
-    assertXPath(
-        pDocument, aXPathPrefix + 
"mask/group/mask/polypolygoncolor/polypolygon", "path",
-        u"m3613 287-12-33-12-33-12-33-12-33-33 12-12-34-13-33-45-21-12-33-33 "
-        "12-12-33-45-21-46-21-12-33-33 12-12-33-45-21-33 12-46-21-45-21-33 
12-45-21-34 12-45-21-33 "
-        "12-45-21-34 12-45-21-33 12-45-21-33 12-34 12-45-21-33 12-33 
12-45-21-34 12-66 24-45-21-33 "
-        "12-34 12-66 24-33 12-45-21-34 12-66 24-33 12-33 12-34 12-66 24-33 
12-33 12-67 25-33 12-33 "
-        "12-33 12-67 24-33 12-21 45-33 12-66 24-34 12-33 12-21 46-66 24-33 
12-22 45-33 12-33 12-21 "
-        "45-33 12-33 12-21 46-34 12-21 45-33 12-21 45-33 12-21 45-34 12-21 
45-33 13-21 45-21 45-33 "
-        "12-21 45 12 33-33 12 12 33-21 46-22 45 13 33-34 12 12 33-21 45 12 33 
12 34-33 12 12 33 12 "
-        "33 13 33 12 33 12 33 12 33 12 33 12 34 33-12 12 33 12 33 46 21 12 33 
33-12 12 33 45 21 45 "
-        "21 12 33 34-12 12 33 45 21 33-12 45 21 46 22 33-13 45 22 33-13 46 22 
33-13 45 22 33-13 45 "
-        "22 34-13 45 22 33-12 33-13 46 22 33-13 33-12 45 21 33-12 67-24 45 21 
33-12 33-12 67-24 "
-        "33-12 45 21 33-12 67-24 33-12 33-12 33-12 67-24 33-12 33-12 66-25 
34-12 33-12 33-12 66-24 "
-        "33-12 22-45 33-12 66-24 33-12 33-12 22-45 66-25 33-12 21-45 33-12 
34-12 21-45 33-12 33-12 "
-        "21-45 33-12 21-46 34-12 21-45 33-12 21-45 33-12 21-45 33-12 22-46 
21-45 33-12 21-45-12-33 "
-        "33-12-12-33 21-46 21-45-12-33 33-12-12-33 21-45-12-33-12-33 
33-12-12-34-12-33-12-33z");
-    assertXPathContent(
-        pDocument, aXPathPrefix + "mask/group/mask/polygonstroke/polygon",
-        u"3613,287 3601,254 3601,254 3589,221 3577,188 3565,155 3532,167 
3520,133 3507,100 "
-        u"3507,100 "
-        "3462,79 3450,46 3417,58 3405,25 3360,4 3360,4 3314,-17 3302,-50 
3269,-38 3257,-71 "
-        "3212,-92 3179,-80 3133,-101 3133,-101 3088,-122 3055,-110 3010,-131 
2976,-119 2931,-140 "
-        "2898,-128 2853,-149 2819,-137 2774,-158 2741,-146 2696,-167 2663,-155 
2629,-143 2584,-164 "
-        "2551,-152 2518,-140 2473,-161 2439,-149 2373,-125 2328,-146 2295,-134 
2261,-122 2195,-98 "
-        "2162,-86 2117,-107 2083,-95 2017,-71 1984,-59 1951,-47 1917,-35 
1851,-11 1818,1 1818,1 "
-        "1785,13 1718,38 1685,50 1652,62 1619,74 1552,98 1519,110 1498,155 
1465,167 1399,191 "
-        "1365,203 1332,215 1311,261 1245,285 1212,297 1190,342 1157,354 
1124,366 1103,411 1070,423 "
-        "1037,435 1016,481 982,493 961,538 928,550 907,595 874,607 853,652 
819,664 798,709 765,722 "
-        "744,767 744,767 723,812 690,824 669,869 681,902 648,914 660,947 
639,993 639,993 617,1038 "
-        "630,1071 596,1083 608,1116 587,1161 587,1161 599,1194 611,1228 
578,1240 590,1273 602,1306 "
-        "615,1339 615,1339 627,1372 627,1372 639,1405 639,1405 651,1438 
663,1471 675,1505 708,1493 "
-        "720,1526 732,1559 732,1559 778,1580 790,1613 823,1601 835,1634 
880,1655 880,1655 925,1676 "
-        "937,1709 971,1697 983,1730 1028,1751 1061,1739 1106,1760 1106,1760 
1152,1782 1185,1769 "
-        "1230,1791 1263,1778 1309,1800 1342,1787 1387,1809 1420,1796 1465,1818 
1499,1805 1544,1827 "
-        "1577,1815 1610,1802 1656,1824 1689,1811 1722,1799 1767,1820 1800,1808 
1867,1784 1912,1805 "
-        "1945,1793 1978,1781 2045,1757 2078,1745 2123,1766 2156,1754 2223,1730 
2256,1718 2289,1706 "
-        "2322,1694 2389,1670 2422,1658 2422,1658 2455,1646 2521,1621 2555,1609 
2588,1597 2621,1585 "
-        "2687,1561 2720,1549 2742,1504 2775,1492 2841,1468 2874,1456 2907,1444 
2929,1399 2995,1374 "
-        "3028,1362 3049,1317 3082,1305 3116,1293 3137,1248 3170,1236 3203,1224 
3224,1179 3257,1167 "
-        "3278,1121 3312,1109 3333,1064 3366,1052 3387,1007 3420,995 3441,950 
3474,938 3496,892 "
-        "3496,892 3517,847 3550,835 3571,790 3559,757 3592,745 3580,712 
3601,666 3601,666 3622,621 "
-        "3610,588 3643,576 3631,543 3652,498 3652,498 3640,465 3628,432 
3661,420 3649,386 3637,353 "
-        "3625,320 3625,320");
+    assertXPath(pDocument, aXPathPrefix + "mask/group/mask/polypolygoncolor", 
"color", u"#bbaa00");
+    assertXPath(pDocument, aXPathPrefix + 
"mask/group/mask/polypolygoncolor/polypolygon", "path",
+                u"m627 1372c157 431 965 587 1795 286 796-290 1348-940 "
+                u"1191-1371-169-464-999-575-1795-286-830 302-1360 907-1191 
1371z");
+    assertXPathContent(pDocument, aXPathPrefix + 
"mask/group/mask/polygonstroke/polygon",
+                       u"627,1372 2422,1658 3613,287 1818,1");
 }
 
 CPPUNIT_TEST_FIXTURE(Test, testSetArcDirection)
diff --git a/emfio/qa/cppunit/emf/data/TestEllipseWithSelectClipPath.emf 
b/emfio/qa/cppunit/emf/data/TestEllipseWithSelectClipPath.emf
index ed0d52401238..b1bc76092c9e 100644
Binary files a/emfio/qa/cppunit/emf/data/TestEllipseWithSelectClipPath.emf and 
b/emfio/qa/cppunit/emf/data/TestEllipseWithSelectClipPath.emf differ
diff --git a/emfio/qa/cppunit/emf/data/TestEllipseXformIntersectClipRect.emf 
b/emfio/qa/cppunit/emf/data/TestEllipseXformIntersectClipRect.emf
index bda2ad233f4a..b5add75de831 100644
Binary files a/emfio/qa/cppunit/emf/data/TestEllipseXformIntersectClipRect.emf 
and b/emfio/qa/cppunit/emf/data/TestEllipseXformIntersectClipRect.emf differ
diff --git a/emfio/source/reader/emfreader.cxx 
b/emfio/source/reader/emfreader.cxx
index 1764013bb14d..7a7b2a370377 100644
--- a/emfio/source/reader/emfreader.cxx
+++ b/emfio/source/reader/emfreader.cxx
@@ -1315,9 +1315,9 @@ namespace emfio
                     }
                     break;
 
-                    case EMR_ELLIPSE :
+                    case EMR_ELLIPSE:
                     {
-                        mpInputStream->ReadInt32( nX32 ).ReadInt32( nY32 
).ReadInt32( nx32 ).ReadInt32( ny32 );
+                        
mpInputStream->ReadInt32(nX32).ReadInt32(nY32).ReadInt32(nx32).ReadInt32(ny32);
                         SAL_INFO("emfio", "             Rectangle, left: " << 
nX32 << ", top: " << nY32 << ", right: " << nx32 << ", bottom: " << ny32);
 
                         sal_Int32 w(0), h(0);
@@ -1327,9 +1327,9 @@ namespace emfio
                         {
                             tools::Long dw = w / 2;
                             tools::Long dh = h / 2;
-                            Point aCenter( nX32 + dw, nY32 + dh );
-                            tools::Polygon aPoly( aCenter, dw, dh );
-                            DrawPolygon( std::move(aPoly), mbRecordPath );
+                            Point aCenter(nX32 + dw, nY32 + dh);
+                            tools::Polygon aPoly(aCenter, dw, dh);
+                            DrawPolygon(std::move(aPoly), mbRecordPath);
                         }
                     }
                     break;
diff --git a/tools/source/generic/poly.cxx b/tools/source/generic/poly.cxx
index 60345425fc53..f4bae3abb277 100644
--- a/tools/source/generic/poly.cxx
+++ b/tools/source/generic/poly.cxx
@@ -44,6 +44,10 @@
 #include <limits.h>
 #include <cmath>
 
+// Best approximation of circle with Bazier curve.
+// Euclidean error between two curves is 0.00735
+constexpr double fKappa = 4.0 / 3.0 * (M_SQRT2 - 1);
+
 constexpr int EDGE_LEFT   = 1;
 constexpr int EDGE_TOP    = 2;
 constexpr int EDGE_RIGHT  = 4;
@@ -194,46 +198,45 @@ ImplPolygon::ImplPolygon(const tools::Rectangle& rRect, 
sal_uInt32 nHorzRound,
         mnPoints = 0;
 }
 
-ImplPolygon::ImplPolygon( const Point& rCenter, tools::Long nRadX, tools::Long 
nRadY )
+ImplPolygon::ImplPolygon(const Point& rCenter, tools::Long nRadX, tools::Long 
nRadY)
 {
-    if( nRadX && nRadY )
+    if(nRadX && nRadY)
     {
-        // Compute default (depends on size)
-        sal_uInt16 nPoints = std::clamp(
-            ( M_PI * ( 1.5 * ( nRadX + nRadY ) - sqrt( std::fabs(double(nRadX) 
* nRadY) ) ) ),
-            32.0, 256.0 );
+        ImplInitSize(13, true);
 
-        if( ( nRadX > 32 ) && ( nRadY > 32 ) && ( nRadX + nRadY ) < 8192 )
-            nPoints >>= 1;
+        mxPointAry[0] = Point(rCenter.X() - nRadX, rCenter.Y());
 
-        // Ceil number of points until divisible by four
-        nPoints = (nPoints + 3) & ~3;
-        ImplInitSize(nPoints);
+        mxPointAry[1] = Point(rCenter.X() - nRadX, rCenter.Y() + fKappa * 
nRadY);
+        mxFlagAry[1] = PolyFlags::Control;
 
-        sal_uInt16 i;
-        sal_uInt16 nPoints2 = nPoints >> 1;
-        sal_uInt16 nPoints4 = nPoints >> 2;
-        double nAngle;
-        double nAngleStep = M_PI_2 / ( nPoints4 - 1 );
+        mxPointAry[2] = Point(rCenter.X() - fKappa * nRadX, rCenter.Y() + 
nRadY);
+        mxFlagAry[2] = PolyFlags::Control;
 
-        for( i=0, nAngle = 0.0; i < nPoints4; i++, nAngle += nAngleStep )
-        {
-            tools::Long nX = basegfx::fround<tools::Long>(nRadX * cos(nAngle));
-            tools::Long nY = basegfx::fround<tools::Long>(nRadY * 
-sin(nAngle));
-
-            Point* pPt = &(mxPointAry[i]);
-            pPt->setX(  nX + rCenter.X() );
-            pPt->setY(  nY + rCenter.Y() );
-            pPt = &(mxPointAry[nPoints2-i-1]);
-            pPt->setX( -nX + rCenter.X() );
-            pPt->setY(  nY + rCenter.Y() );
-            pPt = &(mxPointAry[i+nPoints2]);
-            pPt->setX( -nX + rCenter.X() );
-            pPt->setY( -nY + rCenter.Y() );
-            pPt = &(mxPointAry[nPoints-i-1]);
-            pPt->setX(  nX + rCenter.X() );
-            pPt->setY( -nY + rCenter.Y() );
-        }
+        mxPointAry[3] = Point(rCenter.X(), rCenter.Y() + nRadY);
+
+        mxPointAry[4] = Point(rCenter.X() + fKappa * nRadX, rCenter.Y() + 
nRadY);
+        mxFlagAry[4] = PolyFlags::Control;
+
+        mxPointAry[5] = Point(rCenter.X() + nRadX, rCenter.Y() + fKappa * 
nRadY);
+        mxFlagAry[5] = PolyFlags::Control;
+
+        mxPointAry[6] = Point(rCenter.X() + nRadX, rCenter.Y());
+
+        mxPointAry[7] = Point(rCenter.X() + nRadX, rCenter.Y() - fKappa * 
nRadY);
+        mxFlagAry[7] = PolyFlags::Control;
+
+        mxPointAry[8] = Point(rCenter.X() + fKappa * nRadX, rCenter.Y() - 
nRadY);
+        mxFlagAry[8] = PolyFlags::Control;
+
+        mxPointAry[9] = Point(rCenter.X(), rCenter.Y() - nRadY);
+
+        mxPointAry[10] = Point(rCenter.X() - fKappa * nRadX, rCenter.Y() - 
nRadY);
+        mxFlagAry[10] = PolyFlags::Control;
+
+        mxPointAry[11] = Point(rCenter.X() - nRadX, rCenter.Y() - fKappa * 
nRadY);
+        mxFlagAry[11] = PolyFlags::Control;
+
+        mxPointAry[12] = mxPointAry[0];
     }
     else
         mnPoints = 0;

Reply via email to