diff options
author | Xisco Fauli <xiscofauli@libreoffice.org> | 2022-07-28 18:37:32 +0200 |
---|---|---|
committer | Xisco Fauli <xiscofauli@libreoffice.org> | 2022-07-29 08:21:59 +0200 |
commit | 4f61276dae10fdaf2ed33ab23d98adbe311cb7ee (patch) | |
tree | 4a00f4c0aea4f648261a31e3070109284ffcf200 /svgio | |
parent | d07f18e0c3f8d50deea643c0ecab171795bd1231 (diff) |
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>
Diffstat (limited to 'svgio')
-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 8489430b7546..529e91b75b8e 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 f23556ee621c..8037f850768a 100644 --- a/svgio/qa/cppunit/SvgImportTest.cxx +++ b/svgio/qa/cppunit/SvgImportTest.cxx @@ -66,6 +66,7 @@ class Test : public test::BootstrapFixture, public XmlTestTools void testShapeWithClipPath(); void testClipPathUsingClipPath(); void testFillRule(); + void testClipRule(); void testi125329(); void testMaskingPath07b(); void test123926(); @@ -112,6 +113,7 @@ public: CPPUNIT_TEST(testShapeWithClipPath); CPPUNIT_TEST(testClipPathUsingClipPath); CPPUNIT_TEST(testFillRule); + CPPUNIT_TEST(testClipRule); CPPUNIT_TEST(testi125329); CPPUNIT_TEST(testMaskingPath07b); CPPUNIT_TEST(test123926); @@ -719,6 +721,28 @@ void Test::testFillRule() assertXPath(pDocument, "/primitive2D/transform/polypolygonstroke/polypolygon/polygon", 2); } +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(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 6ad1b1d25cc2..c787c4dffa92 100644 --- a/svgio/source/svgreader/svgstyleattributes.cxx +++ b/svgio/source/svgreader/svgstyleattributes.cxx @@ -1125,17 +1125,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); + } } } @@ -1275,10 +1276,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) { @@ -2348,6 +2349,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()) |