summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXisco Fauli <xiscofauli@libreoffice.org>2022-07-28 18:37:32 +0200
committerChristian Lohmaier <lohmaier+LibreOffice@googlemail.com>2022-08-18 19:19:42 +0200
commitddd79065bd3844397c05aa2150269201526984c2 (patch)
treea94ac5cdbe48816d0ea87b38e29ff376822b5b49
parenttdf#149609 release mouse before showing popups from calc grid window (diff)
downloadcore-ddd79065bd3844397c05aa2150269201526984c2.tar.gz
core-ddd79065bd3844397c05aa2150269201526984c2.zip
svgio: Add support for clip-rule="evenodd"
Change-Id: I028aa88bdd72b4f87526a3d1edabd612d7686571 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137577 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org> Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137586 (cherry picked from commit 2b22203c0be09e9685cf081f0a1fafa538a21294) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137973 Reviewed-by: Christian Lohmaier <lohmaier+LibreOffice@googlemail.com>
-rw-r--r--svgio/inc/svgstyleattributes.hxx3
-rw-r--r--svgio/qa/cppunit/SvgImportTest.cxx24
-rw-r--r--svgio/qa/cppunit/data/ClipRule.svg18
-rw-r--r--svgio/source/svgreader/svgstyleattributes.cxx44
4 files changed, 78 insertions, 11 deletions
diff --git a/svgio/inc/svgstyleattributes.hxx b/svgio/inc/svgstyleattributes.hxx
index 8db2fa0676f6..dd5c16daab43 100644
--- a/svgio/inc/svgstyleattributes.hxx
+++ b/svgio/inc/svgstyleattributes.hxx
@@ -338,6 +338,9 @@ namespace svgio::svgreader
/// fill rule content
FillRule getFillRule() const;
+ /// clip rule content
+ FillRule getClipRule() const;
+
/// fill StrokeDasharray content
const SvgNumberVector& getStrokeDasharray() const;
diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx
index f9fc88f812de..cc4aae90bd39 100644
--- a/svgio/qa/cppunit/SvgImportTest.cxx
+++ b/svgio/qa/cppunit/SvgImportTest.cxx
@@ -62,6 +62,7 @@ class Test : public test::BootstrapFixture, public XmlTestTools
void testClipPathAndParentStyle();
void testClipPathAndStyle();
void testClipPathUsingClipPath();
+ void testClipRule();
void testi125329();
void testMaskingPath07b();
void test123926();
@@ -103,6 +104,7 @@ public:
CPPUNIT_TEST(testClipPathAndParentStyle);
CPPUNIT_TEST(testClipPathAndStyle);
CPPUNIT_TEST(testClipPathUsingClipPath);
+ CPPUNIT_TEST(testClipRule);
CPPUNIT_TEST(testi125329);
CPPUNIT_TEST(testMaskingPath07b);
CPPUNIT_TEST(test123926);
@@ -624,6 +626,28 @@ void Test::testClipPathUsingClipPath()
assertXPath(pDocument, "/primitive2D/transform/mask/mask/polypolygon/polygon/point", 13);
}
+void Test::testClipRule()
+{
+ Primitive2DSequence aSequence = parseSvg(u"/svgio/qa/cppunit/data/ClipRule.svg");
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(aSequence.getLength()));
+
+ drawinglayer::Primitive2dXmlDump dumper;
+ xmlDocUniquePtr pDocument = dumper.dumpAndParse(comphelper::sequenceToContainer<Primitive2DContainer>(aSequence));
+
+ CPPUNIT_ASSERT (pDocument);
+
+ // Without the place in place, this test would have failed with
+ // - Expected: 5
+ // - Actual : 10
+ assertXPath(pDocument, "/primitive2D/transform/mask[1]/polypolygon/polygon/point", 5);
+ assertXPath(pDocument, "/primitive2D/transform/mask[1]/polypolygoncolor", "color", "#0000ff");
+ assertXPath(pDocument, "/primitive2D/transform/mask[1]/polypolygoncolor/polypolygon/polygon/point", 5);
+
+ assertXPath(pDocument, "/primitive2D/transform/mask[2]/polypolygon/polygon/point", 5);
+ assertXPath(pDocument, "/primitive2D/transform/mask[2]/polypolygoncolor", "color", "#ff0000");
+ assertXPath(pDocument, "/primitive2D/transform/mask[2]/polypolygoncolor/polypolygon/polygon/point", 5);
+}
+
void Test::testi125329()
{
//Check style inherit from * css element
diff --git a/svgio/qa/cppunit/data/ClipRule.svg b/svgio/qa/cppunit/data/ClipRule.svg
new file mode 100644
index 000000000000..55f0cb9eee3a
--- /dev/null
+++ b/svgio/qa/cppunit/data/ClipRule.svg
@@ -0,0 +1,18 @@
+<svg version="1.1" baseProfile="basic" id="svg-root"
+ width="100%" height="100%" viewBox="0 0 480 360"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <!-- Define star path -->
+ <defs>
+ <path d="M50,0 21,90 98,35 2,35 79,90z" id="star" />
+ </defs>
+ <clipPath id="emptyStar">
+ <use xlink:href="#star" clip-rule="evenodd" />
+ </clipPath>
+ <rect clip-path="url(#emptyStar)" width="50" height="90" fill="blue" />
+
+ <clipPath id="filledStar">
+ <use xlink:href="#star" clip-rule="evenodd" />
+ </clipPath>
+ <rect clip-path="url(#filledStar)" width="50" height="90" x="50" fill="red" />
+</svg>
+
diff --git a/svgio/source/svgreader/svgstyleattributes.cxx b/svgio/source/svgreader/svgstyleattributes.cxx
index 8084ed5f0239..333ff7dbd317 100644
--- a/svgio/source/svgreader/svgstyleattributes.cxx
+++ b/svgio/source/svgreader/svgstyleattributes.cxx
@@ -1117,17 +1117,18 @@ namespace svgio::svgreader
{
// create fill
basegfx::B2DPolyPolygon aPath(rPath);
- const bool bNeedToCheckClipRule(SVGToken::Path == mrOwner.getType() || SVGToken::Polygon == mrOwner.getType());
- const bool bClipPathIsNonzero(bNeedToCheckClipRule && mbIsClipPathContent && FillRule::nonzero == maClipRule);
- const bool bFillRuleIsNonzero(bNeedToCheckClipRule && !mbIsClipPathContent && FillRule::nonzero == getFillRule());
- if(bClipPathIsNonzero || bFillRuleIsNonzero)
+ if(SVGToken::Path == mrOwner.getType() || SVGToken::Polygon == mrOwner.getType())
{
- if(getFill() || getSvgGradientNodeFill() || getSvgPatternNodeFill()) {
- // nonzero is wanted, solve geometrically (see description on basegfx)
- // basegfx::utils::createNonzeroConform() is expensive for huge paths
- // and is only needed if path will be filled later on
- aPath = basegfx::utils::createNonzeroConform(aPath);
+ if(FillRule::evenodd != getClipRule() && FillRule::evenodd != getFillRule())
+ {
+ if(getFill() || getSvgGradientNodeFill() || getSvgPatternNodeFill())
+ {
+ // nonzero is wanted, solve geometrically (see description on basegfx)
+ // basegfx::utils::createNonzeroConform() is expensive for huge paths
+ // and is only needed if path will be filled later on
+ aPath = basegfx::utils::createNonzeroConform(aPath);
+ }
}
}
@@ -1267,10 +1268,10 @@ namespace svgio::svgreader
mpMarkerMidXLink(nullptr),
mpMarkerEndXLink(nullptr),
maFillRule(FillRule::notset),
- maClipRule(FillRule::nonzero),
+ maClipRule(FillRule::notset),
maBaselineShift(BaselineShift::Baseline),
maBaselineShiftNumber(0),
- maResolvingParent(31, 0),
+ maResolvingParent(32, 0),
mbIsClipPathContent(SVGToken::ClipPathNode == mrOwner.getType()),
mbStrokeDasharraySet(false)
{
@@ -2341,6 +2342,27 @@ namespace svgio::svgreader
return FillRule::nonzero;
}
+ FillRule SvgStyleAttributes::getClipRule() const
+ {
+ if(FillRule::notset != maClipRule)
+ {
+ return maClipRule;
+ }
+
+ const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+ if (pSvgStyleAttributes && maResolvingParent[31] < nStyleDepthLimit)
+ {
+ ++maResolvingParent[31];
+ auto ret = pSvgStyleAttributes->getClipRule();
+ --maResolvingParent[31];
+ return ret;
+ }
+
+ // default is NonZero
+ return FillRule::nonzero;
+ }
+
const SvgNumberVector& SvgStyleAttributes::getStrokeDasharray() const
{
if(!maStrokeDasharray.empty())