drawinglayer/source/tools/emfphelperdata.cxx | 56 ++- drawinglayer/source/tools/emfphelperdata.hxx | 2 drawinglayer/source/tools/emfppath.cxx | 126 ++++++- drawinglayer/source/tools/emfppath.hxx | 5 emfio/qa/cppunit/emf/EmfImportTest.cxx | 186 +++++++++-- emfio/qa/cppunit/emf/data/TestEmfPlusFillClosedCurve.emf |binary emfio/qa/cppunit/emf/data/TestEmfPlusRecordTypeDrawCurve.emf |binary 7 files changed, 318 insertions(+), 57 deletions(-)
New commits: commit 62d5a612f1a3c8180c0e5059e8e05e0bedc9629b Author: Bartosz Kosiorek <gan...@poczta.onet.pl> AuthorDate: Thu Jun 1 21:16:06 2023 +0200 Commit: Bartosz Kosiorek <gan...@poczta.onet.pl> CommitDate: Fri Jun 2 15:25:52 2023 +0200 tdf#143877 EMF+ Implement EmfPlusDrawCurve with cardinal spline Change-Id: I98d30b2a8ba63fdddc08668f453c5f0feeb452db Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152288 Tested-by: Jenkins Reviewed-by: Bartosz Kosiorek <gan...@poczta.onet.pl> Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152552 diff --git a/drawinglayer/source/tools/emfphelperdata.cxx b/drawinglayer/source/tools/emfphelperdata.cxx index 94c4c32f026f..03b270228628 100644 --- a/drawinglayer/source/tools/emfphelperdata.cxx +++ b/drawinglayer/source/tools/emfphelperdata.cxx @@ -81,6 +81,8 @@ namespace emfplushelper case EmfPlusRecordTypeFillPolygon: return "EmfPlusRecordTypeFillPolygon"; case EmfPlusRecordTypeDrawLines: return "EmfPlusRecordTypeDrawLines"; case EmfPlusRecordTypeFillClosedCurve: return "EmfPlusRecordTypeFillClosedCurve"; + case EmfPlusRecordTypeDrawClosedCurve: return "EmfPlusRecordTypeDrawClosedCurve"; + case EmfPlusRecordTypeDrawCurve: return "EmfPlusRecordTypeDrawCurve"; case EmfPlusRecordTypeFillEllipse: return "EmfPlusRecordTypeFillEllipse"; case EmfPlusRecordTypeDrawEllipse: return "EmfPlusRecordTypeDrawEllipse"; case EmfPlusRecordTypeFillPie: return "EmfPlusRecordTypeFillPie"; @@ -90,7 +92,6 @@ namespace emfplushelper case EmfPlusRecordTypeFillPath: return "EmfPlusRecordTypeFillPath"; case EmfPlusRecordTypeDrawPath: return "EmfPlusRecordTypeDrawPath"; case EmfPlusRecordTypeDrawBeziers: return "EmfPlusRecordTypeDrawBeziers"; - case EmfPlusRecordTypeDrawClosedCurve: return "EmfPlusRecordTypeDrawClosedCurve"; case EmfPlusRecordTypeDrawImage: return "EmfPlusRecordTypeDrawImage"; case EmfPlusRecordTypeDrawImagePoints: return "EmfPlusRecordTypeDrawImagePoints"; case EmfPlusRecordTypeDrawString: return "EmfPlusRecordTypeDrawString"; @@ -1383,6 +1384,30 @@ namespace emfplushelper EMFPPlusDrawPolygon(::basegfx::B2DPolyPolygon(aPolygon), flags & 0xff); break; } + case EmfPlusRecordTypeDrawCurve: + { + sal_uInt32 aOffset, aNumSegments, points; + float aTension; + rMS.ReadFloat(aTension); + rMS.ReadUInt32(aOffset); + rMS.ReadUInt32(aNumSegments); + rMS.ReadUInt32(points); + SAL_WARN("drawinglayer.emf", + "EMF+\t Tension: " << aTension << " Offset: " << aOffset + << " NumSegments: " << aNumSegments + << " Points: " << points); + + EMFPPath path(points, true); + path.Read(rMS, flags); + + if (points >= 2) + EMFPPlusDrawPolygon( + path.GetCardinalSpline(*this, aTension, aOffset, aNumSegments), + flags & 0xff); + else + SAL_WARN("drawinglayer.emf", "Not enough number of points"); + break; + } case EmfPlusRecordTypeDrawClosedCurve: case EmfPlusRecordTypeFillClosedCurve: { @@ -1392,28 +1417,29 @@ namespace emfplushelper if (type == EmfPlusRecordTypeFillClosedCurve) { rMS.ReadUInt32(brushIndexOrColor); - SAL_INFO("drawinglayer.emf", + SAL_INFO( + "drawinglayer.emf", "EMF+\t Fill Mode: " << (flags & 0x2000 ? "Winding" : "Alternate")); } rMS.ReadFloat(aTension); rMS.ReadUInt32(points); SAL_WARN("drawinglayer.emf", - "EMF+\t Tension: " << aTension << " Points: " << points); - SAL_WARN_IF(aTension != 0, "drawinglayer.emf", - "EMF+\t TODO Add support for tension different than 0"); + "EMF+\t Tension: " << aTension << " Points: " << points); SAL_INFO("drawinglayer.emf", - "EMF+\t " << (flags & 0x8000 ? "Color" : "Brush index") << " : 0x" - << std::hex << brushIndexOrColor << std::dec); - + "EMF+\t " << (flags & 0x8000 ? "Color" : "Brush index") << " : 0x" + << std::hex << brushIndexOrColor << std::dec); + if (points < 3) + { + SAL_WARN("drawinglayer.emf", "Not enough number of points"); + break; + } EMFPPath path(points, true); path.Read(rMS, flags); if (type == EmfPlusRecordTypeFillClosedCurve) - EMFPPlusFillPolygon(path.GetPolygon(*this, /* bMapIt */ true, - /*bAddLineToCloseShape */ true), + EMFPPlusFillPolygon(path.GetClosedCardinalSpline(*this, aTension), flags & 0x8000, brushIndexOrColor); else - EMFPPlusDrawPolygon(path.GetPolygon(*this, /* bMapIt */ true, - /*bAddLineToCloseShape */ true), + EMFPPlusDrawPolygon(path.GetClosedCardinalSpline(*this, aTension), flags & 0xff); break; } @@ -1440,7 +1466,7 @@ namespace emfplushelper ::tools::Rectangle aSource(Point(sx, sy), Size(sw + 1, sh + 1)); SAL_INFO("drawinglayer.emf", - "EMF+\t " + "EMF+\t " << (type == EmfPlusRecordTypeDrawImage ? "DrawImage" : "DrawImagePoints") << " source rectangle: " << sx << "," << sy << " " << sw << "x" @@ -1518,8 +1544,8 @@ namespace emfplushelper SAL_INFO( "drawinglayer.emf", "EMF+\t TODO: Add support for SrcRect to ImageDataTypeMetafile"); - ::basegfx::B2DPoint aDstPoint(dx, dy); - ::basegfx::B2DSize aDstSize(dw, dh); + const ::basegfx::B2DPoint aDstPoint(dx, dy); + const ::basegfx::B2DSize aDstSize(dw, dh); const basegfx::B2DHomMatrix aTransformMatrix = maMapTransform diff --git a/drawinglayer/source/tools/emfphelperdata.hxx b/drawinglayer/source/tools/emfphelperdata.hxx index ef870f31e687..cf9e3b8855d6 100644 --- a/drawinglayer/source/tools/emfphelperdata.hxx +++ b/drawinglayer/source/tools/emfphelperdata.hxx @@ -56,7 +56,7 @@ namespace emfplushelper #define EmfPlusRecordTypeDrawPath 0x4015 #define EmfPlusRecordTypeFillClosedCurve 0x4016 #define EmfPlusRecordTypeDrawClosedCurve 0x4017 - //TODO EmfPlusRecordTypeDrawCurve 0x4018 + #define EmfPlusRecordTypeDrawCurve 0x4018 #define EmfPlusRecordTypeDrawBeziers 0x4019 #define EmfPlusRecordTypeDrawImage 0x401A #define EmfPlusRecordTypeDrawImagePoints 0x401B diff --git a/drawinglayer/source/tools/emfppath.cxx b/drawinglayer/source/tools/emfppath.cxx index 4217e3616087..bd5b2d357b0f 100644 --- a/drawinglayer/source/tools/emfppath.cxx +++ b/drawinglayer/source/tools/emfppath.cxx @@ -34,6 +34,8 @@ namespace namespace emfplushelper { + typedef float matrix [4][4]; + // see 2.2.2.21 EmfPlusInteger7 // 2.2.2.22 EmfPlusInteger15 // and 2.2.2.37 EmfPlusPointR Object @@ -65,7 +67,6 @@ namespace emfplushelper } nPoints = _nPoints; - pPoints.reset( new float [nPoints*2] ); if (!bLines) pPointTypes.reset( new sal_uInt8 [_nPoints] ); @@ -77,7 +78,8 @@ namespace emfplushelper void EMFPPath::Read (SvStream& s, sal_uInt32 pathFlags) { - for (sal_uInt32 i = 0; i < nPoints; i ++) + float fx, fy; + for (sal_uInt32 i = 0; i < nPoints; i++) { if (pathFlags & 0x800) { @@ -86,8 +88,8 @@ namespace emfplushelper // If 0x800 bit is set, the 0x4000 bit is undefined and must be ignored sal_Int32 x = GetEmfPlusInteger(s); sal_Int32 y = GetEmfPlusInteger(s); - pPoints [i*2] = x; - pPoints [i*2 + 1] = y; + xPoints.push_back(x); + yPoints.push_back(y); SAL_INFO("drawinglayer.emf", "EMF+\t\t\t" << i << ". EmfPlusPointR [x,y]: " << x << ", " << y); } else if (pathFlags & 0x4000) @@ -95,16 +97,18 @@ namespace emfplushelper // EMFPlusPoint: stored in signed short 16bit integer format sal_Int16 x, y; - s.ReadInt16( x ).ReadInt16( y ); - SAL_INFO ("drawinglayer.emf", "EMF+\t\t\t" << i << ". EmfPlusPoint [x,y]: " << x << ", " << y); - pPoints [i*2] = x; - pPoints [i*2 + 1] = y; + s.ReadInt16(x).ReadInt16(y); + SAL_INFO("drawinglayer.emf", "EMF+\t\t\t" << i << ". EmfPlusPoint [x,y]: " << x << ", " << y); + xPoints.push_back(x); + yPoints.push_back(y); } else { // EMFPlusPointF: stored in Single (float) format - s.ReadFloat( pPoints [i*2] ).ReadFloat( pPoints [i*2 + 1] ); - SAL_INFO("drawinglayer.emf", "EMF+\t" << i << ". EMFPlusPointF [x,y]: " << pPoints [i * 2] << ", " << pPoints [i * 2 + 1]); + s.ReadFloat(fx).ReadFloat(fy); + SAL_INFO("drawinglayer.emf", "EMF+\t" << i << ". EMFPlusPointF [x,y]: " << fx << ", " << fy); + xPoints.push_back(fx); + yPoints.push_back(fy); } } @@ -128,7 +132,7 @@ namespace emfplushelper ::basegfx::B2DPoint prev, mapped; bool hasPrev = false; - for (sal_uInt32 i = 0; i < nPoints; i ++) + for (sal_uInt32 i = 0; i < nPoints; i++) { if (p && pPointTypes && (pPointTypes [i] == 0)) { @@ -139,9 +143,9 @@ namespace emfplushelper } if (bMapIt) - mapped = rR.Map (pPoints [i*2], pPoints [i*2 + 1]); + mapped = rR.Map(xPoints[i], yPoints [i]); else - mapped = ::basegfx::B2DPoint (pPoints [i*2], pPoints [i*2 + 1]); + mapped = ::basegfx::B2DPoint(xPoints[i], yPoints[i]); if (pPointTypes) { @@ -167,7 +171,7 @@ namespace emfplushelper } polygon.append (mapped); - SAL_INFO ("drawinglayer.emf", "EMF+\t\tPoint: " << pPoints [i*2] << "," << pPoints [i*2 + 1] << " mapped: " << mapped.getX () << ":" << mapped.getY ()); + SAL_INFO ("drawinglayer.emf", "EMF+\t\tPoint: " << xPoints[i] << "," << yPoints[i] << " mapped: " << mapped.getX () << ":" << mapped.getY ()); if (hasPrev) { @@ -221,6 +225,100 @@ namespace emfplushelper return aPolygon; } + + static void GetCardinalMatrix(float tension, matrix& m) + { + m[0][1] = 2. - tension; + m[0][2] = tension - 2.; + m[1][0] = 2. * tension; + m[1][1] = tension - 3.; + m[1][2] = 3. - 2 * tension; + m[3][1] = 1.; + m[0][3] = m[2][2] = tension; + m[0][0] = m[1][3] = m[2][0] = -tension; + m[2][1] = m[2][3] = m[3][0] = m[3][2] = m[3][3] = 0.; + } + + static float calculateSplineCoefficients(float p0, float p1, float p2, float p3, float alpha, matrix m) + { + float a, b, c, d; + a = m[0][0] * p0 + m[0][1] * p1 + m[0][2] * p2 + m[0][3] * p3; + b = m[1][0] * p0 + m[1][1] * p1 + m[1][2] * p2 + m[1][3] * p3; + c = m[2][0] * p0 + m[2][2] * p2; + d = p1; + return (d + alpha * (c + alpha * (b + alpha * a))); + } + + ::basegfx::B2DPolyPolygon& EMFPPath::GetCardinalSpline(EmfPlusHelperData const& rR, float fTension, + sal_uInt32 aOffset, sal_uInt32 aNumSegments) + { + ::basegfx::B2DPolygon polygon; + matrix mat; + float x, y; + constexpr sal_uInt32 nDetails = 8; + constexpr float alpha[nDetails] + = { 1. / nDetails, 2. / nDetails, 3. / nDetails, 4. / nDetails, + 5. / nDetails, 6. / nDetails, 7. / nDetails, 8. / nDetails }; + if (aNumSegments >= nPoints) + aNumSegments = nPoints - 1; + GetCardinalMatrix(fTension, mat); + // duplicate first point + xPoints.push_front(xPoints.front()); + yPoints.push_front(yPoints.front()); + // duplicate last point + xPoints.push_back(xPoints.back()); + yPoints.push_back(yPoints.back()); + + for (sal_uInt32 i = 3 + aOffset; i < aNumSegments + 3; i++) + { + for (sal_uInt32 s = 0; s < nDetails; s++) + { + x = calculateSplineCoefficients(xPoints[i - 3], xPoints[i - 2], xPoints[i - 1], + xPoints[i], alpha[s], mat); + y = calculateSplineCoefficients(yPoints[i - 3], yPoints[i - 2], yPoints[i - 1], + yPoints[i], alpha[s], mat); + polygon.append(rR.Map(x, y)); + } + } + if (polygon.count()) + aPolygon.append(polygon); + return aPolygon; + } + + ::basegfx::B2DPolyPolygon& EMFPPath::GetClosedCardinalSpline(EmfPlusHelperData const& rR, float fTension) + { + ::basegfx::B2DPolygon polygon; + matrix mat; + float x, y; + constexpr sal_uInt32 nDetails = 8; + constexpr float alpha[nDetails] + = { 1. / nDetails, 2. / nDetails, 3. / nDetails, 4. / nDetails, + 5. / nDetails, 6. / nDetails, 7. / nDetails, 8. / nDetails }; + GetCardinalMatrix(fTension, mat); + // add three first points at the end + xPoints.push_back(xPoints[0]); + yPoints.push_back(yPoints[0]); + xPoints.push_back(xPoints[1]); + yPoints.push_back(yPoints[1]); + xPoints.push_back(xPoints[2]); + yPoints.push_back(yPoints[2]); + + for (sal_uInt32 i = 3; i < nPoints + 3; i++) + { + for (sal_uInt32 s = 0; s < nDetails; s++) + { + x = calculateSplineCoefficients(xPoints[i - 3], xPoints[i - 2], xPoints[i - 1], + xPoints[i], alpha[s], mat); + y = calculateSplineCoefficients(yPoints[i - 3], yPoints[i - 2], yPoints[i - 1], + yPoints[i], alpha[s], mat); + polygon.append(rR.Map(x, y)); + } + } + polygon.setClosed(true); + if (polygon.count()) + aPolygon.append(polygon); + return aPolygon; + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/drawinglayer/source/tools/emfppath.hxx b/drawinglayer/source/tools/emfppath.hxx index 94a3d342f887..e6104fcb1fc7 100644 --- a/drawinglayer/source/tools/emfppath.hxx +++ b/drawinglayer/source/tools/emfppath.hxx @@ -27,7 +27,7 @@ namespace emfplushelper { ::basegfx::B2DPolyPolygon aPolygon; sal_uInt32 nPoints; - std::unique_ptr<float[]> pPoints; + std::deque<float> xPoints, yPoints; std::unique_ptr<sal_uInt8[]> pPointTypes; public: @@ -38,6 +38,9 @@ namespace emfplushelper void Read(SvStream& s, sal_uInt32 pathFlags); ::basegfx::B2DPolyPolygon& GetPolygon(EmfPlusHelperData const & rR, bool bMapIt = true, bool bAddLineToCloseShape = false); + ::basegfx::B2DPolyPolygon& GetCardinalSpline(EmfPlusHelperData const& rR, float fTension, + sal_uInt32 aOffset, sal_uInt32 aNumSegments); + ::basegfx::B2DPolyPolygon& GetClosedCardinalSpline(EmfPlusHelperData const& rR, float fTension); }; } diff --git a/emfio/qa/cppunit/emf/EmfImportTest.cxx b/emfio/qa/cppunit/emf/EmfImportTest.cxx index 930e4f0961dc..1881b53f0a1a 100644 --- a/emfio/qa/cppunit/emf/EmfImportTest.cxx +++ b/emfio/qa/cppunit/emf/EmfImportTest.cxx @@ -64,6 +64,7 @@ class Test : public UnoApiXmlTest void TestDrawPolyLine16WithClip(); void TestFillRegion(); void TestEmfPlusBrushPathGradientWithBlendColors(); + void testEmfPlusRecordTypeDrawCurve(); void TestEmfPlusGetDC(); void TestEmfPlusSave(); void TestEmfPlusDrawPathWithCustomCap(); @@ -119,6 +120,7 @@ public: CPPUNIT_TEST(TestDrawPolyLine16WithClip); CPPUNIT_TEST(TestFillRegion); CPPUNIT_TEST(TestEmfPlusBrushPathGradientWithBlendColors); + CPPUNIT_TEST(testEmfPlusRecordTypeDrawCurve); CPPUNIT_TEST(TestEmfPlusGetDC); CPPUNIT_TEST(TestEmfPlusSave); CPPUNIT_TEST(TestEmfPlusDrawPathWithCustomCap); @@ -1004,6 +1006,99 @@ void Test::TestEmfPlusBrushPathGradientWithBlendColors() assertXPath(pDocument, aXPathPrefix + "svgradialgradient", "spreadmethod", "pad"); } +void Test::testEmfPlusRecordTypeDrawCurve() +{ + // tdf#143877 EMF+ records: DrawCurve, DrawClosedCurve + Primitive2DSequence aSequence + = parseEmf(u"emfio/qa/cppunit/emf/data/TestEmfPlusRecordTypeDrawCurve.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/polypolygonstroke", 26); + assertXPath(pDocument, aXPathPrefix + "mask/polypolygonstroke[1]/line", "color", "#ff0000"); + assertXPath( + pDocument, aXPathPrefix + "mask/polypolygonstroke[1]/polypolygon", "path", + "m15171.856932876 0c2167.40813326801 2167.4834989758 2167.40813326801 4334.9669979516 0 " + "5418.7087474395-2167.40813326801-541.87087474395-2167.40813326801-2709.35437371975 " + "0-5418.7087474395"); + assertXPath(pDocument, aXPathPrefix + "mask/polypolygonstroke[5]/line", "color", "#ff0000"); + assertXPath( + pDocument, aXPathPrefix + "mask/polypolygonstroke[5]/polypolygon", "path", + "m9067.13138473787 655.113420833017 134.193869426752 101.812405648104 139.272492038215 " + "99.2724892764088 141.812836844685 105.622473993772 141.813870345419 120.862553588321 " + "139.272492038217 144.992857252138 134.19386942675 178.012997408972 126.573868508085 " + "219.923426231116 106.674845357667 213.255822775207 76.1979421852029 161.820449175038 " + "45.7189720112692 124.990111480451 15.2400018373355 102.765068075616-15.2400018373355 " + "95.1448021921942-45.7179385105337 102.129959790608-76.1979421852029 " + "123.72002410252-106.676912359138 159.915511896266"); + assertXPath(pDocument, aXPathPrefix + "mask/polypolygonstroke[10]/line", "color", "#ff0000"); + assertXPath( + pDocument, aXPathPrefix + "mask/polypolygonstroke[10]/polypolygon", "path", + "m9067.13138473787 4990.08041878461 134.193869426752 101.812664032273 139.272492038215 " + "99.2722308922403 141.812836844685 105.622796973982 141.813870345419 120.862295204153 " + "139.272492038217 144.992792656096 134.19386942675 178.013255793139 126.573868508085 " + "219.923684615284 106.674845357667 213.255306006871 76.1979421852029 161.820319982953 " + "45.7189720112692 124.990240672536 15.2400018373355 102.765068075615-15.2400018373355 " + "95.14531896053-45.7179385105337 102.129959790608-76.1979421852029 " + "123.720540870856-106.676912359138 159.915511896266-113.239642025967 " + "159.967188729871-101.809123897599 119.010714256079-99.2687790911332 " + "85.355142834027-105.618607606564 59.002541537061-120.857575943166 " + "39.9523935968437-144.987751102401 28.2052157817125-178.007066082802 " + "23.7599745549942-219.914487383636 26.6171866850245"); + assertXPath(pDocument, aXPathPrefix + "mask/polypolygonstroke[15]/line", "color", "#ff0000"); + assertXPath( + pDocument, aXPathPrefix + "mask/polypolygonstroke[15]/polypolygon", "path", + "m9067.13138473787 9325.04741673621 134.193869426752 101.812664032272 139.272492038215 " + "99.2722308922421 141.812836844685 105.623313742317 141.813870345419 120.862811972489 " + "139.272492038217 144.993826192769 134.19386942675 178.013255793139 126.573868508085 " + "219.924201383621 106.674845357667 213.252722165189 76.1979421852029 161.820836751291 " + "45.7189720112692 124.989723904198 15.2400018373355 102.765584843952-15.2400018373355 " + "95.1442854238576-45.7179385105337 102.130993327281-76.1979421852029 " + "123.719507334185-106.676912359138 159.916028664602-113.239642025967 " + "159.967705498208-101.809123897599 119.009680719406-99.2687790911332 " + "85.3556596023645-105.618607606564 59.0025415370601-120.857575943166 " + "39.9523935968446-144.987751102401 28.2052157817125-178.007066082802 " + "23.7599745549942-219.914487383636 26.6177034533594-219.91758788584 " + "15.0276232123888-178.007066082802-11.6417570745762-144.987751102401-31.9621215848092-120." + "858092693532-45.9314032449638-105.618607606566-53.5516691283865-99.2687790911314-54." + "8218856984004-101.808607147232-49.7410194183394-113.238608525233-38.3111373615429"); + assertXPath(pDocument, aXPathPrefix + "mask/polypolygonstroke[20]/line", "color", "#ff0000"); + assertXPath( + pDocument, aXPathPrefix + "mask/polypolygonstroke[20]/polypolygon", "path", + "m10130.9395287237 14843.7694408618 76.1979421852029 161.820836751291 45.7189720112692 " + "124.989723904198 15.2400018373355 102.765584843952-15.2400018373355 " + "95.1453189605309-45.7179385105337 102.129959790607-76.1979421852029 " + "123.720540870856-106.676912359138 159.916028664602-113.239642025967 " + "159.966671961536-101.809123897599 119.010714256079-99.2687790911332 " + "85.3546260656913-105.618607606564 59.0025415370601-120.857575943166 " + "39.953427133516-144.987751102401 28.2052157817125-178.007066082802 " + "23.7599745549942-219.914487383636 26.6177034533612"); + assertXPath(pDocument, aXPathPrefix + "mask/polypolygonstroke[25]/line", "color", "#ff0000"); + assertXPath(pDocument, aXPathPrefix + "mask/polypolygonstroke[25]/polypolygon", "path", + "m10130.9395287237 19178.7364388134 76.1979421852029 161.820836751289 " + "45.7189720112692 124.9897239042 15.2400018373355 " + "102.764551307278-15.2400018373355 95.1453189605309-45.7179385105337 " + "102.129959790607-76.1979421852029 123.720540870858-106.676912359138 " + "159.914995127929-113.239642025967 159.968739034881-101.809123897599 " + "119.009680719406-99.2687790911332 85.3556596023627-105.618607606564 " + "59.0025415370619-120.857575943166 39.9544606701893-144.987751102401 " + "28.2052157817125-178.007066082802 23.7610080916638-219.914487383636 " + "26.6177034533612-233.252847868691 45.0291257302197-210.390778111221 " + "61.2246453820844-184.991464049484 58.0496207253782-157.052321931652 " + "35.5081859067977-126.572835007349-6.40379322035369-93.5540367773156-67." + "6801154360437-57.9948937408126-148.324914886958-19.895922648212-248.340258646444 " + "19.8948891474765-321.473313564504 57.9954104911813-345.283931416434 " + "93.5540367773147-354.809005386542 126.573351757716-350.046468401488 " + "157.05283868202-330.996320461269 184.991980799852-297.658561565891 " + "210.390778111219-250.033191715345 233.250780867224-188.120210909645 " + "219.914487383634-96.7845081224878 178.007066082804 3.22670149030819 " + "144.987751102401 86.4140011546006 120.8586094439 152.773256723693 " + "105.618607606564 202.300334050906 99.2698125918669 235.005568502958 " + "101.809123897599 250.880691786475 113.238608525233 249.927770974791z"); +} + void Test::TestEmfPlusGetDC() { // tdf#147818 EMF+ records: GetDC, DrawPath, FillRects @@ -1152,38 +1247,77 @@ void Test::TestEmfPlusFillClosedCurve() assertXPath(pDocument, aXPathPrefix + "polypolygoncolor", 2); assertXPath(pDocument, aXPathPrefix + "polypolygoncolor[1]", "color", "#808080"); - assertXPath(pDocument, aXPathPrefix + "polypolygoncolor[1]/polypolygon", "path", - "m18202.841744243 13758.4401790456 1269.96570308672 " - "3175.02465670283-2539.93140617345-2116.68310446856h2539.93140617345l-2539." - "93140617345 2116.68310446856z"); + assertXPath( + pDocument, aXPathPrefix + "polypolygoncolor[1]/polypolygon", "path", + "m19296.3351298383 " + "18361.4321751005-414.061734443902-308.241977088233-546.349828515435-482.86833320689-607." + "202351788335-586.056634549728-596.619304262618-617.806881116761-514.600685938261-578." + "119072907972-361.146496815287-466.993209923374-136.25673689368-284.429292162964 " + "145.516903478681-148.167817312798 383.635472807451-105.834155223427 " + "542.381185693288-63.5004931340554 621.754042136206-21.1668310446876 621.758176139148 " + "21.1688981180305 542.381185693288 63.5004931340554 383.639606810386 105.836222296773 " + "145.516903478689 148.167817312798-136.265004899564 284.425158016275-361.146496815287 " + "466.993209923374-514.600685938261 578.119072907972-596.619304262618 " + "617.806881116761-607.202351788335 586.058701623075-546.349828515435 " + "482.868333206887-414.061734443902 308.244044161576-210.338069573736 " + "62.1775661937645-10.5830475257244-283.110499369355 116.413522782947-605.900538654125 " + "211.660950514459-817.568849100979 275.159235668783-918.111296563235 " + "306.912512248899-907.527881040893 306.908378245957-785.818602533949 " + "275.163369671733-552.983461042411 211.660950514452-209.022456566268 211.652682508575 " + "209.022456566268 275.159235668791 552.983461042411 306.908378245957 785.818602533949 " + "306.908378245957 907.527881040893 275.163369671733 918.113363636578 211.660950514452 " + "817.568849100979 116.417656785889 605.902605727468-10.5830475257171 283.106365222669z"); + assertXPath(pDocument, aXPathPrefix + "polypolygoncolor[2]", "color", "#808080"); + assertXPath( + pDocument, aXPathPrefix + "polypolygoncolor[2]/polypolygon", "path", + "m24376.1979421852 " + "18361.4321751005-414.061734443902-308.241977088233-546.349828515435-482.86833320689-607." + "202351788335-586.056634549728-596.619304262618-617.806881116761-514.600685938261-578." + "119072907972-361.146496815287-466.993209923374-136.25673689368-284.429292162964 " + "145.516903478681-148.167817312798 383.635472807451-105.834155223427 " + "542.381185693288-63.5004931340554 621.754042136206-21.1668310446876 621.754042136206 " + "21.1688981180305 542.381185693288 63.5004931340554 383.635472807451 105.836222296773 " + "145.516903478681 148.167817312798-136.25673689368 284.425158016275-361.146496815287 " + "466.993209923374-514.600685938261 578.119072907972-596.619304262618 " + "617.806881116761-607.202351788335 586.058701623075-546.349828515435 " + "482.868333206887-414.061734443902 308.244044161576-210.338069573736 " + "62.1775661937645-10.5830475257244-283.110499369355 116.413522782947-605.900538654125 " + "211.660950514459-817.568849100979 275.159235668783-918.111296563235 " + "306.908378245964-907.527881040893 306.908378245957-785.818602533949 " + "275.159235668791-552.983461042411 211.660950514452-209.022456566268 211.660950514452 " + "209.022456566268 275.159235668791 552.983461042411 306.908378245957 785.818602533949 " + "306.908378245964 907.527881040893 275.159235668783 918.113363636578 211.660950514459 " + "817.568849100979 116.413522782947 605.902605727468-10.5830475257244 283.106365222669z"); assertXPath(pDocument, aXPathPrefix + "polypolygonstroke", 2); - assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[1]/line", "color", "#000000"); - assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[1]/line", "width", "10"); + assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[1]/line", "color", "#00ff00"); + assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[1]/line", "width", "33"); assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[1]/line", "linejoin", "Miter"); assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[1]/line", "miterangle", "3"); assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[1]/line", "linecap", "BUTT"); - assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[1]/polypolygon", "path", - "m18202.841744243 13758.4401790456 1269.96570308672 " - "3175.02465670283-2539.93140617345-2116.68310446856h2539.93140617345l-2539." - "93140617345 2116.68310446856z"); - - assertXPath(pDocument, aXPathPrefix + "polypolygoncolor[2]", "color", "#808080"); - //TODO Check path with implemented Winding - assertXPath(pDocument, aXPathPrefix + "polypolygoncolor[2]/polypolygon", "path", - "m22012.7388535032 13758.4401790456 1269.96570308672 " - "3175.02465670283-2539.93140617344-2116.68310446856h2539.93140617344l-2539." - "93140617344 2116.68310446856z"); - assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[2]/line", "color", "#000000"); - assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[2]/line", "width", "10"); - assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[2]/line", "linejoin", "Miter"); - assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[2]/line", "miterangle", "3"); - assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[2]/line", "linecap", "BUTT"); - assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[2]/polypolygon", "path", - "m22012.7388535032 13758.4401790456 1269.96570308672 " - "3175.02465670283-2539.93140617344-2116.68310446856h2539.93140617344l-2539." - "93140617344 2116.68310446856z"); + assertXPath( + pDocument, aXPathPrefix + "polypolygonstroke[1]/polypolygon", "path", + "m19296.3351298383 " + "18361.4321751005-414.061734443902-308.241977088233-546.349828515435-482.86833320689-607." + "202351788335-586.056634549728-596.619304262618-617.806881116761-514.600685938261-578." + "119072907972-361.146496815287-466.993209923374-136.25673689368-284.429292162964 " + "145.516903478681-148.167817312798 383.635472807451-105.834155223427 " + "542.381185693288-63.5004931340554 621.754042136206-21.1668310446876 621.758176139148 " + "21.1688981180305 542.381185693288 63.5004931340554 383.639606810386 105.836222296773 " + "145.516903478689 148.167817312798-136.265004899564 284.425158016275-361.146496815287 " + "466.993209923374-514.600685938261 578.119072907972-596.619304262618 " + "617.806881116761-607.202351788335 586.058701623075-546.349828515435 " + "482.868333206887-414.061734443902 308.244044161576-210.338069573736 " + "62.1775661937645-10.5830475257244-283.110499369355 116.413522782947-605.900538654125 " + "211.660950514459-817.568849100979 275.159235668783-918.111296563235 " + "306.912512248899-907.527881040893 306.908378245957-785.818602533949 " + "275.163369671733-552.983461042411 211.660950514452-209.022456566268 211.652682508575 " + "209.022456566268 275.159235668791 552.983461042411 306.908378245957 785.818602533949 " + "306.908378245957 907.527881040893 275.163369671733 918.113363636578 211.660950514452 " + "817.568849100979 116.417656785889 605.902605727468-10.5830475257171 283.106365222669z"); + assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[2]/line", "color", "#aaaa00"); + assertXPath(pDocument, aXPathPrefix + "polypolygonstroke[2]/line", "width", "33"); } void Test::TestExtTextOutOpaqueAndClipTransform() diff --git a/emfio/qa/cppunit/emf/data/TestEmfPlusFillClosedCurve.emf b/emfio/qa/cppunit/emf/data/TestEmfPlusFillClosedCurve.emf index ad9140a770d0..f9f50092b64f 100644 Binary files a/emfio/qa/cppunit/emf/data/TestEmfPlusFillClosedCurve.emf and b/emfio/qa/cppunit/emf/data/TestEmfPlusFillClosedCurve.emf differ diff --git a/emfio/qa/cppunit/emf/data/TestEmfPlusRecordTypeDrawCurve.emf b/emfio/qa/cppunit/emf/data/TestEmfPlusRecordTypeDrawCurve.emf new file mode 100644 index 000000000000..299663ef4416 Binary files /dev/null and b/emfio/qa/cppunit/emf/data/TestEmfPlusRecordTypeDrawCurve.emf differ