filter/qa/unit/data/attributeRedefinedTest.odp |binary
 filter/qa/unit/svg.cxx                         |   42 +++++++++++++++++++++++++
 filter/source/svg/svgwriter.cxx                |   14 +++++++-
 3 files changed, 55 insertions(+), 1 deletion(-)

New commits:
commit e3a0ef15eb7abccff6b55940dbd9b3278004388a
Author:     Rash419 <rashesh.pa...@collabora.com>
AuthorDate: Mon Jan 24 15:56:15 2022 +0530
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Tue Jan 25 09:24:33 2022 +0100

    svgexport: fix: attribute id redefined
    
    If there is a id for empty paragraph exist we need to create a empty
    text paragraph to accomodate the id if we don't do that then we
    get multiple id attribute on same element for example:
    <tspan id="id14" id="id15" id="id17" class="TextParagraph">
    
    Change-Id: I41c21dc94deef93e423aaff2248f6931fa6ca8de
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128884
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Andras Timar <andras.ti...@collabora.com>

diff --git a/filter/qa/unit/data/attributeRedefinedTest.odp 
b/filter/qa/unit/data/attributeRedefinedTest.odp
new file mode 100644
index 000000000000..dfb814bfb9ec
Binary files /dev/null and b/filter/qa/unit/data/attributeRedefinedTest.odp 
differ
diff --git a/filter/qa/unit/svg.cxx b/filter/qa/unit/svg.cxx
index c59d3cf63dca..95f894ed42cd 100644
--- a/filter/qa/unit/svg.cxx
+++ b/filter/qa/unit/svg.cxx
@@ -138,6 +138,48 @@ CPPUNIT_TEST_FIXTURE(SvgFilterTest, testShapeNographic)
     xStorable->storeToURL("private:stream", 
aMediaDescriptor.getAsConstPropertyValueList());
 }
 
+CPPUNIT_TEST_FIXTURE(SvgFilterTest, attributeRedefinedTest)
+{
+    // Load document containing empty paragraphs with ids.
+    load("attributeRedefinedTest.odp");
+
+    // Export 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());
+    aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+    xmlDocPtr pXmlDoc = parseXmlStream(&aStream);
+
+    // We expect four paragraph
+    // 2 empty paragraphs with ids
+    // 2 paragraphs with text
+    // Without the accompanying fix the test would have failed with
+    // Expected : 4
+    // Actual : 2
+    // i.e. 2 of the empty paragraph do not get generated even if there
+    // is id imported for the paragraphs
+    // If we don't create the empty paragraphs the id attribute attribute gets 
redefined like this:
+    // <tspan id="id14" id="id15" id="id17" class="TextParagraph" 
font-family="Bahnschrift Light" font-size="1129px" font-weight="400">
+
+    OString xPath = 
"//svg:g[@class='TextShape']//svg:text[@class='SVGTextShape']//"
+                    "svg:tspan[@class='TextParagraph']";
+    assertXPath(pXmlDoc, xPath, 4);
+
+    //assert that each tspan element with TextParagraph class has id and the 
tspan element of
+    //each empty paragraph doesnot contain tspan element with class 
TextPosition
+    assertXPath(pXmlDoc, xPath + "[1]", "id", "id4");
+    assertXPath(pXmlDoc, xPath + "[2]", "id", "id5");
+    assertXPath(pXmlDoc, xPath + "[2]//svg:tspan[@class='TextPosition']", 0);
+    assertXPath(pXmlDoc, xPath + "[3]", "id", "id6");
+    assertXPath(pXmlDoc, xPath + "[3]//svg:tspan[@class='TextPosition']", 0);
+    assertXPath(pXmlDoc, xPath + "[4]", "id", "id7");
+}
+
 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 95980ce9b932..694cc073a81c 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -1077,7 +1077,19 @@ bool SVGTextWriter::nextParagraph()
         const OUString& rParagraphId = implGetValidIDFromInterface( 
Reference<XInterface>(xTextContent, UNO_QUERY) );
         if( !rParagraphId.isEmpty() )
         {
-            mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", rParagraphId );
+            // if there is id for empty paragraph we need to create a empty 
text paragraph
+            Reference < XTextRange > xRange( xTextContent, UNO_QUERY_THROW );
+            if ( xRange.is() && xRange->getString().isEmpty() )
+            {
+                endTextParagraph();
+                mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", 
"TextParagraph" );
+                mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", rParagraphId 
);
+                mpTextParagraphElem.reset(new SvXMLElementExport( mrExport, 
XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS ));
+            }
+            else
+            {
+                mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", rParagraphId 
);
+            }
         }
         return true;
     }

Reply via email to