[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-5.3-desktop' - 6 commits - chart2/inc chart2/qa chart2/source include/oox offapi/com offapi/UnoApi_offapi.mk oox/inc oox/source sd/qa sd/source sw/qa sw/source writerfilter/source

Szymon Kłos szymon.klos at collabora.com
Mon Feb 12 21:59:40 UTC 2018


 chart2/inc/unonames.hxx                                      |    1 
 chart2/qa/extras/chart2export.cxx                            |  159 ++++++++++
 chart2/qa/extras/chart2import.cxx                            |  154 ++++++++++
 chart2/qa/extras/data/pptx/tdf115107-2.pptx                  |binary
 chart2/qa/extras/data/pptx/tdf115107.pptx                    |binary
 chart2/source/chartcore.component                            |    1 
 chart2/source/model/main/DataPointProperties.cxx             |   12 
 chart2/source/model/main/DataPointProperties.hxx             |    3 
 chart2/source/model/main/FormattedString.cxx                 |   44 +++
 chart2/source/model/main/FormattedString.hxx                 |   19 +
 chart2/source/view/charttypes/VSeriesPlotter.cxx             |  126 +++++++-
 chart2/source/view/inc/AbstractShapeFactory.hxx              |    7 
 chart2/source/view/inc/OpenglShapeFactory.hxx                |    7 
 chart2/source/view/inc/ShapeFactory.hxx                      |    7 
 chart2/source/view/inc/VSeriesPlotter.hxx                    |    2 
 chart2/source/view/main/OpenglShapeFactory.cxx               |   12 
 chart2/source/view/main/ShapeFactory.cxx                     |   94 ++++++
 include/oox/ppt/slidetransition.hxx                          |    4 
 include/oox/ppt/slidetransitioncontext.hxx                   |    1 
 offapi/UnoApi_offapi.mk                                      |    3 
 offapi/com/sun/star/chart2/DataPointCustomLabelField.idl     |   26 +
 offapi/com/sun/star/chart2/DataPointCustomLabelFieldType.idl |   33 ++
 offapi/com/sun/star/chart2/DataPointProperties.idl           |    8 
 offapi/com/sun/star/chart2/XDataPointCustomLabelField.idl    |   43 ++
 offapi/com/sun/star/presentation/DrawPage.idl                |    9 
 oox/inc/drawingml/textfield.hxx                              |    2 
 oox/source/drawingml/chart/seriesconverter.cxx               |  112 ++++++-
 oox/source/export/chartexport.cxx                            |  107 +++++++
 oox/source/ppt/slidetransition.cxx                           |   30 +-
 oox/source/ppt/slidetransitioncontext.cxx                    |   15 -
 oox/source/token/properties.txt                              |    2 
 sd/qa/unit/data/ppt/tdf115394.ppt                            |binary
 sd/qa/unit/data/pptx/tdf114821.pptx                          |binary
 sd/qa/unit/data/pptx/tdf115394-zero.pptx                     |binary
 sd/qa/unit/data/pptx/tdf115394.pptx                          |binary
 sd/qa/unit/export-tests-ooxml2.cxx                           |   52 +++
 sd/qa/unit/export-tests.cxx                                  |   39 ++
 sd/qa/unit/import-tests.cxx                                  |  108 +++++++
 sd/source/filter/eppt/eppt.cxx                               |   26 +
 sd/source/filter/eppt/pptx-epptooxml.cxx                     |  161 +++++++----
 sd/source/filter/ppt/pptin.cxx                               |    6 
 sd/source/ui/inc/unoprnms.hxx                                |    1 
 sd/source/ui/unoidl/unopage.cxx                              |    2 
 sw/qa/extras/ooxmlexport/data/graphic-object-fliph.docx      |binary
 sw/qa/extras/ooxmlexport/ooxmlexport9.cxx                    |    6 
 sw/source/filter/ww8/docxattributeoutput.cxx                 |   18 +
 writerfilter/source/dmapper/GraphicImport.cxx                |   11 
 47 files changed, 1375 insertions(+), 98 deletions(-)

New commits:
commit 2ef5ccadeff6fdcb427fde71b0d2796a0afde057
Author: Szymon Kłos <szymon.klos at collabora.com>
Date:   Mon Feb 12 20:39:14 2018 +0100

    tdf#114821 import/export/place complex data labels in charts
    
    Change-Id: Ia44abcebb4febcabb1704aef85e396730ac2cd6f

diff --git a/chart2/inc/unonames.hxx b/chart2/inc/unonames.hxx
index 867a155e14aa..44c3bf67d3cb 100644
--- a/chart2/inc/unonames.hxx
+++ b/chart2/inc/unonames.hxx
@@ -29,6 +29,7 @@
 #define CHART_UNONAME_LABEL_BORDER_DASH     "LabelBorderDash"
 #define CHART_UNONAME_LABEL_BORDER_DASHNAME "LabelBorderDashName"
 #define CHART_UNONAME_LABEL_BORDER_TRANS    "LabelBorderTransparency"
+#define CHART_UNONAME_CUSTOM_LABEL_FIELDS   "CustomLabelFields"
 
 #endif
 
diff --git a/chart2/qa/extras/chart2export.cxx b/chart2/qa/extras/chart2export.cxx
index 5975c7a3cfa2..77c5ddffb9cb 100644
--- a/chart2/qa/extras/chart2export.cxx
+++ b/chart2/qa/extras/chart2export.cxx
@@ -13,6 +13,8 @@
 
 #include <com/sun/star/chart/ErrorBarStyle.hpp>
 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
+#include <com/sun/star/chart2/DataPointCustomLabelField.hpp>
+#include <com/sun/star/chart2/DataPointCustomLabelFieldType.hpp>
 #include <com/sun/star/lang/XServiceName.hpp>
 #include <com/sun/star/packages/zip/ZipFileAccess.hpp>
 #include <com/sun/star/text/XTextDocument.hpp>
@@ -100,6 +102,8 @@ public:
     void testMultipleAxisXLSX();
     void testAxisTitleRotationXLSX();
     void testAxisCrossBetweenXSLX();
+    void testCustomDataLabel();
+    void testCustomDataLabelMultipleSeries();
 
     CPPUNIT_TEST_SUITE(Chart2ExportTest);
     CPPUNIT_TEST(testErrorBarXLSX);
@@ -164,6 +168,8 @@ public:
     CPPUNIT_TEST(testMultipleAxisXLSX);
     CPPUNIT_TEST(testAxisTitleRotationXLSX);
     CPPUNIT_TEST(testAxisCrossBetweenXSLX);
+    CPPUNIT_TEST(testCustomDataLabel);
+    CPPUNIT_TEST(testCustomDataLabelMultipleSeries);
     CPPUNIT_TEST_SUITE_END();
 
 protected:
@@ -1486,6 +1492,159 @@ void Chart2ExportTest::testAxisCrossBetweenXSLX()
     assertXPath(pXmlDoc, "(//c:crossBetween)[1]", "val", "midCat");
 }
 
+void Chart2ExportTest::testCustomDataLabel()
+{
+    load("/chart2/qa/extras/data/pptx/", "tdf115107.pptx");
+    xmlDocPtr pXmlDoc = parseExport("ppt/charts/chart1", "Impress MS PowerPoint 2007 XML");
+    CPPUNIT_ASSERT(pXmlDoc);
+
+    Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xChartDoc.is());
+
+    uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+    CPPUNIT_ASSERT(xDataSeries.is());
+    float nFontSize;
+    sal_Int64 nFontColor;
+    sal_Int32 nCharUnderline;
+    uno::Reference<beans::XPropertySet> xPropertySet;
+    uno::Sequence<uno::Reference<chart2::XDataPointCustomLabelField>> aFields;
+
+    // 1
+    xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_QUERY_THROW);
+    xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), aFields.getLength());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[0]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("90.0 = "), aFields[0]->getString());
+    aFields[0]->getPropertyValue("CharHeight") >>= nFontSize;
+    aFields[0]->getPropertyValue("CharColor") >>= nFontColor;
+    CPPUNIT_ASSERT_EQUAL(static_cast<float>(18), nFontSize);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xed7d31), nFontColor);
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_VALUE, aFields[1]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("90"), aFields[1]->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("{0C576297-5A9F-4B4E-A675-B6BA406B7D87}"), aFields[1]->getGuid());
+
+    // 2
+    xPropertySet.set(xDataSeries->getDataPointByIndex(1), uno::UNO_QUERY_THROW);
+    xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(8), aFields.getLength());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[0]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("Text"), aFields[0]->getString());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[1]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString(" : "), aFields[1]->getString());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CATEGORYNAME, aFields[2]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("B"), aFields[2]->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("{0CCAAACD-B393-42CE-8DBD-82F9F9ADC852}"), aFields[2]->getGuid());
+    aFields[2]->getPropertyValue("CharHeight") >>= nFontSize;
+    aFields[2]->getPropertyValue("CharColor") >>= nFontColor;
+    CPPUNIT_ASSERT_EQUAL(static_cast<float>(16), nFontSize);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xed7d31), nFontColor);
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_NEWLINE, aFields[3]->getFieldType());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[4]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("Multi"), aFields[4]->getString());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[5]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("line"), aFields[5]->getString());
+    aFields[5]->getPropertyValue("CharHeight") >>= nFontSize;
+    aFields[5]->getPropertyValue("CharColor") >>= nFontColor;
+    CPPUNIT_ASSERT_EQUAL(static_cast<float>(13), nFontSize);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xbf9000), nFontColor);
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_NEWLINE, aFields[6]->getFieldType());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[7]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("Abc"), aFields[7]->getString());
+    aFields[7]->getPropertyValue("CharHeight") >>= nFontSize;
+    aFields[7]->getPropertyValue("CharColor") >>= nFontColor;
+    aFields[7]->getPropertyValue("CharUnderline") >>= nCharUnderline;
+    CPPUNIT_ASSERT_EQUAL(static_cast<float>(12), nFontSize);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xa9d18e), nFontColor);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), nCharUnderline);
+
+    // 3
+    xPropertySet.set(xDataSeries->getDataPointByIndex(2), uno::UNO_QUERY_THROW);
+    xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aFields.getLength());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_SERIESNAME, aFields[0]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("DATA"), aFields[0]->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("{C8F3EB90-8960-4F9A-A3AD-B4FAC4FE4566}"), aFields[0]->getGuid());
+
+    // 4
+    xPropertySet.set(xDataSeries->getDataPointByIndex(3), uno::UNO_QUERY_THROW);
+    xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), aFields.getLength());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CELLREF, aFields[0]->getFieldType());
+    //CPPUNIT_ASSERT_EQUAL(OUString("70"), aFields[0]->getString()); TODO: Not implemented yet
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[1]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString(" <CELLREF"), aFields[1]->getString());
+}
+
+void Chart2ExportTest::testCustomDataLabelMultipleSeries()
+{
+    load("/chart2/qa/extras/data/pptx/", "tdf115107-2.pptx");
+    xmlDocPtr pXmlDoc = parseExport("ppt/charts/chart2", "Impress MS PowerPoint 2007 XML");
+    CPPUNIT_ASSERT(pXmlDoc);
+
+    Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xChartDoc.is());
+
+    uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+    CPPUNIT_ASSERT(xDataSeries.is());
+    float nFontSize;
+    sal_Int64 nFontColor;
+    uno::Reference<beans::XPropertySet> xPropertySet;
+    uno::Sequence<uno::Reference<chart2::XDataPointCustomLabelField>> aFields;
+
+    // First series
+    xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_QUERY_THROW);
+    xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), aFields.getLength());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_VALUE, aFields[0]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("4.3"), aFields[0]->getString());
+    aFields[0]->getPropertyValue("CharHeight") >>= nFontSize;
+    aFields[0]->getPropertyValue("CharColor") >>= nFontColor;
+    CPPUNIT_ASSERT_EQUAL(static_cast<float>(18), nFontSize);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xc00000), nFontColor);
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[1]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString(" "), aFields[1]->getString());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_SERIESNAME, aFields[2]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("Bars"), aFields[2]->getString());
+
+    // Second series
+    xDataSeries = uno::Reference<chart2::XDataSeries>(getDataSeriesFromDoc(xChartDoc, 0, 1));
+    CPPUNIT_ASSERT(xDataSeries.is());
+
+    xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_QUERY_THROW);
+    xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), aFields.getLength());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_VALUE, aFields[0]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("2"), aFields[0]->getString());
+    aFields[0]->getPropertyValue("CharHeight") >>= nFontSize;
+    aFields[0]->getPropertyValue("CharColor") >>= nFontColor;
+    CPPUNIT_ASSERT_EQUAL(static_cast<float>(18), nFontSize);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xffd966), nFontColor);
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[1]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString(" "), aFields[1]->getString());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_SERIESNAME, aFields[2]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("Line"), aFields[2]->getString());
+
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(Chart2ExportTest);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/chart2/qa/extras/chart2import.cxx b/chart2/qa/extras/chart2import.cxx
index b0f98a642f85..cc8f678686de 100644
--- a/chart2/qa/extras/chart2import.cxx
+++ b/chart2/qa/extras/chart2import.cxx
@@ -11,6 +11,8 @@
 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
 #include <com/sun/star/chart2/CurveStyle.hpp>
 #include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart2/DataPointCustomLabelField.hpp>
