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>
This commit is contained in:
parent
d07f18e0c3
commit
4f61276dae
4 changed files with 78 additions and 11 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
18
svgio/qa/cppunit/data/ClipRule.svg
Normal file
18
svgio/qa/cppunit/data/ClipRule.svg
Normal file
|
@ -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>
|
||||
|
After Width: | Height: | Size: 640 B |
|
@ -1125,19 +1125,20 @@ 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(FillRule::evenodd != getClipRule() && FillRule::evenodd != getFillRule())
|
||||
{
|
||||
if(getFill() || getSvgGradientNodeFill() || getSvgPatternNodeFill())
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
add_fill(aPath, rTarget, aGeoRange);
|
||||
}
|
||||
|
@ -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())
|
||||
|
|
Loading…
Reference in a new issue