svgio/inc/svgstyleattributes.hxx | 7 +++++ svgio/qa/cppunit/SvgImportTest.cxx | 8 +++++ svgio/qa/cppunit/data/contextFill.svg | 8 +++++ svgio/source/svgreader/svgstyleattributes.cxx | 36 ++++++++++++++++++++++++-- 4 files changed, 57 insertions(+), 2 deletions(-)
New commits: commit 3b0f96a0773f19f7d5bdb5725ff9667eb4809215 Author: Xisco Fauli <xiscofa...@libreoffice.org> AuthorDate: Mon May 6 17:15:59 2024 +0200 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Mon May 6 22:02:01 2024 +0200 tdf#155651: Add support for "context-fill" Change-Id: I6f96cc7c059ece5f9401fc0ae552cf279e53109c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167230 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> Tested-by: Jenkins diff --git a/svgio/inc/svgstyleattributes.hxx b/svgio/inc/svgstyleattributes.hxx index 61a3816e82cb..30cbab965644 100644 --- a/svgio/inc/svgstyleattributes.hxx +++ b/svgio/inc/svgstyleattributes.hxx @@ -247,6 +247,9 @@ namespace svgio::svgreader // #121221# Defines if evtl. an empty array *is* set bool mbStrokeDasharraySet : 1; + // tdf#155651 Defines if 'context-fill' is used in fill + bool mbContextFill : 1; + // tdf#155651 Defines if 'context-stroke' is used in stroke bool mbContextStroke : 1; @@ -254,6 +257,7 @@ namespace svgio::svgreader OUString maNodeFillURL; OUString maNodeStrokeURL; + const basegfx::BColor* maContextFill; const basegfx::BColor* maContextStroke; /// internal helpers @@ -332,6 +336,9 @@ namespace svgio::svgreader /// stroke content const basegfx::BColor* getStroke() const; + /// context fill content + const basegfx::BColor* getContextFill() const; + /// context stroke content const basegfx::BColor* getContextStroke() const; diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx index c12f5abaaf16..dc2aa1a6eaf4 100644 --- a/svgio/qa/cppunit/SvgImportTest.cxx +++ b/svgio/qa/cppunit/SvgImportTest.cxx @@ -646,6 +646,14 @@ CPPUNIT_TEST_FIXTURE(Test, testMarkerOrient) assertXPath(pDocument, "/primitive2D/transform/transform[2]"_ostr, "xy33"_ostr, "1"); } +CPPUNIT_TEST_FIXTURE(Test, testContextFill) +{ + xmlDocUniquePtr pDocument = dumpAndParseSvg(u"/svgio/qa/cppunit/data/contextFill.svg"); + + assertXPath(pDocument, "/primitive2D/transform/polypolygonstroke/line"_ostr, "color"_ostr, "#ff0000"); + assertXPath(pDocument, "/primitive2D/transform/transform/polypolygoncolor"_ostr, "color"_ostr, "#ff0000"); +} + CPPUNIT_TEST_FIXTURE(Test, testContextStroke) { xmlDocUniquePtr pDocument = dumpAndParseSvg(u"/svgio/qa/cppunit/data/contextStroke.svg"); diff --git a/svgio/qa/cppunit/data/contextFill.svg b/svgio/qa/cppunit/data/contextFill.svg new file mode 100644 index 000000000000..399d3c16b09e --- /dev/null +++ b/svgio/qa/cppunit/data/contextFill.svg @@ -0,0 +1,8 @@ +<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"> +<defs> + <marker id="triangle" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" orient="auto"> + <path d="M 0 0 L 10 5 L 0 10 z" fill="context-fill" /> + </marker> +</defs> +<line x1="10" y1="10" x2="90" y2="90" fill="red" stroke="red" marker-end="url(#triangle)" /> +</svg> diff --git a/svgio/source/svgreader/svgstyleattributes.cxx b/svgio/source/svgreader/svgstyleattributes.cxx index f694d8b1cfd9..cd6a705114a9 100644 --- a/svgio/source/svgreader/svgstyleattributes.cxx +++ b/svgio/source/svgreader/svgstyleattributes.cxx @@ -823,6 +823,11 @@ namespace svgio::svgreader rMarkerTransform.identity(); rClipRange.reset(); + // Set the current fill to the marker before calling getMarkerPrimitives, + // which calls decomposeSvgNode to decompose the children of the marker. + // If any of the children uses 'fill="context-fill"', then it will use it + const_cast<SvgStyleAttributes*>(rMarker.getSvgStyleAttributes())->maContextFill = getFill(); + // Set the current stroke to the marker before calling getMarkerPrimitives, // which calls decomposeSvgNode to decompose the children of the marker. // If any of the children uses 'stroke="context-stroke"', then it will use it @@ -1298,9 +1303,11 @@ namespace svgio::svgreader maBaselineShift(BaselineShift::Baseline), maBaselineShiftNumber(0), maDominantBaseline(DominantBaseline::Auto), - maResolvingParent(33, 0), + maResolvingParent(34, 0), mbStrokeDasharraySet(false), + mbContextFill(false), mbContextStroke(false), + maContextFill(nullptr), maContextStroke(nullptr) { } @@ -1321,7 +1328,11 @@ namespace svgio::svgreader OUString aURL; SvgNumber aOpacity; - if(readSvgPaint(aContent, aSvgPaint, aURL, aOpacity)) + if(o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent), u"context-fill")) + { + mbContextFill = true; + } + else if(readSvgPaint(aContent, aSvgPaint, aURL, aOpacity)) { setFill(aSvgPaint); if(aOpacity.isSet()) @@ -2013,6 +2024,23 @@ namespace svgio::svgreader } } + const basegfx::BColor* SvgStyleAttributes::getContextFill() const + { + if (SVGToken::Marker == mrOwner.getType()) + return maContextFill; + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + if (pSvgStyleAttributes && maResolvingParent[33] < nStyleDepthLimit) + { + ++maResolvingParent[33]; + auto ret = pSvgStyleAttributes->getContextFill(); + --maResolvingParent[33]; + return ret; + } + + return nullptr; + } + const basegfx::BColor* SvgStyleAttributes::getContextStroke() const { if (SVGToken::Marker == mrOwner.getType()) @@ -2098,6 +2126,10 @@ namespace svgio::svgreader } } } + else if (mbContextFill) + { + return getContextFill(); + } else if (maNodeFillURL.isEmpty()) { const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();