svgio/inc/SvgNumber.hxx                       |    8 ++--
 svgio/inc/svgnode.hxx                         |    7 +--
 svgio/inc/svgtspannode.hxx                    |    2 -
 svgio/qa/cppunit/SvgImportTest.cxx            |   52 ++++++++++++++++++++++++++
 svgio/qa/cppunit/SvgNumberTest.cxx            |    4 +-
 svgio/qa/cppunit/data/dy_in_ems.svg           |    7 +++
 svgio/qa/cppunit/data/dy_in_exs.svg           |    7 +++
 svgio/source/svgreader/SvgNumber.cxx          |    5 +-
 svgio/source/svgreader/svgnode.cxx            |   36 +++---------------
 svgio/source/svgreader/svgstyleattributes.cxx |    8 ++--
 svgio/source/svgreader/svgtspannode.cxx       |    5 --
 11 files changed, 88 insertions(+), 53 deletions(-)

New commits:
commit c10fba9c937e4a52bfd1ed13aa813d4faee833fe
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Apr 9 16:04:40 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Apr 22 08:15:12 2024 +0500

    tdf#160717: fix ex handling
    
    Same as in commit e27572686130df43d1d65c574b0c34f39fc0d1a9
    (tdf#160593: make sure to use current element's font size for em unit,
    2024-04-18) for em.
    
    Change-Id: Id9003c0426a6b373456da1aa1550f7ff07f766a3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166235
    Tested-by: Mike Kaganski <mike.kagan...@collabora.com>
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/svgio/inc/SvgNumber.hxx b/svgio/inc/SvgNumber.hxx
index fe4ab8e2683e..c62576c2b082 100644
--- a/svgio/inc/SvgNumber.hxx
+++ b/svgio/inc/SvgNumber.hxx
@@ -39,8 +39,8 @@ public:
     virtual basegfx::B2DRange getCurrentViewPort() const = 0;
     /// return font size of node, either set here or inherited from parents
     virtual double getCurrentFontSize() const = 0;
-    /// return xheight of node inherited from parents
-    virtual double getCurrentXHeightInherited() const = 0;
+    /// return xheight of node, either set here or inherited from parents
+    virtual double getCurrentXHeight() const = 0;
 };
 
 enum class SvgUnit
diff --git a/svgio/inc/svgnode.hxx b/svgio/inc/svgnode.hxx
index 5d3a2453d727..d24cdecf3729 100644
--- a/svgio/inc/svgnode.hxx
+++ b/svgio/inc/svgnode.hxx
@@ -157,9 +157,7 @@ namespace svgio::svgreader
             /// InfoProvider support for %, em and ex values
             virtual basegfx::B2DRange getCurrentViewPort() const override;
             virtual double getCurrentFontSize() const override;
-            virtual double getCurrentXHeightInherited() const override;
-
-            double getCurrentXHeight() const;
+            virtual double getCurrentXHeight() const override;
 
             /// Id access
             std::optional<OUString> const & getId() const { return mpId; }
