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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> Reviewed-by: Szymon Kłos <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/49524 Reviewed-by: Andras Timar <[email protected]> Tested-by: Andras Timar <[email protected]> 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 <[email protected]> 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 <[email protected]> Reviewed-by: Szymon Kłos <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/49522 Reviewed-by: Andras Timar <[email protected]> Tested-by: Andras Timar <[email protected]> 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 <[email protected]> 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 <[email protected]> Reviewed-by: Szymon Kłos <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/49523 Reviewed-by: Andras Timar <[email protected]> Tested-by: Andras Timar <[email protected]> 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 <[email protected]> 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 <[email protected]> Reviewed-by: Szymon Kłos <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/49521 Reviewed-by: Andras Timar <[email protected]> Tested-by: Andras Timar <[email protected]> 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 _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
