diff options
-rw-r--r-- | drawinglayer/source/tools/primitive2dxmldump.cxx | 13 | ||||
-rw-r--r-- | svgio/Library_svgio.mk | 1 | ||||
-rw-r--r-- | svgio/inc/svgfegaussianblurnode.hxx | 59 | ||||
-rw-r--r-- | svgio/inc/svgfilternode.hxx | 2 | ||||
-rw-r--r-- | svgio/inc/svgtoken.hxx | 3 | ||||
-rw-r--r-- | svgio/qa/cppunit/SvgImportTest.cxx | 21 | ||||
-rw-r--r-- | svgio/qa/cppunit/data/filterFeGaussianBlur.svg | 11 | ||||
-rw-r--r-- | svgio/source/svgreader/svgdocumenthandler.cxx | 11 | ||||
-rw-r--r-- | svgio/source/svgreader/svgfegaussianblurnode.cxx | 86 | ||||
-rw-r--r-- | svgio/source/svgreader/svgfilternode.cxx | 22 | ||||
-rw-r--r-- | svgio/source/svgreader/svgstyleattributes.cxx | 6 | ||||
-rw-r--r-- | svgio/source/svgreader/svgtoken.cxx | 6 |
12 files changed, 235 insertions, 6 deletions
diff --git a/drawinglayer/source/tools/primitive2dxmldump.cxx b/drawinglayer/source/tools/primitive2dxmldump.cxx index 2267a1080c13..7edb5bce5c89 100644 --- a/drawinglayer/source/tools/primitive2dxmldump.cxx +++ b/drawinglayer/source/tools/primitive2dxmldump.cxx @@ -28,6 +28,7 @@ #include <drawinglayer/primitive2d/PolyPolygonStrokePrimitive2D.hxx> #include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx> #include <drawinglayer/primitive2d/hiddengeometryprimitive2d.hxx> +#include <drawinglayer/primitive2d/softedgeprimitive2d.hxx> #include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx> #include <primitive2d/textlineprimitive2d.hxx> #include <drawinglayer/primitive2d/textprimitive2d.hxx> @@ -1134,6 +1135,18 @@ void Primitive2dXmlDump::decomposeAndWrite( rWriter.endElement(); break; } + case PRIMITIVE2D_ID_SOFTEDGEPRIMITIVE2D: + { + // SoftEdgePrimitive2D. + const SoftEdgePrimitive2D& rSoftEdgePrimitive2D + = dynamic_cast<const SoftEdgePrimitive2D&>(*pBasePrimitive); + rWriter.startElement("softedge"); + rWriter.attribute("radius", OUString::number(rSoftEdgePrimitive2D.getRadius())); + + decomposeAndWrite(rSoftEdgePrimitive2D.getChildren(), rWriter); + rWriter.endElement(); + break; + } case PRIMITIVE2D_ID_SCENEPRIMITIVE2D: { diff --git a/svgio/Library_svgio.mk b/svgio/Library_svgio.mk index 8770f733d441..247653732d6f 100644 --- a/svgio/Library_svgio.mk +++ b/svgio/Library_svgio.mk @@ -57,6 +57,7 @@ $(eval $(call gb_Library_add_exception_objects,svgio,\ svgio/source/svgreader/svgellipsenode \ svgio/source/svgreader/svggnode \ svgio/source/svgreader/svganode \ + svgio/source/svgreader/svgfegaussianblurnode \ svgio/source/svgreader/svgfilternode \ svgio/source/svgreader/svggradientnode \ svgio/source/svgreader/svggradientstopnode \ diff --git a/svgio/inc/svgfegaussianblurnode.hxx b/svgio/inc/svgfegaussianblurnode.hxx new file mode 100644 index 000000000000..5dec4463198f --- /dev/null +++ b/svgio/inc/svgfegaussianblurnode.hxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include "svgnode.hxx" +#include "svgstyleattributes.hxx" +#include <basegfx/matrix/b2dhommatrix.hxx> + +namespace svgio::svgreader +{ +/* +FIXME: If no value is provided and this is the first filter primitive, +then this filter primitive will use SourceGraphic as its input. +If no value is provided and this is a subsequent filter primitive, +then this filter primitive will use the result from the previous +filter primitive as its input. +*/ +enum class In +{ + None, + SourceGraphic +}; + +class SvgFeGaussianBlurNode final : public SvgNode +{ +private: + SvgNumber maStdDeviation; + In maIn; + +public: + SvgFeGaussianBlurNode(SvgDocument& rDocument, SvgNode* pParent); + virtual ~SvgFeGaussianBlurNode() override; + + virtual void parseAttribute(const OUString& rTokenName, SVGToken aSVGToken, + const OUString& aContent) override; + + void apply(drawinglayer::primitive2d::Primitive2DContainer& rTarget) const; +}; + +} // end of namespace svgio::svgreader + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svgio/inc/svgfilternode.hxx b/svgio/inc/svgfilternode.hxx index e6c24450b4e2..19ce2cb34b33 100644 --- a/svgio/inc/svgfilternode.hxx +++ b/svgio/inc/svgfilternode.hxx @@ -30,6 +30,8 @@ class SvgFilterNode final : public SvgNode public: SvgFilterNode(SvgDocument& rDocument, SvgNode* pParent); virtual ~SvgFilterNode() override; + + void apply(drawinglayer::primitive2d::Primitive2DContainer& rTarget) const; }; } // end of namespace svgio::svgreader diff --git a/svgio/inc/svgtoken.hxx b/svgio/inc/svgtoken.hxx index 73c083a620e6..262b5f3dda55 100644 --- a/svgio/inc/svgtoken.hxx +++ b/svgio/inc/svgtoken.hxx @@ -41,6 +41,7 @@ namespace svgio::svgreader Xmlns, Version, Id, + In, Rx, Ry, Points, @@ -69,6 +70,7 @@ namespace svgio::svgreader StartOffset, Method, Spacing, + StdDeviation, TextAlign, PathLength, Type, @@ -78,6 +80,7 @@ namespace svgio::svgreader Color, ClipPathNode, ClipPathProperty, + FeGaussianBlur, Filter, Mask, ClipPathUnits, diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx index 6e4ac0255677..967bcc0275cf 100644 --- a/svgio/qa/cppunit/SvgImportTest.cxx +++ b/svgio/qa/cppunit/SvgImportTest.cxx @@ -24,9 +24,6 @@ #include <memory> #include <string_view> -namespace -{ - using namespace css; using namespace css::uno; using namespace css::io; @@ -82,6 +79,8 @@ void Test::checkRectPrimitive(Primitive2DSequence const & rPrimitive) } +namespace +{ bool arePrimitive2DSequencesEqual(const Primitive2DSequence& rA, const Primitive2DSequence& rB) { return std::equal(rA.begin(), rA.end(), rB.begin(), rB.end(), @@ -91,6 +90,7 @@ bool arePrimitive2DSequencesEqual(const Primitive2DSequence& rA, const Primitive return drawinglayer::primitive2d::arePrimitive2DReferencesEqual(a, b); }); } +} // Attributes for an object (like rect as in this case) can be defined // in different ways (directly with xml attributes, or with CSS styles), @@ -135,6 +135,19 @@ CPPUNIT_TEST_FIXTURE(Test, testSymbol) assertXPath(pDocument, "/primitive2D/transform/polypolygoncolor", "color", "#00d000"); } +CPPUNIT_TEST_FIXTURE(Test, testFilterFeGaussianBlur) +{ + Primitive2DSequence aSequenceTdf132246 = parseSvg(u"/svgio/qa/cppunit/data/filterFeGaussianBlur.svg"); + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aSequenceTdf132246.getLength())); + + drawinglayer::Primitive2dXmlDump dumper; + xmlDocUniquePtr pDocument = dumper.dumpAndParse(aSequenceTdf132246); + + CPPUNIT_ASSERT (pDocument); + + assertXPath(pDocument, "/primitive2D/transform/softedge", "radius", "5"); +} + CPPUNIT_TEST_FIXTURE(Test, testTdf87309) { Primitive2DSequence aSequenceTdf87309 = parseSvg(u"/svgio/qa/cppunit/data/tdf87309.svg"); @@ -1055,8 +1068,6 @@ CPPUNIT_TEST_FIXTURE(Test, testTspanFillOpacity) CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(70), nTransparence); } -} - CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svgio/qa/cppunit/data/filterFeGaussianBlur.svg b/svgio/qa/cppunit/data/filterFeGaussianBlur.svg new file mode 100644 index 000000000000..e8fd73068a0b --- /dev/null +++ b/svgio/qa/cppunit/data/filterFeGaussianBlur.svg @@ -0,0 +1,11 @@ +<svg + width="230" + height="120" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <filter id="blurMe"> + <feGaussianBlur in="SourceGraphic" stdDeviation="5"/> + </filter> + <circle cx="170" cy="60" r="50" fill="green" filter="url(#blurMe)" /> +</svg> + diff --git a/svgio/source/svgreader/svgdocumenthandler.cxx b/svgio/source/svgreader/svgdocumenthandler.cxx index ac866b37f0d2..5e61693e64c7 100644 --- a/svgio/source/svgreader/svgdocumenthandler.cxx +++ b/svgio/source/svgreader/svgdocumenthandler.cxx @@ -41,6 +41,7 @@ #include <svgstylenode.hxx> #include <svgimagenode.hxx> #include <svgclippathnode.hxx> +#include <svgfegaussianblurnode.hxx> #include <svgfilternode.hxx> #include <svgmasknode.hxx> #include <svgmarkernode.hxx> @@ -341,6 +342,13 @@ namespace mpTarget->parseAttributes(xAttribs); break; } + case SVGToken::FeGaussianBlur: + { + /// new node for feGaussianBlur + mpTarget = new SvgFeGaussianBlurNode(maDocument, mpTarget); + mpTarget->parseAttributes(xAttribs); + break; + } case SVGToken::Filter: { /// new node for Filter @@ -442,8 +450,9 @@ namespace /// styles (as stylesheets) case SVGToken::Style: - /// structural elements clip-path, filter and mask + /// structural elements clip-path, feGaussianBlur, filter and mask case SVGToken::ClipPathNode: + case SVGToken::FeGaussianBlur: case SVGToken::Filter: case SVGToken::Mask: diff --git a/svgio/source/svgreader/svgfegaussianblurnode.cxx b/svgio/source/svgreader/svgfegaussianblurnode.cxx new file mode 100644 index 000000000000..fff21345c4d8 --- /dev/null +++ b/svgio/source/svgreader/svgfegaussianblurnode.cxx @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <svgfegaussianblurnode.hxx> +#include <drawinglayer/primitive2d/softedgeprimitive2d.hxx> +#include <o3tl/string_view.hxx> + +namespace svgio::svgreader +{ +SvgFeGaussianBlurNode::SvgFeGaussianBlurNode(SvgDocument& rDocument, SvgNode* pParent) + : SvgNode(SVGToken::FeGaussianBlur, rDocument, pParent) + , maStdDeviation(SvgNumber(0.0)) + , maIn(In::None) +{ +} + +SvgFeGaussianBlurNode::~SvgFeGaussianBlurNode() {} + +void SvgFeGaussianBlurNode::parseAttribute(const OUString& /*rTokenName*/, SVGToken aSVGToken, + const OUString& aContent) +{ + // parse own + switch (aSVGToken) + { + case SVGToken::StdDeviation: + { + SvgNumber aNum; + + if (readSingleNumber(aContent, aNum)) + { + if (aNum.isPositive()) + { + maStdDeviation = aNum; + } + } + break; + } + case SVGToken::In: + { + if (!aContent.isEmpty()) + { + if (o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent), u"SourceGraphic")) + { + maIn = In::SourceGraphic; + } + } + break; + } + default: + { + break; + } + } +} + +void SvgFeGaussianBlurNode::apply(drawinglayer::primitive2d::Primitive2DContainer& rTarget) const +{ + if (maIn == In::SourceGraphic) + { + const drawinglayer::primitive2d::Primitive2DReference xRef( + new drawinglayer::primitive2d::SoftEdgePrimitive2D(maStdDeviation.getNumber(), + std::move(rTarget))); + + rTarget = drawinglayer::primitive2d::Primitive2DContainer{ xRef }; + } +} + +} // end of namespace svgio::svgreader + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svgio/source/svgreader/svgfilternode.cxx b/svgio/source/svgreader/svgfilternode.cxx index 374feb06247b..8eb0beb65e6b 100644 --- a/svgio/source/svgreader/svgfilternode.cxx +++ b/svgio/source/svgreader/svgfilternode.cxx @@ -18,6 +18,7 @@ */ #include <svgfilternode.hxx> +#include <svgfegaussianblurnode.hxx> namespace svgio::svgreader { @@ -28,6 +29,27 @@ SvgFilterNode::SvgFilterNode(SvgDocument& rDocument, SvgNode* pParent) SvgFilterNode::~SvgFilterNode() {} +void SvgFilterNode::apply(drawinglayer::primitive2d::Primitive2DContainer& rTarget) const +{ + if (rTarget.empty()) + return; + + const auto& rChildren = getChildren(); + const sal_uInt32 nCount(rChildren.size()); + + // apply children's filters + for (sal_uInt32 a(0); a < nCount; a++) + { + SvgNode* pCandidate = rChildren[a].get(); + if (pCandidate->getType() == SVGToken::FeGaussianBlur) + { + const SvgFeGaussianBlurNode* pFeGaussianBlurNode + = dynamic_cast<const SvgFeGaussianBlurNode*>(pCandidate); + pFeGaussianBlurNode->apply(rTarget); + } + } +} + } // end of namespace svgio::svgreader /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svgio/source/svgreader/svgstyleattributes.cxx b/svgio/source/svgreader/svgstyleattributes.cxx index 5a3c9396ae91..eda757af80d3 100644 --- a/svgio/source/svgreader/svgstyleattributes.cxx +++ b/svgio/source/svgreader/svgstyleattributes.cxx @@ -1208,6 +1208,12 @@ namespace svgio::svgreader if(!aSource.empty()) // test again, applied clipPath may have lead to empty geometry { + const SvgFilterNode* pFilter = accessFilterXLink(); + if(pFilter) + { + pFilter->apply(aSource); + } + const SvgMaskNode* pMask = accessMaskXLink(); if(pMask) { diff --git a/svgio/source/svgreader/svgtoken.cxx b/svgio/source/svgreader/svgtoken.cxx index a472466b3995..48a0c8eb47df 100644 --- a/svgio/source/svgreader/svgtoken.cxx +++ b/svgio/source/svgreader/svgtoken.cxx @@ -34,6 +34,7 @@ namespace svgio::svgreader const char aSVGStrXmlns[] = "xmlns"; const char aSVGStrVersion[] = "version"; const char aSVGStrId[] = "id"; + const char aSVGStrIn[] = "in"; const char aSVGStrRx[] = "rx"; const char aSVGStrRy[] = "ry"; const char aSVGStrPoints[] = "points"; @@ -61,6 +62,7 @@ namespace svgio::svgreader const char aSVGStrStartOffset[] = "startOffset"; const char aSVGStrMethod[] = "method"; const char aSVGStrSpacing[] = "spacing"; + const char aSVGStrStdDeviation[] = "stdDeviation"; const char aSVGStrTextAlign[] = "text-align"; const char aSVGStrPathLength[] = "pathLength"; const char aSVGStrType[] = "type"; @@ -70,6 +72,7 @@ namespace svgio::svgreader const char aSVGStrColor[] = "color"; const char aSVGStrClipPathNode[] = "clipPath"; const char aSVGStrClipPathProperty[] = "clip-path"; + const char aSVGStrFeGaussianBlur[] = "feGaussianBlur"; const char aSVGStrFilter[] = "filter"; const char aSVGStrMask[] = "mask"; const char aSVGStrClipPathUnits[] = "clipPathUnits"; @@ -182,6 +185,7 @@ namespace svgio::svgreader { aSVGStrXmlns, SVGToken::Xmlns }, { aSVGStrVersion, SVGToken::Version }, { aSVGStrId, SVGToken::Id }, + { aSVGStrIn, SVGToken::In }, { aSVGStrRx, SVGToken::Rx }, { aSVGStrRy, SVGToken::Ry }, { aSVGStrPoints, SVGToken::Points }, @@ -209,6 +213,7 @@ namespace svgio::svgreader { aSVGStrStartOffset, SVGToken::StartOffset }, { aSVGStrMethod, SVGToken::Method }, { aSVGStrSpacing, SVGToken::Spacing }, + { aSVGStrStdDeviation, SVGToken::StdDeviation }, { aSVGStrTextAlign, SVGToken::TextAlign }, { aSVGStrPathLength, SVGToken::PathLength }, { aSVGStrType, SVGToken::Type }, @@ -218,6 +223,7 @@ namespace svgio::svgreader { aSVGStrColor, SVGToken::Color }, { aSVGStrClipPathNode, SVGToken::ClipPathNode }, { aSVGStrClipPathProperty, SVGToken::ClipPathProperty }, + { aSVGStrFeGaussianBlur, SVGToken::FeGaussianBlur }, { aSVGStrFilter, SVGToken::Filter }, { aSVGStrMask, SVGToken::Mask }, { aSVGStrClipPathUnits, SVGToken::ClipPathUnits }, |