diff --git a/svgio/qa/cppunit/SvgImportTest.cxx 
b/svgio/qa/cppunit/SvgImportTest.cxx
index 4d6f7568e2cd..d61c5c761f79 100644
--- a/svgio/qa/cppunit/SvgImportTest.cxx
+++ b/svgio/qa/cppunit/SvgImportTest.cxx
@@ -1148,7 +1148,7 @@ CPPUNIT_TEST_FIXTURE(Test, testDyInEms)
 
 CPPUNIT_TEST_FIXTURE(Test, testExs)
 {
-    // tdf#160594 given an SVG file with <tspan dy="3ex" 
style="font-size:1ex">:
+    // tdf#160594, tdf#160717 given an SVG file with <tspan dy="3ex" 
style="font-size:1ex">:
     std::u16string_view aPath = u"/svgio/qa/cppunit/data/dy_in_exs.svg";
     Primitive2DSequence aSequence = parseSvg(aPath);
     drawinglayer::Primitive2dXmlDump aDumper;
@@ -1156,6 +1156,7 @@ CPPUNIT_TEST_FIXTURE(Test, testExs)
 
     assertXPath(pDocument, "//textsimpleportion", 2);
     assertXPath(pDocument, "//textsimpleportion[1]", "height", "16");
+    assertXPath(pDocument, "//textsimpleportion[1]", "y", "20");
 
     sal_Int32 nSize = getXPath(pDocument, "//textsimpleportion[2]", 
"height").toInt32();
     // Without the accompanying fix in place, this test would have failed with:
@@ -1163,6 +1164,17 @@ CPPUNIT_TEST_FIXTURE(Test, testExs)
     // - Actual  : 16
     // i.e. the parent font-size was used, instead of its x-size.
     CPPUNIT_ASSERT_LESS(sal_Int32(16), nSize);
+
+    sal_Int32 nYPos = getXPath(pDocument, "//textsimpleportion[2]", 
"y").toInt32();
+    // Then make sure that the vertical offset is based on x-size of tspan, 
not of its parent.
+    // Given the tspan's font-size is nSize, its x-size is less than nSize, 
and the expected
+    // vertical offset is less than 3 * nSize, which means that the resulting 
y is expected
+    // to be strictly less than 20 + 3 * nSize.
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected less than: 44
+    // - Actual  : 44
+    // i.e. the parent x-size (or current font-size) was used, instead of 
current x-size.
+    CPPUNIT_ASSERT_LESS(sal_Int32(20 + 3 * nSize), nYPos);
 }
 
 }
diff --git a/svgio/qa/cppunit/SvgNumberTest.cxx 
b/svgio/qa/cppunit/SvgNumberTest.cxx
index 9b12e52bf956..49e1394bcef2 100644
--- a/svgio/qa/cppunit/SvgNumberTest.cxx
+++ b/svgio/qa/cppunit/SvgNumberTest.cxx
@@ -40,7 +40,7 @@ public:
 
     double getCurrentFontSize() const override { return 12.0; }
 
-    double getCurrentXHeightInherited() const override { return 5.0; }
+    double getCurrentXHeight() const override { return 5.0; }
 };
 
 void TestNumber::testSetting()
diff --git a/svgio/source/svgreader/SvgNumber.cxx 
b/svgio/source/svgreader/SvgNumber.cxx
index 4a48ffbfb4e9..72a44dbdd032 100644
--- a/svgio/source/svgreader/SvgNumber.cxx
+++ b/svgio/source/svgreader/SvgNumber.cxx
@@ -39,7 +39,7 @@ double SvgNumber::solveNonPercentage(const InfoProvider& 
rInfoProvider) const
         case SvgUnit::em:
             return mfNumber * rInfoProvider.getCurrentFontSize();
         case SvgUnit::ex:
-            return mfNumber * rInfoProvider.getCurrentXHeightInherited() * 0.5;
+            return mfNumber * rInfoProvider.getCurrentXHeight();
         case SvgUnit::px:
             return mfNumber;
         case SvgUnit::pt:
diff --git a/svgio/source/svgreader/svgnode.cxx 
b/svgio/source/svgreader/svgnode.cxx
index ec2e8e0589a9..5e3c37b07bb7 100644
--- a/svgio/source/svgreader/svgnode.cxx
+++ b/svgio/source/svgreader/svgnode.cxx
@@ -609,25 +609,12 @@ namespace svgio::svgreader
             return 0.0;
         }
 
-        double SvgNode::getCurrentXHeightInherited() const
-        {
-            if(getParent())
-            {
-                return getParent()->getCurrentXHeight();
-            }
-            else
-            {
-                return 0.0;
-            }
-        }
-
         double SvgNode::getCurrentXHeight() const
         {
-            if(getSvgStyleAttributes())
-                // for XHeight, use FontSize currently
-                return 
getSvgStyleAttributes()->getFontSizeNumber().solve(*this, 
NumberType::ycoordinate);
-
-            return getCurrentXHeightInherited();
+            // https://drafts.csswg.org/css-values-4/#ex
+            // for XHeight, use 0.5em fallback currently
+            // FIXME: use "x-height of the first available font"
+            return getCurrentFontSize() * 0.5;
         }
 
         void SvgNode::setId(OUString const & rId)
