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 )
         {

Reply via email to