filter/qa/unit/data/YAxis.odg   |binary
 filter/qa/unit/svg.cxx          |   28 ++++++++++++++++++++++++++++
 filter/source/svg/svgwriter.cxx |   36 ++++++++++++++++++++++++++++++++++--
 3 files changed, 62 insertions(+), 2 deletions(-)

New commits:
commit 623eb17d6b699a280e6d096fb1be4d543cf9f064
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Thu Sep 12 13:06:53 2024 +0100
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Thu Sep 12 20:32:05 2024 +0200

    tdf#155488 svg export "peek-ahead" didn't see MapMode changes
    
    normal 'playback' case is ok, but during the peek-ahead to get text 
positions
    then the MapMode was skipped over so the rotate values were created with
    the wrong MapMode.
    
    Change-Id: I2b51dbc1b15e8d0d24b00b2bd4decb4c71772208
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173260
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/filter/qa/unit/data/YAxis.odg b/filter/qa/unit/data/YAxis.odg
new file mode 100644
index 000000000000..1d01ec508b65
Binary files /dev/null and b/filter/qa/unit/data/YAxis.odg differ
diff --git a/filter/qa/unit/svg.cxx b/filter/qa/unit/svg.cxx
index a7b055c8dbe8..63b914eb9b7b 100644
--- a/filter/qa/unit/svg.cxx
+++ b/filter/qa/unit/svg.cxx
@@ -341,6 +341,34 @@ CPPUNIT_TEST_FIXTURE(SvgFilterTest, 
testSemiTransparentTextBullet)
         0);
 }
 
+CPPUNIT_TEST_FIXTURE(SvgFilterTest, testMapModeText)
+{
+    loadFromFile(u"YAxis.odg");
+
+    // Export to SVG.
+    save(u"draw_svg_Export"_ustr);
+
+    xmlDocUniquePtr pXmlDoc = parseExportedFile();
+
+    OUString sTransform
+        = getXPath(pXmlDoc, 
"(//svg:text[@class='SVGTextShape'])[last()]"_ostr, "transform"_ostr);
+
+    OUString aTextPositionX
+        = getXPath(pXmlDoc, 
"(//svg:tspan[@class='TextPosition'])[last()]"_ostr, "x"_ostr);
+    OUString aTextPositionY
+        = getXPath(pXmlDoc, 
"(//svg:tspan[@class='TextPosition'])[last()]"_ostr, "y"_ostr);
+
+    OUString sExpectedTransform("rotate(-90 " + aTextPositionX + " " + 
aTextPositionY + ")");
+
+    // We expect the rotate point of the rotated text to match the start 
position of the text
+    CPPUNIT_ASSERT_EQUAL(sExpectedTransform, sTransform);
+    // Without the accompanying fix, this test would have failed with:
+    // - Expected: rotate(-90 3386 14754)
+    // - Actual  : rotate(-90 -1651 14488)
+    // Because the (local) MapMode wasn't taken into account for the text 
position when peeking
+    // ahead to get the rotation.
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index 92825412250a..c3aa21599512 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -601,6 +601,11 @@ sal_Int32 SVGTextWriter::setTextPosition(const 
GDIMetaFile& rMtf, size_t& nCurAc
     bool bConfigured = false;
     bool bEmpty = true;
 
+    // similar to OutputDevice::Push, but we may conditionally not restore 
these
+    MapMode aOrigMapMode = mpVDev->GetMapMode();
+    bool bOrigMapMapModeEnabled = mpVDev->IsMapModeEnabled();
+    int nPopsNeeded = 0;
+
     size_t nActionIndex = nCurAction + 1;
     for( ; nActionIndex < nCount; ++nActionIndex )
     {
@@ -717,6 +722,23 @@ sal_Int32 SVGTextWriter::setTextPosition(const 
GDIMetaFile& rMtf, size_t& nCurAc
                 }
             }
             break;
+
+            case MetaActionType::PUSH:
+                const_cast<MetaAction*>(pAction)->Execute(mpVDev);
+                ++nPopsNeeded;
+                break;
+            case MetaActionType::POP:
+                const_cast<MetaAction*>(pAction)->Execute(mpVDev);
+                --nPopsNeeded;
+                break;
+            case MetaActionType::MAPMODE:
+            {
+                // keep MapMode up to date
+                const_cast<MetaAction*>(pAction)->Execute(mpVDev);
+                break;
+            }
+            break;
+
             default: break;
         }
         if( bConfigured || bEOL || bEOP || bETS ) break;
@@ -725,13 +747,23 @@ sal_Int32 SVGTextWriter::setTextPosition(const 
GDIMetaFile& rMtf, size_t& nCurAc
 
     if( bEmpty )
     {
+        // If we fast-forward to this nActionIndex, then leave
+        // the OutputDevice state as it is.
         nCurAction = nActionIndex;
         return ( bEOL ? -2 : ( bEOP ? -1 : 0 ) );
     }
-    else
+
+    // If we are leaving nCurAction untouched, then restore the OutputDevice
+    // to its original state
+    while (nPopsNeeded > 0)
     {
-        return 1;
+        mpVDev->Pop();
+        --nPopsNeeded;
     }
+
+    mpVDev->SetMapMode(aOrigMapMode);
+    mpVDev->EnableMapMode(bOrigMapMapModeEnabled);
+    return 1;
 }
 
 

Reply via email to