+#include <com/sun/star/chart2/DataPointCustomLabelFieldType.hpp>
 #include <com/sun/star/chart/ErrorBarStyle.hpp>
 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
 #include <com/sun/star/chart2/XChartDocument.hpp>
@@ -99,6 +101,9 @@ public:
 
     void testInternalDataProvider();
 
+    void testTdf115107(); // import complex data point labels
+    void testTdf115107_2(); // import complex data point labels in cobo charts with multiple data series
+
     CPPUNIT_TEST_SUITE(Chart2ImportTest);
     CPPUNIT_TEST(Fdo60083);
     CPPUNIT_TEST(testSteppedLines);
@@ -156,6 +161,9 @@ public:
 
     CPPUNIT_TEST(testInternalDataProvider);
 
+    CPPUNIT_TEST(testTdf115107);
+    CPPUNIT_TEST(testTdf115107_2);
+
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -1287,6 +1295,152 @@ void Chart2ImportTest::testTdf111173()
     CPPUNIT_ASSERT_MESSAGE( "failed to load chart", xChart1Doc.is() );
 }
 
+void Chart2ImportTest::testTdf115107()
+{
+    load("/chart2/qa/extras/data/pptx/", "tdf115107.pptx");
+
+    Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xChartDoc.is());
+
+    uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+    CPPUNIT_ASSERT(xDataSeries.is());
+    float nFontSize;
+    sal_Int64 nFontColor;
+    sal_Int32 nCharUnderline;
+    uno::Reference<beans::XPropertySet> xPropertySet;
+    uno::Sequence<uno::Reference<chart2::XDataPointCustomLabelField>> aFields;
+
+    // 1
+    xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_QUERY_THROW);
+    xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), aFields.getLength());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[0]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("90.0 = "), aFields[0]->getString());
+    aFields[0]->getPropertyValue("CharHeight") >>= nFontSize;
+    aFields[0]->getPropertyValue("CharColor") >>= nFontColor;
+    CPPUNIT_ASSERT_EQUAL(static_cast<float>(18), nFontSize);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xed7d31), nFontColor);
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_VALUE, aFields[1]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("90"), aFields[1]->getString());
+
+    // 2
+    xPropertySet.set(xDataSeries->getDataPointByIndex(1), uno::UNO_QUERY_THROW);
+    xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(8), aFields.getLength());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[0]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("Text"), aFields[0]->getString());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[1]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString(" : "), aFields[1]->getString());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CATEGORYNAME, aFields[2]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("B"), aFields[2]->getString());
+    aFields[2]->getPropertyValue("CharHeight") >>= nFontSize;
+    aFields[2]->getPropertyValue("CharColor") >>= nFontColor;
+    CPPUNIT_ASSERT_EQUAL(static_cast<float>(16), nFontSize);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xed7d31), nFontColor);
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_NEWLINE, aFields[3]->getFieldType());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[4]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("Multi"), aFields[4]->getString());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[5]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("line"), aFields[5]->getString());
+    aFields[5]->getPropertyValue("CharHeight") >>= nFontSize;
+    aFields[5]->getPropertyValue("CharColor") >>= nFontColor;
+    CPPUNIT_ASSERT_EQUAL(static_cast<float>(13), nFontSize);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xbf9000), nFontColor);
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_NEWLINE, aFields[6]->getFieldType());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[7]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("Abc"), aFields[7]->getString());
+    aFields[7]->getPropertyValue("CharHeight") >>= nFontSize;
+    aFields[7]->getPropertyValue("CharColor") >>= nFontColor;
+    aFields[7]->getPropertyValue("CharUnderline") >>= nCharUnderline;
+    CPPUNIT_ASSERT_EQUAL(static_cast<float>(12), nFontSize);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xa9d18e), nFontColor);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), nCharUnderline);
+
+    // 3
+    xPropertySet.set(xDataSeries->getDataPointByIndex(2), uno::UNO_QUERY_THROW);
+    xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aFields.getLength());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_SERIESNAME, aFields[0]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("DATA"), aFields[0]->getString());
+
+    // 4
+    xPropertySet.set(xDataSeries->getDataPointByIndex(3), uno::UNO_QUERY_THROW);
+    xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), aFields.getLength());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CELLREF, aFields[0]->getFieldType());
+    //CPPUNIT_ASSERT_EQUAL(OUString("70"), aFields[0]->getString()); TODO: Not implemented yet
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[1]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString(" <CELLREF"), aFields[1]->getString());
+}
+
+void Chart2ImportTest::testTdf115107_2()
+{
+    load("/chart2/qa/extras/data/pptx/", "tdf115107-2.pptx");
+
+    Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xChartDoc.is());
+
+    uno::Reference<chart2::XDataSeries> xDataSeries(getDataSeriesFromDoc(xChartDoc, 0));
+    CPPUNIT_ASSERT(xDataSeries.is());
+    float nFontSize;
+    sal_Int64 nFontColor;
+    uno::Reference<beans::XPropertySet> xPropertySet;
+    uno::Sequence<uno::Reference<chart2::XDataPointCustomLabelField>> aFields;
+
+    // First series
+    xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_QUERY_THROW);
+    xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), aFields.getLength());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_VALUE, aFields[0]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("4.3"), aFields[0]->getString());
+    aFields[0]->getPropertyValue("CharHeight") >>= nFontSize;
+    aFields[0]->getPropertyValue("CharColor") >>= nFontColor;
+    CPPUNIT_ASSERT_EQUAL(static_cast<float>(18), nFontSize);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xc00000), nFontColor);
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[1]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString(" "), aFields[1]->getString());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_SERIESNAME, aFields[2]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("Bars"), aFields[2]->getString());
+
+    // Second series
+    xDataSeries = uno::Reference<chart2::XDataSeries>(getDataSeriesFromDoc(xChartDoc, 0, 1));
+    CPPUNIT_ASSERT(xDataSeries.is());
+
+    xPropertySet.set(xDataSeries->getDataPointByIndex(0), uno::UNO_QUERY_THROW);
+    xPropertySet->getPropertyValue("CustomLabelFields") >>= aFields;
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), aFields.getLength());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_VALUE, aFields[0]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("2"), aFields[0]->getString());
+    aFields[0]->getPropertyValue("CharHeight") >>= nFontSize;
+    aFields[0]->getPropertyValue("CharColor") >>= nFontColor;
+    CPPUNIT_ASSERT_EQUAL(static_cast<float>(18), nFontSize);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int64>(0xffd966), nFontColor);
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT, aFields[1]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString(" "), aFields[1]->getString());
+
+    CPPUNIT_ASSERT_EQUAL(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_SERIESNAME, aFields[2]->getFieldType());
+    CPPUNIT_ASSERT_EQUAL(OUString("Line"), aFields[2]->getString());
+
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(Chart2ImportTest);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/chart2/qa/extras/data/pptx/tdf115107-2.pptx b/chart2/qa/extras/data/pptx/tdf115107-2.pptx
new file mode 100644
index 000000000000..629056ecc87a
Binary files /dev/null and b/chart2/qa/extras/data/pptx/tdf115107-2.pptx differ
diff --git a/chart2/qa/extras/data/pptx/tdf115107.pptx b/chart2/qa/extras/data/pptx/tdf115107.pptx
new file mode 100644
index 000000000000..2ec5c2cd223b
Binary files /dev/null and b/chart2/qa/extras/data/pptx/tdf115107.pptx differ
diff --git a/chart2/source/chartcore.component b/chart2/source/chartcore.component
index f7a1783eda68..45c87f93d633 100644
--- a/chart2/source/chartcore.component
+++ b/chart2/source/chartcore.component
@@ -158,6 +158,7 @@
     constructor="com_sun_star_comp_chart_FormattedString_get_implementation">
     <service name="com.sun.star.beans.PropertySet"/>
     <service name="com.sun.star.chart2.FormattedString"/>
+    <service name="com.sun.star.chart2.DataPointCustomLabelField"/>
   </implementation>
   <implementation name="com.sun.star.comp.chart.LineChartType"
     constructor="com_sun_star_comp_chart_LineChartType_get_implementation">
diff --git a/chart2/source/model/main/DataPointProperties.cxx b/chart2/source/model/main/DataPointProperties.cxx
index 2dd85a0e78b1..4c9b6406aacf 100644
--- a/chart2/source/model/main/DataPointProperties.cxx
+++ b/chart2/source/model/main/DataPointProperties.cxx
@@ -31,7 +31,7 @@
 #include <com/sun/star/style/XStyle.hpp>
 #include <com/sun/star/drawing/BitmapMode.hpp>
 #include <com/sun/star/drawing/RectanglePoint.hpp>
-
+#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp>
 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
 #include <com/sun/star/chart2/DataPointLabel.hpp>
 #include <com/sun/star/chart2/Symbol.hpp>
@@ -464,6 +464,13 @@ void DataPointProperties::AddPropertiesToVector(
                   cppu::UnoType<sal_Int16>::get(),
                   beans::PropertyAttribute::BOUND
                   | beans::PropertyAttribute::MAYBEDEFAULT ));
+
+    rOutProperties.push_back(
+        Property( CHART_UNONAME_CUSTOM_LABEL_FIELDS,
+                  PROP_DATAPOINT_CUSTOM_LABEL_FIELDS,
+                  cppu::UnoType<uno::Sequence<uno::Reference<chart2::XDataPointCustomLabelField>>>::get(),
+                  beans::PropertyAttribute::BOUND
+                  | beans::PropertyAttribute::MAYBEDEFAULT ));
 }
 
 void DataPointProperties::AddDefaultsToMap(
@@ -544,6 +551,9 @@ void DataPointProperties::AddDefaultsToMap(
     PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_DASH, drawing::LineDash());
     PropertyHelper::setEmptyPropertyValueDefault(rOutMap, PROP_DATAPOINT_LABEL_BORDER_DASH_NAME);
     PropertyHelper::setPropertyValueDefault<sal_Int16>(rOutMap, PROP_DATAPOINT_LABEL_BORDER_TRANS, 0);
+
+    uno::Sequence<uno::Reference<chart2::XDataPointCustomLabelField>> aFields(0);
+    PropertyHelper::setPropertyValueDefault(rOutMap, PROP_DATAPOINT_CUSTOM_LABEL_FIELDS, aFields);
 }
 
 } //  namespace chart
diff --git a/chart2/source/model/main/DataPointProperties.hxx b/chart2/source/model/main/DataPointProperties.hxx
index 39362498a52a..c65ad8c4f5fd 100644
--- a/chart2/source/model/main/DataPointProperties.hxx
+++ b/chart2/source/model/main/DataPointProperties.hxx
@@ -80,7 +80,8 @@ namespace DataPointProperties
         PROP_DATAPOINT_LABEL_BORDER_WIDTH,
         PROP_DATAPOINT_LABEL_BORDER_DASH,
         PROP_DATAPOINT_LABEL_BORDER_DASH_NAME,
-        PROP_DATAPOINT_LABEL_BORDER_TRANS
+        PROP_DATAPOINT_LABEL_BORDER_TRANS,
+        PROP_DATAPOINT_CUSTOM_LABEL_FIELDS
 
         // additionally some properites from ::chart::LineProperties
     };
diff --git a/chart2/source/model/main/FormattedString.cxx b/chart2/source/model/main/FormattedString.cxx
index 4396a584b71a..2ec870a9222a 100644
--- a/chart2/source/model/main/FormattedString.cxx
+++ b/chart2/source/model/main/FormattedString.cxx
@@ -97,6 +97,8 @@ FormattedString::FormattedString(
         uno::Reference< uno::XComponentContext > const & /* xContext */ ) :
         ::property::OPropertySet( m_aMutex ),
     m_aString(),
+    m_aType(chart2::DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT),
+    m_aGuid(),
     m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder())
 {}
 
@@ -105,6 +107,8 @@ FormattedString::FormattedString( const FormattedString & rOther ) :
         impl::FormattedString_Base(),
         ::property::OPropertySet( rOther, m_aMutex ),
     m_aString( rOther.m_aString ),
+    m_aType(rOther.m_aType),
+    m_aGuid(rOther.m_aGuid),
     m_xModifyEventForwarder( ModifyListenerHelper::createModifyEventForwarder())
 {}
 
@@ -138,6 +142,45 @@ void SAL_CALL FormattedString::setString( const OUString& String )
 
 }
 
