filter/qa/unit/svg.cxx          |   39 +++++++++++++++++++++++++++++++++++++++
 filter/source/svg/svgwriter.cxx |    6 ++++++
 2 files changed, 45 insertions(+)

New commits:
commit cd04f3973c33e081fb0feb176e7c5e4f11759d77
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Oct 6 15:27:24 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri Oct 7 16:31:00 2022 +0200

    SVG export: don't loose tab portions
    
    Impress slides are exported to SVG via a metafile. In case shape text
    has a string like "A\tB", that was exported as "AB", loosing the tab
    character.
    
    The relevant shape is exported as a metafile, with two text array
    metafile actions (one for "A", one for "B") and the tab needs no
    explicit action as both "A" and "B" has an explicit position. The SVG
    contained no explicit position for "B", so the tab was lost visually.
    
    Fix the problem by detecting when the doc model has a "\t" without a
    matching metafile action and emitting the explicit position in that
    case.
    
    An alternative would be to use implWriteTextPortion() to write a <tspan>
    for the tab, but that doesn't guarantee that the width of the tab in the
    SVG is the same as in Impress.
    
    (cherry picked from commit e7ca10a35fd665722c67eea85e15f71c11c66248)
    
    Change-Id: Ie21bffce9d09194159e460fb28ab23fbefd52102
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141026
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Marco Cecchetti <marco.cecche...@collabora.com>

diff --git a/filter/qa/unit/svg.cxx b/filter/qa/unit/svg.cxx
index a93d92c7d1ea..8bf13756f35c 100644
--- a/filter/qa/unit/svg.cxx
+++ b/filter/qa/unit/svg.cxx
@@ -18,6 +18,10 @@
 #include <com/sun/star/frame/Desktop.hpp>
 #include <com/sun/star/frame/XStorable.hpp>
 #include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+
 #include <unotools/streamwrap.hxx>
 #include <unotools/mediadescriptor.hxx>
 #include <tools/stream.hxx>
@@ -251,6 +255,41 @@ CPPUNIT_TEST_FIXTURE(SvgFilterTest, attributeRedefinedTest)
     assertXPath(pXmlDoc, xPath + "[4]", "id", "id7");
 }
 
+CPPUNIT_TEST_FIXTURE(SvgFilterTest, testTab)
+{
+    // Given a shape with "A\tB" text:
+    getComponent() = loadFromDesktop("private:factory/simpress",
+                                     
"com.sun.star.presentation.PresentationDocument");
+    uno::Reference<lang::XMultiServiceFactory> xFactory(getComponent(), 
uno::UNO_QUERY);
+    uno::Reference<drawing::XShape> xShape(
+        xFactory->createInstance("com.sun.star.drawing.TextShape"), 
uno::UNO_QUERY);
+    uno::Reference<drawing::XDrawPagesSupplier> 
xDrawPagesSupplier(getComponent(), uno::UNO_QUERY);
+    uno::Reference<drawing::XShapes> 
xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0),
+                                               uno::UNO_QUERY);
+    xDrawPage->add(xShape);
+    xShape->setSize(awt::Size(10000, 10000));
+    uno::Reference<text::XTextRange> xShapeText(xShape, uno::UNO_QUERY);
+    xShapeText->setString("A\tB");
+
+    // When exporting that document to SVG:
+    uno::Reference<frame::XStorable> xStorable(getComponent(), 
uno::UNO_QUERY_THROW);
+    SvMemoryStream aStream;
+    uno::Reference<io::XOutputStream> xOut = new 
utl::OOutputStreamWrapper(aStream);
+    utl::MediaDescriptor aMediaDescriptor;
+    aMediaDescriptor["FilterName"] <<= OUString("impress_svg_Export");
+    aMediaDescriptor["OutputStream"] <<= xOut;
+    xStorable->storeToURL("private:stream", 
aMediaDescriptor.getAsConstPropertyValueList());
+
+    // Then make sure the the tab is not lost:
+    aStream.Seek(STREAM_SEEK_TO_BEGIN);
+    xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 2
+    // - Actual  : 1
+    // i.e. the 2nd text portion was not positioned, which looked as if the 
tab is lost.
+    assertXPath(pXmlDoc, 
"//svg:g[@class='TextShape']//svg:tspan[@class='TextPosition']", 2);
+}
+
 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 4ad2d95b4085..e43ff6fce264 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -1628,6 +1628,12 @@ void SVGTextWriter::writeTextPortion( const Point& rPos,
                 continue;
             if( sContent == "\n" )
                 mbLineBreak = true;
+            else if (sContent == "\t")
+            {
+                // Need to emit position for the next text portion after a 
tab, otherwise the tab
+                // would appear as if it has 0 width.
+                mbPositioningNeeded = true;
+            }
             if( sContent.match( rText, nStartPos ) )
                 bNotSync = false;
         }

Reply via email to