commit 28ff1b05047ef3a19cf692527a23cb38768c9764
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Apr 9 13:56:13 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sat Apr 20 17:35:25 2024 +0500

    tdf#160594: Use the recommended fallback of 0.5em for ex in font-size
    
    This fixes the error of identical treatment of em and ex in font-size,
    which violated https://drafts.csswg.org/css-values-4/#font-relative-length.
    The fix uses the fallback of 0.5em for ex, similar to the code used in
    SvgNumber::solveNonPercentage. A follow-up should implement the correct
    use of "x-height of the first available font".
    
    Change-Id: Id9d581994e158d629d9752299ad93ac7e9fe4cad
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166234
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/svgio/qa/cppunit/SvgImportTest.cxx 
b/svgio/qa/cppunit/SvgImportTest.cxx
index 995f705fb653..4d6f7568e2cd 100644
--- a/svgio/qa/cppunit/SvgImportTest.cxx
+++ b/svgio/qa/cppunit/SvgImportTest.cxx
@@ -1146,6 +1146,25 @@ CPPUNIT_TEST_FIXTURE(Test, testDyInEms)
     assertXPath(pDocument, "//textsimpleportion[2]", "y", "32");
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testExs)
+{
+    // tdf#160594 given an SVG file with <tspan dy="3ex" 
style="font-size:1ex">:
+    std::u16string_view aPath = u"/svgio/qa/cppunit/data/dy_in_exs.svg";
+    Primitive2DSequence aSequence = parseSvg(aPath);
+    drawinglayer::Primitive2dXmlDump aDumper;
+    xmlDocUniquePtr pDocument = 
aDumper.dumpAndParse(Primitive2DContainer(aSequence));
+
+    assertXPath(pDocument, "//textsimpleportion", 2);
+    assertXPath(pDocument, "//textsimpleportion[1]", "height", "16");
+
+    sal_Int32 nSize = getXPath(pDocument, "//textsimpleportion[2]", 
"height").toInt32();
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected less than: 16
+    // - Actual  : 16
+    // i.e. the parent font-size was used, instead of its x-size.
+    CPPUNIT_ASSERT_LESS(sal_Int32(16), nSize);
+}
+
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/svgio/qa/cppunit/data/dy_in_exs.svg 
b/svgio/qa/cppunit/data/dy_in_exs.svg
new file mode 100644
index 000000000000..816a64a4586c
--- /dev/null
+++ b/svgio/qa/cppunit/data/dy_in_exs.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+
+<svg xmlns="http://www.w3.org/2000/svg"; width="1in" height="1in" viewBox="0 0 
100% 100%">
+
+       <text x="5" y="20" style="font-size:16px;font-family:Liberation 
Sans">foo
+               <tspan x="5" dy="3ex" style="font-size:1ex">bar</tspan></text>
+</svg>
\ No newline at end of file
diff --git a/svgio/source/svgreader/svgstyleattributes.cxx 
b/svgio/source/svgreader/svgstyleattributes.cxx
index 6c42fbe744f9..0a656e2a1ad9 100644
--- a/svgio/source/svgreader/svgstyleattributes.cxx
+++ b/svgio/source/svgreader/svgstyleattributes.cxx
@@ -2562,11 +2562,11 @@ namespace svgio::svgreader
                     if(pSvgStyleAttributes)
                     {
                         const SvgNumber aParentNumber = 
pSvgStyleAttributes->getFontSizeNumber();
+                        double n = aParentNumber.getNumber() * 
maFontSizeNumber.getNumber();
+                        if (SvgUnit::ex == maFontSizeNumber.getUnit())
+                            n *= 0.5; // FIXME: use "x-height of the first 
available font"
 
-                        return SvgNumber(
-                            aParentNumber.getNumber() * 
maFontSizeNumber.getNumber(),
-                            aParentNumber.getUnit(),
-                            true);
+                        return SvgNumber(n, aParentNumber.getUnit());
                     }
                 }
 
