svgio/source/svgreader/svgsymbolnode.cxx |   96 +++++++++++++++++++++++--------
 1 file changed, 72 insertions(+), 24 deletions(-)

New commits:
commit b0323cf3a358a56a425c2d735ebc7b602b7c83f4
Author:     Armin Le Grand (Collabora) <armin.le.gr...@me.com>
AuthorDate: Mon Jan 6 13:57:39 2025 +0100
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Wed Jan 8 09:29:44 2025 +0100

    tdf#164434 Correct SvgSymbolNode SVG import
    
    The embedding cannot rely on SVG providing all
    values of x/y/w/h, so added fallbacks to real
    geometric size. Also removed double-adding
    geometry.
    
    Change-Id: I1914ed0c3e1e42ba899db4f3eb9193fd29e9c4be
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/179831
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <armin.le.gr...@me.com>
    (cherry picked from commit 6700b311310a94e0de8123b307275cd553bb0d9b)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/179920
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/svgio/source/svgreader/svgsymbolnode.cxx 
b/svgio/source/svgreader/svgsymbolnode.cxx
index f2d25c330316..0853e7d566f7 100644
--- a/svgio/source/svgreader/svgsymbolnode.cxx
+++ b/svgio/source/svgreader/svgsymbolnode.cxx
@@ -127,35 +127,83 @@ namespace svgio::svgreader
         void 
SvgSymbolNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DContainer&
 rTarget, bool bReferenced) const
         {
             // decompose children
-            SvgNode::decomposeSvgNode(rTarget, bReferenced);
+            drawinglayer::primitive2d::Primitive2DContainer aContent;
+            SvgNode::decomposeSvgNode(aContent, bReferenced);
 
-            if (rTarget.empty())
+            // no geometry provided, done
+            if (aContent.empty())
                 return;
 
-            if(getViewBox())
+            // if no ViewBox append aContent without embedding
+            if(nullptr == getViewBox())
             {
-                // create mapping
-                const SvgAspectRatio& rRatio = getSvgAspectRatio();
-
-                const double fX(maX.solve(*this, NumberType::xcoordinate));
-                const double fY(maY.solve(*this, NumberType::ycoordinate));
-                const double fWidth(maWidth.solve(*this, 
NumberType::xcoordinate));
-                const double fHeight(maHeight.solve(*this, 
NumberType::ycoordinate));
-                const basegfx::B2DRange aRange(fX, fY, fX + fWidth, fY + 
fHeight);
-
-                // let mapping be created from SvgAspectRatio
-                const basegfx::B2DHomMatrix aEmbeddingTransform(
-                    rRatio.createMapping(aRange, *getViewBox()));
-
-                // prepare embedding in transformation
-                // create embedding group element with transformation
-                const drawinglayer::primitive2d::Primitive2DReference xRef(
-                    new drawinglayer::primitive2d::TransformPrimitive2D(
-                        aEmbeddingTransform,
-                        
drawinglayer::primitive2d::Primitive2DContainer(rTarget)));
-
-                rTarget.push_back(xRef);
+                rTarget.append(aContent);
+                return;
+            }
+
+            // prepare range of imported geometry
+            // tdf#164434 CAUTION: There *are* svg files which do not define
+            // all needed data, e.g. x/y/w/h might be missing in any 
combination.
+            // As fallback, use size of imported geometry. Do this separate for
+            // position and size to do the best if only one value pair is 
provided
+            basegfx::B2DRange aImportedRange;
+            basegfx::B2DPoint aPosition;
+            basegfx::B2DVector aSize;
+
+            // evaluate position
+            if (maX.isSet() && maY.isSet())
+            {
+                // use values from imported svg if both provided
+                aPosition = basegfx::B2DPoint(
+                    maX.solve(*this, NumberType::xcoordinate),
+                    maY.solve(*this, NumberType::ycoordinate));
+            }
+            else
+            {
+                // fallback to imported geometry
+                drawinglayer::geometry::ViewInformation2D aViewInfo;
+                aImportedRange = aContent.getB2DRange(aViewInfo);
+                aPosition = aImportedRange.getMinimum();
             }
+
+            // evaluate size
+            if (maWidth.isSet() && maHeight.isSet())
+            {
+                // use values from imported svg if both provided
+                aSize = basegfx::B2DVector(
+                    maWidth.solve(*this, NumberType::xcoordinate),
+                    maHeight.solve(*this, NumberType::ycoordinate));
+            }
+            else
+            {
+                // fallback to imported geometry
+                if (aImportedRange.isEmpty())
+                {
+                    drawinglayer::geometry::ViewInformation2D aViewInfo;
+                    aImportedRange = aContent.getB2DRange(aViewInfo);
+                }
+
+                aSize = aImportedRange.getRange();
+            }
+
+            // tdf#164434 no size, no geometry, done
+            if (0.0 == aSize.getX() || 0.0 == aSize.getY())
+                return;
+
+            // create mapping using SvgAspectRatio
+            const SvgAspectRatio& rRatio = getSvgAspectRatio();
+            const basegfx::B2DHomMatrix aEmbeddingTransform(
+                rRatio.createMapping(basegfx::B2DRange(aPosition, aPosition + 
aSize), *getViewBox()));
+
+            // prepare embedding in transformation
+            // create embedding group element with transformation
+            const drawinglayer::primitive2d::Primitive2DReference xRef(
+                new drawinglayer::primitive2d::TransformPrimitive2D(
+                    aEmbeddingTransform,
+                    
drawinglayer::primitive2d::Primitive2DContainer(aContent)));
+
+            // add embedded geometry to result
+            rTarget.push_back(xRef);
         }
 
 } // end of namespace svgio::svgreader

Reply via email to