svgio/CppunitTest_svgio.mk                    |    1 
 svgio/CppunitTest_svgio_tools.mk              |    1 
 svgio/Library_svgio.mk                        |    2 
 svgio/inc/svgdocument.hxx                     |    6 -
 svgio/inc/svgnode.hxx                         |    7 +
 svgio/inc/svgswitchnode.hxx                   |   55 +++++++++++
 svgio/inc/svgtoken.hxx                        |    1 
 svgio/qa/cppunit/SvgImportTest.cxx            |   11 ++
 svgio/qa/cppunit/data/tdf160386.svg           |   16 +++
 svgio/source/svgreader/svgdocumenthandler.cxx |    9 +
 svgio/source/svgreader/svgnode.cxx            |   44 +++++++-
 svgio/source/svgreader/svgswitchnode.cxx      |  129 ++++++++++++++++++++++++++
 svgio/source/svgreader/svgtoken.cxx           |    1 
 13 files changed, 270 insertions(+), 13 deletions(-)

New commits:
commit 0a2535ceb06bb9233bc2eeee9158d4c9d2513abd
Author:     Xisco Fauli <xiscofa...@libreoffice.org>
AuthorDate: Wed Mar 27 11:38:44 2024 +0100
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Wed Mar 27 23:44:40 2024 +0100

    tdf#160386: Add support for switch element
    
    For now, only use language tag, meaning if
    there is a file like in the unittest with
    
    <text systemLanguage="en-us">Howdy!</text>
    <text systemLanguage="en-gb">Wotcha!</text>
    <text systemLanguage="en-au">G'day!</text>
    <text systemLanguage="en">Hello!</text>
    
    "Hello!" with be displayed in a en_AU system locale
    
    This patch partially reverts 13a41e7a12598c7896d6dc8d34aba6af5b80b83c
    "tdf#150124: do nothing when parent is of unkown type"
    making 0dfd8288a87b58e503bb3a41be6137485fbf3f68
    "ofz#60384 Direct-leak" no longer necessary
    
    Change-Id: Ifc73bc69aa997088dc0a2b11d7d30446303fa3b3
    
    Change-Id: I885ef0f2c44b86196881fe55a963db2e5c7eb1be
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165394
    Tested-by: Jenkins
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/svgio/CppunitTest_svgio.mk b/svgio/CppunitTest_svgio.mk
index 9309f5dcb9b8..a179d6af30fa 100644
--- a/svgio/CppunitTest_svgio.mk
+++ b/svgio/CppunitTest_svgio.mk
@@ -34,6 +34,7 @@ $(eval $(call gb_CppunitTest_use_libraries,svgio,\
     cppu \
     cppuhelper \
     comphelper \
+    i18nlangtag \
     sal \
     salhelper \
     sax \
diff --git a/svgio/CppunitTest_svgio_tools.mk b/svgio/CppunitTest_svgio_tools.mk
index abb6bb6e0fc7..5f4d7adbe523 100644
--- a/svgio/CppunitTest_svgio_tools.mk
+++ b/svgio/CppunitTest_svgio_tools.mk
@@ -33,6 +33,7 @@ $(eval $(call gb_CppunitTest_use_libraries,svgio_tools,\
     comphelper \
     cppu \
     cppuhelper \
+    i18nlangtag \
     sal \
     salhelper \
     sax \
diff --git a/svgio/Library_svgio.mk b/svgio/Library_svgio.mk
index 7bc518c71b93..8686792ca52a 100644
--- a/svgio/Library_svgio.mk
+++ b/svgio/Library_svgio.mk
@@ -41,6 +41,7 @@ $(eval $(call gb_Library_use_libraries,svgio,\
     comphelper \
     cppu \
     cppuhelper \
+    i18nlangtag \
     sal \
     salhelper \
     tk \
@@ -87,6 +88,7 @@ $(eval $(call gb_Library_add_exception_objects,svgio,\
     svgio/source/svgreader/svgstyleattributes \
     svgio/source/svgreader/svgstylenode \
     svgio/source/svgreader/svgsvgnode \
+    svgio/source/svgreader/svgswitchnode \
     svgio/source/svgreader/svgsymbolnode \
     svgio/source/svgreader/svgtextnode \
     svgio/source/svgreader/svgtextposition \
diff --git a/svgio/inc/svgdocument.hxx b/svgio/inc/svgdocument.hxx
index 77b4d3891179..9f79342c0c55 100644
--- a/svgio/inc/svgdocument.hxx
+++ b/svgio/inc/svgdocument.hxx
@@ -34,9 +34,6 @@ namespace svgio::svgreader
             /// the document hierarchy with all root nodes
             SvgNodeVector           maNodes;
 
-            /// invalid nodes that have no parent
-            SvgNodeVector           maOrphanNodes;
-
             /// the absolute path of the Svg file in progress (if available)
             const OUString     maAbsolutePath;
 
@@ -75,9 +72,6 @@ namespace svgio::svgreader
             /// data read access
             const SvgNodeVector& getSvgNodeVector() const { return maNodes; }
             const OUString& getAbsolutePath() const { return maAbsolutePath; }
-
-            /// invalid nodes that have no parent
-            void addOrphanNode(SvgNode* pOrphan) { 
maOrphanNodes.emplace_back(pOrphan); }
         };
 
 } // end of namespace svgio::svgreader
diff --git a/svgio/inc/svgnode.hxx b/svgio/inc/svgnode.hxx
index 63abc4f8cb0a..16c1f50bc3db 100644
--- a/svgio/inc/svgnode.hxx
+++ b/svgio/inc/svgnode.hxx
@@ -95,6 +95,9 @@ namespace svgio::svgreader
             /// Class svan value
             std::optional<OUString>   mpClass;
 
+            /// systemLanguage values
+            std::vector<OUString>  maSystemLanguage;
+
             /// XmlSpace value
             XmlSpace                    maXmlSpace;
 
@@ -174,6 +177,10 @@ namespace svgio::svgreader
             std::optional<OUString> const & getClass() const { return mpClass; 
}
             void setClass(OUString const &);
 
+            /// SystemLanguage access
+            std::vector<OUString> const & getSystemLanguage() const { return 
maSystemLanguage; }
+            void setSystemLanguage(OUString const &);
+
             /// XmlSpace access
             XmlSpace getXmlSpace() const;
             void setXmlSpace(XmlSpace eXmlSpace) { maXmlSpace = eXmlSpace; }
diff --git a/svgio/inc/svgswitchnode.hxx b/svgio/inc/svgswitchnode.hxx
new file mode 100644
index 000000000000..b83ae0c4ac0f
--- /dev/null
+++ b/svgio/inc/svgswitchnode.hxx
@@ -0,0 +1,55 @@
+/* -*- 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 "svgstyleattributes.hxx"
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+namespace svgio::svgreader
+{
+class SvgSwitchNode final : public SvgNode
+{
+private:
+    /// use styles
+    SvgStyleAttributes maSvgStyleAttributes;
+
+    /// variable scan values, dependent of given XAttributeList
+    std::optional<basegfx::B2DHomMatrix> mpaTransform;
+
+public:
+    SvgSwitchNode(SvgDocument& rDocument, SvgNode* pParent);
+    virtual ~SvgSwitchNode() override;
+
+    virtual const SvgStyleAttributes* getSvgStyleAttributes() const override;
+    virtual void parseAttribute(SVGToken aSVGToken, const OUString& aContent) 
override;
+    virtual void 
decomposeSvgNode(drawinglayer::primitive2d::Primitive2DContainer& rTarget,
+                                  bool bReferenced) const override;
+
+    /// transform content
+    const std::optional<basegfx::B2DHomMatrix>& getTransform() const { return 
mpaTransform; }
+    void setTransform(const std::optional<basegfx::B2DHomMatrix>& pMatrix)
+    {
+        mpaTransform = pMatrix;
+    }
+};
+
+} // 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 203e7f0996c0..d988f4b2d993 100644
--- a/svgio/inc/svgtoken.hxx
+++ b/svgio/inc/svgtoken.hxx
@@ -116,6 +116,7 @@ namespace svgio::svgreader
             PatternContentUnits,
             PatternTransform,
             Opacity,
+            SystemLanguage,
             Visibility,
             Title,
             Desc,
diff --git a/svgio/qa/cppunit/SvgImportTest.cxx 
b/svgio/qa/cppunit/SvgImportTest.cxx
index 4cab973b5003..3bfe3022df39 100644
--- a/svgio/qa/cppunit/SvgImportTest.cxx
+++ b/svgio/qa/cppunit/SvgImportTest.cxx
@@ -422,6 +422,17 @@ CPPUNIT_TEST_FIXTURE(Test, testFontsizeRelative)
     assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, 
"familyname"_ostr, "DejaVu Serif");
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testTdf160386)
+{
+    xmlDocUniquePtr pDocument = 
dumpAndParseSvg(u"/svgio/qa/cppunit/data/tdf160386.svg");
+
+    // Without the fix in place, this test would have failed with
+    // - Expected: 1
+    // - Actual  : 11
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion"_ostr, 1);
+    assertXPath(pDocument, "/primitive2D/transform/textsimpleportion"_ostr, 
"text"_ostr, "Hello!");
+}
+
 CPPUNIT_TEST_FIXTURE(Test, testTdf145896)
 {
     xmlDocUniquePtr pDocument = 
dumpAndParseSvg(u"/svgio/qa/cppunit/data/tdf145896.svg");
diff --git a/svgio/qa/cppunit/data/tdf160386.svg 
b/svgio/qa/cppunit/data/tdf160386.svg
new file mode 100644
index 000000000000..1644b0d15514
--- /dev/null
+++ b/svgio/qa/cppunit/data/tdf160386.svg
@@ -0,0 +1,16 @@
+<svg viewBox="0 -20 100 50" xmlns="http://www.w3.org/2000/svg";>
+  <switch font-family="DejaVu Sans">
+    <text systemLanguage="ar">مرحبا</text>
+    <text systemLanguage="de,nl">Hallo!</text>
+    <text systemLanguage="en-us">Howdy!</text>
+    <text systemLanguage="en-gb">Wotcha!</text>
+    <text systemLanguage="en-au">G'day!</text>
+    <text systemLanguage="en">Hello!</text>
+    <text systemLanguage="es">Hola!</text>
+    <text systemLanguage="fr">Bonjour!</text>
+    <text systemLanguage="ja">こんにちは</text>
+    <text systemLanguage="ru">Привет!</text>
+    <text>☺</text>
+  </switch>
+</svg>
+
diff --git a/svgio/source/svgreader/svgdocumenthandler.cxx 
b/svgio/source/svgreader/svgdocumenthandler.cxx
index 6e31aaf8fdf0..85a54448e7d9 100644
--- a/svgio/source/svgreader/svgdocumenthandler.cxx
+++ b/svgio/source/svgreader/svgdocumenthandler.cxx
@@ -27,6 +27,7 @@
 #include <svgrectnode.hxx>
 #include <svggradientnode.hxx>
 #include <svggradientstopnode.hxx>
+#include <svgswitchnode.hxx>
 #include <svgsymbolnode.hxx>
 #include <svgusenode.hxx>
 #include <svgcirclenode.hxx>
@@ -203,7 +204,13 @@ namespace
                     mpTarget->parseAttributes(xAttribs);
                     break;
                 }
-                case SVGToken::Switch: //TODO: Support switch element
+                case SVGToken::Switch:
+                {
+                    /// new node for Switch
+                    mpTarget = new SvgSwitchNode(maDocument, mpTarget);
+                    mpTarget->parseAttributes(xAttribs);
+                    break;
+                }
                 case SVGToken::Defs:
                 case SVGToken::G:
                 {
diff --git a/svgio/source/svgreader/svgnode.cxx 
b/svgio/source/svgreader/svgnode.cxx
index c372184b1e37..20a48de25977 100644
--- a/svgio/source/svgreader/svgnode.cxx
+++ b/svgio/source/svgreader/svgnode.cxx
@@ -367,17 +367,13 @@ namespace {
             mpParent(pParent),
             mpAlternativeParent(nullptr),
             maXmlSpace(XmlSpace::NotSet),
-            maDisplay(Display::Inline),
+            maDisplay(maType == SVGToken::Unknown ? Display::None : 
Display::Inline), // tdf#150124: do not display unknown nodes
             mbDecomposing(false),
             mbCssStyleVectorBuilt(false)
         {
             if (pParent)
             {
-                // tdf#150124 ignore when parent is unknown
-                if (pParent->getType() != SVGToken::Unknown)
-                    pParent->maChildren.emplace_back(this);
-                else
-                    mrDocument.addOrphanNode(this);
+                pParent->maChildren.emplace_back(this);
             }
         }
 
@@ -527,6 +523,14 @@ namespace {
                     }
                     break;
                 }
+                case SVGToken::SystemLanguage:
+                {
+                    if(!aContent.isEmpty())
+                    {
+                        setSystemLanguage(aContent);
+                    }
+                    break;
+                }
                 case SVGToken::XmlSpace:
                 {
                     if(!aContent.isEmpty())
@@ -751,6 +755,34 @@ namespace {
             mrDocument.addSvgNodeToMapper(*mpClass, *this);
         }
 
+        void SvgNode::setSystemLanguage(OUString const & rSystemClass)
+        {
+            const sal_Int32 nLen(rSystemClass.getLength());
+            sal_Int32 nPos(0);
+            OUStringBuffer aToken;
+
+            // split into single tokens (currently only comma separator)
+            while(nPos < nLen)
+            {
+                const sal_Int32 nInitPos(nPos);
+                copyToLimiter(rSystemClass, u',', nPos, aToken, nLen);
+                skip_char(rSystemClass, u',', nPos, nLen);
+                const OUString aLang(o3tl::trim(aToken));
+                aToken.setLength(0);
+
+                if(!aLang.isEmpty())
+                {
+                    maSystemLanguage.push_back(aLang);
+                }
+
+                if(nInitPos == nPos)
+                {
+                    OSL_ENSURE(false, "Could not interpret on current position 
(!)");
+                    nPos++;
+                }
+            }
+        }
+
         XmlSpace SvgNode::getXmlSpace() const
         {
             if(maXmlSpace != XmlSpace::NotSet)
diff --git a/svgio/source/svgreader/svgswitchnode.cxx 
b/svgio/source/svgreader/svgswitchnode.cxx
new file mode 100644
index 000000000000..bbad79a3b5d9
--- /dev/null
+++ b/svgio/source/svgreader/svgswitchnode.cxx
@@ -0,0 +1,129 @@
+/* -*- 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 <svgswitchnode.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <unotools/syslocaleoptions.hxx>
+
+namespace svgio::svgreader
+{
+SvgSwitchNode::SvgSwitchNode(SvgDocument& rDocument, SvgNode* pParent)
+    : SvgNode(SVGToken::Switch, rDocument, pParent)
+    , maSvgStyleAttributes(*this)
+{
+}
+
+SvgSwitchNode::~SvgSwitchNode() {}
+
+const SvgStyleAttributes* SvgSwitchNode::getSvgStyleAttributes() const
+{
+    return checkForCssStyle(maSvgStyleAttributes);
+}
+
+void SvgSwitchNode::parseAttribute(SVGToken aSVGToken, const OUString& 
aContent)
+{
+    // call parent
+    SvgNode::parseAttribute(aSVGToken, aContent);
+
+    // read style attributes
+    maSvgStyleAttributes.parseStyleAttribute(aSVGToken, aContent);
+
+    // parse own
+    switch (aSVGToken)
+    {
+        case SVGToken::Style:
+        {
+            readLocalCssStyle(aContent);
+            break;
+        }
+        case SVGToken::Transform:
+        {
+            const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, 
*this));
+
+            if (!aMatrix.isIdentity())
+            {
+                setTransform(aMatrix);
+            }
+            break;
+        }
+        default:
+        {
+            break;
+        }
+    }
+}
+
+void 
SvgSwitchNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DContainer&
 rTarget,
+                                     bool bReferenced) const
+{
+    // #i125258# for SVGTokenG decompose children
+    const SvgStyleAttributes* pStyle = getSvgStyleAttributes();
+
+    if (pStyle)
+    {
+        drawinglayer::primitive2d::Primitive2DContainer aContent;
+
+        const auto& rChildren = getChildren();
+        const sal_uInt32 nCount(rChildren.size());
+        OUString 
sLanguage(SvtSysLocaleOptions().GetRealUILanguageTag().getLanguage());
+
+        SvgNode* pNodeToDecompose = nullptr;
+        for (sal_uInt32 a(0); a < nCount; a++)
+        {
+            SvgNode* pCandidate = rChildren[a].get();
+
+            if (pCandidate && Display::None != pCandidate->getDisplay())
+            {
+                std::vector<OUString> aSystemLanguage = 
pCandidate->getSystemLanguage();
+                if (!sLanguage.isEmpty() && !aSystemLanguage.empty())
+                {
+                    for (const OUString& sSystemLang : aSystemLanguage)
+                    {
+                        if (sSystemLang == sLanguage)
+                        {
+                            pNodeToDecompose = pCandidate;
+                            break;
+                        }
+                    }
+                }
+                else
+                {
+                    pNodeToDecompose = pCandidate;
+                }
+            }
+
+            if (pNodeToDecompose)
+            {
+                pNodeToDecompose->decomposeSvgNode(aContent, bReferenced);
+                // break once it's descomposed
+                break;
+            }
+        }
+
+        if (!aContent.empty())
+        {
+            pStyle->add_postProcess(rTarget, std::move(aContent), 
getTransform());
+        }
+    }
+}
+
+} // end of namespace svgio::svgreader
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svgio/source/svgreader/svgtoken.cxx 
b/svgio/source/svgreader/svgtoken.cxx
index b6e22b63c547..3f5ac5c7a306 100644
--- a/svgio/source/svgreader/svgtoken.cxx
+++ b/svgio/source/svgreader/svgtoken.cxx
@@ -114,6 +114,7 @@ constexpr auto aSVGTokenMap = 
frozen::make_unordered_map<std::u16string_view, SV
     { u"patternContentUnits", SVGToken::PatternContentUnits },
     { u"patternTransform", SVGToken::PatternTransform },
     { u"opacity", SVGToken::Opacity },
+    { u"systemLanguage", SVGToken::SystemLanguage },
     { u"visibility", SVGToken::Visibility },
     { u"title", SVGToken::Title },
     { u"desc", SVGToken::Desc },

Reply via email to