tdf#48062: Add support for atop operator in feComposite

Change-Id: Ifb83b4361d37566d189a7c5b11835f2a5e0eecc2
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164862
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
diff --git a/svgio/inc/svgfecompositenode.hxx b/svgio/inc/svgfecompositenode.hxx
index 2fa321c..fcbc24e 100644
--- a/svgio/inc/svgfecompositenode.hxx
+++ b/svgio/inc/svgfecompositenode.hxx
@@ -30,6 +30,7 @@ enum class Operator
    In,
    Out,
    Xor,
    Atop,
};

class SvgFeCompositeNode : public SvgFilterNode
diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx
index dc933c9..88bf4bc 100644
--- a/svgio/qa/cppunit/SvgImportTest.cxx
+++ b/svgio/qa/cppunit/SvgImportTest.cxx
@@ -249,6 +249,10 @@ CPPUNIT_TEST_FIXTURE(Test, testFilterFeComposite)
    // out operator
    assertXPath(pDocument, "/primitive2D/transform/mask[4]/polypolygoncolor"_ostr, 3);
    assertXPath(pDocument, "/primitive2D/transform/mask[4]/polypolygon/polygon/point"_ostr, 6);
    // atop operator
    assertXPath(pDocument, "/primitive2D/transform/mask[5]/polypolygoncolor"_ostr, 3);
    assertXPath(pDocument, "/primitive2D/transform/mask[5]/polypolygon/polygon[1]/point"_ostr, 6);
    assertXPath(pDocument, "/primitive2D/transform/mask[5]/polypolygon/polygon[2]/point"_ostr, 4);
}

CPPUNIT_TEST_FIXTURE(Test, testFilterFeGaussianBlur)
diff --git a/svgio/source/svgreader/svgfecompositenode.cxx b/svgio/source/svgreader/svgfecompositenode.cxx
index 95ec021..1e20a0e 100644
--- a/svgio/source/svgreader/svgfecompositenode.cxx
+++ b/svgio/source/svgreader/svgfecompositenode.cxx
@@ -78,6 +78,10 @@ void SvgFeCompositeNode::parseAttribute(SVGToken aSVGToken, const OUString& aCon
                {
                    maOperator = Operator::Xor;
                }
                else if (o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent), u"atop"))
                {
                    maOperator = Operator::Atop;
                }
            }
            break;
        }
@@ -131,6 +135,13 @@ void SvgFeCompositeNode::apply(drawinglayer::primitive2d::Primitive2DContainer& 
    {
        aResult = basegfx::utils::solvePolygonOperationXor(aPolyPolygon, aPolyPolygon2);
    }
    else if (maOperator == Operator::Atop)
    {
        // Atop is the union of In and Out.
        // The parts of in2 graphic that do not overlap with the in graphic stay untouched.
        aResult = basegfx::utils::solvePolygonOperationDiff(aPolyPolygon2, aPolyPolygon);
        aResult.append(basegfx::utils::solvePolygonOperationAnd(aPolyPolygon, aPolyPolygon2));
    }

    rTarget = drawinglayer::primitive2d::Primitive2DContainer{
        new drawinglayer::primitive2d::MaskPrimitive2D(std::move(aResult), std::move(rTarget))