emfio/qa/cppunit/emf/EmfImportTest.cxx | 24 +++++++ emfio/qa/cppunit/emf/data/TestEmfPolydraw.emf |binary emfio/source/reader/emfreader.cxx | 88 +++++++++++++++++++++++++- emfio/source/reader/mtftools.cxx | 6 + 4 files changed, 115 insertions(+), 3 deletions(-)
New commits: commit ba0bf0ab2c24d309e8a938cec26daa41eba9c8cf Author: Bartosz Kosiorek <gan...@poczta.onet.pl> AuthorDate: Mon Mar 21 20:20:02 2022 +0100 Commit: Bartosz Kosiorek <gan...@poczta.onet.pl> CommitDate: Wed May 10 16:45:47 2023 +0200 tdf#142249 EMF Implement EMR_POLYDRAW record The EMR_POLYDRAW record specifies a set of line segments and Bezier curves. Change-Id: I93d846d2fbb7a60b0565668a17ee092da30ef21c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151424 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 5f8ad7e18044..ba0a8050f24e 100644 --- a/emfio/qa/cppunit/emf/EmfImportTest.cxx +++ b/emfio/qa/cppunit/emf/EmfImportTest.cxx @@ -891,6 +891,30 @@ CPPUNIT_TEST_FIXTURE(Test, testPolylinetoCloseStroke) assertXPath(pDocument, aXPathPrefix + "polygonhairline[2]", "color", "#000000"); } +CPPUNIT_TEST_FIXTURE(Test, testEmfPolydraw) +{ + // tdf#142249 EMF import with records: POLYDRAW, CREATEPEN. + Primitive2DSequence aSequence = parseEmf(u"/emfio/qa/cppunit/emf/data/TestEmfPolydraw.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 + "polygonhairline", 2); + assertXPath(pDocument, aXPathPrefix + "polygonhairline[1]", "color", "#000000"); + assertXPathContent(pDocument, aXPathPrefix + "polygonhairline[1]/polygon", + "2000,200 3000,200 3000,1000"); + assertXPath(pDocument, aXPathPrefix + "polygonhairline[2]", "color", "#000000"); + assertXPathContent(pDocument, aXPathPrefix + "polygonhairline[2]/polygon", + "3000,2000 3000,2000 4000,2000 3000,3000"); + + assertXPath(pDocument, aXPathPrefix + "polygonstroke", 1); + assertXPathContent(pDocument, aXPathPrefix + "polygonstroke[1]/polygon", + "50,50 50,50 1000,1000 1000,1000 2000,2500 2000,1000"); + assertXPath(pDocument, aXPathPrefix + "polygonstroke[1]/line", "color", "#ff0000"); + assertXPath(pDocument, aXPathPrefix + "polygonstroke[1]/stroke", "dotDashArray", "30 10 "); +} + CPPUNIT_TEST_FIXTURE(Test, testEmfPlusBrushPathGradientWithBlendColors) { // tdf#131506 EMF+ records: FillRects, Brush with PathGradient and BlendColor, FillRects diff --git a/emfio/qa/cppunit/emf/data/TestEmfPolydraw.emf b/emfio/qa/cppunit/emf/data/TestEmfPolydraw.emf new file mode 100644 index 000000000000..962b163bf363 Binary files /dev/null and b/emfio/qa/cppunit/emf/data/TestEmfPolydraw.emf differ diff --git a/emfio/source/reader/emfreader.cxx b/emfio/source/reader/emfreader.cxx index af676e7de669..ee848097b84f 100644 --- a/emfio/source/reader/emfreader.cxx +++ b/emfio/source/reader/emfreader.cxx @@ -175,6 +175,16 @@ constexpr sal_Int32 ARCDIRECTION_CLOCKWISE = 0x00000002; namespace { +/* [MS-EMF] - v20210625 - page 41 */ +/* 2.1.26 Point Enumeration */ +enum EMFPointTypes +{ + PT_CLOSEFIGURE = 0x01, + PT_LINETO = 0x02, + PT_BEZIERTO = 0x04, + PT_MOVETO = 0x06 +}; + const char * record_type_name(sal_uInt32 nRecType) { @@ -932,6 +942,83 @@ namespace emfio DrawPolyLine(ReadPolygonWithSkip<sal_Int32>(true, nNextPos), true, mbRecordPath); break; + case EMR_POLYDRAW: + { + sal_uInt32 nPointsCount, nBezierCount = 0; + std::vector<Point> aPoints; + sal_Int32 nX, nY; + bool wrongFile = false; + unsigned char nPointType; + std::vector<unsigned char> aPointTypes; + mpInputStream->ReadInt32(nX32) + .ReadInt32(nY32) + .ReadInt32(nx32) + .ReadInt32(ny32) + .ReadUInt32(nPointsCount); + + aPoints.reserve(nPointsCount); + for (sal_uInt32 i = 0; i < nPointsCount && mpInputStream->good(); i++) + { + *mpInputStream >> nX >> nY; + aPoints.push_back(Point(nX, nY)); + } + aPointTypes.reserve(nPointsCount); + for (sal_uInt32 i = 0; i < nPointsCount && mpInputStream->good(); i++) + { + mpInputStream->ReadUChar(nPointType); + aPointTypes.push_back(nPointType); + SAL_INFO_IF(aPointTypes[i] == PT_MOVETO, "emfio", + "\t\t" << i << "/" << nPointsCount - 1 << " PT_MOVETO, " + << aPoints[i].getX() << ", " << aPoints[i].getY()); + SAL_INFO_IF((aPointTypes[i] != PT_MOVETO) && (aPointTypes[i] & PT_LINETO), "emfio", + "\t\t" << i << "/" << nPointsCount - 1 << " PT_LINETO, " + << aPoints[i].getX() << ", " << aPoints[i].getY()); + SAL_INFO_IF((aPointTypes[i] != PT_MOVETO) && (aPointTypes[i] & PT_CLOSEFIGURE), "emfio", + "\t\t" << i << "/" << nPointsCount - 1 << " PT_CLOSEFIGURE, " + << aPoints[i].getX() << ", " << aPoints[i].getY()); + SAL_INFO_IF((aPointTypes[i] != PT_MOVETO) && (aPointTypes[i] & PT_BEZIERTO), "emfio", + "\t\t" << i << "/" << nPointsCount - 1 << " PT_BEZIERTO, " + << aPoints[i].getX() << ", " << aPoints[i].getY()); + + if ((aPointTypes[i] != PT_MOVETO) && (nPointType & PT_BEZIERTO)) + nBezierCount++; + else if (nBezierCount % 3 == 0) + nBezierCount = 0; + else + { + SAL_WARN( + "emfio", + "EMF file error: Number of Bezier points is not set of three."); + wrongFile = true; + } + } + if (wrongFile) break; + for (sal_uInt32 i = 0; i < nPointsCount; i++) + { + if (aPointTypes[i] == PT_MOVETO) + MoveTo(aPoints[i], true); + else if (aPointTypes[i] & PT_LINETO) + { + LineTo(aPoints[i], true); + if (aPointTypes[i] & PT_CLOSEFIGURE) + ClosePath(); + } + else if (aPointTypes[i] & PT_BEZIERTO) + { + tools::Polygon aPolygon(4); + aPolygon[0] = maActPos; + aPolygon[1] = aPoints[i++]; + aPolygon[2] = aPoints[i++]; + aPolygon[3] = aPoints[i]; + DrawPolyBezier(std::move(aPolygon), true, true); + if (aPointTypes[i] & PT_CLOSEFIGURE) + ClosePath(); + } + } + StrokeAndFillPath(true, false); + } + break; + case EMR_POLYLINE : DrawPolyLine(ReadPolygonWithSkip<sal_Int32>(false, nNextPos), false, mbRecordPath); break; @@ -2047,7 +2134,6 @@ namespace emfio case EMR_INVERTRGN : case EMR_FLATTENPATH : case EMR_WIDENPATH : - case EMR_POLYDRAW : case EMR_SETPALETTEENTRIES : case EMR_RESIZEPALETTE : case EMR_EXTFLOODFILL : diff --git a/emfio/source/reader/mtftools.cxx b/emfio/source/reader/mtftools.cxx index 5b82c54daa21..8c85d0e126a3 100644 --- a/emfio/source/reader/mtftools.cxx +++ b/emfio/source/reader/mtftools.cxx @@ -1618,10 +1618,12 @@ namespace emfio { sal_uInt16 nPoints = rPolygon.GetSize(); if ( ( nPoints < 4 ) || ( ( ( nPoints - 4 ) % 3 ) != 0 ) ) + { + SAL_WARN("emfio", + "EMF file error: Number of Bezier points is not set of three"); return; - + } UpdateClipRegion(); - ImplMap( rPolygon ); if ( bTo ) {