diff options
author | Xisco Fauli <xiscofauli@libreoffice.org> | 2022-07-28 18:37:32 +0200 |
---|---|---|
committer | Christian Lohmaier <lohmaier+LibreOffice@googlemail.com> | 2022-08-18 19:19:42 +0200 |
commit | ddd79065bd3844397c05aa2150269201526984c2 (patch) | |
tree | a94ac5cdbe48816d0ea87b38e29ff376822b5b49 | |
parent | tdf#149609 release mouse before showing popups from calc grid window (diff) | |
download | core-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.hxx | 3 | ||||
-rw-r--r-- | svgio/qa/cppunit/SvgImportTest.cxx | 24 | ||||
-rw-r--r-- | svgio/qa/cppunit/data/ClipRule.svg | 18 | ||||
-rw-r--r-- | svgio/source/svgreader/svgstyleattributes.cxx | 44 |
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()) |