tdf#144092 pptx export: export endParaRPr for empty shape & cells

Alters ShapeExport::WriteTextBox so that when it is called with an empty
text (on PPTX export) an attempt to export empty text's char properties
(stored in the Shape or Cell's properties directly) made on
ShapeExport::WriteText.

These properties are exported into endParaRPr.

Implementing this caused some tests that contain connector shapes fail
with XML schema validation errors, therefore disabled export of txBody
inside cxnSp tags.

Also adds a unit test that checks roundtrip of empty shape or cell's
endParaRPr.

Change-Id: I3e3feda802f42560fa7fecc9c0b1afe73a900a84
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138960
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 2a536b8..51ac5f6 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -3781,6 +3781,24 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo
    sal_Int32 nCharHeight = -1;
    bool bFirstParagraph = true;

    // tdf#144092 For shapes without text: Export run properties (into
    // endParaRPr) from the shape's propset instead of the paragraph's.
    if(xXText->getString().isEmpty() && enumeration->hasMoreElements())
    {
        Any aAny (enumeration->nextElement());
        Reference<XTextContent> xParagraph;
        if( aAny >>= xParagraph )
        {
            mpFS->startElementNS(XML_a, XML_p);
            WriteParagraphProperties(xParagraph, nCharHeight, XML_pPr);
            sal_Int16 nDummy = -1;
            WriteRunProperties(rXPropSet, false, XML_endParaRPr, false,
                               bOverridingCharHeight, nCharHeight, nDummy, rXPropSet);
            mpFS->endElementNS(XML_a, XML_p);
        }
        return;
    }

    while( enumeration->hasMoreElements() )
    {
        Reference< XTextContent > paragraph;
diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx
index 79258d7..90e4ad8 100644
--- a/oox/source/export/shapes.cxx
+++ b/oox/source/export/shapes.cxx
@@ -1797,8 +1797,12 @@ ShapeExport& ShapeExport::WriteConnectorShape( const Reference< XShape >& xShape
        WriteOutline( xShapeProps );
    pFS->endElementNS( mnXmlNamespace, XML_spPr );

    // write text
    WriteTextBox( xShape, mnXmlNamespace );
    // connector shape (cxnSp) cannot contain text (txBody) (according to schema)
    if( nShapeNode != XML_cxnSp )
    {
        // write text
        WriteTextBox( xShape, mnXmlNamespace );
    }

    pFS->endElementNS(mnXmlNamespace, nShapeNode);

@@ -2025,7 +2029,8 @@ ShapeExport& ShapeExport::WriteTextBox( const Reference< XInterface >& xIface, s
    }

    Reference< XText > xXText( xIface, UNO_QUERY );
    if( NonEmptyText( xIface ) && xXText.is() )
    if( (NonEmptyText( xIface ) || GetDocumentType() == DOCUMENT_PPTX)
        && xXText.is() )
    {
        FSHelperPtr pFS = GetFS();

diff --git a/sd/qa/unit/data/pptx/tdf144092-emptyShapeTextProps.pptx b/sd/qa/unit/data/pptx/tdf144092-emptyShapeTextProps.pptx
new file mode 100644
index 0000000..5d75c87d
--- /dev/null
+++ b/sd/qa/unit/data/pptx/tdf144092-emptyShapeTextProps.pptx
Binary files differ
diff --git a/sd/qa/unit/data/xml/tdf90338_0.xml b/sd/qa/unit/data/xml/tdf90338_0.xml
index 8bff660..741d6ca 100644
--- a/sd/qa/unit/data/xml/tdf90338_0.xml
+++ b/sd/qa/unit/data/xml/tdf90338_0.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<XShapes>
 <XShape positionX="5498" positionY="2715" sizeX="11630" sizeY="8623" type="com.sun.star.drawing.CustomShape" name="Freeform 3" fontHeight="18.000000" fontColor="ffffffff" textAutoGrowHeight="false" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="BLOCK" textVerticalAdjust="TOP" textLeftDistance="250" textRightDistance="250" textUpperDistance="125" textLowerDistance="125" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="e7e6e6" fillTransparence="0" fillTransparenceGradientName="">
 <XShape positionX="5498" positionY="2715" sizeX="11630" sizeY="8623" type="com.sun.star.drawing.CustomShape" name="Freeform 3" fontHeight="11.000000" fontColor="000000" textAutoGrowHeight="false" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="BLOCK" textVerticalAdjust="CENTER" textLeftDistance="250" textRightDistance="250" textUpperDistance="125" textLowerDistance="125" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="e7e6e6" fillTransparence="0" fillTransparenceGradientName="">
  <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
  <FillGradient style="LINEAR" startColor="3465a4" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
  <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
diff --git a/sd/qa/unit/data/xml/tdf92001_0.xml b/sd/qa/unit/data/xml/tdf92001_0.xml
index 08d9622..d67952e 100644
--- a/sd/qa/unit/data/xml/tdf92001_0.xml
+++ b/sd/qa/unit/data/xml/tdf92001_0.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<XShapes>
 <XShape positionX="4826" positionY="4826" sizeX="19557" sizeY="12953" type="com.sun.star.drawing.CustomShape" fontHeight="18.000000" fontColor="ffffffff" textAutoGrowHeight="false" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="BLOCK" textVerticalAdjust="TOP" textLeftDistance="250" textRightDistance="250" textUpperDistance="125" textLowerDistance="125" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
 <XShape positionX="4826" positionY="4826" sizeX="19557" sizeY="12953" type="com.sun.star.drawing.CustomShape" fontHeight="18.000000" fontColor="000000" textAutoGrowHeight="false" textAutoGrowWidth="false" textContourFrame="false" textFitToSize="NONE" textHorizontalAdjust="BLOCK" textVerticalAdjust="CENTER" textLeftDistance="325" textRightDistance="325" textUpperDistance="200" textLowerDistance="200" textMaximumFrameHeight="0" textMaximumFrameWidth="0" textMinimumFrameHeight="0" textMinimumFrameWidth="0" textAnimationAmount="0" textAnimationCount="0" textAnimationDelay="0" textAnimationDirection="LEFT" textAnimationKind="NONE" textAnimationStartInside="false" textAnimationStopInside="false" textWritingMode="LR_TB" fillStyle="SOLID" fillColor="729fcf" fillTransparence="0" fillTransparenceGradientName="">
  <FillTransparenceGradient style="LINEAR" startColor="000000" endColor="000000" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
  <FillGradient style="LINEAR" startColor="3465a4" endColor="ffffff" angle="0" border="0" xOffset="50" yOffset="50" startIntensity="100" endIntensity="100" stepCount="0"/>
  <FillHatch style="SINGLE" color="3465a4" distance="20" angle="0"/>
diff --git a/sd/qa/unit/export-tests-ooxml3.cxx b/sd/qa/unit/export-tests-ooxml3.cxx
index d20c56d..6d30263 100644
--- a/sd/qa/unit/export-tests-ooxml3.cxx
+++ b/sd/qa/unit/export-tests-ooxml3.cxx
@@ -20,6 +20,7 @@
#include <svx/xlineit0.hxx>
#include <svx/xlndsit.hxx>
#include <svx/svdoole2.hxx>
#include <svx/svdotable.hxx>

#include <com/sun/star/awt/FontUnderline.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
@@ -116,6 +117,7 @@ public:
    void testTdf74670();
    void testTdf109169_OctagonBevel();
    void testTdf109169_DiamondBevel();
    void testTdf144092_emptyShapeTextProps();

    CPPUNIT_TEST_SUITE(SdOOXMLExportTest3);

@@ -199,6 +201,7 @@ public:
    CPPUNIT_TEST(testTdf74670);
    CPPUNIT_TEST(testTdf109169_OctagonBevel);
    CPPUNIT_TEST(testTdf109169_DiamondBevel);
    CPPUNIT_TEST(testTdf144092_emptyShapeTextProps);
    CPPUNIT_TEST_SUITE_END();

    virtual void registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) override
@@ -2095,6 +2098,43 @@ void SdOOXMLExportTest3::testTdf109169_DiamondBevel()
    CPPUNIT_ASSERT_EQUAL(sal_Int32(20), aCoordinates.getLength());
}

void SdOOXMLExportTest3::testTdf144092_emptyShapeTextProps()
{
    // Document contains one shape and one table. Both without any text but with
    // text properties contained inside endParaRPr - The import and export
    // of endParaRPr for empty cells and shapes are tested here
    ::sd::DrawDocShellRef xDocShRef = loadURL(
        m_directories.getURLFromSrc(u"sd/qa/unit/data/pptx/tdf144092-emptyShapeTextProps.pptx"),
        PPTX);
    xDocShRef = saveAndReload(xDocShRef.get(), PPTX);

    Color aColor;
    // check text properties of empty shape
    uno::Reference<beans::XPropertySet> xRectShapeProps(getShapeFromPage(1, 0, xDocShRef));
    CPPUNIT_ASSERT_EQUAL(OUString("Calibri"),
                         xRectShapeProps->getPropertyValue("CharFontName").get<OUString>());
    CPPUNIT_ASSERT_EQUAL(float(196), xRectShapeProps->getPropertyValue("CharHeight").get<float>());
    xRectShapeProps->getPropertyValue("CharColor") >>= aColor;
    CPPUNIT_ASSERT_EQUAL(Color(0x70AD47), aColor);

    const SdrPage* pPage = GetPage(1, xDocShRef);
    sdr::table::SdrTableObj* pTableObj = dynamic_cast<sdr::table::SdrTableObj*>(pPage->GetObj(0));
    CPPUNIT_ASSERT(pTableObj);
    uno::Reference<table::XCellRange> xTable(pTableObj->getTable(), uno::UNO_QUERY_THROW);
    uno::Reference<beans::XPropertySet> xCell;

    // check text properties of empty cells
    xCell.set(xTable->getCellByPosition(0, 0), uno::UNO_QUERY_THROW);
    xCell->getPropertyValue("CharColor") >>= aColor;
    CPPUNIT_ASSERT_EQUAL(Color(0xFFFFFF), aColor);

    xCell.set(xTable->getCellByPosition(0, 1), uno::UNO_QUERY_THROW);
    xCell->getPropertyValue("CharColor") >>= aColor;
    CPPUNIT_ASSERT_EQUAL(Color(0x70AD47), aColor);
    CPPUNIT_ASSERT_EQUAL(float(96), xCell->getPropertyValue("CharHeight").get<float>());
    xDocShRef->DoClose();
}

CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest3);

CPPUNIT_PLUGIN_IMPLEMENT();