From b240f6198fae7221b7cd3e4678403ad99827b53d Mon Sep 17 00:00:00 2001 From: Xisco Fauli Date: Thu, 14 Mar 2024 23:53:49 +0100 Subject: tdf#48062: Add support for xor, in and out operators in feComposite atop and arithmetic are still missing Change-Id: I9b5bfeaa87b48071708ca4cb082916ea5f260adb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164852 Tested-by: Jenkins Reviewed-by: Xisco Fauli --- svgio/source/svgreader/svgfecompositenode.cxx | 69 +++++++++++++++++++++++++-- svgio/source/svgreader/svgtoken.cxx | 1 + 2 files changed, 66 insertions(+), 4 deletions(-) (limited to 'svgio/source') diff --git a/svgio/source/svgreader/svgfecompositenode.cxx b/svgio/source/svgreader/svgfecompositenode.cxx index b3418fca8709..95ec021969d8 100644 --- a/svgio/source/svgreader/svgfecompositenode.cxx +++ b/svgio/source/svgreader/svgfecompositenode.cxx @@ -18,11 +18,16 @@ #include #include +#include +#include +#include +#include namespace svgio::svgreader { SvgFeCompositeNode::SvgFeCompositeNode(SvgDocument& rDocument, SvgNode* pParent) : SvgFilterNode(SVGToken::FeComposite, rDocument, pParent) + , maOperator(Operator::Over) { } @@ -53,6 +58,29 @@ void SvgFeCompositeNode::parseAttribute(SVGToken aSVGToken, const OUString& aCon maResult = aContent.trim(); break; } + case SVGToken::Operator: + { + if (!aContent.isEmpty()) + { + if (o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent), u"over")) + { + maOperator = Operator::Over; + } + else if (o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent), u"in")) + { + maOperator = Operator::In; + } + else if (o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent), u"out")) + { + maOperator = Operator::Out; + } + else if (o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent), u"xor")) + { + maOperator = Operator::Xor; + } + } + break; + } default: { break; @@ -63,18 +91,51 @@ void SvgFeCompositeNode::parseAttribute(SVGToken aSVGToken, const OUString& aCon void SvgFeCompositeNode::apply(drawinglayer::primitive2d::Primitive2DContainer& rTarget, const SvgFilterNode* pParent) const { - if (const drawinglayer::primitive2d::Primitive2DContainer* rSource2 + basegfx::B2DPolyPolygon aPolyPolygon, aPolyPolygon2; + + // Process maIn2 first + if (const drawinglayer::primitive2d::Primitive2DContainer* pSource2 = pParent->findGraphicSource(maIn2)) { - rTarget = *rSource2; + rTarget.append(*pSource2); + const basegfx::B2DRange aRange2( + pSource2->getB2DRange(drawinglayer::geometry::ViewInformation2D())); + + aPolyPolygon2 = basegfx::B2DPolyPolygon(basegfx::utils::createPolygonFromRect(aRange2)); } - if (const drawinglayer::primitive2d::Primitive2DContainer* rSource + if (const drawinglayer::primitive2d::Primitive2DContainer* pSource = pParent->findGraphicSource(maIn)) { - rTarget.append(*rSource); + rTarget.append(*pSource); + const basegfx::B2DRange aRange( + pSource->getB2DRange(drawinglayer::geometry::ViewInformation2D())); + + aPolyPolygon = basegfx::B2DPolyPolygon(basegfx::utils::createPolygonFromRect(aRange)); + } + + basegfx::B2DPolyPolygon aResult; + if (maOperator == Operator::Over) + { + aResult = basegfx::utils::solvePolygonOperationOr(aPolyPolygon, aPolyPolygon2); + } + else if (maOperator == Operator::Out) + { + aResult = basegfx::utils::solvePolygonOperationDiff(aPolyPolygon, aPolyPolygon2); + } + else if (maOperator == Operator::In) + { + aResult = basegfx::utils::solvePolygonOperationAnd(aPolyPolygon, aPolyPolygon2); + } + else if (maOperator == Operator::Xor) + { + aResult = basegfx::utils::solvePolygonOperationXor(aPolyPolygon, aPolyPolygon2); } + rTarget = drawinglayer::primitive2d::Primitive2DContainer{ + new drawinglayer::primitive2d::MaskPrimitive2D(std::move(aResult), std::move(rTarget)) + }; + pParent->addGraphicSourceToMapper(maResult, rTarget); } diff --git a/svgio/source/svgreader/svgtoken.cxx b/svgio/source/svgreader/svgtoken.cxx index 04b3f9fa3ec6..b6e22b63c547 100644 --- a/svgio/source/svgreader/svgtoken.cxx +++ b/svgio/source/svgreader/svgtoken.cxx @@ -93,6 +93,7 @@ constexpr auto aSVGTokenMap = frozen::make_unordered_map