svgio/Library_svgio.mk                        |    3 
 svgio/inc/svgfeoffsetnode.hxx                 |   45 ++++++++++++
 svgio/inc/svgtoken.hxx                        |    3 
 svgio/qa/cppunit/SvgImportTest.cxx            |   21 +++++
 svgio/qa/cppunit/data/filterFeOffset.svg      |   18 +++++
 svgio/source/svgreader/svgdocumenthandler.cxx |   17 +++-
 svgio/source/svgreader/svgfeoffsetnode.cxx    |   92 ++++++++++++++++++++++++++
 svgio/source/svgreader/svgfilternode.cxx      |    9 ++
 svgio/source/svgreader/svgtoken.cxx           |    5 -
 9 files changed, 204 insertions(+), 9 deletions(-)

New commits:
commit bf673a46987f797df00f7ae92a3f515d18740f63
Author:     Xisco Fauli <xiscofa...@libreoffice.org>
AuthorDate: Mon Jun 26 23:24:52 2023 +0200
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Tue Jun 27 22:15:58 2023 +0200

    tdf#156068: Add support for feOffset filter
    
    Change-Id: I1b3dea0ee4f9eb2ee7498962b04baaf5ba68855c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153629
    Tested-by: Jenkins
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>
    (cherry picked from commit 1dce8c1d4b6be58c7c791dca3b17ae7488ea9215)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153662

