svgio/inc/svgstyleattributes.hxx | 8 +++++ svgio/qa/cppunit/SvgImportTest.cxx | 11 +++++++ svgio/qa/cppunit/data/contextStroke.svg | 14 +++++++++ svgio/source/svgreader/svgmarkernode.cxx | 2 - svgio/source/svgreader/svgstyleattributes.cxx | 37 +++++++++++++++++++++++--- 5 files changed, 68 insertions(+), 4 deletions(-)
New commits: commit f4a868ce3b7e5fe6e708f2c795402d646e0746d5 Author: Xisco Fauli <xiscofa...@libreoffice.org> AuthorDate: Thu May 2 22:16:36 2024 +0200 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Fri May 3 18:26:48 2024 +0200 tdf#155651: Add support for "context-stroke" Change-Id: Ib4f4a7b644d0d6c6b36e31b80fd7adc18999110d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166908 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> Tested-by: Jenkins diff --git a/svgio/inc/svgstyleattributes.hxx b/svgio/inc/svgstyleattributes.hxx index c5c095462f3d..61a3816e82cb 100644 --- a/svgio/inc/svgstyleattributes.hxx +++ b/svgio/inc/svgstyleattributes.hxx @@ -247,10 +247,15 @@ namespace svgio::svgreader // #121221# Defines if evtl. an empty array *is* set bool mbStrokeDasharraySet : 1; + // tdf#155651 Defines if 'context-stroke' is used in stroke + bool mbContextStroke : 1; + // tdf#94765 Check id references in gradient/pattern getters OUString maNodeFillURL; OUString maNodeStrokeURL; + const basegfx::BColor* maContextStroke; + /// internal helpers void add_fillGradient( const basegfx::B2DPolyPolygon& rPath, @@ -327,6 +332,9 @@ namespace svgio::svgreader /// stroke content const basegfx::BColor* getStroke() const; + /// context stroke content + const basegfx::BColor* getContextStroke() const; + /// stop color content const basegfx::BColor& getStopColor() const; diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx index 2c9f9ea72485..407e8aa0c3bb 100644 --- a/svgio/qa/cppunit/SvgImportTest.cxx +++ b/svgio/qa/cppunit/SvgImportTest.cxx @@ -669,6 +669,17 @@ CPPUNIT_TEST_FIXTURE(Test, testMarkerOrient) assertXPath(pDocument, "/primitive2D/transform/transform[2]"_ostr, "xy33"_ostr, "1"); } +CPPUNIT_TEST_FIXTURE(Test, testContextStroke) +{ + xmlDocUniquePtr pDocument = dumpAndParseSvg(u"/svgio/qa/cppunit/data/contextStroke.svg"); + + assertXPath(pDocument, "/primitive2D/transform/polypolygonstroke/line"_ostr, "color"_ostr, "#ff0000"); + assertXPath(pDocument, "/primitive2D/transform/transform[1]/polypolygonstroke/line"_ostr, "color"_ostr, "#ff0000"); + assertXPath(pDocument, "/primitive2D/transform/transform[2]/polypolygonstroke/line"_ostr, "color"_ostr, "#ff0000"); + assertXPath(pDocument, "/primitive2D/transform/transform[3]/polypolygonstroke/line"_ostr, "color"_ostr, "#ff0000"); + assertXPath(pDocument, "/primitive2D/transform/transform[4]/polypolygonstroke/line"_ostr, "color"_ostr, "#ff0000"); +} + CPPUNIT_TEST_FIXTURE(Test, testMarkerInPresentation) { Primitive2DSequence aSequence = parseSvg(u"/svgio/qa/cppunit/data/markerInPresentation.svg"); diff --git a/svgio/qa/cppunit/data/contextStroke.svg b/svgio/qa/cppunit/data/contextStroke.svg new file mode 100644 index 000000000000..5a9b27d69c84 --- /dev/null +++ b/svgio/qa/cppunit/data/contextStroke.svg @@ -0,0 +1,14 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"> + <style> + path { + fill: none; + stroke-width: 4px; + marker: url(#diamond); + } + </style> + <path d="M 10,50 v -20 h 40 v -20" stroke="red"/> + + <marker id="diamond" markerWidth="12" markerHeight="12" refX="6" refY="6" markerUnits="userSpaceOnUse"> + <circle cx="6" cy="6" r="3" fill="white" stroke="context-stroke" stroke-width="2"/> + </marker> +</svg> diff --git a/svgio/source/svgreader/svgmarkernode.cxx b/svgio/source/svgreader/svgmarkernode.cxx index 083471b49c6b..2279920634a6 100644 --- a/svgio/source/svgreader/svgmarkernode.cxx +++ b/svgio/source/svgreader/svgmarkernode.cxx @@ -174,7 +174,7 @@ namespace svgio::svgreader const drawinglayer::primitive2d::Primitive2DContainer& SvgMarkerNode::getMarkerPrimitives() const { - if(aPrimitives.empty() && Display::None != getDisplay()) + if(Display::None != getDisplay()) { decomposeSvgNode(const_cast< SvgMarkerNode* >(this)->aPrimitives, true); } diff --git a/svgio/source/svgreader/svgstyleattributes.cxx b/svgio/source/svgreader/svgstyleattributes.cxx index 50f72199e40b..81ef74d62f63 100644 --- a/svgio/source/svgreader/svgstyleattributes.cxx +++ b/svgio/source/svgreader/svgstyleattributes.cxx @@ -817,6 +817,11 @@ namespace svgio::svgreader rMarkerTransform.identity(); rClipRange.reset(); + // 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 + const_cast<SvgStyleAttributes*>(rMarker.getSvgStyleAttributes())->maContextStroke = getStroke(); + // get marker primitive representation rMarkerPrimitives = rMarker.getMarkerPrimitives(); @@ -1287,8 +1292,9 @@ namespace svgio::svgreader maBaselineShift(BaselineShift::Baseline), maBaselineShiftNumber(0), maDominantBaseline(DominantBaseline::Auto), - maResolvingParent(32, 0), - mbStrokeDasharraySet(false) + maResolvingParent(33, 0), + mbStrokeDasharraySet(false), + mbContextStroke(false) { } @@ -1353,7 +1359,11 @@ namespace svgio::svgreader OUString aURL; SvgNumber aOpacity; - if(readSvgPaint(aContent, aSvgPaint, aURL, aOpacity)) + if(o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent), u"context-stroke")) + { + mbContextStroke = true; + } + else if(readSvgPaint(aContent, aSvgPaint, aURL, aOpacity)) { maStroke = aSvgPaint; if(aOpacity.isSet()) @@ -1996,6 +2006,23 @@ namespace svgio::svgreader } } + const basegfx::BColor* SvgStyleAttributes::getContextStroke() const + { + if (SVGToken::Marker == mrOwner.getType()) + return maContextStroke; + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + if (pSvgStyleAttributes && maResolvingParent[32] < nStyleDepthLimit) + { + ++maResolvingParent[32]; + auto ret = pSvgStyleAttributes->getContextStroke(); + --maResolvingParent[32]; + return ret; + } + + return nullptr; + } + bool SvgStyleAttributes::isClipPathContent() const { if (SVGToken::ClipPathNode == mrOwner.getType()) @@ -2109,6 +2136,10 @@ namespace svgio::svgreader return &maStroke.getBColor(); } } + else if (mbContextStroke) + { + return getContextStroke(); + } else if (maNodeStrokeURL.isEmpty()) { const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();