summaryrefslogtreecommitdiff
path: root/svgio
diff options
context:
space:
mode:
authorXisco Fauli <xiscofauli@libreoffice.org>2024-02-28 13:10:04 +0100
committerXisco Fauli <xiscofauli@libreoffice.org>2024-02-29 17:52:05 +0100
commitc73f3491bedafef884196c761d8f3d89f4dcff75 (patch)
treeb717a9b94efa2180f82ef2c13e4a00b229b5dd34 /svgio
parent1245614991654b9d3ddb15f644a689585fd4c9de (diff)
tdf#159947: Add support for in and result filter attributes
Change-Id: I8bc7e319a64c528893de8454c64545146ad4e9d8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164108 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Diffstat (limited to 'svgio')
-rw-r--r--svgio/inc/svgfilternode.hxx9
-rw-r--r--svgio/inc/svgtoken.hxx1
-rw-r--r--svgio/qa/cppunit/SvgImportTest.cxx47
-rw-r--r--svgio/qa/cppunit/data/inFilterAttribute.svg13
-rw-r--r--svgio/qa/cppunit/data/resultFilterAttribute.svg13
-rw-r--r--svgio/source/svgreader/svgfecolormatrixnode.cxx3
-rw-r--r--svgio/source/svgreader/svgfedropshadownode.cxx3
-rw-r--r--svgio/source/svgreader/svgfefloodnode.cxx3
-rw-r--r--svgio/source/svgreader/svgfegaussianblurnode.cxx3
-rw-r--r--svgio/source/svgreader/svgfeimagenode.cxx3
-rw-r--r--svgio/source/svgreader/svgfeoffsetnode.cxx3
-rw-r--r--svgio/source/svgreader/svgfilternode.cxx52
-rw-r--r--svgio/source/svgreader/svgtoken.cxx1
13 files changed, 154 insertions, 0 deletions
diff --git a/svgio/inc/svgfilternode.hxx b/svgio/inc/svgfilternode.hxx
index 0c87ba54b47b..c3aa068bd3eb 100644
--- a/svgio/inc/svgfilternode.hxx
+++ b/svgio/inc/svgfilternode.hxx
@@ -27,11 +27,20 @@ namespace svgio::svgreader
{
class SvgFilterNode : public SvgNode
{
+private:
+ OUString maIn;
+ OUString maResult;
+
public:
SvgFilterNode(SVGToken aType, SvgDocument& rDocument, SvgNode* pParent);
virtual ~SvgFilterNode() override;
+ virtual void parseAttribute(SVGToken aSVGToken, const OUString& aContent) override;
+
virtual void apply(drawinglayer::primitive2d::Primitive2DContainer& rTarget) const;
+
+ const OUString& getIn() const { return maIn; }
+ const OUString& getResult() const { return maResult; }
};
} // end of namespace svgio::svgreader
diff --git a/svgio/inc/svgtoken.hxx b/svgio/inc/svgtoken.hxx
index 3927a27d1db5..8ad390f0b4a5 100644
--- a/svgio/inc/svgtoken.hxx
+++ b/svgio/inc/svgtoken.hxx
@@ -42,6 +42,7 @@ namespace svgio::svgreader
Version,
Id,
In,
+ Result,
Rx,
Ry,
Points,
diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx
index 9eb8b37d70ca..99541f0b63b7 100644
--- a/svgio/qa/cppunit/SvgImportTest.cxx
+++ b/svgio/qa/cppunit/SvgImportTest.cxx
@@ -212,6 +212,53 @@ CPPUNIT_TEST_FIXTURE(Test, testFilterFeGaussianBlur)
assertXPath(pDocument, "/primitive2D/transform/softedge"_ostr, "radius"_ostr, "5");
}
+CPPUNIT_TEST_FIXTURE(Test, testInFilterAttribute)
+{
+ Primitive2DSequence aSequence = parseSvg(u"/svgio/qa/cppunit/data/inFilterAttribute.svg");
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aSequence.getLength()));
+
+ drawinglayer::Primitive2dXmlDump dumper;
+ xmlDocUniquePtr pDocument = dumper.dumpAndParse(aSequence);
+
+ CPPUNIT_ASSERT (pDocument);
+
+ // Without the fix in place, the feGaussianBlur and feColorMatrix filter would have been applied
+ assertXPath(pDocument, "/primitive2D/transform/transform"_ostr, "xy11"_ostr, "1");
+ assertXPath(pDocument, "/primitive2D/transform/transform"_ostr, "xy12"_ostr, "0");
+ assertXPath(pDocument, "/primitive2D/transform/transform"_ostr, "xy13"_ostr, "40");
+ assertXPath(pDocument, "/primitive2D/transform/transform"_ostr, "xy21"_ostr, "0");
+ assertXPath(pDocument, "/primitive2D/transform/transform"_ostr, "xy22"_ostr, "1");
+ assertXPath(pDocument, "/primitive2D/transform/transform"_ostr, "xy23"_ostr, "40");
+ assertXPath(pDocument, "/primitive2D/transform/transform"_ostr, "xy31"_ostr, "0");
+ assertXPath(pDocument, "/primitive2D/transform/transform"_ostr, "xy32"_ostr, "0");
+ assertXPath(pDocument, "/primitive2D/transform/transform"_ostr, "xy33"_ostr, "1");
+ assertXPath(pDocument, "/primitive2D/transform/transform/polypolygoncolor"_ostr, "color"_ostr, "#ffffff");
+}
+
+CPPUNIT_TEST_FIXTURE(Test, testResultFilterAttribute)
+{
+ Primitive2DSequence aSequence = parseSvg(u"/svgio/qa/cppunit/data/resultFilterAttribute.svg");
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aSequence.getLength()));
+
+ drawinglayer::Primitive2dXmlDump dumper;
+ xmlDocUniquePtr pDocument = dumper.dumpAndParse(aSequence);
+
+ CPPUNIT_ASSERT (pDocument);
+
+ // Without the fix in place, the feColorMatrix filter would have been applied
+ assertXPath(pDocument, "/primitive2D/transform/transform"_ostr, "xy11"_ostr, "1");
+ assertXPath(pDocument, "/primitive2D/transform/transform"_ostr, "xy12"_ostr, "0");
+ assertXPath(pDocument, "/primitive2D/transform/transform"_ostr, "xy13"_ostr, "40");
+ assertXPath(pDocument, "/primitive2D/transform/transform"_ostr, "xy21"_ostr, "0");
+ assertXPath(pDocument, "/primitive2D/transform/transform"_ostr, "xy22"_ostr, "1");
+ assertXPath(pDocument, "/primitive2D/transform/transform"_ostr, "xy23"_ostr, "40");
+ assertXPath(pDocument, "/primitive2D/transform/transform"_ostr, "xy31"_ostr, "0");
+ assertXPath(pDocument, "/primitive2D/transform/transform"_ostr, "xy32"_ostr, "0");
+ assertXPath(pDocument, "/primitive2D/transform/transform"_ostr, "xy33"_ostr, "1");
+ assertXPath(pDocument, "/primitive2D/transform/transform/softedge"_ostr, "radius"_ostr, "2");
+ assertXPath(pDocument, "/primitive2D/transform/transform/softedge/polypolygoncolor"_ostr, "color"_ostr, "#ffffff");
+}
+
CPPUNIT_TEST_FIXTURE(Test, testFilterFeOffset)
{
Primitive2DSequence aSequenceTdf132246 = parseSvg(u"/svgio/qa/cppunit/data/filterFeOffset.svg");
diff --git a/svgio/qa/cppunit/data/inFilterAttribute.svg b/svgio/qa/cppunit/data/inFilterAttribute.svg
new file mode 100644
index 000000000000..f6e17e46e4cc
--- /dev/null
+++ b/svgio/qa/cppunit/data/inFilterAttribute.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 500 500">
+ <defs>
+ <filter height="100" id="f1" width="100">
+ <feGaussianBlur stdDeviation="2.0"/>
+ <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0"/>
+ <feOffset dx="40" dy="40" in="SourceGraphic"/>
+ </filter>
+ </defs>
+ <g>
+ <rect fill="#FFFFFF" filter="url(#f1)" height="70" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="10" y="10"/>
+ </g>
+</svg>
diff --git a/svgio/qa/cppunit/data/resultFilterAttribute.svg b/svgio/qa/cppunit/data/resultFilterAttribute.svg
new file mode 100644
index 000000000000..8d46731095e1
--- /dev/null
+++ b/svgio/qa/cppunit/data/resultFilterAttribute.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 500 500">
+ <defs>
+ <filter height="100" id="f1" width="100">
+ <feGaussianBlur stdDeviation="2.0" result="output"/>
+ <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0"/>
+ <feOffset dx="40" dy="40" in="output"/>
+ </filter>
+ </defs>
+ <g>
+ <rect fill="#FFFFFF" filter="url(#f1)" height="70" style="stroke: #A80036; stroke-width: 1.0;" width="10" x="10" y="10"/>
+ </g>
+</svg>
diff --git a/svgio/source/svgreader/svgfecolormatrixnode.cxx b/svgio/source/svgreader/svgfecolormatrixnode.cxx
index 3a7943ac4e4e..da42fa72f899 100644
--- a/svgio/source/svgreader/svgfecolormatrixnode.cxx
+++ b/svgio/source/svgreader/svgfecolormatrixnode.cxx
@@ -33,6 +33,9 @@ SvgFeColorMatrixNode::~SvgFeColorMatrixNode() {}
void SvgFeColorMatrixNode::parseAttribute(SVGToken aSVGToken, const OUString& aContent)
{
+ // call parent
+ SvgFilterNode::parseAttribute(aSVGToken, aContent);
+
// parse own
switch (aSVGToken)
{
diff --git a/svgio/source/svgreader/svgfedropshadownode.cxx b/svgio/source/svgreader/svgfedropshadownode.cxx
index 2abe6c71c560..d5c67e162af1 100644
--- a/svgio/source/svgreader/svgfedropshadownode.cxx
+++ b/svgio/source/svgreader/svgfedropshadownode.cxx
@@ -40,6 +40,9 @@ SvgFeDropShadowNode::~SvgFeDropShadowNode() {}
void SvgFeDropShadowNode::parseAttribute(SVGToken aSVGToken, const OUString& aContent)
{
+ // call parent
+ SvgFilterNode::parseAttribute(aSVGToken, aContent);
+
// parse own
switch (aSVGToken)
{
diff --git a/svgio/source/svgreader/svgfefloodnode.cxx b/svgio/source/svgreader/svgfefloodnode.cxx
index 775bdb3b1cb9..4c4efe9bf4c9 100644
--- a/svgio/source/svgreader/svgfefloodnode.cxx
+++ b/svgio/source/svgreader/svgfefloodnode.cxx
@@ -41,6 +41,9 @@ SvgFeFloodNode::~SvgFeFloodNode() {}
void SvgFeFloodNode::parseAttribute(SVGToken aSVGToken, const OUString& aContent)
{
+ // call parent
+ SvgFilterNode::parseAttribute(aSVGToken, aContent);
+
// parse own
switch (aSVGToken)
{
diff --git a/svgio/source/svgreader/svgfegaussianblurnode.cxx b/svgio/source/svgreader/svgfegaussianblurnode.cxx
index 53b1513d255c..8c6d26681a2a 100644
--- a/svgio/source/svgreader/svgfegaussianblurnode.cxx
+++ b/svgio/source/svgreader/svgfegaussianblurnode.cxx
@@ -33,6 +33,9 @@ SvgFeGaussianBlurNode::~SvgFeGaussianBlurNode() {}
void SvgFeGaussianBlurNode::parseAttribute(SVGToken aSVGToken, const OUString& aContent)
{
+ // call parent
+ SvgFilterNode::parseAttribute(aSVGToken, aContent);
+
// parse own
switch (aSVGToken)
{
diff --git a/svgio/source/svgreader/svgfeimagenode.cxx b/svgio/source/svgreader/svgfeimagenode.cxx
index 7174bcaf4a27..777f1fd48f22 100644
--- a/svgio/source/svgreader/svgfeimagenode.cxx
+++ b/svgio/source/svgreader/svgfeimagenode.cxx
@@ -38,6 +38,9 @@ SvgFeImageNode::~SvgFeImageNode() {}
void SvgFeImageNode::parseAttribute(SVGToken aSVGToken, const OUString& aContent)
{
+ // call parent
+ SvgFilterNode::parseAttribute(aSVGToken, aContent);
+
// parse own
switch (aSVGToken)
{
diff --git a/svgio/source/svgreader/svgfeoffsetnode.cxx b/svgio/source/svgreader/svgfeoffsetnode.cxx
index 324920cde112..fd85b22a3116 100644
--- a/svgio/source/svgreader/svgfeoffsetnode.cxx
+++ b/svgio/source/svgreader/svgfeoffsetnode.cxx
@@ -34,6 +34,9 @@ SvgFeOffsetNode::~SvgFeOffsetNode() {}
void SvgFeOffsetNode::parseAttribute(SVGToken aSVGToken, const OUString& aContent)
{
+ // call parent
+ SvgFilterNode::parseAttribute(aSVGToken, aContent);
+
// parse own
switch (aSVGToken)
{
diff --git a/svgio/source/svgreader/svgfilternode.cxx b/svgio/source/svgreader/svgfilternode.cxx
index 3e21e9c2adac..1d7198b7d466 100644
--- a/svgio/source/svgreader/svgfilternode.cxx
+++ b/svgio/source/svgreader/svgfilternode.cxx
@@ -17,6 +17,7 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
+#include <unordered_map>
#include <svgfilternode.hxx>
#include <svgfecolormatrixnode.hxx>
#include <svgfedropshadownode.hxx>
@@ -25,6 +26,9 @@
#include <svgfegaussianblurnode.hxx>
#include <svgfeoffsetnode.hxx>
+typedef std::unordered_map<OUString, const drawinglayer::primitive2d::Primitive2DContainer*>
+ IdGraphicSourceMapper;
+
namespace svgio::svgreader
{
SvgFilterNode::SvgFilterNode(SVGToken aType, SvgDocument& rDocument, SvgNode* pParent)
@@ -34,6 +38,30 @@ SvgFilterNode::SvgFilterNode(SVGToken aType, SvgDocument& rDocument, SvgNode* pP
SvgFilterNode::~SvgFilterNode() {}
+void SvgFilterNode::parseAttribute(SVGToken aSVGToken, const OUString& aContent)
+{
+ // call parent
+ SvgNode::parseAttribute(aSVGToken, aContent);
+
+ switch (aSVGToken)
+ {
+ case SVGToken::In:
+ {
+ maIn = aContent.trim();
+ break;
+ }
+ case SVGToken::Result:
+ {
+ maResult = aContent.trim();
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
+
void SvgFilterNode::apply(drawinglayer::primitive2d::Primitive2DContainer& rTarget) const
{
if (rTarget.empty())
@@ -42,12 +70,36 @@ void SvgFilterNode::apply(drawinglayer::primitive2d::Primitive2DContainer& rTarg
const auto& rChildren = getChildren();
const sal_uInt32 nCount(rChildren.size());
+ IdGraphicSourceMapper aIdGraphicSourceMapperList;
+ drawinglayer::primitive2d::Primitive2DContainer aNewTarget = rTarget;
+ aIdGraphicSourceMapperList.emplace("SourceGraphic", &aNewTarget);
+ //TODO: Add SourceAlpha, BackgroundImage, BackgroundAlpha, FillPaint, StrokePaint ??
+
// apply children's filters
for (sal_uInt32 a(0); a < nCount; a++)
{
SvgFilterNode* pFilterNode = dynamic_cast<SvgFilterNode*>(rChildren[a].get());
if (pFilterNode)
+ {
+ if (!pFilterNode->getIn().isEmpty())
+ {
+ const IdGraphicSourceMapper::const_iterator aResult(
+ aIdGraphicSourceMapperList.find(pFilterNode->getIn()));
+
+ if (aResult != aIdGraphicSourceMapperList.end())
+ {
+ rTarget = *aResult->second;
+ }
+ }
+
pFilterNode->apply(rTarget);
+
+ if (!pFilterNode->getResult().isEmpty())
+ {
+ aNewTarget = rTarget;
+ aIdGraphicSourceMapperList.emplace(pFilterNode->getResult(), &aNewTarget);
+ }
+ }
}
}
diff --git a/svgio/source/svgreader/svgtoken.cxx b/svgio/source/svgreader/svgtoken.cxx
index fa28c8647cea..14c27a396631 100644
--- a/svgio/source/svgreader/svgtoken.cxx
+++ b/svgio/source/svgreader/svgtoken.cxx
@@ -41,6 +41,7 @@ constexpr auto aSVGTokenMap = frozen::make_unordered_map<std::u16string_view, SV
{ u"version", SVGToken::Version },
{ u"id", SVGToken::Id },
{ u"in", SVGToken::In },
+ { u"result", SVGToken::Result },
{ u"rx", SVGToken::Rx },
{ u"ry", SVGToken::Ry },
{ u"points", SVGToken::Points },