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();

Reply via email to