emfio/qa/cppunit/emf/EmfImportTest.cxx |   59 ++-------------------------
 emfio/source/reader/emfreader.cxx      |   10 ++--
 tools/source/generic/poly.cxx          |   70 +++++++++++++++++++++------------
 3 files changed, 57 insertions(+), 82 deletions(-)

New commits:
commit e24f16560d0549acfa9db29cce42355b8ccc23e0
Author:     Bartosz Kosiorek <gan...@poczta.onet.pl>
AuthorDate: Wed Aug 6 18:03:05 2025 +0200
Commit:     Bartosz Kosiorek <gan...@poczta.onet.pl>
CommitDate: Wed Aug 6 22:06:09 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>

diff --git a/emfio/qa/cppunit/emf/EmfImportTest.cxx 
b/emfio/qa/cppunit/emf/EmfImportTest.cxx
index 43bb00f8f32b..e3f7f07f7f83 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 50ecf6bd577a..1764013bb14d 100644
--- a/emfio/source/reader/emfreader.cxx
+++ b/emfio/source/reader/emfreader.cxx
@@ -1348,11 +1348,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

Reply via email to