tdf#55058 tdf#141394 EMF FILLRGN record is not displayed correctly

The EMR_FILLRGN record fills the specified region by using the specified brush.

After deep analyse of [EMF] documentation, it seems that
bounds from RegionDataHeader was treated as first rectangle of
region. As a result whole bounds was treated as the Region.

Change-Id: Ie34877b71292c05a1f17381a6de51aaed2386565
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113423
Tested-by: Jenkins
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
diff --git a/emfio/qa/cppunit/emf/EmfImportTest.cxx b/emfio/qa/cppunit/emf/EmfImportTest.cxx
index f587135..4213b37 100644
--- a/emfio/qa/cppunit/emf/EmfImportTest.cxx
+++ b/emfio/qa/cppunit/emf/EmfImportTest.cxx
@@ -51,6 +51,7 @@ class Test : public test::BootstrapFixture, public XmlTestTools, public unotest:
    void TestLinearGradient();
    void TestTextMapMode();
    void TestEnglishMapMode();
    void TestFillRegion();
    void TestCreatePen();
    void TestPdfInEmf();

@@ -69,6 +70,7 @@ public:
    CPPUNIT_TEST(TestLinearGradient);
    CPPUNIT_TEST(TestTextMapMode);
    CPPUNIT_TEST(TestEnglishMapMode);
    CPPUNIT_TEST(TestFillRegion);
    CPPUNIT_TEST(TestCreatePen);
    CPPUNIT_TEST(TestPdfInEmf);
    CPPUNIT_TEST_SUITE_END();
@@ -309,6 +311,28 @@ void Test::TestEnglishMapMode()

}

void Test::TestFillRegion()
{
    // Check import of EMF image with records: CREATEBRUSHINDIRECT, FILLRGN. The SETICMMODE is also used.
    Primitive2DSequence aSequence = parseEmf(u"/emfio/qa/cppunit/emf/data/TestFillRegion.emf");
    CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aSequence.getLength()));
    drawinglayer::Primitive2dXmlDump dumper;
    xmlDocUniquePtr pDocument = dumper.dumpAndParse(comphelper::sequenceToContainer<Primitive2DContainer>(aSequence));
    CPPUNIT_ASSERT (pDocument);

    assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polypolygon", "path", "m0 0h3943v3939h-3943z");

    assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polypolygoncolor", 1);
    assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polypolygoncolor[1]/polypolygon",
                "path", "m1323 0h1323v1322h1323v1322h-1323v1322h-1323v-1322h-1323v-1322h1323z");
    assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polypolygoncolor[1]", "color", "#ff0000");

    assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polygonhairline", 1);
    assertXPathContent(pDocument, "/primitive2D/metafile/transform/mask/polygonhairline[1]/polygon",
                       "1323,0 2646,0 2646,1322 3969,1322 3969,2644 2646,2644 2646,3966 1323,3966 1323,2644 0,2644 0,1322 1323,1322");
    assertXPath(pDocument, "/primitive2D/metafile/transform/mask/polygonhairline[1]", "color", "#000000");
}

void Test::TestCreatePen()
{
    // Check import of EMF image with records: RESTOREDC, SAVEDC, MOVETOEX, LINETO, POLYLINE16, EXTTEXTOUTW with DxBuffer
diff --git a/emfio/qa/cppunit/emf/data/TestFillRegion.emf b/emfio/qa/cppunit/emf/data/TestFillRegion.emf
new file mode 100644
index 0000000..da7d4cd
--- /dev/null
+++ b/emfio/qa/cppunit/emf/data/TestFillRegion.emf
Binary files differ
diff --git a/emfio/source/reader/emfreader.cxx b/emfio/source/reader/emfreader.cxx
index 451c998..12b4fce 100644
--- a/emfio/source/reader/emfreader.cxx
+++ b/emfio/source/reader/emfreader.cxx
@@ -333,38 +333,42 @@ bool ImplReadRegion( tools::PolyPolygon& rPolyPoly, SvStream& rStream, sal_uInt3
    if (nLen == 0)
        return false;

    sal_uInt32 nHdSize, nType, nCount, nRgnSize, i;
    sal_uInt32 nHdSize, nType, nCountRects, nRgnSize, i;
    rStream.ReadUInt32(nHdSize);
    rStream.ReadUInt32(nType);
    rStream.ReadUInt32(nCount);
    rStream.ReadUInt32(nCountRects);
    rStream.ReadUInt32(nRgnSize);

    if (!rStream.good() || nCount == 0 || nType != RDH_RECTANGLES)
    if (!rStream.good() || nCountRects == 0 || nType != RDH_RECTANGLES)
        return false;

    sal_uInt32 nSize;
    if (o3tl::checked_multiply<sal_uInt32>(nCount, 16, nSize))
    if (o3tl::checked_multiply<sal_uInt32>(nCountRects, 16, nSize))
        return false;
    if (o3tl::checked_add<sal_uInt32>(nSize, nHdSize - 16, nSize))
        return false;
    if (nLen < nSize)
        return false;

    sal_Int32 nx1, ny1, nx2, ny2;
    for (i = 0; i < nCount; i++)
    sal_Int32 nLeft, nTop, nRight, nBottom;

    //bounds of the region
    rStream.ReadInt32(nLeft);
    rStream.ReadInt32(nTop);
    rStream.ReadInt32(nRight);
    rStream.ReadInt32(nBottom);
    SAL_INFO("emfio", "\t\tLeft: " << nLeft << ", top: " << nTop << ", right: " << nRight << ", bottom: " << nBottom);

    for (i = 0; i < nCountRects; i++)
    {
        rStream.ReadInt32(nx1);
        rStream.ReadInt32(ny1);
        rStream.ReadInt32(nx2);
        rStream.ReadInt32(ny2);
        rStream.ReadInt32(nLeft);
        rStream.ReadInt32(nTop);
        rStream.ReadInt32(nRight);
        rStream.ReadInt32(nBottom);

        tools::Rectangle aRectangle(Point(nx1, ny1), Point(nx2, ny2));

        tools::Polygon aPolygon(aRectangle);
        tools::PolyPolygon aPolyPolyOr1(aPolygon);
        tools::PolyPolygon aPolyPolyOr2(rPolyPoly);
        rPolyPoly.GetUnion(aPolyPolyOr1, aPolyPolyOr2);
        rPolyPoly = aPolyPolyOr2;
        SAL_INFO("emfio", "\t\tLeft: " << nLeft << ", top: " << nTop << ", right: " << nRight << ", bottom: " << nBottom);
        tools::PolyPolygon aPolyPolyOr1(tools::Polygon(tools::Rectangle(nLeft, nTop, nRight, nBottom)));
        rPolyPoly.GetUnion(aPolyPolyOr1, rPolyPoly);
    }
    return true;
}
@@ -1915,10 +1919,10 @@ namespace emfio

                    case EMR_FILLRGN :
                    {
                        sal_uInt32 nLen;
                        sal_uInt32 nRgnDataSize;
                        tools::PolyPolygon aPolyPoly;
                        mpInputStream->SeekRel( 0x10 );
                        mpInputStream->ReadUInt32( nLen ).ReadUInt32( nIndex );
                        mpInputStream->SeekRel( 0x10 );  // RectL bounds
                        mpInputStream->ReadUInt32( nRgnDataSize ).ReadUInt32( nIndex );

                        if ( ImplReadRegion( aPolyPoly, *mpInputStream, nRecSize ) )
                        {