+// ____ XDataPointCustomLabelField ____
+css::chart2::DataPointCustomLabelFieldType SAL_CALL FormattedString::getFieldType()
+    throw (uno::RuntimeException, std::exception)
+{
+    MutexGuard aGuard(GetMutex());
+    return m_aType;
+}
+
+void SAL_CALL
+FormattedString::setFieldType(const css::chart2::DataPointCustomLabelFieldType Type)
+    throw (uno::RuntimeException, std::exception)
+{
+    {
+        MutexGuard aGuard(GetMutex());
+        m_aType = Type;
+    }
+    //don't keep the mutex locked while calling out
+    fireModifyEvent();
+}
+
+OUString SAL_CALL FormattedString::getGuid()
+    throw (uno::RuntimeException, std::exception)
+{
+    MutexGuard aGuard( GetMutex());
+    return m_aGuid;
+}
+
+void SAL_CALL FormattedString::setGuid( const OUString& guid )
+    throw (uno::RuntimeException, std::exception)
+{
+    {
+        MutexGuard aGuard( GetMutex());
+        m_aGuid= guid;
+    }
+    //don't keep the mutex locked while calling out
+    fireModifyEvent();
+
+}
+
 // ____ XModifyBroadcaster ____
 void SAL_CALL FormattedString::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
     throw (uno::RuntimeException, std::exception)
@@ -240,6 +283,7 @@ css::uno::Sequence< OUString > SAL_CALL FormattedString::getSupportedServiceName
     throw( css::uno::RuntimeException, std::exception )
 {
     return {
+        "com.sun.star.chart2.DataPointCustomLabelField",
         "com.sun.star.chart2.FormattedString",
         "com.sun.star.beans.PropertySet" };
 }
diff --git a/chart2/source/model/main/FormattedString.hxx b/chart2/source/model/main/FormattedString.hxx
index 2eb5565bd64b..e1069665038f 100644
--- a/chart2/source/model/main/FormattedString.hxx
+++ b/chart2/source/model/main/FormattedString.hxx
@@ -26,6 +26,8 @@
 #include "ModifyListenerHelper.hxx"
 #include <com/sun/star/lang/XServiceInfo.hpp>
 #include <com/sun/star/chart2/XFormattedString2.hpp>
+#include <com/sun/star/chart2/DataPointCustomLabelFieldType.hpp>
+#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp>
 #include <com/sun/star/util/XCloneable.hpp>
 #include <com/sun/star/uno/XComponentContext.hpp>
 