commit fdb48ffa8341d015d127e1c99c4be3072199dc67
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Apr 9 13:03:07 2024 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sat Apr 20 16:15:29 2024 +0500

    tdf#160593: make sure to use current element's font size for em unit
    
    According to https://drafts.csswg.org/css-values-4/#font-relative-length
    em is "equal to the computed value of the font-size property of the element
    on which it is used". This means, that for an element that defines its own
    font-size, attributes like 'dy' using em refer to the new font-size, not to
    inherited font-size.
    
    Change-Id: Ie5a013df99a68edddf466e4c0ee5311f6219fcb2
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166233
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/svgio/inc/SvgNumber.hxx b/svgio/inc/SvgNumber.hxx
index 4d03335cf424..fe4ab8e2683e 100644
--- a/svgio/inc/SvgNumber.hxx
+++ b/svgio/inc/SvgNumber.hxx
@@ -37,8 +37,8 @@ class InfoProvider
 public:
     virtual ~InfoProvider() {}
     virtual basegfx::B2DRange getCurrentViewPort() const = 0;
-    /// return font size of node inherited from parents
-    virtual double getCurrentFontSizeInherited() const = 0;
+    /// return font size of node, either set here or inherited from parents
+    virtual double getCurrentFontSize() const = 0;
     /// return xheight of node inherited from parents
     virtual double getCurrentXHeightInherited() const = 0;
 };
diff --git a/svgio/inc/svgnode.hxx b/svgio/inc/svgnode.hxx
index 4bdbd3046d75..5d3a2453d727 100644
--- a/svgio/inc/svgnode.hxx
+++ b/svgio/inc/svgnode.hxx
@@ -156,10 +156,9 @@ namespace svgio::svgreader
 
             /// InfoProvider support for %, em and ex values
             virtual basegfx::B2DRange getCurrentViewPort() const override;
-            virtual double getCurrentFontSizeInherited() const override;
+            virtual double getCurrentFontSize() const override;
             virtual double getCurrentXHeightInherited() const override;
 
-            double getCurrentFontSize() const;
             double getCurrentXHeight() const;
 
             /// Id access
diff --git a/svgio/inc/svgtspannode.hxx b/svgio/inc/svgtspannode.hxx
index 10a7b7ee16a9..ff53238a3488 100644
--- a/svgio/inc/svgtspannode.hxx
+++ b/svgio/inc/svgtspannode.hxx
@@ -42,8 +42,6 @@ namespace svgio::svgreader
             virtual const SvgStyleAttributes* getSvgStyleAttributes() const 
override;
             virtual void parseAttribute(const OUString& rTokenName, SVGToken 
aSVGToken, const OUString& aContent) override;
 
-            double getCurrentFontSize() const;
-
             /// access to SvgTextPositions
             const SvgTextPositions& getSvgTextPositions() const { return 
maSvgTextPositions; }
         };
diff --git a/svgio/qa/cppunit/SvgImportTest.cxx 
b/svgio/qa/cppunit/SvgImportTest.cxx
index 67793f0db3f1..995f705fb653 100644
--- a/svgio/qa/cppunit/SvgImportTest.cxx
+++ b/svgio/qa/cppunit/SvgImportTest.cxx
@@ -1125,6 +1125,27 @@ CPPUNIT_TEST_FIXTURE(Test, testTspanFillOpacity)
     CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(70), nTransparence);
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testDyInEms)
+{
+    // tdf#160593 given an SVG file with <tspan dy="1.5em" 
style="font-size:0.5em">:
+    std::u16string_view aPath = u"/svgio/qa/cppunit/data/dy_in_ems.svg";
+    Primitive2DSequence aSequence = parseSvg(aPath);
+    drawinglayer::Primitive2dXmlDump aDumper;
+    xmlDocUniquePtr pDocument = 
aDumper.dumpAndParse(Primitive2DContainer(aSequence));
+
+    assertXPath(pDocument, "//textsimpleportion", 2);
+    assertXPath(pDocument, "//textsimpleportion[1]", "y", "20");
+    // Then make sure that the vertical offset is based on font-size of tspan, 
not of its parent.
+    // Given the parent's font-size is 16 px, the expected vertical offset is 
1.5 * (16 * 0.5) = 12,
+    // which means that the resulting y is expected to be 20 + 12 = 32.
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 32
+    // - Actual  : 44
+    // i.e. the offset was calculated as 1.5 multiplied by the parent's 
font-size of 16 px,
+    // not by the current tspan's half font-size.
+    assertXPath(pDocument, "//textsimpleportion[2]", "y", "32");
+}
+
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/svgio/qa/cppunit/SvgNumberTest.cxx 
b/svgio/qa/cppunit/SvgNumberTest.cxx
index f420a44b42fe..9b12e52bf956 100644
--- a/svgio/qa/cppunit/SvgNumberTest.cxx
+++ b/svgio/qa/cppunit/SvgNumberTest.cxx
@@ -38,7 +38,7 @@ public:
         return basegfx::B2DRange(0.0, 0.0, 0.0, 0.0);
     }
 
