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 be982751a2d365ef6de3dcb03afc32abda8f9b30
Author:     Rash419 <rashesh.pa...@collabora.com>
AuthorDate: Mon Jan 24 15:56:15 2022 +0530
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Mon Jan 24 20:40:20 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/+/128856
    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 8f03e7120d75..31c8076637a8 100644
--- a/filter/qa/unit/svg.cxx
+++ b/filter/qa/unit/svg.cxx
@@ -206,6 +206,48 @@ CPPUNIT_TEST_FIXTURE(SvgFilterTest, testCustomBullet)
     CPPUNIT_ASSERT(!getXPath(pXmlDoc, 
"//svg:g[@class='BulletChars']//svg:path", "d").isEmpty());
 }
 
+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);
+
+    xmlDocUniquePtr 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 866594439abc..f5c96878d4f4 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -1106,7 +1106,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