@@ -35,7 +37,7 @@ namespace chart
 namespace impl
 {
 typedef ::cppu::WeakImplHelper<
-    css::chart2::XFormattedString2,
+    css::chart2::XDataPointCustomLabelField, // inherits from XFormattedString2
     css::lang::XServiceInfo,
     css::util::XCloneable,
     css::util::XModifyBroadcaster,
@@ -88,6 +90,16 @@ protected:
     virtual void SAL_CALL setString( const OUString& String )
         throw (css::uno::RuntimeException, std::exception) override;
 
+    // ____ XDataPointCustomLabelField ____
+    virtual css::chart2::DataPointCustomLabelFieldType SAL_CALL getFieldType()
+        throw (css::uno::RuntimeException, std::exception) override;
+    virtual void SAL_CALL setFieldType( const css::chart2::DataPointCustomLabelFieldType FieldType )
+        throw (css::uno::RuntimeException, std::exception) override;
+    virtual OUString SAL_CALL getGuid()
+        throw (css::uno::RuntimeException, std::exception) override;
+    void SAL_CALL setGuid( const OUString& guid )
+        throw (css::uno::RuntimeException, std::exception) override;
+
     // ____ OPropertySet ____
     virtual css::uno::Any GetDefaultValue( sal_Int32 nHandle ) const
         throw (css::beans::UnknownPropertyException,
@@ -130,8 +142,13 @@ protected:
     void fireModifyEvent();
 
 private:
+    // ____ XFormattedString ____
     OUString m_aString;
 
+    // ____ XDataPointCustomLabelField ____
+    css::chart2::DataPointCustomLabelFieldType m_aType;
+    OUString m_aGuid;
+
     css::uno::Reference< css::util::XModifyListener > m_xModifyEventForwarder;
 };
 
diff --git a/chart2/source/view/charttypes/VSeriesPlotter.cxx b/chart2/source/view/charttypes/VSeriesPlotter.cxx
index 9336ea3a9732..e5cdf429d3b5 100644
--- a/chart2/source/view/charttypes/VSeriesPlotter.cxx
+++ b/chart2/source/view/charttypes/VSeriesPlotter.cxx
@@ -56,6 +56,7 @@
 
 #include <com/sun/star/chart/ErrorBarStyle.hpp>
 #include <com/sun/star/chart/TimeUnit.hpp>
+#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp>
 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
 #include <com/sun/star/container/XChild.hpp>
 #include <com/sun/star/chart2/RelativePosition.hpp>
@@ -429,9 +430,21 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re
                     , sal_Int32 nTextWidth )
 {
     uno::Reference< drawing::XShape > xTextShape;
+    Sequence<uno::Reference<XDataPointCustomLabelField>> aCustomLabels;
 
     try
     {
+        const uno::Reference< css::beans::XPropertySet >& xPropertySet(
+            rDataSeries.getPropertiesOfPoint( nPointIndex ) );
+        if( xPropertySet.is() )
+        {
+            uno::Any aAny = xPropertySet->getPropertyValue( CHART_UNONAME_CUSTOM_LABEL_FIELDS );
+            if( aAny.hasValue() )
+            {
+                aAny >>= aCustomLabels;
+            }
+        }
+
         awt::Point aScreenPosition2D(rScreenPosition2D);
         if(LABEL_ALIGN_LEFT==eAlignment)
             aScreenPosition2D.X -= nOffset;
@@ -511,26 +524,75 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re
         }
 
         sal_Int32 nLineCountForSymbolsize = 0;
-        Sequence< OUString > aTextList(3);
+        sal_uInt32 nTextListLength = 3;
+        sal_uInt32 nCustomLabelsCount = aCustomLabels.getLength();
+        bool bUseCustomLabel = false;
+        Sequence< OUString > aTextList( nTextListLength );
+
+        bUseCustomLabel = nCustomLabelsCount > 0;
+        if( bUseCustomLabel )
         {
-            if(pLabel->ShowCategoryName)
+            nTextListLength = ( nCustomLabelsCount > 3 ) ? nCustomLabelsCount : 3;
+            aSeparator = "";
+            aTextList = Sequence< OUString >( nTextListLength );
+            for( sal_uInt32 i = 0; i < nCustomLabelsCount; ++i )
             {
-                if( m_pExplicitCategoriesProvider )
+                switch( aCustomLabels[i]->getFieldType() )
                 {
-                    Sequence< OUString > aCategories( m_pExplicitCategoriesProvider->getSimpleCategories() );
-                    if( nPointIndex >= 0 && nPointIndex < aCategories.getLength() )
+                    case DataPointCustomLabelFieldType_VALUE:
+                    {
+                        aTextList[i] = getLabelTextForValue( rDataSeries, nPointIndex, fValue, false );
+                        break;
+                    }
+                    case DataPointCustomLabelFieldType_CATEGORYNAME:
+                    {
+                        aTextList[i] = getCategoryName( nPointIndex );
+                        break;
+                    }
+                    case DataPointCustomLabelFieldType_SERIESNAME:
                     {
-                        aTextList[0] = aCategories[nPointIndex];
+                        OUString aRole;
+                        if ( m_xChartTypeModel.is() )
+                            aRole = m_xChartTypeModel->getRoleOfSequenceForSeriesLabel();
+                        uno::Reference< XDataSeries > xSeries( rDataSeries.getModel() );
+                        aTextList[i] = DataSeriesHelper::getDataSeriesLabel( xSeries, aRole );
+                        break;
                     }
+                    case DataPointCustomLabelFieldType_CELLREF:
+                    {
+                        // TODO: for now doesn't show placeholder
+                        aTextList[i] = OUString();
+                        break;
+                    }
+                    case DataPointCustomLabelFieldType_TEXT:
+                    {
+                        aTextList[i] = aCustomLabels[i]->getString();
+                        break;
+                    }
+                    case DataPointCustomLabelFieldType_NEWLINE:
+                    {
+                        aTextList[i] = "\n";
+                        break;
+                    }
+                    default:
+                    break;
                 }
+                aCustomLabels[i]->setString( aTextList[i] );
+            }
+        }
+        else
+        {
+            if( pLabel->ShowCategoryName )
+            {
+                aTextList[0] = getCategoryName( nPointIndex );
             }
 
-            if(pLabel->ShowNumber)
+            if( pLabel->ShowNumber )
             {
                 aTextList[1] = getLabelTextForValue(rDataSeries, nPointIndex, fValue, false);
             }
 
-            if(pLabel->ShowNumberInPercent)
+            if( pLabel->ShowNumberInPercent )
             {
                 if(fSumValue==0.0)
                     fSumValue=1.0;
@@ -540,13 +602,13 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re
 
                 aTextList[2] = getLabelTextForValue(rDataSeries, nPointIndex, fValue, true);
             }
+        }
 
-            for( sal_Int32 nN = 0; nN < 3; ++nN)
+        for( sal_Int32 nN = 0; nN < aTextList.getLength(); ++nN )
+        {
+            if( !aTextList[nN].isEmpty() )
             {
-                if( !aTextList[nN].isEmpty() )
-                {
-                    ++nLineCountForSymbolsize;
-                }
+                ++nLineCountForSymbolsize;
             }
         }
 
@@ -565,7 +627,28 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re
         // a multi-line label.
         bool bMultiLineLabel = ( aSeparator == "\n" );
 
-        if( bMultiLineLabel )
+        if( bUseCustomLabel )
+        {
+            Sequence< uno::Reference< XFormattedString > > aFormattedLabels( aCustomLabels.getLength() );
+            for( int i = 0; i < aFormattedLabels.getLength(); i++ )
+            {
+                uno::Reference< XFormattedString > xString( aCustomLabels[i], uno::UNO_QUERY );
+                aFormattedLabels[i] = xString;
+            }
+
+            // center the text
+            sal_uInt32 nProperties = pPropNames->getLength();
+            pPropNames->realloc( nProperties + 1 );
+            pPropValues->realloc( nProperties + 1 );
+            (*pPropNames)[ nProperties ] = UNO_NAME_EDIT_PARA_ADJUST;
+            (*pPropValues)[ nProperties ] <<= style::ParagraphAdjust_CENTER;
+
+            // create text shape
+            xTextShape = AbstractShapeFactory::getOrCreateShapeFactory( m_xShapeFactory )->
+                createText( xTarget_, aFormattedLabels, *pPropNames, *pPropValues,
+                    AbstractShapeFactory::makeTransformation( aScreenPosition2D ) );
+        }
+        else if( bMultiLineLabel )
         {
             // prepare properties for each paragraph
             // we want to have the value and percent value centered respect
@@ -591,7 +674,7 @@ uno::Reference< drawing::XShape > VSeriesPlotter::createDataLabel( const uno::Re
         {
             // join text list elements
             OUStringBuffer aText;
-            for( sal_Int32 nN = 0; nN < 3; ++nN)
+            for( sal_uInt32 nN = 0; nN < nTextListLength; ++nN)
             {
                 if( !aTextList[nN].isEmpty() )
                 {
@@ -2085,6 +2168,19 @@ VDataSeries* VSeriesPlotter::getFirstSeries() const
     return nullptr;
 }
 
+OUString VSeriesPlotter::getCategoryName( sal_Int32 nPointIndex ) const
+{
+    if (m_pExplicitCategoriesProvider)
+    {
+        Sequence< OUString > aCategories(m_pExplicitCategoriesProvider->getSimpleCategories());
+        if (nPointIndex >= 0 && nPointIndex < aCategories.getLength())
+        {
+            return aCategories[nPointIndex];
+        }
+    }
+    return OUString();
+}
+
 uno::Sequence< OUString > VSeriesPlotter::getSeriesNames() const
 {
     ::std::vector< OUString > aRetVector;
diff --git a/chart2/source/view/inc/AbstractShapeFactory.hxx b/chart2/source/view/inc/AbstractShapeFactory.hxx
index be0ceb56dbc3..eff988e5278b 100644
--- a/chart2/source/view/inc/AbstractShapeFactory.hxx
+++ b/chart2/source/view/inc/AbstractShapeFactory.hxx
@@ -200,6 +200,13 @@ public:
                     , const css::uno::Any& rATransformation ) = 0;
 
     virtual css::uno::Reference< css::drawing::XShape >
+        createText(const css::uno::Reference< css::drawing::XShapes >& xTarget
+            , css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > >& xFormattedString
+            , const tNameSequence& rPropNames
+            , const tAnySequence& rPropValues
+            , const css::uno::Any& rATransformation) = 0;
+
+    virtual css::uno::Reference< css::drawing::XShape >
         createText( const css::uno::Reference< css::drawing::XShapes >& xTarget2D,
                 const css::awt::Size& rSize,
                 const css::awt::Point& rPosition,
diff --git a/chart2/source/view/inc/OpenglShapeFactory.hxx b/chart2/source/view/inc/OpenglShapeFactory.hxx
index 01b2223cf59c..7963068ce79e 100644
--- a/chart2/source/view/inc/OpenglShapeFactory.hxx
+++ b/chart2/source/view/inc/OpenglShapeFactory.hxx
@@ -151,6 +151,13 @@ public:
                     , const css::uno::Any& rATransformation ) override;
 
     virtual css::uno::Reference< css::drawing::XShape >
+        createText( const css::uno::Reference< css::drawing::XShapes >& xTarget
+                    , css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > >& xFormattedString
+                    , const tNameSequence& rPropNames
+                    , const tAnySequence& rPropValues
+                    , const css::uno::Any& rATransformation ) override;
+
+    virtual css::uno::Reference< css::drawing::XShape >
         createText( const css::uno::Reference< css::drawing::XShapes >& xTarget2D,
                 const css::awt::Size& rSize,
                 const css::awt::Point& rPosition,
diff --git a/chart2/source/view/inc/ShapeFactory.hxx b/chart2/source/view/inc/ShapeFactory.hxx
index 02a75d3a0764..ec1080732142 100644
--- a/chart2/source/view/inc/ShapeFactory.hxx
+++ b/chart2/source/view/inc/ShapeFactory.hxx
@@ -189,6 +189,13 @@ public:
                     , const css::uno::Any& rATransformation ) override;
 
     virtual css::uno::Reference< css::drawing::XShape >
+        createText(const css::uno::Reference< css::drawing::XShapes >& xTarget
+            , css::uno::Sequence< css::uno::Reference< css::chart2::XFormattedString > >& xFormattedString
+            , const tNameSequence& rPropNames
+            , const tAnySequence& rPropValues
+            , const css::uno::Any& rATransformation) override;
+
+    virtual css::uno::Reference< css::drawing::XShape >
         createText( const css::uno::Reference< css::drawing::XShapes >& xTarget2D,
                 const css::awt::Size& rSize,
                 const css::awt::Point& rPosition,
diff --git a/chart2/source/view/inc/VSeriesPlotter.hxx b/chart2/source/view/inc/VSeriesPlotter.hxx
index cd8cf9ffd6d3..aca74315c366 100644
--- a/chart2/source/view/inc/VSeriesPlotter.hxx
+++ b/chart2/source/view/inc/VSeriesPlotter.hxx
@@ -387,6 +387,8 @@ protected:
 
     VDataSeries* getFirstSeries() const;
 
+    OUString getCategoryName( sal_Int32 nPointIndex ) const;
+
 protected:
     PlottingPositionHelper*    m_pMainPosHelper;
 
diff --git a/chart2/source/view/main/OpenglShapeFactory.cxx b/chart2/source/view/main/OpenglShapeFactory.cxx
index 39c740cc8c92..e0c78c24f1f1 100644
--- a/chart2/source/view/main/OpenglShapeFactory.cxx
+++ b/chart2/source/view/main/OpenglShapeFactory.cxx
@@ -409,6 +409,18 @@ uno::Reference< drawing::XShape >
 }
 
 uno::Reference< drawing::XShape >
+        OpenglShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget
+                    , uno::Sequence< uno::Reference< chart2::XFormattedString > >& rFormattedString
+                    , const tNameSequence& rPropNames
+                    , const tAnySequence& rPropValues
+                    , const uno::Any& rATransformation )
+{
+    dummy::DummyText* pText = new dummy::DummyText( rFormattedString[0]->getString(), rPropNames, rPropValues,
+            rATransformation, xTarget, 0 );
+    return pText;
+}
+
+uno::Reference< drawing::XShape >
         OpenglShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget,
                 const awt::Size& , const awt::Point& rPos,
                 uno::Sequence< uno::Reference< chart2::XFormattedString > >& rFormattedString,
diff --git a/chart2/source/view/main/ShapeFactory.cxx b/chart2/source/view/main/ShapeFactory.cxx
index d9ccc32000d6..b18b0c6907a0 100644
--- a/chart2/source/view/main/ShapeFactory.cxx
+++ b/chart2/source/view/main/ShapeFactory.cxx
@@ -2243,6 +2243,100 @@ uno::Reference< drawing::XShape >
 }
 
 uno::Reference< drawing::XShape >
+    ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget
+                , uno::Sequence< uno::Reference< chart2::XFormattedString > >& xFormattedString
+                , const tNameSequence& rPropNames
+                , const tAnySequence& rPropValues
+                , const uno::Any& rATransformation )
+{
+    if( !xTarget.is() )
+        return nullptr;
+
+    if( !xFormattedString.hasElements() )
+        return nullptr;
+
+    sal_Int32 nNumberOfParagraphs = xFormattedString.getLength();
+
+    bool bNotEmpty = false;
+    for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN )
+    {
+        if( !xFormattedString[nN]->getString().isEmpty() )
+        {
+            bNotEmpty = true;
+            break;
+        }
+    }
+    if( !bNotEmpty )
+        return nullptr;
+
+    //create shape and add to page
+    uno::Reference< drawing::XShape > xShape(
+            m_xShapeFactory->createInstance(
+            "com.sun.star.drawing.TextShape" ), uno::UNO_QUERY );
+    xTarget->add(xShape);
+
+    //set paragraph properties
+    bNotEmpty = false;
+    Reference< text::XText > xText( xShape, uno::UNO_QUERY );
+    if( xText.is() )
+    {
+        // the first cursor is used for appending the next paragraph,
+        // after a new string has been inserted the cursor is moved at the end
+        // of the inserted string
+        // the second cursor is used for selecting the paragraph and apply the
+        // passed text properties
+        Reference< text::XTextCursor > xInsertCursor = xText->createTextCursor();
+        Reference< text::XTextCursor > xSelectionCursor = xText->createTextCursor();
+        if( xInsertCursor.is() && xSelectionCursor.is() )
+        {
+            uno::Reference< beans::XPropertySet > xSelectionProp( xSelectionCursor, uno::UNO_QUERY );
+            if( xSelectionProp.is() )
+            {
+                for( sal_Int32 nN = 0; nN < nNumberOfParagraphs; ++nN )
+                {
+                    if( !xFormattedString[nN]->getString().isEmpty() )
+                    {
+                        xInsertCursor->gotoEnd( false );
+                        xSelectionCursor->gotoEnd( false );
+                        xText->insertString( xInsertCursor, xFormattedString[nN]->getString(), false );
+                        bNotEmpty = true;
+                        xSelectionCursor->gotoEnd( true ); // select current paragraph
+                        uno::Reference< beans::XPropertySet > xStringProperties( xFormattedString[nN], uno::UNO_QUERY );
+                        PropertyMapper::setMappedProperties( xSelectionProp, xStringProperties,
+                            PropertyMapper::getPropertyNameMapForTextShapeProperties() );
+                    }
+                }
+            }
+        }
+    }
+
+    if( !bNotEmpty )
+        return nullptr;
+
+    uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY );
+    if( xProp.is() )
+    {
+        //set whole text shape properties
+        PropertyMapper::setMultiProperties( rPropNames, rPropValues, xProp );
+
+        if( rATransformation.hasValue() )
+        {
+            //set position matrix
+            //the matrix needs to be set at the end behind autogrow and such position influencing properties
+            try
+            {
+                xProp->setPropertyValue( "Transformation", rATransformation );
+            }
+            catch( const uno::Exception& e )
+            {
+                ASSERT_EXCEPTION( e );
+            }
+        }
+    }
+    return xShape;
+}
+
+uno::Reference< drawing::XShape >
         ShapeFactory::createText( const uno::Reference< drawing::XShapes >& xTarget,
                 const awt::Size& rSize,
                 const awt::Point& rPos,
diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index 416d64faca88..ce984d6fbd25 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -69,6 +69,8 @@ $(eval $(call gb_UnoApi_add_idlfiles_nohdl,offapi,com/sun/star/awt/tree,\
 $(eval $(call gb_UnoApi_add_idlfiles_nohdl,offapi,com/sun/star/chart2,\
 	CartesianCoordinateSystem2d \
 	CartesianCoordinateSystem3d \
+	DataPointCustomLabelField \
+	DataPointCustomLabelFieldType \
 	ExponentialRegressionCurve \
 	ExponentialScaling \
 	FormattedString \
@@ -2033,6 +2035,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/chart2,\
 	XCoordinateSystem \
 	XCoordinateSystemContainer \
 	XDataInterpreter \
+	XDataPointCustomLabelField \
 	XDataSeries \
 	XDataSeriesContainer \
 	XDefaultSizeTransmitter \
diff --git a/offapi/com/sun/star/chart2/DataPointCustomLabelField.idl b/offapi/com/sun/star/chart2/DataPointCustomLabelField.idl
new file mode 100644
index 000000000000..cebe1c3273f3
--- /dev/null
+++ b/offapi/com/sun/star/chart2/DataPointCustomLabelField.idl
@@ -0,0 +1,26 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef com_sun_star_chart2_DataPointCustomLabelField_idl
+#define com_sun_star_chart2_DataPointCustomLabelField_idl
+
+#include <com/sun/star/chart2/XDataPointCustomLabelField.idl>
+
+module com { module sun { module star { module chart2 {
+
+/**
+    @since LibreOffice 6.1
+*/
+service DataPointCustomLabelField : XDataPointCustomLabelField;
+
+}; }; }; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
\ No newline at end of file
diff --git a/offapi/com/sun/star/chart2/DataPointCustomLabelFieldType.idl b/offapi/com/sun/star/chart2/DataPointCustomLabelFieldType.idl
new file mode 100644
index 000000000000..0b7f925342a6
--- /dev/null
+++ b/offapi/com/sun/star/chart2/DataPointCustomLabelFieldType.idl
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef com_sun_star_chart2_DataPointCustomLabelFieldType_idl
+#define com_sun_star_chart2_DataPointCustomLabelFieldType_idl
+
+module com { module sun { module star { module chart2 {
+
+/** The Field type enumeration for custom data point labels.
+
+    @since LibreOffice 6.1
+ */
+enum DataPointCustomLabelFieldType
+{
+    TEXT,
+    VALUE,
+    SERIESNAME,
+    CATEGORYNAME,
+    CELLREF,
+    NEWLINE
+};
+
+}; }; }; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
\ No newline at end of file
diff --git a/offapi/com/sun/star/chart2/DataPointProperties.idl b/offapi/com/sun/star/chart2/DataPointProperties.idl
index 31bd0a42696c..df5cf071ee90 100644
--- a/offapi/com/sun/star/chart2/DataPointProperties.idl
+++ b/offapi/com/sun/star/chart2/DataPointProperties.idl
@@ -31,6 +31,7 @@
 #include <com/sun/star/drawing/RectanglePoint.idl>
 #include <com/sun/star/chart2/DataPointLabel.idl>
 #include <com/sun/star/chart2/Symbol.idl>
+#include <com/sun/star/chart2/XFormattedString2.idl>
 
 module com
 {
@@ -258,6 +259,13 @@ service DataPointProperties
 
     [property] DataPointLabel                         Label;
 
+    /** specifies a text with possible fields that is used as a data point label,
+        if set then Label property is ignored
+
+        @since LibreOffice 6.1
+    */
+    [optional, property] sequence<XDataPointCustomLabelField>  CustomLabelFields;
+
     /** specifies a string that is used to separate the parts of a data label (caption)
      */
     [optional, property] string LabelSeparator;
diff --git a/offapi/com/sun/star/chart2/XDataPointCustomLabelField.idl b/offapi/com/sun/star/chart2/XDataPointCustomLabelField.idl
new file mode 100644
index 000000000000..a6a1b0151c94
--- /dev/null
+++ b/offapi/com/sun/star/chart2/XDataPointCustomLabelField.idl
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+#ifndef com_sun_star_chart2_DataPointCustomLabelField_idl
+#define com_sun_star_chart2_DataPointCustomLabelField_idl
+
+#include <com/sun/star/chart2/XFormattedString2.idl>
+#include <com/sun/star/chart2/DataPointCustomLabelFieldType.idl>
+
+module com { module sun { module star { module chart2 {
+
+/**
+    Provides interface for DataPointCustomLabelField service.
+
+    @since LibreOffice 6.1
+*/
+interface XDataPointCustomLabelField : XFormattedString2
+{
+    DataPointCustomLabelFieldType getFieldType();
+
+    void setFieldType( [in] DataPointCustomLabelFieldType fieldType );
+
+    string getGuid();
+
+    void setGuid( [in] string guid );
+
+};
+
+
+
+} ; // chart2
+} ; // com
+} ; // sun
+} ; // star
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/oox/inc/drawingml/textfield.hxx b/oox/inc/drawingml/textfield.hxx
index 9f5bf9cf27af..7cc15a04fce4 100644
--- a/oox/inc/drawingml/textfield.hxx
+++ b/oox/inc/drawingml/textfield.hxx
@@ -38,7 +38,9 @@ public:
     const TextParagraphProperties& getTextParagraphProperties() const { return maTextParagraphProperties; }
 
     void setType( const OUString& sType ) { msType = sType; }
+    const OUString& getType() const { return msType; }
     void setUuid( const OUString & sUuid ) { msUuid = sUuid; }
+    const OUString& getUuid() const { return msUuid; }
 
     virtual sal_Int32    insertAt(
                         const ::oox::core::XmlFilterBase& rFilterBase,
diff --git a/oox/source/drawingml/chart/seriesconverter.cxx b/oox/source/drawingml/chart/seriesconverter.cxx
index d0ed206cd0b1..666620b09845 100644
--- a/oox/source/drawingml/chart/seriesconverter.cxx
+++ b/oox/source/drawingml/chart/seriesconverter.cxx
@@ -22,11 +22,16 @@
 #include <com/sun/star/chart/DataLabelPlacement.hpp>
 #include <com/sun/star/chart/ErrorBarStyle.hpp>
 #include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart2/XDataPointCustomLabelField.hpp>
+#include <com/sun/star/chart2/DataPointCustomLabelField.hpp>
+#include <com/sun/star/chart2/DataPointCustomLabelFieldType.hpp>
 #include <com/sun/star/chart2/XDataSeries.hpp>
 #include <com/sun/star/chart2/XRegressionCurve.hpp>
 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
 #include <com/sun/star/chart2/data/XDataSink.hpp>
 #include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
+#include <com/sun/star/chart2/XFormattedString2.hpp>
+#include <com/sun/star/chart2/FormattedString.hpp>
 #include <osl/diagnose.h>
 #include <basegfx/numeric/ftools.hxx>
 #include "drawingml/chart/datasourceconverter.hxx"
@@ -41,6 +46,10 @@
 #include <oox/token/properties.hxx>
 #include <oox/token/tokens.hxx>
 #include <oox/drawingml/lineproperties.hxx>
+#include <drawingml/textparagraph.hxx>
+#include <drawingml/textrun.hxx>
+#include <drawingml/textfield.hxx>
+#include <drawingml/textbody.hxx>
 
 namespace oox {
 namespace drawingml {
@@ -54,13 +63,30 @@ using namespace ::com::sun::star::uno;
 
 namespace {
 
-/** nested-up sgn function - employs some gratuity around 0 - values
-   smaller than 0.33 are clamped to 0
+/** Function to get vertical position of label from chart height factor.
+    Value can be negative, prefer top placement.
  */
-int lclSgn( double nVal )
+int lclGetPositionY( double nVal )
 {
-    const int intVal=nVal*3;
-    return intVal == 0 ? 0 : (intVal < 0 ? -1 : 1);
+    if( nVal <= 0.1 )
+        return -1;
+    else if( nVal <= 0.6 )
+        return 0;
+    else
+        return 1;
+}
+
+/** Function to get horizontal position of label from chart width factor.
+    Value can be negative, prefer center placement.
+*/
+int lclGetPositionX( double nVal )
+{
+    if( nVal <= -0.2 )
+        return -1;
+    else if( nVal <= 0.2 )
+        return 0;
+    else
+        return 1;
 }
 
 Reference< XLabeledDataSequence > lclCreateLabeledDataSequence(
@@ -193,6 +219,20 @@ void importBorderProperties( PropertySet& rPropSet, Shape& rShape, const Graphic
     rPropSet.setProperty(PROP_LabelBorderColor, uno::makeAny(nColor));
 }
 
+DataPointCustomLabelFieldType lcl_ConvertFieldNameToFieldEnum( const OUString& rField )
+{
+    if (rField == "VALUE")
+        return DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_VALUE;
+    else if (rField == "SERIESNAME")
+        return DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_SERIESNAME;
+    else if (rField == "CATEGORYNAME")
+        return DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CATEGORYNAME;
+    else if (rField == "CELLREF")
+        return DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_CELLREF;
+    else
+        return DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT;
+}
+
 } // namespace
 
 DataLabelConverter::DataLabelConverter( const ConverterRoot& rParent, DataLabelModel& rModel ) :
@@ -228,17 +268,69 @@ void DataLabelConverter::convertFromModel( const Reference< XDataSeries >& rxDat
                     csscd::LEFT,        csscd::CENTER, csscd::RIGHT,
                     csscd::BOTTOM_LEFT, csscd::BOTTOM, csscd::BOTTOM_RIGHT
                 };
-            const double nMax=std::max(
-                fabs(mrModel.mxLayout->mfX),
-                fabs(mrModel.mxLayout->mfY));
-            const int simplifiedX=lclSgn(mrModel.mxLayout->mfX/nMax);
-            const int simplifiedY=lclSgn(mrModel.mxLayout->mfY/nMax);
+            const int simplifiedX = lclGetPositionX(mrModel.mxLayout->mfX);
+            const int simplifiedY = lclGetPositionY(mrModel.mxLayout->mfY);
             aPropSet.setProperty( PROP_LabelPlacement,
                                   aPositionsLookupTable[ simplifiedX+1 + 3*(simplifiedY+1) ] );
         }
 
         if (mrModel.mxShapeProp)
             importBorderProperties(aPropSet, *mrModel.mxShapeProp, getFilter().getGraphicHelper());
+
+        if( mrModel.mxText && mrModel.mxText->mxTextBody && mrModel.mxText->mxTextBody->getParagraphs().size() )
+        {
+            css::uno::Reference< XComponentContext > xContext = getComponentContext();
+            uno::Sequence< css::uno::Reference< XDataPointCustomLabelField > > aSequence;
+
+            auto& rParagraphs = mrModel.mxText->mxTextBody->getParagraphs();
+
+            int nSequenceSize = 0;
+            for( auto& pParagraph : rParagraphs )
+                nSequenceSize += pParagraph->getRuns().size();
+
+            int nParagraphs = rParagraphs.size();
+            if( nParagraphs > 1 )
+                nSequenceSize += nParagraphs - 1;
+
+            aSequence.realloc( nSequenceSize );
+
+            int nPos = 0;
+            for( auto& pParagraph : rParagraphs )
+            {
+                for( auto& pRun : pParagraph->getRuns() )
+                {
+                    css::uno::Reference< XDataPointCustomLabelField > xCustomLabel = DataPointCustomLabelField::create( xContext );
+
+                    // Store properties
+                    oox::PropertySet aPropertySet( xCustomLabel );
+                    pRun->getTextCharacterProperties().pushToPropSet( aPropertySet, getFilter() );
+
+                    TextField* pField = nullptr;
+                    if( ( pField = dynamic_cast< TextField* >( pRun.get() ) ) )
+                    {
+                        xCustomLabel->setString( pField->getText() );
+                        xCustomLabel->setFieldType( lcl_ConvertFieldNameToFieldEnum( pField->getType() ) );
+                        xCustomLabel->setGuid( pField->getUuid() );
+                    }
+                    else if( pRun.get() )
+                    {
+                        xCustomLabel->setString( pRun->getText() );
+                        xCustomLabel->setFieldType( DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_TEXT );
+                    }
+                    aSequence[ nPos++ ] = xCustomLabel;
+                }
+
+                if( nParagraphs > 1 && nPos < nSequenceSize )
+                {
+                    css::uno::Reference< XDataPointCustomLabelField > xCustomLabel = DataPointCustomLabelField::create( xContext );
+                    xCustomLabel->setFieldType( DataPointCustomLabelFieldType::DataPointCustomLabelFieldType_NEWLINE );
+                    xCustomLabel->setString("\n");
+                    aSequence[ nPos++ ] = xCustomLabel;
+                }
+            }
+
+            aPropSet.setProperty( PROP_CustomLabelFields, makeAny( aSequence ) );
+        }
     }
     catch( Exception& )
     {
diff --git a/oox/source/export/chartexport.cxx b/oox/source/export/chartexport.cxx
index 18b9a02bcd0d..142761afb89d 100644
--- a/oox/source/export/chartexport.cxx
+++ b/oox/source/export/chartexport.cxx
@@ -57,6 +57,8 @@
 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
 #include <com/sun/star/chart2/DataPointGeometry3D.hpp>
 #include <com/sun/star/chart2/DataPointLabel.hpp>
+#include <com/sun/star/chart2/DataPointCustomLabelField.hpp>
+#include <com/sun/star/chart2/DataPointCustomLabelFieldType.hpp>
 #include <com/sun/star/chart2/Symbol.hpp>
 #include <com/sun/star/chart2/data/XDataSource.hpp>
 #include <com/sun/star/chart2/data/XDataSink.hpp>
@@ -2955,17 +2957,111 @@ const char* toOOXMLPlacement( sal_Int32 nPlacement )
     return "outEnd";
 }
 
-void writeLabelProperties(
-    const FSHelperPtr& pFS, const uno::Reference<beans::XPropertySet>& xPropSet, const LabelPlacementParam& rLabelParam )
+OUString getFieldTypeString( const chart2::DataPointCustomLabelFieldType aType )
+{
+    switch (aType)
+    {
+    case chart2::DataPointCustomLabelFieldType_CATEGORYNAME:
+        return OUString("CATEGORYNAME");
+
+    case chart2::DataPointCustomLabelFieldType_SERIESNAME:
+        return OUString("SERIESNAME");
+
+    case chart2::DataPointCustomLabelFieldType_VALUE:
+        return OUString("VALUE");
+
+    case chart2::DataPointCustomLabelFieldType_CELLREF:
+        return OUString("CELLREF");
+
+    default:
+        break;
+    }
+    return OUString();
+}
+
+void writeRunProperties( ChartExport* pChartExport, Reference<XPropertySet>& xPropertySet )
+{
+    bool bDummy = false;
+    sal_Int32 nDummy;
+    pChartExport->WriteRunProperties(xPropertySet, false, XML_rPr, true, bDummy, nDummy);
+}
+
+void writeCustomLabel( const FSHelperPtr& pFS, ChartExport* pChartExport,
+                       const Sequence<Reference<chart2::XDataPointCustomLabelField>>& rCustomLabelFields )
+{
+    pFS->startElement(FSNS(XML_c, XML_tx), FSEND);
+    pFS->startElement(FSNS(XML_c, XML_rich), FSEND);
+
+    // TODO: body properties?
+    pFS->singleElement(FSNS(XML_a, XML_bodyPr), FSEND);
+
+    OUString sFieldType;
+    bool bNewParagraph;
+    pFS->startElement(FSNS(XML_a, XML_p), FSEND);
+
+    for (auto& rField : rCustomLabelFields)
+    {
+        Reference<XPropertySet> xPropertySet(rField, UNO_QUERY);
+        chart2::DataPointCustomLabelFieldType aType = rField->getFieldType();
+        sFieldType.clear();
+        bNewParagraph = false;
+
+        if (aType == chart2::DataPointCustomLabelFieldType_NEWLINE)
+            bNewParagraph = true;
+        else if (aType != chart2::DataPointCustomLabelFieldType_TEXT)
+            sFieldType = getFieldTypeString(aType);
+
+        if (bNewParagraph)
+        {
+            pFS->endElement(FSNS(XML_a, XML_p));
+            pFS->startElement(FSNS(XML_a, XML_p), FSEND);
+            continue;
+        }
+
+        if (sFieldType.isEmpty())
+        {
+            // Normal text run
+            pFS->startElement(FSNS(XML_a, XML_r), FSEND);
+            writeRunProperties(pChartExport, xPropertySet);
+
+            pFS->startElement(FSNS(XML_a, XML_t), FSEND);
+            pFS->writeEscaped(rField->getString());
+            pFS->endElement(FSNS(XML_a, XML_t));
+
+            pFS->endElement(FSNS(XML_a, XML_r));
+        }
+        else
+        {
+            // Field
+            pFS->startElement(FSNS(XML_a, XML_fld), XML_id, USS(rField->getGuid()), XML_type, USS(sFieldType), FSEND);
+            writeRunProperties(pChartExport, xPropertySet);
+
+            pFS->startElement(FSNS(XML_a, XML_t), FSEND);
+            pFS->writeEscaped(rField->getString());
+            pFS->endElement(FSNS(XML_a, XML_t));
+
+            pFS->endElement(FSNS(XML_a, XML_fld));
+        }
+    }
+
+    pFS->endElement(FSNS(XML_a, XML_p));
+    pFS->endElement(FSNS(XML_c, XML_rich));
+    pFS->endElement(FSNS(XML_c, XML_tx));
+}
+
+void writeLabelProperties( const FSHelperPtr& pFS, ChartExport* pChartExport,
+    const uno::Reference<beans::XPropertySet>& xPropSet, const LabelPlacementParam& rLabelParam )
 {
     if (!xPropSet.is())
         return;
 
     chart2::DataPointLabel aLabel;
+    Sequence<Reference<chart2::XDataPointCustomLabelField>> aCustomLabelFields;
     sal_Int32 nLabelBorderWidth = 0;
     sal_Int32 nLabelBorderColor = 0x00FFFFFF;
 
     xPropSet->getPropertyValue("Label") >>= aLabel;
+    xPropSet->getPropertyValue("CustomLabelFields") >>= aCustomLabelFields;
     xPropSet->getPropertyValue("LabelBorderWidth") >>= nLabelBorderWidth;
     xPropSet->getPropertyValue("LabelBorderColor") >>= nLabelBorderColor;
 
@@ -2986,6 +3082,9 @@ void writeLabelProperties(
         pFS->endElement(FSNS(XML_c, XML_spPr));
     }
 
+    if (aCustomLabelFields.getLength() > 0)
+        writeCustomLabel(pFS, pChartExport, aCustomLabelFields);
+
     if (rLabelParam.mbExport)
     {
         sal_Int32 nLabelPlacement = rLabelParam.meDefault;
@@ -3081,12 +3180,12 @@ void ChartExport::exportDataLabels(
         // Individual label property that overwrites the baseline.
         pFS->startElement(FSNS(XML_c, XML_dLbl), FSEND);
         pFS->singleElement(FSNS(XML_c, XML_idx), XML_val, I32S(nIdx), FSEND);
-        writeLabelProperties(pFS, xLabelPropSet, aParam);
+        writeLabelProperties(pFS, this, xLabelPropSet, aParam);
         pFS->endElement(FSNS(XML_c, XML_dLbl));
     }
 
     // Baseline label properties for all labels.
-    writeLabelProperties(pFS, xPropSet, aParam);
+    writeLabelProperties(pFS, this, xPropSet, aParam);
 
     pFS->singleElement(FSNS(XML_c, XML_showLeaderLines),
             XML_val, "0",
diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt
index f4ca60265708..c8715881b80e 100644
--- a/oox/source/token/properties.txt
+++ b/oox/source/token/properties.txt
@@ -278,6 +278,7 @@ LabelBorderWidth
 LabelPlacement
 LabelPosition
 LabelSeparator
+CustomLabelFields
 LayoutInfo
 LeftBorder
 LeftBorderDistance
diff --git a/sd/qa/unit/data/pptx/tdf114821.pptx b/sd/qa/unit/data/pptx/tdf114821.pptx
new file mode 100644
index 000000000000..3813b0607903
Binary files /dev/null and b/sd/qa/unit/data/pptx/tdf114821.pptx differ
diff --git a/sd/qa/unit/import-tests.cxx b/sd/qa/unit/import-tests.cxx
index 0796cebbaef0..221a92a5478a 100644
--- a/sd/qa/unit/import-tests.cxx
+++ b/sd/qa/unit/import-tests.cxx
@@ -56,6 +56,7 @@
 #include <com/sun/star/animations/XAnimationNode.hpp>
 #include <com/sun/star/animations/XAnimate.hpp>
 #include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/chart/DataLabelPlacement.hpp>
 #include <com/sun/star/chart/XChartDocument.hpp>
 #include <com/sun/star/chart2/XChartDocument.hpp>
 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
@@ -152,6 +153,7 @@ public:
     void testTdf108926();
     void testTdf115394();
     void testTdf115394PPT();
+    void testTdf114821();
 
     bool checkPattern(sd::DrawDocShellRef& rDocRef, int nShapeNumber, std::vector<sal_uInt8>& rExpected);
     void testPatternImport();
@@ -223,6 +225,7 @@ public:
     CPPUNIT_TEST(testTdf108926);
     CPPUNIT_TEST(testTdf115394);
     CPPUNIT_TEST(testTdf115394PPT);
+    CPPUNIT_TEST(testTdf114821);
 
     CPPUNIT_TEST_SUITE_END();
 };
@@ -2318,6 +2321,52 @@ void SdImportTest::testTdf115394PPT()
     xDocShRef->DoClose();
 }
 
+void SdImportTest::testTdf114821()
+{
+    css::uno::Any aAny;
+    sd::DrawDocShellRef xDocShRef = loadURL( m_directories.getURLFromSrc( "/sd/qa/unit/data/pptx/tdf114821.pptx" ), PPTX );
+
+    uno::Reference< beans::XPropertySet > xPropSet( getShapeFromPage( 0, 0, xDocShRef ) );
+    aAny = xPropSet->getPropertyValue( "Model" );
+    CPPUNIT_ASSERT_MESSAGE( "The shape doesn't have the property", aAny.hasValue() );
+
+    uno::Reference< chart::XChartDocument > xChartDoc;
+    aAny >>= xChartDoc;
+    CPPUNIT_ASSERT_MESSAGE( "failed to load chart", xChartDoc.is() );
+    uno::Reference< chart2::XChartDocument > xChart2Doc( xChartDoc, uno::UNO_QUERY );
+    CPPUNIT_ASSERT_MESSAGE( "failed to load chart", xChart2Doc.is() );
+
+    uno::Reference< chart2::XCoordinateSystemContainer > xBCooSysCnt( xChart2Doc->getFirstDiagram(), uno::UNO_QUERY );
+    uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > aCooSysSeq( xBCooSysCnt->getCoordinateSystems() );
+    uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[0], uno::UNO_QUERY );
+
+    uno::Reference< chart2::XDataSeriesContainer > xDSCnt( xCTCnt->getChartTypes()[0], uno::UNO_QUERY );
+    CPPUNIT_ASSERT_MESSAGE( "failed to load data series", xDSCnt.is() );
+    uno::Sequence< uno::Reference< chart2::XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries() );
+    CPPUNIT_ASSERT_EQUAL_MESSAGE( "Invalid Series count", static_cast<sal_Int32>( 1 ), aSeriesSeq.getLength() );
+
+    // Check the first label
+    const css::uno::Reference< css::beans::XPropertySet >& rPropSet0( aSeriesSeq[0]->getDataPointByIndex( 0 ) );
+    CPPUNIT_ASSERT( rPropSet0.is() );
+    sal_Int32 aPlacement;
+    rPropSet0->getPropertyValue( "LabelPlacement" ) >>= aPlacement;
+    CPPUNIT_ASSERT_EQUAL( css::chart::DataLabelPlacement::TOP, aPlacement );
+
+    // Check the second label
+    const css::uno::Reference< css::beans::XPropertySet >& rPropSet1( aSeriesSeq[0]->getDataPointByIndex( 1 ) );
+    CPPUNIT_ASSERT( rPropSet1.is() );
+    rPropSet1->getPropertyValue( "LabelPlacement" ) >>= aPlacement;
+    CPPUNIT_ASSERT_EQUAL( css::chart::DataLabelPlacement::CENTER, aPlacement );
+
+    // Check the third label
+    const css::uno::Reference< css::beans::XPropertySet >& rPropSet2( aSeriesSeq[0]->getDataPointByIndex( 2 ) );
+    CPPUNIT_ASSERT( rPropSet2.is() );
+    rPropSet2->getPropertyValue( "LabelPlacement") >>= aPlacement;
+    CPPUNIT_ASSERT_EQUAL( css::chart::DataLabelPlacement::TOP, aPlacement );
+
+    xDocShRef->DoClose();
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SdImportTest);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
commit 02aaacf21749099a58033ff5993e3644bccf6c97
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Mon Jan 29 16:20:46 2018 +0100

    DOCX import: handle horizontal flip of bitmaps
    
    Horizontal mirror on the UNO API level, mirror on the vertical axis
    internally.
    
    (cherry picked from commit 4bdbb5502f5995727017e22bb8a74b9f45552067)
    
    Conflicts:
            sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
    
    Change-Id: If142274a8f81a6875059a2651af6d8470870a36a

diff --git a/sw/qa/extras/ooxmlexport/data/graphic-object-fliph.docx b/sw/qa/extras/ooxmlexport/data/graphic-object-fliph.docx
new file mode 100644
index 000000000000..2f95a2b8583b
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/graphic-object-fliph.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
index 7fef2cd0e199..be729d8ecd33 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
@@ -641,6 +641,12 @@ DECLARE_OOXMLEXPORT_TEST(testWatermarkTrim, "tdf114308.docx")
     CPPUNIT_ASSERT_MESSAGE(ss.str(), nDifference >= -4);
 }
 
+DECLARE_OOXMLEXPORT_TEST(testGraphicObjectFliph, "graphic-object-fliph.docx")
+{
+    CPPUNIT_ASSERT(getProperty<bool>(getShape(1), "HoriMirroredOnEvenPages"));
+    CPPUNIT_ASSERT(getProperty<bool>(getShape(1), "HoriMirroredOnOddPages"));
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 4e819406fb68..2deae355d258 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -119,6 +119,7 @@
 #include <IDocumentSettingAccess.hxx>
 #include <IDocumentStylePoolAccess.hxx>
 #include <IDocumentRedlineAccess.hxx>
+#include <grfatr.hxx>
 
 #include <osl/file.hxx>
 #include <vcl/embeddedfontshelper.hxx>
@@ -4380,8 +4381,21 @@ void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode* pGrfNode, const Size
     m_pSerializer->startElementNS( XML_pic, XML_spPr,
             XML_bwMode, "auto",
             FSEND );
-    m_pSerializer->startElementNS( XML_a, XML_xfrm,
-            FSEND );
+
+    rtl::Reference<sax_fastparser::FastAttributeList> xFrameAttributes(
+        FastSerializerHelper::createAttrList());
+
+    if (pGrfNode)
+    {
+        sal_uInt16 eMirror = pGrfNode->GetSwAttrSet().GetMirrorGrf().GetValue();
+        if (eMirror == RES_MIRROR_GRAPH_VERT || eMirror == RES_MIRROR_GRAPH_BOTH)
+            // Mirror on the vertical axis is a horizontal flip.
+            xFrameAttributes->add(XML_flipH, "1");
+    }
+
+    m_pSerializer->startElementNS(
+        XML_a, XML_xfrm, uno::Reference<xml::sax::XFastAttributeList>(xFrameAttributes.get()));
+
     m_pSerializer->singleElementNS( XML_a, XML_off,
             XML_x, "0", XML_y, "0",
             FSEND );
diff --git a/writerfilter/source/dmapper/GraphicImport.cxx b/writerfilter/source/dmapper/GraphicImport.cxx
index 991b1461ed8d..5044454ddaef 100644
--- a/writerfilter/source/dmapper/GraphicImport.cxx
+++ b/writerfilter/source/dmapper/GraphicImport.cxx
@@ -1368,6 +1368,17 @@ uno::Reference< text::XTextContent > GraphicImport::createGraphicObject( const b
                 m_pImpl->applyMargins(xGraphicObjectProperties);
                 m_pImpl->applyName(xGraphicObjectProperties);
             }
+
+            // Handle horizontal flip.
+            bool bMirrored = false;
+            xShapeProps->getPropertyValue("IsMirrored") >>= bMirrored;
+            if (bMirrored)
+            {
+                xGraphicObjectProperties->setPropertyValue("HoriMirroredOnEvenPages",
+                                                           uno::makeAny(true));
+                xGraphicObjectProperties->setPropertyValue("HoriMirroredOnOddPages",
+                                                           uno::makeAny(true));
+            }
         }
     }
     catch( const uno::Exception& e )
commit 6c1100a596a1a3e544f25b400943d77f524604e2
Author: Szymon Kłos <szymon.klos at collabora.com>
Date:   Thu Feb 8 23:21:38 2018 +0100

    tdf#115394 correct transition in case of 0s
    
    Change-Id: I23d18acef0bd5db4a4ad6fc67d409e7ed5c93949
    Reviewed-on: https://gerrit.libreoffice.org/49462
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Szymon Kłos <szymon.klos at collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/49524
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/include/oox/ppt/slidetransitioncontext.hxx b/include/oox/ppt/slidetransitioncontext.hxx
index 4edaa3fcae9f..54b8d89ffb9b 100644
--- a/include/oox/ppt/slidetransitioncontext.hxx
+++ b/include/oox/ppt/slidetransitioncontext.hxx
@@ -47,6 +47,7 @@ namespace oox { namespace ppt {
     private:
         PropertyMap&                    maSlideProperties;
         bool                            mbHasTransition;
+        bool                            mbHasTransitionDuration;
         SlideTransition                 maTransition;
     };
 
diff --git a/oox/source/ppt/slidetransitioncontext.cxx b/oox/source/ppt/slidetransitioncontext.cxx
index bed6060d4d4a..bc2a56845b54 100644
--- a/oox/source/ppt/slidetransitioncontext.cxx
+++ b/oox/source/ppt/slidetransitioncontext.cxx
@@ -47,6 +47,7 @@ SlideTransitionContext::SlideTransitionContext( FragmentHandler2& rParent, const
 : FragmentHandler2( rParent )
 , maSlideProperties( aProperties )
 , mbHasTransition( false )
+, mbHasTransitionDuration( false )
 {
     // ST_TransitionSpeed
     maTransition.setOoxTransitionSpeed( rAttribs.getToken( XML_spd, XML_fast ) );
@@ -54,7 +55,13 @@ SlideTransitionContext::SlideTransitionContext( FragmentHandler2& rParent, const
     // p14:dur
     sal_Int32 nDurationInMs = rAttribs.getInteger( P14_TOKEN( dur ), -1 );
     if( nDurationInMs > -1 )
+    {
+        // In MSO 0 is visible as 0.01s
+        if( nDurationInMs == 0.0 )
+            nDurationInMs = 10;
         maTransition.setOoxTransitionSpeed( nDurationInMs / 1000.0 );
+        mbHasTransitionDuration = true;
+    }
 
     // TODO
     rAttribs.getBool( XML_advClick, true );
@@ -182,7 +189,7 @@ void SlideTransitionContext::onEndElement()
 {
     if( isCurrentElement(PPT_TOKEN( transition )) )
     {
-        if( mbHasTransition )
+        if( mbHasTransition || mbHasTransitionDuration )
         {
             maTransition.setSlideProperties( maSlideProperties );
             mbHasTransition = false;
diff --git a/sd/qa/unit/data/pptx/tdf115394-zero.pptx b/sd/qa/unit/data/pptx/tdf115394-zero.pptx
new file mode 100644
index 000000000000..e8fb0cfa240c
Binary files /dev/null and b/sd/qa/unit/data/pptx/tdf115394-zero.pptx differ
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx
index 59d1d0e7f424..80518487b96a 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -126,6 +126,7 @@ public:
     void testAccentColor();
     void testTdf114848();
     void testTdf115394();
+    void testTdf115394Zero();
 
     CPPUNIT_TEST_SUITE(SdOOXMLExportTest2);
 
@@ -173,6 +174,7 @@ public:
     CPPUNIT_TEST(testAccentColor);
     CPPUNIT_TEST(testTdf114848);
     CPPUNIT_TEST(testTdf115394);
+    CPPUNIT_TEST(testTdf115394Zero);
 
     CPPUNIT_TEST_SUITE_END();
 
@@ -1166,6 +1168,20 @@ void SdOOXMLExportTest2::testTdf115394()
     xDocShRef->DoClose();
 }
 
+void SdOOXMLExportTest2::testTdf115394Zero()
+{
+    sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc("/sd/qa/unit/data/pptx/tdf115394-zero.pptx"), PPTX);
+    utl::TempFile tempFile;
+    xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
+    double fTransitionDuration;
+
+    SdPage* pPage = xDocShRef->GetDoc()->GetSdPage(0, PageKind::Standard);
+    fTransitionDuration = pPage->getTransitionDuration();
+    CPPUNIT_ASSERT_EQUAL(0.01, fTransitionDuration);
+
+    xDocShRef->DoClose();
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest2);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx
index 07c290895970..9d6f3066b7e9 100644
--- a/sd/source/filter/eppt/pptx-epptooxml.cxx
+++ b/sd/source/filter/eppt/pptx-epptooxml.cxx
@@ -634,10 +634,6 @@ void PowerPointExport::WriteTransition( const FSHelperPtr& pFS )
         }
     }
 
-    // check if we resolved what transition to export
-    if (!nPPTTransitionType && !bOOXmlSpecificTransition)
-        return;
-
     AnimationSpeed animationSpeed = AnimationSpeed_MEDIUM;
     const char* speed = nullptr;
     sal_Int32 advanceTiming = -1;
@@ -695,7 +691,11 @@ void PowerPointExport::WriteTransition( const FSHelperPtr& pFS )
         }
     }
 
-    if( GETA( Change ) )
+    // check if we resolved what transition to export or time is set
+    if (!nPPTTransitionType && !bOOXmlSpecificTransition && !isTransitionDurationSet)
+        return;
+
+    if (GETA(Change))
         mAny >>= changeType;
 
     // 1 means automatic, 2 half automatic - not sure what it means - at least I don't see it in UI
commit 02fca905d44b85b1bc37139a907cb069dd49c52c
Author: Szymon Kłos <szymon.klos at collabora.com>
Date:   Mon Feb 5 12:41:58 2018 +0100

    tdf#115394 export custom transition time in PPTX
    
    Change-Id: Ib8f4cef713895029dc18f68a07baa4b65e4260c0
    Reviewed-on: https://gerrit.libreoffice.org/49245
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Szymon Kłos <szymon.klos at collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/49522
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx
index 3d1ad4f28b78..59d1d0e7f424 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -125,6 +125,7 @@ public:
     void testGroupsRotatedPosition();
     void testAccentColor();
     void testTdf114848();
+    void testTdf115394();
 
     CPPUNIT_TEST_SUITE(SdOOXMLExportTest2);
 
@@ -171,6 +172,7 @@ public:
     CPPUNIT_TEST(testGroupsRotatedPosition);
     CPPUNIT_TEST(testAccentColor);
     CPPUNIT_TEST(testTdf114848);
+    CPPUNIT_TEST(testTdf115394);
 
     CPPUNIT_TEST_SUITE_END();
 
@@ -1130,6 +1132,40 @@ void SdOOXMLExportTest2::testGroupRotation()
     assertXPath(pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:grpSp/p:sp[2]/p:spPr/a:xfrm", "rot", "20400000");
 }
 
+void SdOOXMLExportTest2::testTdf115394()
+{
+    sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc("/sd/qa/unit/data/pptx/tdf115394.pptx"), PPTX);
+    utl::TempFile tempFile;
+    xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
+    double fTransitionDuration;
+
+    // Slow in MS formats
+    SdPage* pPage1 = xDocShRef->GetDoc()->GetSdPage(0, PageKind::Standard);
+    fTransitionDuration = pPage1->getTransitionDuration();
+    CPPUNIT_ASSERT_EQUAL(1.0, fTransitionDuration);
+
+    // Medium in MS formats
+    SdPage* pPage2 = xDocShRef->GetDoc()->GetSdPage(1, PageKind::Standard);
+    fTransitionDuration = pPage2->getTransitionDuration();
+    CPPUNIT_ASSERT_EQUAL(0.75, fTransitionDuration);
+
+    // Fast in MS formats
+    SdPage* pPage3 = xDocShRef->GetDoc()->GetSdPage(2, PageKind::Standard);
+    fTransitionDuration = pPage3->getTransitionDuration();
+    CPPUNIT_ASSERT_EQUAL(0.5, fTransitionDuration);
+
+    // Custom values
+    SdPage* pPage4 = xDocShRef->GetDoc()->GetSdPage(3, PageKind::Standard);
+    fTransitionDuration = pPage4->getTransitionDuration();
+    CPPUNIT_ASSERT_EQUAL(0.25, fTransitionDuration);
+
+    SdPage* pPage5 = xDocShRef->GetDoc()->GetSdPage(4, PageKind::Standard);
+    fTransitionDuration = pPage5->getTransitionDuration();
+    CPPUNIT_ASSERT_EQUAL(4.25, fTransitionDuration);
+
+    xDocShRef->DoClose();
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest2);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx
index f61d7017382e..07c290895970 100644
--- a/sd/source/filter/eppt/pptx-epptooxml.cxx
+++ b/sd/source/filter/eppt/pptx-epptooxml.cxx
@@ -643,7 +643,43 @@ void PowerPointExport::WriteTransition( const FSHelperPtr& pFS )
     sal_Int32 advanceTiming = -1;
     sal_Int32 changeType = 0;
 
-    if( GETA( Speed ) ) {
+    sal_Int32 nTransitionDuration = -1;
+    bool isTransitionDurationSet = false;
+
+    // try to use TransitionDuration instead of old Speed property
+    if (GETA(TransitionDuration))
+    {
+        double fTransitionDuration = -1.0;
+        mAny >>= fTransitionDuration;
+        if (fTransitionDuration >= 0)
+        {
+            nTransitionDuration = fTransitionDuration * 1000.0;
+
+            // override values because in MS formats meaning of fast/medium/slow is different
+            if (nTransitionDuration <= 500)
+            {
+                // fast is default
+                speed = nullptr;
+            }
+            else if (nTransitionDuration >= 1000)
+            {
+                speed = "slow";
+            }
+            else
+            {
+                speed = "med";
+            }
+
+            bool isStandardValue = nTransitionDuration == 500
+                || nTransitionDuration == 750
+                || nTransitionDuration == 1000;
+
+            if(!isStandardValue)
+                isTransitionDurationSet = true;
+        }
+    }
+    else if (GETA(Speed))
+    {
         mAny >>= animationSpeed;
 
         switch( animationSpeed ) {
@@ -666,45 +702,6 @@ void PowerPointExport::WriteTransition( const FSHelperPtr& pFS )
     if( changeType == 1 && GETA( Duration ) )
         mAny >>= advanceTiming;
 
-    if (nTransition14 || pPresetTransition)
-    {
-        const char* pRequiresNS = nTransition14 ? "p14" : "p15";
-
-        pFS->startElement(FSNS(XML_mc, XML_AlternateContent), FSEND);
-        pFS->startElement(FSNS(XML_mc, XML_Choice), XML_Requires, pRequiresNS, FSEND);
-
-
-        pFS->startElementNS(XML_p, XML_transition,
-                            XML_spd, speed,
-                            XML_advTm, advanceTiming != -1 ? I32S( advanceTiming*1000 ) : nullptr,
-                            FSEND );
-
-        if (nTransition14)
-        {
-            pFS->singleElementNS(XML_p14, nTransition14,
-                                 XML_isInverted, pInverted,
-                                 XML_dir, pDirection14,
-                                 XML_pattern, pPattern,
-                                 FSEND );
-        }
-        else if (pPresetTransition)
-        {
-            pFS->singleElementNS(XML_p15, XML_prstTrans,
-                                 XML_prst, pPresetTransition,
-                                 FSEND );
-        }
-
-        pFS->endElement(FSNS(XML_p, XML_transition));
-
-        pFS->endElement(FSNS(XML_mc, XML_Choice));
-        pFS->startElement(FSNS(XML_mc, XML_Fallback), FSEND );
-    }
-
-    pFS->startElementNS(XML_p, XML_transition,
-                        XML_spd, speed,
-                        XML_advTm, advanceTiming != -1 ? I32S( advanceTiming*1000 ) : nullptr,
-                        FSEND );
-
     if (!bOOXmlSpecificTransition)
     {
         switch(nPPTTransitionType)
@@ -797,6 +794,78 @@ void PowerPointExport::WriteTransition( const FSHelperPtr& pFS )
         }
     }
 
+    bool isAdvanceTimingSet = advanceTiming != -1;
+    if (nTransition14 || pPresetTransition || isTransitionDurationSet)
+    {
+        const char* pRequiresNS = (nTransition14 || isTransitionDurationSet) ? "p14" : "p15";
+
+        pFS->startElement(FSNS(XML_mc, XML_AlternateContent), FSEND);
+        pFS->startElement(FSNS(XML_mc, XML_Choice), XML_Requires, pRequiresNS, FSEND);
+
+        if(isTransitionDurationSet && isAdvanceTimingSet)
+        {
+            pFS->startElementNS(XML_p, XML_transition,
+                XML_spd, speed,
+                XML_advTm, I32S(advanceTiming * 1000),
+                FSNS(XML_p14, XML_dur), I32S(nTransitionDuration),
+                FSEND);
+        }
+        else if(isTransitionDurationSet)
+        {
+            pFS->startElementNS(XML_p, XML_transition,
+                XML_spd, speed,
+                FSNS(XML_p14, XML_dur), I32S(nTransitionDuration),
+                FSEND);
+        }
+        else if(isAdvanceTimingSet)
+        {
+            pFS->startElementNS(XML_p, XML_transition,
+                XML_spd, speed,
+                XML_advTm, I32S(advanceTiming * 1000),
+                FSEND);
+        }
+        else
+        {
+            pFS->startElementNS(XML_p, XML_transition,
+                XML_spd, speed,
+                FSEND);
+        }
+
+        if (nTransition14)
+        {
+            pFS->singleElementNS(XML_p14, nTransition14,
+                XML_isInverted, pInverted,
+                XML_dir, pDirection14,
+                XML_pattern, pPattern,
+                FSEND);
+        }
+        else if (pPresetTransition)
+        {
+            pFS->singleElementNS(XML_p15, XML_prstTrans,
+                XML_prst, pPresetTransition,
+                FSEND);
+        }
+        else if (isTransitionDurationSet && nTransition)
+        {
+            pFS->singleElementNS(XML_p, nTransition,
+                XML_dir, pDirection,
+                XML_orient, pOrientation,
+                XML_spokes, pSpokes,
+                XML_thruBlk, pThruBlk,
+                FSEND);
+        }
+
+        pFS->endElement(FSNS(XML_p, XML_transition));
+
+        pFS->endElement(FSNS(XML_mc, XML_Choice));
+        pFS->startElement(FSNS(XML_mc, XML_Fallback), FSEND);
+    }
+
+    pFS->startElementNS(XML_p, XML_transition,
+        XML_spd, speed,
+        XML_advTm, isAdvanceTimingSet ? I32S(advanceTiming * 1000) : nullptr,
+        FSEND);
+
     if (nTransition)
     {
         pFS->singleElementNS( XML_p, nTransition,
@@ -809,7 +878,7 @@ void PowerPointExport::WriteTransition( const FSHelperPtr& pFS )
 
     pFS->endElementNS(XML_p, XML_transition);
 
-    if (nTransition14 || pPresetTransition)
+    if (nTransition14 || pPresetTransition || isTransitionDurationSet)
     {
         pFS->endElement(FSNS(XML_mc, XML_Fallback));
         pFS->endElement(FSNS(XML_mc, XML_AlternateContent));
commit 82bb1ac1a8cd76c3ead019a94e382120a7967f6d
Author: Szymon Kłos <szymon.klos at collabora.com>
Date:   Wed Feb 7 12:22:52 2018 +0100

    tdf#115394 export correct slide transition time in PPT
    
    Change-Id: Ie293dd4cc128c256e39d54fdcd83bb5e13484662
    Reviewed-on: https://gerrit.libreoffice.org/49345
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Szymon Kłos <szymon.klos at collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/49523
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/sd/qa/unit/data/ppt/tdf115394.ppt b/sd/qa/unit/data/ppt/tdf115394.ppt
new file mode 100644
index 000000000000..1fd299a5e4be
Binary files /dev/null and b/sd/qa/unit/data/ppt/tdf115394.ppt differ
diff --git a/sd/qa/unit/export-tests.cxx b/sd/qa/unit/export-tests.cxx
index f42673006e82..a1f067287de5 100644
--- a/sd/qa/unit/export-tests.cxx
+++ b/sd/qa/unit/export-tests.cxx
@@ -95,6 +95,7 @@ public:
     void testEmbeddedPdf();
     void testTdf100926();
     void testTextRotation();
+    void testTdf115394PPT();
 
     CPPUNIT_TEST_SUITE(SdExportTest);
 
@@ -112,6 +113,7 @@ public:
     CPPUNIT_TEST(testEmbeddedPdf);
     CPPUNIT_TEST(testTdf100926);
     CPPUNIT_TEST(testTextRotation);
+    CPPUNIT_TEST(testTdf115394PPT);
 
     CPPUNIT_TEST_SUITE_END();
 
@@ -708,6 +710,43 @@ void SdExportTest::testTextRotation()
     xDocShRef->DoClose();
 }
 
+void SdExportTest::testTdf115394PPT()
+{
+    sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/ppt/tdf115394.ppt"), PPT);
+
+    // Export the document and import again for a check
+    uno::Reference< lang::XComponent > xComponent(xDocShRef->GetModel(), uno::UNO_QUERY);
+    uno::Reference<frame::XStorable> xStorable(xComponent, uno::UNO_QUERY);
+    utl::MediaDescriptor aMediaDescriptor;
+    aMediaDescriptor["FilterName"] <<= OStringToOUString(OString(aFileFormats[PPT].pFilterName), RTL_TEXTENCODING_UTF8);
+
+    utl::TempFile aTempFile;
+    aTempFile.EnableKillingFile();
+    xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+    xComponent.set(xStorable, uno::UNO_QUERY);
+    xComponent->dispose();
+    xDocShRef = loadURL(aTempFile.GetURL(), PPT);
+
+    double fTransitionDuration;
+
+    // Fast
+    SdPage* pPage1 = xDocShRef->GetDoc()->GetSdPage(0, PageKind::Standard);
+    fTransitionDuration = pPage1->getTransitionDuration();
+    CPPUNIT_ASSERT_EQUAL(0.5, fTransitionDuration);
+
+    // Medium
+    SdPage* pPage2 = xDocShRef->GetDoc()->GetSdPage(1, PageKind::Standard);
+    fTransitionDuration = pPage2->getTransitionDuration();
+    CPPUNIT_ASSERT_EQUAL(0.75, fTransitionDuration);
+
+    // Slow
+    SdPage* pPage3 = xDocShRef->GetDoc()->GetSdPage(2, PageKind::Standard);
+    fTransitionDuration = pPage3->getTransitionDuration();
+    CPPUNIT_ASSERT_EQUAL(1.0, fTransitionDuration);
+
+    xDocShRef->DoClose();
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SdExportTest);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sd/qa/unit/import-tests.cxx b/sd/qa/unit/import-tests.cxx
index 187d678a2958..0796cebbaef0 100644
--- a/sd/qa/unit/import-tests.cxx
+++ b/sd/qa/unit/import-tests.cxx
@@ -151,6 +151,7 @@ public:
     void testActiveXCheckbox();
     void testTdf108926();
     void testTdf115394();
+    void testTdf115394PPT();
 
     bool checkPattern(sd::DrawDocShellRef& rDocRef, int nShapeNumber, std::vector<sal_uInt8>& rExpected);
     void testPatternImport();
@@ -221,6 +222,7 @@ public:
     CPPUNIT_TEST(testActiveXCheckbox);
     CPPUNIT_TEST(testTdf108926);
     CPPUNIT_TEST(testTdf115394);
+    CPPUNIT_TEST(testTdf115394PPT);
 
     CPPUNIT_TEST_SUITE_END();
 };
@@ -2293,6 +2295,29 @@ void SdImportTest::testTdf115394()
     xDocShRef->DoClose();
 }
 
+void SdImportTest::testTdf115394PPT()
+{
+    sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc("/sd/qa/unit/data/ppt/tdf115394.ppt"), PPT);
+    double fTransitionDuration;
+
+    // Fast
+    SdPage* pPage1 = xDocShRef->GetDoc()->GetSdPage(0, PageKind::Standard);
+    fTransitionDuration = pPage1->getTransitionDuration();
+    CPPUNIT_ASSERT_EQUAL(0.5, fTransitionDuration);
+
+    // Medium
+    SdPage* pPage2 = xDocShRef->GetDoc()->GetSdPage(1, PageKind::Standard);
+    fTransitionDuration = pPage2->getTransitionDuration();
+    CPPUNIT_ASSERT_EQUAL(0.75, fTransitionDuration);
+
+    // Slow
+    SdPage* pPage3 = xDocShRef->GetDoc()->GetSdPage(2, PageKind::Standard);
+    fTransitionDuration = pPage3->getTransitionDuration();
+    CPPUNIT_ASSERT_EQUAL(1.0, fTransitionDuration);
+
+    xDocShRef->DoClose();
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SdImportTest);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sd/source/filter/eppt/eppt.cxx b/sd/source/filter/eppt/eppt.cxx
index 96556e6280a7..0e2df631615c 100644
--- a/sd/source/filter/eppt/eppt.cxx
+++ b/sd/source/filter/eppt/eppt.cxx
@@ -242,11 +242,31 @@ void PPTWriter::ImplWriteSlide( sal_uInt32 nPageNum, sal_uInt32 nMasterNum, sal_
         sal_Int32   nSlideTime = 0;         // still has to !!!
         sal_uInt8   nSpeed = 1;
 
-        if ( GetPropertyValue( aAny, mXPagePropSet, "Speed" ) )
+        if ( GetPropertyValue( aAny, mXPagePropSet, "TransitionDuration" ) )
         {
             css::presentation::AnimationSpeed aAs;
-            aAny >>= aAs;
-            nSpeed = (sal_uInt8)aAs;
+            double fTransitionDuration = -1.0;
+            aAny >>= fTransitionDuration;
+
+            if (fTransitionDuration >= 0)
+            {
+                if (fTransitionDuration <= 0.5)
+                {
+                    aAs = css::presentation::AnimationSpeed::AnimationSpeed_FAST;
+                }
+                else if (fTransitionDuration >= 1.0)
+                {
+                    aAs = css::presentation::AnimationSpeed::AnimationSpeed_SLOW;
+                }
+                else
+                {
+                    aAs = css::presentation::AnimationSpeed::AnimationSpeed_MEDIUM;
+                }
+            }
+            else
+                aAs = css::presentation::AnimationSpeed::AnimationSpeed_MEDIUM;
+
+            nSpeed = static_cast<sal_uInt8>(aAs);
         }
         sal_Int16 nTT = 0;
         if ( GetPropertyValue( aAny, mXPagePropSet, "TransitionType" )
diff --git a/sd/source/filter/ppt/pptin.cxx b/sd/source/filter/ppt/pptin.cxx
index 755ea064ac68..f54b6afe0d2e 100644
--- a/sd/source/filter/ppt/pptin.cxx
+++ b/sd/source/filter/ppt/pptin.cxx
@@ -1777,11 +1777,11 @@ void ImplSdPPTImport::ImportPageEffect( SdPage* pPage, const bool bNewAnimations
                                 }
 
                                 if ( nSpeed == 0 )
-                                    pPage->setTransitionDuration( 3.0 );    // slow
+                                    pPage->setTransitionDuration( 1.0 );    // slow
                                 else if ( nSpeed == 1 )
-                                    pPage->setTransitionDuration( 2.0 );    // medium
+                                    pPage->setTransitionDuration( 0.75 );    // medium
                                 else if ( nSpeed == 2 )
-                                    pPage->setTransitionDuration( 1.0 );    // fast
+                                    pPage->setTransitionDuration( 0.5 );    // fast
 
                                 if ( nBuildFlags & 0x400 )                      // slidechange by time
                                 {   // time to show (in Ticks)
commit 384025dde281510ad9b9e6df9eab5eea00e848c7
Author: Szymon Kłos <szymon.klos at collabora.com>
Date:   Fri Feb 2 10:21:50 2018 +0100

    tdf#115394 import custom slide transition time in PPTX
    
    * custom values are imported correctly
    * standard (fast, slow, medium) values are changed
      to match values in the MSO
    
    Change-Id: I004242afbbf641fe414abc8df248a2844c104502
    Reviewed-on: https://gerrit.libreoffice.org/49139
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Szymon Kłos <szymon.klos at collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/49521
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/include/oox/ppt/slidetransition.hxx b/include/oox/ppt/slidetransition.hxx
index 41df7b2f7948..e0383aaf154f 100644
--- a/include/oox/ppt/slidetransition.hxx
+++ b/include/oox/ppt/slidetransition.hxx
@@ -42,7 +42,10 @@ namespace oox { namespace ppt {
         void setSlideProperties( PropertyMap& props );
         void setTransitionFilterProperties( const css::uno::Reference< css::animations::XTransitionFilter > & xFilter );
 
+        /// Set one of standard values for slide transition duration
         void setOoxTransitionSpeed( sal_Int32 nToken );
+        /// Set slide transition time directly
+        void setOoxTransitionSpeed( double fDuration );
         void setMode( bool bMode )
             { mbMode = bMode; }
         void setOoxAdvanceTime( sal_Int32 nAdvanceTime )
@@ -66,6 +69,7 @@ namespace oox { namespace ppt {
         bool  mbTransitionDirectionNormal;
         ::sal_Int16 mnAnimationSpeed;
         ::sal_Int32 mnFadeColor;
+        double mfTransitionDurationInSeconds;
         bool  mbMode; /**< http://api.libreoffice.org/docs/common/ref/com/sun/star/animations/XTransitionFilter.html Mode property */
         ::sal_Int32 mnAdvanceTime;
     };
diff --git a/offapi/com/sun/star/presentation/DrawPage.idl b/offapi/com/sun/star/presentation/DrawPage.idl
index 18e499e81420..0e070470ad25 100644
--- a/offapi/com/sun/star/presentation/DrawPage.idl
+++ b/offapi/com/sun/star/presentation/DrawPage.idl
@@ -79,11 +79,11 @@ published service DrawPage
     [property] short Layout;
 
 
-    /** defines the speed of the fade-in effect of this page.
+    /** Defines the speed of the fade-in effect of this page.
+        @see TransitionSpeed
      */
     [property] com::sun::star::presentation::AnimationSpeed Speed;
 
-
     /** defines if a header presentation shape from the master page is visible
         on this page.
     */
@@ -142,6 +142,11 @@ published service DrawPage
     */
     [optional, property] long DateTimeFormat;
 
+    /** Specifies slide transition time in seconds.
+        @since LibreOffice 6.1
+        @see Speed
+     */
+    [property, optional] double TransitionDuration;
 };
 
 
diff --git a/oox/source/ppt/slidetransition.cxx b/oox/source/ppt/slidetransition.cxx
index 9ae715fa49c0..dc2dbf923b67 100644
--- a/oox/source/ppt/slidetransition.cxx
+++ b/oox/source/ppt/slidetransition.cxx
@@ -47,6 +47,7 @@ namespace oox { namespace ppt {
         , mbTransitionDirectionNormal( true )
         , mnAnimationSpeed( AnimationSpeed_FAST )
         , mnFadeColor( 0 )
+        , mfTransitionDurationInSeconds( -1.0 )
         , mbMode( true )
         , mnAdvanceTime( -1 )
     {
@@ -59,6 +60,7 @@ namespace oox { namespace ppt {
         , mbTransitionDirectionNormal( true )
         , mnAnimationSpeed( AnimationSpeed_FAST )
         , mnFadeColor( 0 )
+        , mfTransitionDurationInSeconds( -1.0 )
         , mbMode( true )
         , mnAdvanceTime( -1 )
     {
@@ -79,11 +81,13 @@ namespace oox { namespace ppt {
             aProps.setProperty( PROP_TransitionSubtype, mnTransitionSubType);
             aProps.setProperty( PROP_TransitionDirection, mbTransitionDirectionNormal);
             aProps.setProperty( PROP_Speed, mnAnimationSpeed);
+            if( mfTransitionDurationInSeconds >= 0.0 )
+                aProps.setProperty( PROP_TransitionDuration, mfTransitionDurationInSeconds);
             aProps.setProperty( PROP_TransitionFadeColor, mnFadeColor);
-        if( mnAdvanceTime != -1 ) {
-        aProps.setProperty( PROP_Duration, mnAdvanceTime/1000);
-        aProps.setProperty( PROP_Change, static_cast<sal_Int32>(1));
-        }
+            if( mnAdvanceTime != -1 ) {
+                aProps.setProperty( PROP_Duration, mnAdvanceTime/1000);
+                aProps.setProperty( PROP_Change, static_cast<sal_Int32>(1));
+            }
         }
         catch( Exception& )
         {
@@ -113,19 +117,21 @@ namespace oox { namespace ppt {
     {
         switch( nToken  )
         {
-            /* In case you want to use time values in second,
-             * the speed values are located in the PPT97 importer
-             * sd/source/filter/ppt/ppt97animations.cxx:664

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list