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 reverts13a41e7a12
"tdf#150124: do nothing when parent is of unkown type" making0dfd8288a8
"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 <xiscofauli@libreoffice.org>
This commit is contained in:
parent
6b15374d18
commit
0a2535ceb0
13 changed files with 270 additions and 13 deletions
|
@ -34,6 +34,7 @@ $(eval $(call gb_CppunitTest_use_libraries,svgio,\
|
|||
cppu \
|
||||
cppuhelper \
|
||||
comphelper \
|
||||
i18nlangtag \
|
||||
sal \
|
||||
salhelper \
|
||||
sax \
|
||||
|
|
|
@ -33,6 +33,7 @@ $(eval $(call gb_CppunitTest_use_libraries,svgio_tools,\
|
|||
comphelper \
|
||||
cppu \
|
||||
cppuhelper \
|
||||
i18nlangtag \
|
||||
sal \
|
||||
salhelper \
|
||||
sax \
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
|
55
svgio/inc/svgswitchnode.hxx
Normal file
55
svgio/inc/svgswitchnode.hxx
Normal file
|
@ -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: */
|
|
@ -116,6 +116,7 @@ namespace svgio::svgreader
|
|||
PatternContentUnits,
|
||||
PatternTransform,
|
||||
Opacity,
|
||||
SystemLanguage,
|
||||
Visibility,
|
||||
Title,
|
||||
Desc,
|
||||
|
|
|
@ -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");
|
||||
|
|
16
svgio/qa/cppunit/data/tdf160386.svg
Normal file
16
svgio/qa/cppunit/data/tdf160386.svg
Normal file
|
@ -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>
|
||||
|
After Width: | Height: | Size: 616 B |
|
@ -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:
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
129
svgio/source/svgreader/svgswitchnode.cxx
Normal file
129
svgio/source/svgreader/svgswitchnode.cxx
Normal file
|
@ -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: */
|
|
@ -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 },
|
||||
|
|
Loading…
Reference in a new issue