diff --git a/svgio/Library_svgio.mk b/svgio/Library_svgio.mk
index 76c0e87123bb..3702806a311c 100644
--- a/svgio/Library_svgio.mk
+++ b/svgio/Library_svgio.mk
@@ -60,8 +60,9 @@ $(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/svgfecolormatrixnode \
+    svgio/source/svgreader/svgfegaussianblurnode \
+    svgio/source/svgreader/svgfeoffsetnode \
     svgio/source/svgreader/svgfilternode \
     svgio/source/svgreader/svggradientnode \
     svgio/source/svgreader/svggradientstopnode \
diff --git a/svgio/inc/svgfeoffsetnode.hxx b/svgio/inc/svgfeoffsetnode.hxx
new file mode 100644
index 000000000000..22bf212d7c20
--- /dev/null
+++ b/svgio/inc/svgfeoffsetnode.hxx
@@ -0,0 +1,45 @@
+/* -*- 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"
+
+namespace svgio::svgreader
+{
+class SvgFeOffsetNode final : public SvgNode
+{
+private:
+    SvgNumber maDx;
+    SvgNumber maDy;
+
+public:
+    SvgFeOffsetNode(SvgDocument& rDocument, SvgNode* pParent);
+    virtual ~SvgFeOffsetNode() 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/svgtoken.hxx b/svgio/inc/svgtoken.hxx
index 9c28674b1cfb..fb2e04c278f4 100644
--- a/svgio/inc/svgtoken.hxx
+++ b/svgio/inc/svgtoken.hxx
@@ -80,8 +80,9 @@ namespace svgio::svgreader
             Color,
             ClipPathNode,
             ClipPathProperty,
-            FeGaussianBlur,
             FeColorMatrix,
+            FeGaussianBlur,
+            FeOffset,
             Filter,
             Mask,
             ClipPathUnits,
diff --git a/svgio/qa/cppunit/SvgImportTest.cxx 
b/svgio/qa/cppunit/SvgImportTest.cxx
index 3d855ea8d24a..6ae8fea1850d 100644
--- a/svgio/qa/cppunit/SvgImportTest.cxx
+++ b/svgio/qa/cppunit/SvgImportTest.cxx
@@ -182,6 +182,27 @@ CPPUNIT_TEST_FIXTURE(Test, testFilterFeGaussianBlur)
     assertXPath(pDocument, "/primitive2D/transform/softedge", "radius", "5");
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testFilterFeOffset)
+{
+    Primitive2DSequence aSequenceTdf132246 = 
parseSvg(u"/svgio/qa/cppunit/data/filterFeOffset.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/mask/transform", "xy11", 
"1");
+    assertXPath(pDocument, "/primitive2D/transform/mask/transform", "xy12", 
"0");
+    assertXPath(pDocument, "/primitive2D/transform/mask/transform", "xy13", 
"44");
+    assertXPath(pDocument, "/primitive2D/transform/mask/transform", "xy21", 
"0");
+    assertXPath(pDocument, "/primitive2D/transform/mask/transform", "xy22", 
"1");
+    assertXPath(pDocument, "/primitive2D/transform/mask/transform", "xy23", 
"66");
+    assertXPath(pDocument, "/primitive2D/transform/mask/transform", "xy31", 
"0");
+    assertXPath(pDocument, "/primitive2D/transform/mask/transform", "xy32", 
"0");
+    assertXPath(pDocument, "/primitive2D/transform/mask/transform", "xy33", 
"1");
+}
+
 CPPUNIT_TEST_FIXTURE(Test, testTdf87309)
 {
     Primitive2DSequence aSequenceTdf87309 = 
parseSvg(u"/svgio/qa/cppunit/data/tdf87309.svg");
diff --git a/svgio/qa/cppunit/data/filterFeOffset.svg 
b/svgio/qa/cppunit/data/filterFeOffset.svg
new file mode 100644
index 000000000000..89bb40eef888
--- /dev/null
+++ b/svgio/qa/cppunit/data/filterFeOffset.svg
@@ -0,0 +1,18 @@
+<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg";>
+  <defs>
+    <filter id="offset" width="180" height="180">
+      <feOffset in="SourceGraphic" dx="44" dy="66" />
+    </filter>
+  </defs>
+
+  <rect x="0" y="0" width="100" height="100" stroke="black" fill="green" />
+  <rect
+    x="0"
+    y="0"
+    width="100"
+    height="100"
+    stroke="black"
+    fill="green"
+    filter="url(#offset)" />
+</svg>
+
diff --git a/svgio/source/svgreader/svgdocumenthandler.cxx 
b/svgio/source/svgreader/svgdocumenthandler.cxx
index f5c346c2a7e7..ec316e03517b 100644
--- a/svgio/source/svgreader/svgdocumenthandler.cxx
+++ b/svgio/source/svgreader/svgdocumenthandler.cxx
@@ -43,6 +43,7 @@
 #include <svgclippathnode.hxx>
 #include <svgfegaussianblurnode.hxx>
 #include <svgfecolormatrixnode.hxx>
+#include <svgfeoffsetnode.hxx>
 #include <svgfilternode.hxx>
 #include <svgmasknode.hxx>
 #include <svgmarkernode.hxx>
@@ -332,6 +333,13 @@ namespace
                     mpTarget->parseAttributes(xAttribs);
                     break;
                 }
+                case SVGToken::FeColorMatrix:
+                {
+                    /// new node for feColorMatrix
+                    mpTarget = new SvgFeColorMatrixNode(maDocument, mpTarget);
+                    mpTarget->parseAttributes(xAttribs);
+                    break;
+                }
                 case SVGToken::FeGaussianBlur:
                 {
                     /// new node for feGaussianBlur
@@ -339,10 +347,10 @@ namespace
                     mpTarget->parseAttributes(xAttribs);
                     break;
                 }
-                case SVGToken::FeColorMatrix:
+                case SVGToken::FeOffset:
                 {
-                    /// new node for feColorMatrix
-                    mpTarget = new SvgFeColorMatrixNode(maDocument, mpTarget);
+                    /// new node for feOffset
+                    mpTarget = new SvgFeOffsetNode(maDocument, mpTarget);
                     mpTarget->parseAttributes(xAttribs);
                     break;
                 }
@@ -452,8 +460,9 @@ namespace
                 case SVGToken::Mask:
 
                 /// structural elements for filters
-                case SVGToken::FeGaussianBlur:
                 case SVGToken::FeColorMatrix:
+                case SVGToken::FeGaussianBlur:
+                case SVGToken::FeOffset:
                 case SVGToken::Filter:
 
                 /// structural element marker
diff --git a/svgio/source/svgreader/svgfeoffsetnode.cxx 
b/svgio/source/svgreader/svgfeoffsetnode.cxx
new file mode 100644
index 000000000000..a2129b8f3ee5
--- /dev/null
+++ b/svgio/source/svgreader/svgfeoffsetnode.cxx
@@ -0,0 +1,92 @@
+/* -*- 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 <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <svgfeoffsetnode.hxx>
+#include <o3tl/string_view.hxx>
+
+namespace svgio::svgreader
+{
+SvgFeOffsetNode::SvgFeOffsetNode(SvgDocument& rDocument, SvgNode* pParent)
+    : SvgNode(SVGToken::FeOffset, rDocument, pParent)
+    , maDx(SvgNumber(0.0))
+    , maDy(SvgNumber(0.0))
+{
+}
+
+SvgFeOffsetNode::~SvgFeOffsetNode() {}
+
+void SvgFeOffsetNode::parseAttribute(const OUString& /*rTokenName*/, SVGToken 
aSVGToken,
+                                     const OUString& aContent)
+{
+    // parse own
+    switch (aSVGToken)
+    {
+        case SVGToken::Dx:
+        {
+            SvgNumber aNum;
+
+            if (readSingleNumber(aContent, aNum))
+            {
+                if (aNum.isPositive())
+                {
+                    maDx = aNum;
+                }
+            }
+            break;
+        }
+        case SVGToken::Dy:
+        {
+            SvgNumber aNum;
+
+            if (readSingleNumber(aContent, aNum))
+            {
+                if (aNum.isPositive())
+                {
+                    maDy = aNum;
+                }
+            }
+            break;
+        }
+        default:
+        {
+            break;
+        }
+    }
+}
+
+void SvgFeOffsetNode::apply(drawinglayer::primitive2d::Primitive2DContainer& 
rTarget) const
+{
+    basegfx::B2DHomMatrix aTransform;
+
+    if (maDx.isSet() || maDy.isSet())
+    {
+        aTransform.translate(maDx.solve(*this, NumberType::xcoordinate),
+                             maDy.solve(*this, NumberType::ycoordinate));
+    }
+
+    const drawinglayer::primitive2d::Primitive2DReference xRef(
+        new drawinglayer::primitive2d::TransformPrimitive2D(aTransform, 
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 60d6371e1a0a..f95cf3530701 100644
--- a/svgio/source/svgreader/svgfilternode.cxx
+++ b/svgio/source/svgreader/svgfilternode.cxx
@@ -18,8 +18,9 @@
  */
 
 #include <svgfilternode.hxx>
-#include <svgfegaussianblurnode.hxx>
 #include <svgfecolormatrixnode.hxx>
+#include <svgfegaussianblurnode.hxx>
+#include <svgfeoffsetnode.hxx>
 
 namespace svgio::svgreader
 {
@@ -54,6 +55,12 @@ void 
SvgFilterNode::apply(drawinglayer::primitive2d::Primitive2DContainer& rTarg
                 = dynamic_cast<const SvgFeColorMatrixNode&>(*pCandidate);
             rFeColorMatrixNode.apply(rTarget);
         }
+        else if (pCandidate->getType() == SVGToken::FeOffset)
+        {
+            const SvgFeOffsetNode& rFeOffsetNode
+                = dynamic_cast<const SvgFeOffsetNode&>(*pCandidate);
+            rFeOffsetNode.apply(rTarget);
+        }
     }
 }
 
diff --git a/svgio/source/svgreader/svgtoken.cxx 
b/svgio/source/svgreader/svgtoken.cxx
index ed50612323e5..83271638b99d 100644
--- a/svgio/source/svgreader/svgtoken.cxx
+++ b/svgio/source/svgreader/svgtoken.cxx
@@ -28,7 +28,7 @@ namespace svgio::svgreader
 constexpr const std::u16string_view constToken_Title = u"title";
 constexpr const std::u16string_view constToken_Desc = u"desc";
 
-constexpr frozen::unordered_map<std::u16string_view, SVGToken, 139> 
aSVGTokenMapperList
+constexpr frozen::unordered_map<std::u16string_view, SVGToken, 140> 
aSVGTokenMapperList
 {
     { u"width", SVGToken::Width },
     { u"height", SVGToken::Height },
@@ -80,8 +80,9 @@ constexpr frozen::unordered_map<std::u16string_view, 
SVGToken, 139> aSVGTokenMap
     { u"color", SVGToken::Color },
     { u"clipPath", SVGToken::ClipPathNode },
     { u"clip-path", SVGToken::ClipPathProperty },
-    { u"feGaussianBlur", SVGToken::FeGaussianBlur },
     { u"feColorMatrix", SVGToken::FeColorMatrix },
+    { u"feGaussianBlur", SVGToken::FeGaussianBlur },
+    { u"feOffset", SVGToken::FeOffset },
     { u"filter", SVGToken::Filter },
     { u"mask", SVGToken::Mask },
     { u"clipPathUnits", SVGToken::ClipPathUnits },

Reply via email to