-    double getCurrentFontSizeInherited() const override { return 12.0; }
+    double getCurrentFontSize() const override { return 12.0; }
 
     double getCurrentXHeightInherited() const override { return 5.0; }
 };
diff --git a/svgio/qa/cppunit/data/dy_in_ems.svg 
b/svgio/qa/cppunit/data/dy_in_ems.svg
new file mode 100644
index 000000000000..316239edf778
--- /dev/null
+++ b/svgio/qa/cppunit/data/dy_in_ems.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+
+<svg xmlns="http://www.w3.org/2000/svg"; width="1in" height="1in" viewBox="0 0 
100% 100%">
+
+       <text x="5" y="20" style="font-size:16px;font-family:Liberation 
Sans">foo
+               <tspan x="5" dy="1.5em" 
style="font-size:0.5em">bar</tspan></text>
+</svg>
\ No newline at end of file
diff --git a/svgio/source/svgreader/SvgNumber.cxx 
b/svgio/source/svgreader/SvgNumber.cxx
index c1558f3e6451..4a48ffbfb4e9 100644
--- a/svgio/source/svgreader/SvgNumber.cxx
+++ b/svgio/source/svgreader/SvgNumber.cxx
@@ -35,8 +35,9 @@ double SvgNumber::solveNonPercentage(const InfoProvider& 
rInfoProvider) const
 
     switch (meUnit)
     {
+        // See https://drafts.csswg.org/css-values-4/#font-relative-length
         case SvgUnit::em:
-            return mfNumber * rInfoProvider.getCurrentFontSizeInherited();
+            return mfNumber * rInfoProvider.getCurrentFontSize();
         case SvgUnit::ex:
             return mfNumber * rInfoProvider.getCurrentXHeightInherited() * 0.5;
         case SvgUnit::px:
diff --git a/svgio/source/svgreader/svgnode.cxx 
b/svgio/source/svgreader/svgnode.cxx
index d45624d3edc6..ec2e8e0589a9 100644
--- a/svgio/source/svgreader/svgnode.cxx
+++ b/svgio/source/svgreader/svgnode.cxx
@@ -598,24 +598,15 @@ namespace svgio::svgreader
             }
         }
 
-        double SvgNode::getCurrentFontSizeInherited() const
-        {
-            if(getParent())
-            {
-                return getParent()->getCurrentFontSize();
-            }
-            else
-            {
-                return 0.0;
-            }
-        }
-
         double SvgNode::getCurrentFontSize() const
         {
             if(getSvgStyleAttributes())
                 return 
getSvgStyleAttributes()->getFontSizeNumber().solve(*this, 
NumberType::xcoordinate);
 
-            return getCurrentFontSizeInherited();
+            if(getParent())
+                return getParent()->getCurrentFontSize();
+
+            return 0.0;
         }
 
         double SvgNode::getCurrentXHeightInherited() const
diff --git a/svgio/source/svgreader/svgtspannode.cxx 
b/svgio/source/svgreader/svgtspannode.cxx
index db024e2f2ff7..5e19e88dc137 100644
--- a/svgio/source/svgreader/svgtspannode.cxx
+++ b/svgio/source/svgreader/svgtspannode.cxx
@@ -65,11 +65,6 @@ namespace svgio::svgreader
             }
         }
 
-        double SvgTspanNode::getCurrentFontSize() const
-        {
-            return getCurrentFontSizeInherited();
-        }
-
 } // end of namespace svgio::svgreader
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to