diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /chart2/qa/extras/chart2dump/chart2dump.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'chart2/qa/extras/chart2dump/chart2dump.cxx')
-rw-r--r-- | chart2/qa/extras/chart2dump/chart2dump.cxx | 1123 |
1 files changed, 1123 insertions, 0 deletions
diff --git a/chart2/qa/extras/chart2dump/chart2dump.cxx b/chart2/qa/extras/chart2dump/chart2dump.cxx new file mode 100644 index 000000000..faaa3ccd9 --- /dev/null +++ b/chart2/qa/extras/chart2dump/chart2dump.cxx @@ -0,0 +1,1123 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + */ + +#include <charttest.hxx> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart/XChartDocument.hpp> +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/drawing/HomogenMatrix3.hpp> +#include <com/sun/star/drawing/LineDash.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> + +#include <editeng/unoprnms.hxx> +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> + +#include <fstream> +#include <string_view> + +#if defined(X86) +#define INT_EPS 2.1 +#else +#define INT_EPS 0.1 +#endif + +#define DECLARE_DUMP_TEST(TestName, BaseClass, DumpMode) \ + class TestName : public BaseClass { \ + protected:\ + virtual OUString getTestName() override { return #TestName; } \ + public:\ + TestName() : BaseClass(DumpMode) {}; \ + CPPUNIT_TEST_SUITE(TestName); \ + CPPUNIT_TEST(verify); \ + CPPUNIT_TEST_SUITE_END(); \ + virtual void verify() override;\ + };\ + CPPUNIT_TEST_SUITE_REGISTRATION(TestName); \ + void TestName::verify() + + +#define CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(aActual) \ + if(isInDumpMode()) \ + writeActual(OUString::number(aActual), #aActual); \ + else \ + { \ + OString sTestFileName = OUStringToOString(getTestFileName(), RTL_TEXTENCODING_UTF8); \ + CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("Failing test file is: " + sTestFileName).getStr(), readExpected(u ## #aActual), OUString(OUString::number(aActual))); \ + } + +#define CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aActual, EPS_) \ + if(isInDumpMode()) \ + writeActual(OUString::number(aActual), #aActual); \ + else \ + { \ + OString sTestFileName = OUStringToOString(getTestFileName(), RTL_TEXTENCODING_UTF8); \ + CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(OString("Failing test file is: " + sTestFileName).getStr(), readExpectedDouble(u ## #aActual), aActual, EPS_); \ + } + +#define CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(aActual) \ + if(isInDumpMode()) \ + writeActual(aActual, #aActual); \ + else \ + { \ + OString sTestFileName = OUStringToOString(getTestFileName(), RTL_TEXTENCODING_UTF8); \ + CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("Failing test file is: " + sTestFileName).getStr(), readExpected(u ## #aActual), aActual.trim()); \ + } + +#define CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aActual, EPS_) \ + if(isInDumpMode()) \ + writeActualTransformation(aActual, #aActual); \ + else \ + { \ + OUString expectedTransform; \ + if (!readAndCheckTransformation (aActual, u ## #aActual, EPS_, expectedTransform)) \ + { \ + OString sTestFileName = OUStringToOString(getTestFileName(), RTL_TEXTENCODING_UTF8); \ + CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("Failing test file is: " + sTestFileName).getStr(), expectedTransform, transformationToOneLineString(aActual)); \ + } \ + } + +class Chart2DumpTest : public ChartTest +{ +protected: + Chart2DumpTest(bool bDumpMode) + { + m_bDumpMode = bDumpMode; + } + + virtual ~Chart2DumpTest() override + { + } + + void CPPUNIT_DUMP_ASSERT_NOTE(OUString const & Note) { + if(isInDumpMode()) + writeNote(Note); + else + readNote(Note); + } + + bool isInDumpMode () const {return m_bDumpMode;} + + virtual OUString getTestName() { return OUString(); } + OUString const & getTestFileName() const { return m_sTestFileName; } + OUString getTestFileDirName() const { return "/chart2/qa/extras/chart2dump/data/"; } + OUString getReferenceDirName() + { + return "/chart2/qa/extras/chart2dump/reference/" + getTestName().toAsciiLowerCase() + "/"; + } + + void setTestFileName (const OUString& sName) + { + m_sTestFileName = sName; + + OUString sFileName = m_sTestFileName; + assert(sFileName.lastIndexOf('.') < sFileName.getLength()); + sFileName = OUString::Concat(sFileName.subView(0, sFileName.lastIndexOf('.'))) + ".txt"; + if (!m_bDumpMode) + { + if (m_aReferenceFile.is_open()) + m_aReferenceFile.close(); + OString sReferenceFile = OUStringToOString(OUStringConcatenation(m_directories.getPathFromSrc(getReferenceDirName()) + sFileName), RTL_TEXTENCODING_UTF8); + m_aReferenceFile.open(sReferenceFile.getStr(), std::ios_base::in); + CPPUNIT_ASSERT_MESSAGE(OString("Can't open reference file: " + sReferenceFile).getStr(), m_aReferenceFile.is_open()); + } + else + { + if (m_aDumpFile.is_open()) + m_aDumpFile.close(); + OString sDumpFile = OUStringToOString(OUStringConcatenation(m_directories.getPathFromSrc(getReferenceDirName()) + sFileName), RTL_TEXTENCODING_UTF8); + m_aDumpFile.open(sDumpFile.getStr(), std::ios_base::out | std::ofstream::binary | std::ofstream::trunc); + CPPUNIT_ASSERT_MESSAGE(OString("Can't open dump file: " + sDumpFile).getStr(), m_aDumpFile.is_open()); + } + } + + virtual void verify() + { + CPPUNIT_FAIL("verify method must be overridden"); + } + + OUString readExpected(std::u16string_view sCheck) + { + assert(!m_bDumpMode); + assert(m_aReferenceFile.is_open()); + std::string sTemp; + getline(m_aReferenceFile, sTemp); + OString sAssertMessage = + "The reference file does not contain the right content. Maybe it needs an update:" + + OUStringToOString(m_sTestFileName, RTL_TEXTENCODING_UTF8); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sAssertMessage.getStr(), OUString(OUString::Concat("// ") + sCheck), OUString(sTemp.data(), sTemp.length(), RTL_TEXTENCODING_UTF8)); + getline(m_aReferenceFile, sTemp); + return OUString(sTemp.data(), sTemp.length(), RTL_TEXTENCODING_UTF8); + } + + void writeActual(std::u16string_view sActualValue, const OUString& sCheck) + { + assert(m_bDumpMode); + assert(m_aDumpFile.is_open()); + m_aDumpFile << "// " << sCheck << "\n"; // Add check string to make dump file readable + m_aDumpFile << OUString(sActualValue) << "\n"; // Write out the checked value, will be used as reference later + } + + void readNote(std::u16string_view sNote) + { + assert(!m_bDumpMode); + assert(m_aReferenceFile.is_open()); + std::string sTemp; + getline(m_aReferenceFile, sTemp); + OString sAssertMessage = + "The reference file does not contain the right content. Maybe it needs an update:" + + OUStringToOString(m_sTestFileName, RTL_TEXTENCODING_UTF8); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sAssertMessage.getStr(), OUString(OUString::Concat("/// ") + sNote), OUString(sTemp.data(), sTemp.length(), RTL_TEXTENCODING_UTF8)); + } + + void writeNote(const OUString& sNote) + { + assert(m_bDumpMode); + assert(m_aDumpFile.is_open()); + m_aDumpFile << "/// " << sNote << "\n"; + } + + double readExpectedDouble(std::u16string_view sCheck) + { + OUString sExpected = readExpected(sCheck); + return sExpected.toDouble(); + } + + void writeActualTransformation(const drawing::HomogenMatrix3& rTransform, const OUString& sCheck) + { + writeActual(transformationToOneLineString(rTransform), sCheck); + } + + bool readAndCheckTransformation(const drawing::HomogenMatrix3& rTransform, std::u16string_view sCheck, const double fEPS, OUString& rExpectedTransform) + { + rExpectedTransform = readExpected(sCheck); // Reference transformation string + + // Convert string back to a transformation; + drawing::HomogenMatrix3 aExpectedTransform; + sal_Int32 nIdx {0}; + aExpectedTransform.Line1.Column1 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx)); + aExpectedTransform.Line1.Column2 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx)); + aExpectedTransform.Line1.Column3 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx)); + aExpectedTransform.Line2.Column1 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx)); + aExpectedTransform.Line2.Column2 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx)); + aExpectedTransform.Line2.Column3 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx)); + aExpectedTransform.Line3.Column1 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx)); + aExpectedTransform.Line3.Column2 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx)); + aExpectedTransform.Line3.Column3 = o3tl::toDouble(o3tl::getToken(rExpectedTransform, 0, ';', nIdx)); + + // Check the equality of the two transformation + return (std::abs(aExpectedTransform.Line1.Column1 - rTransform.Line1.Column1) < fEPS && + std::abs(aExpectedTransform.Line1.Column2 - rTransform.Line1.Column2) < fEPS && + std::abs(aExpectedTransform.Line1.Column3 - rTransform.Line1.Column3) < fEPS && + std::abs(aExpectedTransform.Line2.Column1 - rTransform.Line2.Column1) < fEPS && + std::abs(aExpectedTransform.Line2.Column2 - rTransform.Line2.Column2) < fEPS && + std::abs(aExpectedTransform.Line2.Column3 - rTransform.Line2.Column3) < fEPS && + std::abs(aExpectedTransform.Line3.Column1 - rTransform.Line3.Column1) < fEPS && + std::abs(aExpectedTransform.Line3.Column2 - rTransform.Line3.Column2) < fEPS && + std::abs(aExpectedTransform.Line3.Column3 - rTransform.Line3.Column3) < fEPS); + } + + OUString sequenceToOneLineString(const uno::Sequence<OUString>& rSeq) + { + OUStringBuffer aBuffer; + for (const OUString& seqItem : rSeq) + { + aBuffer.append(seqItem + ";"); + } + return aBuffer.makeStringAndClear(); + } + + OUString doubleVectorToOneLineString(const std::vector<double>& rVector) + { + OUStringBuffer aBuffer; + for (const double& vectorItem : rVector) + { + aBuffer.append(OUString::number(vectorItem) + ";"); + } + return aBuffer.makeStringAndClear(); + } + + OUString transformationToOneLineString(const drawing::HomogenMatrix3& rTransform) + { + return OUString::number(rTransform.Line1.Column1) + ";" + OUString::number(rTransform.Line1.Column2) + ";" + OUString::number(rTransform.Line1.Column3) + ";" + + OUString::number(rTransform.Line2.Column1) + ";" + OUString::number(rTransform.Line2.Column2) + ";" + OUString::number(rTransform.Line2.Column3) + ";" + + OUString::number(rTransform.Line3.Column1) + ";" + OUString::number(rTransform.Line3.Column2) + ";" + OUString::number(rTransform.Line3.Column3); + } + +private: + OUString m_sTestFileName; + bool m_bDumpMode; + std::ifstream m_aReferenceFile; + std::ofstream m_aDumpFile; +}; + +DECLARE_DUMP_TEST(ChartDataTest, Chart2DumpTest, false) +{ + const std::vector<OUString> aTestFiles = + { + "simple_chart.ods", + "multiple_categories.ods" + }; + + for (const OUString& aTestFile : aTestFiles) + { + setTestFileName(aTestFile); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc (getChartDocFromSheet(0, mxComponent), UNO_QUERY_THROW); + + // Check title + uno::Reference< chart2::XChartDocument > xChartDoc2(xChartDoc, UNO_QUERY_THROW); + Reference<chart2::XTitled> xTitled(xChartDoc, uno::UNO_QUERY_THROW); + uno::Reference<chart2::XTitle> xTitle = xTitled->getTitleObject(); + if(xTitle.is()) + { + OUString sChartTitle = getTitleString(xTitled); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sChartTitle); + } + + // Check chart type + Reference<chart2::XChartType> xChartType = getChartTypeFromDoc(xChartDoc2, 0); + CPPUNIT_ASSERT(xChartType.is()); + OUString sChartType = xChartType->getChartType(); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sChartType); + + // Check axis titles and number format + // x Axis + Reference<chart2::XAxis> xAxis = getAxisFromDoc(xChartDoc2, 0, 0, 0); + Reference<chart2::XTitled> xAxisTitled(xAxis, UNO_QUERY_THROW); + uno::Reference<chart2::XTitle> xAxisTitle = xAxisTitled->getTitleObject(); + if (xAxisTitle.is()) + { + OUString sXAxisTitle = getTitleString(xAxisTitled); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sXAxisTitle); + } + sal_Int32 nXAxisNumberFormat = getNumberFormatFromAxis(xAxis); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nXAxisNumberFormat); + sal_Int16 nXAxisNumberType = getNumberFormatType(xChartDoc2, nXAxisNumberFormat); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nXAxisNumberType); + + // y Axis + xAxis.set(getAxisFromDoc(xChartDoc2, 0, 1, 0)); + xAxisTitled.set(xAxis, UNO_QUERY_THROW); + xAxisTitle.set(xAxisTitled->getTitleObject()); + if (xAxisTitle.is()) + { + OUString sYAxisTitle = getTitleString(xAxisTitled); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sYAxisTitle); + } + sal_Int32 nYAxisNumberFormat = getNumberFormatFromAxis(xAxis); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nYAxisNumberFormat); + sal_Int16 nYAxisNumberType = getNumberFormatType(xChartDoc2, nYAxisNumberFormat); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nYAxisNumberType); + + // Check column labels + uno::Reference< chart::XChartDataArray > xChartData(xChartDoc->getData(), UNO_QUERY_THROW); + uno::Sequence < OUString > aColumnLabels = xChartData->getColumnDescriptions(); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(aColumnLabels.getLength()); + OUString sColumnLabels = sequenceToOneLineString(aColumnLabels); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sColumnLabels); + + // Check row labels + uno::Sequence< OUString > aRowLabels = xChartData->getRowDescriptions(); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(aRowLabels.getLength()); + OUString sRowLabels = sequenceToOneLineString(aRowLabels); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sRowLabels); + + // Check Y values + std::vector<std::vector<double> > aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(aDataSeriesYValues.size()); + for (const std::vector<double>& aYValuesOfSeries : aDataSeriesYValues) + { + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(aYValuesOfSeries.size()); + OUString sYValuesOfSeries = doubleVectorToOneLineString(aYValuesOfSeries); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sYValuesOfSeries); + } + + // Check source ranges + for (size_t nIndex = 0; nIndex < aDataSeriesYValues.size(); ++nIndex) + { + Reference< chart2::data::XDataSequence > xDataSeq = getDataSequenceFromDocByRole(xChartDoc2, u"values-x", nIndex); + if (xDataSeq.is()) + { + OUString aXValuesSourceRange = xDataSeq->getSourceRangeRepresentation(); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(aXValuesSourceRange); + } + xDataSeq.set(getDataSequenceFromDocByRole(xChartDoc2, u"values-y", nIndex)); + if (xDataSeq.is()) + { + OUString aYValuesSourceRange = xDataSeq->getSourceRangeRepresentation(); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(aYValuesSourceRange); + } + xDataSeq.set(getDataSequenceFromDocByRole(xChartDoc2, u"categories", nIndex)); + if (xDataSeq.is()) + { + OUString aCategoriesSourceRange = xDataSeq->getSourceRangeRepresentation(); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(aCategoriesSourceRange); + } + } + } +} + +DECLARE_DUMP_TEST(LegendTest, Chart2DumpTest, false) +{ + const std::vector<OUString> aTestFiles = + { + "legend_on_right_side.odp", + "legend_on_bottom.odp", + "legend_on_left_side.odp", + "legend_on_top.odp", + "many_legend_entries.odp", + "custom_legend_position.odp", + "multiple_categories.odp", + "minimal_legend_test.odp" + }; + + for (const OUString& aTestFile : aTestFiles) + { + setTestFileName(aTestFile); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromDrawImpress(0, 0), UNO_SET_THROW); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + // Get legend shape + uno::Reference<drawing::XShape> xLegend = getShapeByName(xShapes, "CID/D=0:Legend="); + CPPUNIT_ASSERT(xLegend.is()); + + /* Check legend position and size + awt::Point aLegendPosition = xLegend->getPosition(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLegendPosition.X, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLegendPosition.Y, INT_EPS); + awt::Size aLegendSize = xLegend->getSize(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLegendSize.Width, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLegendSize.Height, INT_EPS);*/ + + // Check legend entries + uno::Reference< chart2::XChartDocument > xChartDoc2(xChartDoc, UNO_QUERY_THROW); + Reference<chart2::XChartType> xChartType = getChartTypeFromDoc(xChartDoc2, 0); + CPPUNIT_ASSERT(xChartType.is()); + std::vector<std::vector<double> > aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType); + size_t nLegendEntryCount = aDataSeriesYValues.size(); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nLegendEntryCount); + // Check legend entries geometry + for (size_t nSeriesIndex = 0; nSeriesIndex < nLegendEntryCount; ++nSeriesIndex) + { + uno::Reference<drawing::XShape> xLegendEntry = getShapeByName(xShapes, "CID/MultiClick/D=0:CS=0:CT=0:Series=" + OUString::number(nSeriesIndex) + ":LegendEntry=0"); + CPPUNIT_ASSERT(xLegendEntry.is()); + + /* Check position and size + awt::Point aLegendEntryPosition = xLegendEntry->getPosition(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLegendEntryPosition.X, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLegendEntryPosition.Y, INT_EPS); + awt::Size aLegendEntrySize = xLegendEntry->getSize(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLegendEntrySize.Height, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLegendEntrySize.Width, INT_EPS); + + // Check transformation + Reference< beans::XPropertySet > xLegendEntryPropSet(xLegendEntry, UNO_QUERY_THROW); + drawing::HomogenMatrix3 aLegendEntryTransformation; + xLegendEntryPropSet->getPropertyValue("Transformation") >>= aLegendEntryTransformation; + CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aLegendEntryTransformation, INT_EPS);*/ + + uno::Reference<container::XIndexAccess> xLegendEntryContainer(xLegendEntry, UNO_QUERY_THROW); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(xLegendEntryContainer->getCount()); + for (sal_Int32 nEntryGeometryElement = 1; nEntryGeometryElement < xLegendEntryContainer->getCount(); ++nEntryGeometryElement) + { + uno::Reference<drawing::XShape> xLegendEntryGeom(xLegendEntryContainer->getByIndex(nEntryGeometryElement), UNO_QUERY_THROW); + + // Check geometry + uno::Reference< drawing::XShapeDescriptor > xShapeDescriptor(xLegendEntryGeom, uno::UNO_QUERY_THROW); + OUString sEntryGeomShapeType = xShapeDescriptor->getShapeType(); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sEntryGeomShapeType); + + // Check display color + Reference< beans::XPropertySet > xPropSet(xLegendEntryGeom, UNO_QUERY_THROW); + util::Color aEntryGeomColor = 0; + xPropSet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= aEntryGeomColor; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aEntryGeomColor)); + } + } + // Check legend entries' text + uno::Reference<container::XIndexAccess> xLegendContainer(xLegend, UNO_QUERY_THROW); + for (sal_Int32 i = 0; i < xLegendContainer->getCount(); ++i) + { + uno::Reference<drawing::XShape> xShape(xLegendContainer->getByIndex(i), uno::UNO_QUERY); + uno::Reference< drawing::XShapeDescriptor > xShapeDescriptor(xShape, uno::UNO_QUERY_THROW); + OUString sShapeType = xShapeDescriptor->getShapeType(); + + if (sShapeType == "com.sun.star.drawing.TextShape") + { + uno::Reference<text::XText> xLegendEntryText = uno::Reference<text::XTextRange>(xShape, uno::UNO_QUERY_THROW)->getText(); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(xLegendEntryText->getString()); + } + } + } +} + +DECLARE_DUMP_TEST(GridTest, Chart2DumpTest, false) +{ + const std::vector<OUString> aTestFiles = + { + "vertical_grid.ods", + "horizontal_grid.ods", + "minor_grid.ods", + "formated_grid_line.ods" + }; + + for (const OUString& sTestFile : aTestFiles) + { + setTestFileName(sTestFile); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromSheet(0, mxComponent), UNO_QUERY_THROW); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + const std::vector<OUString> aGridShapeNames = + { + "CID/D=0:CS=0:Axis=1,0:Grid=0", // Major vertical grid + "CID/D=0:CS=0:Axis=0,0:Grid=0", // Major horizontal grid + "CID/D=0:CS=0:Axis=1,0:Grid=0:SubGrid=0", // Minor vertical grid + "CID/D=0:CS=0:Axis=0,0:Grid=0:SubGrid=0" // Minor horizontal grid + }; + + for (const OUString& sGridShapeName : aGridShapeNames) + { + uno::Reference<drawing::XShape> xGrid = getShapeByName(xShapes, sGridShapeName); + if (xGrid.is()) + { + CPPUNIT_DUMP_ASSERT_NOTE(sGridShapeName); + // Check position and size + awt::Point aGridPosition = xGrid->getPosition(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aGridPosition.X, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aGridPosition.Y, INT_EPS); + awt::Size aGridSize = xGrid->getSize(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aGridSize.Height, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aGridSize.Width, INT_EPS); + + // Check transformation + Reference< beans::XPropertySet > xPropSet(xGrid, UNO_QUERY_THROW); + drawing::HomogenMatrix3 aGridTransformation; + xPropSet->getPropertyValue("Transformation") >>= aGridTransformation; + CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aGridTransformation, INT_EPS); + + // Check line properties + uno::Reference<container::XIndexAccess> xIndexAccess(xGrid, UNO_QUERY_THROW); + uno::Reference<drawing::XShape> xGridLine(xIndexAccess->getByIndex(0), UNO_QUERY_THROW); + Reference< beans::XPropertySet > xGridLinePropSet(xGridLine, UNO_QUERY_THROW); + // Line type + drawing::LineDash aLineDash; + xGridLinePropSet->getPropertyValue("LineDash") >>= aLineDash; + OUString sGridLineDash = + OUString::number(static_cast<sal_Int32>(aLineDash.Style)) + ";" + OUString::number(aLineDash.Dots) + ";" + OUString::number(aLineDash.DotLen) + + OUString::number(aLineDash.Dashes) + ";" + OUString::number(aLineDash.DashLen) + ";" + OUString::number(aLineDash.Distance); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sGridLineDash); + // Line color + util::Color aLineColor = 0; + xGridLinePropSet->getPropertyValue("LineColor") >>= aLineColor; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aLineColor)); + // Line width + sal_Int32 nLineWidth = 0; + xGridLinePropSet->getPropertyValue("LineWidth") >>= nLineWidth; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nLineWidth); + } + } + } +} + +DECLARE_DUMP_TEST(AxisGeometryTest, Chart2DumpTest, false) +{ + const std::vector<OUString> aTestFiles = + { + "default_formated_axis.odp", + "axis_special_positioning.odp", + "formated_axis_lines.odp", + "rotated_axis_labels.odp" + }; + + for (const OUString& sTestFile : aTestFiles) + { + setTestFileName(sTestFile); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromDrawImpress(0, 0), UNO_SET_THROW); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + const std::vector<OUString> aAxisShapeNames = + { + "CID/D=0:CS=0:Axis=0,0", // X Axis + "CID/D=0:CS=0:Axis=1,0", // Y Axis + }; + + for (const OUString& sAxisShapeName : aAxisShapeNames) + { + uno::Reference<drawing::XShape> xXAxis = getShapeByName(xShapes, sAxisShapeName); + CPPUNIT_ASSERT(xXAxis.is()); + + CPPUNIT_DUMP_ASSERT_NOTE(sAxisShapeName); + // Check position and size + awt::Point aAxisPosition = xXAxis->getPosition(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aAxisPosition.X, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aAxisPosition.Y, INT_EPS); + awt::Size aAxisSize = xXAxis->getSize(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aAxisSize.Height, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aAxisSize.Width, INT_EPS); + + // Check transformation + Reference< beans::XPropertySet > xPropSet(xXAxis, UNO_QUERY_THROW); + drawing::HomogenMatrix3 aAxisTransformation; + xPropSet->getPropertyValue("Transformation") >>= aAxisTransformation; + CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aAxisTransformation, INT_EPS); + + // Check line properties + uno::Reference<container::XIndexAccess> xIndexAccess(xXAxis, UNO_QUERY_THROW); + sal_Int32 nAxisGeometriesCount = xIndexAccess->getCount(); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nAxisGeometriesCount); + uno::Reference<drawing::XShape> xAxisLine(xIndexAccess->getByIndex(0), UNO_QUERY_THROW); + Reference< beans::XPropertySet > xAxisLinePropSet(xAxisLine, UNO_QUERY_THROW); + // Line type + drawing::LineDash aLineDash; + xAxisLinePropSet->getPropertyValue("LineDash") >>= aLineDash; + OUString sAxisLineDash = + OUString::number(static_cast<sal_Int32>(aLineDash.Style)) + ";" + OUString::number(aLineDash.Dots) + ";" + OUString::number(aLineDash.DotLen) + + OUString::number(aLineDash.Dashes) + ";" + OUString::number(aLineDash.DashLen) + ";" + OUString::number(aLineDash.Distance); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sAxisLineDash); + // Line color + util::Color aAxisLineColor = 0; + xAxisLinePropSet->getPropertyValue("LineColor") >>= aAxisLineColor; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aAxisLineColor)); + // Line width + sal_Int32 nAxisLineWidth = 0; + xAxisLinePropSet->getPropertyValue("LineWidth") >>= nAxisLineWidth; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nAxisLineWidth); + } + } +} + +DECLARE_DUMP_TEST(AxisLabelTest, Chart2DumpTest, false) +{ + const std::vector<OUString> aTestFiles = + { + "default_formated_axis.odp", + "rotated_axis_labels.odp", + "formated_axis_labels.odp", + "percent_stacked_column_chart.odp", + "tdf118150.xlsx", + "date-categories.pptx", + }; + + for (const OUString& sTestFile : aTestFiles) + { + setTestFileName(sTestFile); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromDrawImpress(0, 0), UNO_SET_THROW); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + const std::vector<OUString> aAxisShapeNames = + { + "CID/D=0:CS=0:Axis=0,0", // X Axis + "CID/D=0:CS=0:Axis=1,0", // Y Axis + }; + + for (const OUString& sAxisShapeName : aAxisShapeNames) + { + uno::Reference<drawing::XShape> xXAxis = getShapeByName(xShapes, sAxisShapeName, + // Axis occurs twice in chart xshape representation so need to get the one related to labels + [](const uno::Reference<drawing::XShape>& rXShape) -> bool + { + uno::Reference<drawing::XShapes> xAxisShapes(rXShape, uno::UNO_QUERY); + CPPUNIT_ASSERT(xAxisShapes.is()); + uno::Reference<drawing::XShape> xChildShape(xAxisShapes->getByIndex(0), uno::UNO_QUERY); + uno::Reference< drawing::XShapeDescriptor > xShapeDescriptor(xChildShape, uno::UNO_QUERY_THROW); + return (xShapeDescriptor->getShapeType() == "com.sun.star.drawing.TextShape"); + }); + CPPUNIT_ASSERT(xXAxis.is()); + CPPUNIT_DUMP_ASSERT_NOTE(sAxisShapeName); + + // Check label count + uno::Reference<container::XIndexAccess> xIndexAccess(xXAxis, UNO_QUERY_THROW); + sal_Int32 nAxisLabelsCount = xIndexAccess->getCount(); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nAxisLabelsCount); + + // Check labels's text, positioning and font properties + for (sal_Int32 nLabelIndex = 0; nLabelIndex < nAxisLabelsCount; ++nLabelIndex) + { + // Check text + uno::Reference<text::XTextRange> xLabel(xIndexAccess->getByIndex(nLabelIndex), uno::UNO_QUERY); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(xLabel->getString()); + + // Check size and position + uno::Reference<drawing::XShape> xLabelShape(xLabel, uno::UNO_QUERY); + /*awt::Point aLabelPosition = xLabelShape->getPosition(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLabelPosition.X, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLabelPosition.Y, INT_EPS); + awt::Size aLabelSize = xLabelShape->getSize(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLabelSize.Height, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLabelSize.Width, INT_EPS);*/ + + // Check transformation + Reference< beans::XPropertySet > xPropSet(xLabelShape, UNO_QUERY_THROW); + /*drawing::HomogenMatrix3 aLabelTransformation; + xPropSet->getPropertyValue("Transformation") >>= aLabelTransformation; + CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aLabelTransformation, INT_EPS);*/ + + // Check font color and height + util::Color aLabelFontColor = 0; + xPropSet->getPropertyValue("CharColor") >>= aLabelFontColor; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aLabelFontColor)); + float fLabelFontHeight = 0.0f; + xPropSet->getPropertyValue("CharHeight") >>= fLabelFontHeight; + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(fLabelFontHeight, 1E-12); + } + } + } +} + +DECLARE_DUMP_TEST(ColumnBarChartTest, Chart2DumpTest, false) +{ + const std::vector<OUString> aTestFiles = + { + "normal_column_chart.ods", + "stacked_column_chart.ods", + "percent_stacked_column_chart.ods", + "column_chart_small_spacing.ods", + "normal_bar_chart.ods", + "stacked_bar_chart.ods", + "percent_stacked_bar_chart.ods", + }; + + for (const OUString& sTestFile : aTestFiles) + { + setTestFileName(sTestFile); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromSheet(0, mxComponent), UNO_QUERY_THROW); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + uno::Reference< chart2::XChartDocument > xChartDoc2(xChartDoc, UNO_QUERY_THROW); + Reference<chart2::XChartType> xChartType = getChartTypeFromDoc(xChartDoc2, 0); + CPPUNIT_ASSERT(xChartType.is()); + std::vector<std::vector<double> > aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType); + size_t nSeriesCount = aDataSeriesYValues.size(); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nSeriesCount); + + for (size_t nSeries = 0; nSeries < nSeriesCount; ++nSeries) + { + uno::Reference<drawing::XShape> xSeriesColumnsOrBars = getShapeByName(xShapes, "CID/D=0:CS=0:CT=0:Series=" + OUString::number(nSeries)); + CPPUNIT_ASSERT(xSeriesColumnsOrBars.is()); + CPPUNIT_DUMP_ASSERT_NOTE("Series " + OUString::number(nSeries) + " ColumnsOrBars"); + + // Check column/bar count in the series + uno::Reference<container::XIndexAccess> xIndexAccess(xSeriesColumnsOrBars, UNO_QUERY_THROW); + sal_Int32 nColumnOrBarCountInSeries = xIndexAccess->getCount(); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nColumnOrBarCountInSeries); + + // Check column/bar fill style and color + Reference< beans::XPropertySet > xColumnOrBarPropSet(xIndexAccess->getByIndex(0), UNO_QUERY_THROW); + drawing::FillStyle aSeriesColumnOrBarFillStyle; + xColumnOrBarPropSet->getPropertyValue(UNO_NAME_FILLSTYLE) >>= aSeriesColumnOrBarFillStyle; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aSeriesColumnOrBarFillStyle)); + util::Color aSeriesColumnOrBarFillColor = 0; + xColumnOrBarPropSet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= aSeriesColumnOrBarFillColor; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aSeriesColumnOrBarFillColor)); + + for (sal_Int32 nColumnOrBar = 0; nColumnOrBar < nColumnOrBarCountInSeries; ++nColumnOrBar) + { + uno::Reference<drawing::XShape> xColumnOrBar(xIndexAccess->getByIndex(nColumnOrBar), UNO_QUERY_THROW); + uno::Reference<container::XNamed> xNamedShape(xIndexAccess->getByIndex(nColumnOrBar), uno::UNO_QUERY); + CPPUNIT_DUMP_ASSERT_NOTE(xNamedShape->getName()); + + // Check size and position + awt::Point aColumnOrBarPosition = xColumnOrBar->getPosition(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aColumnOrBarPosition.X, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aColumnOrBarPosition.Y, INT_EPS); + awt::Size aColumnOrBarSize = xColumnOrBar->getSize(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aColumnOrBarSize.Height, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aColumnOrBarSize.Width, INT_EPS); + + // Check transformation + Reference< beans::XPropertySet > xPropSet(xColumnOrBar, UNO_QUERY_THROW); + drawing::HomogenMatrix3 aColumnOrBarTransformation; + xPropSet->getPropertyValue("Transformation") >>= aColumnOrBarTransformation; + CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aColumnOrBarTransformation, INT_EPS); + } + } + } +} + +DECLARE_DUMP_TEST(ChartWallTest, Chart2DumpTest, false) +{ + const std::vector<OUString> aTestFiles = + { + "chartwall_auto_adjust_with_titles.ods", + "chartwall_auto_adjust_without_titles.ods", + "chartwall_custom_positioning.ods" + }; + + for (const OUString& sTestFile : aTestFiles) + { + setTestFileName(sTestFile); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromDrawImpress(0, 0), UNO_SET_THROW); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + uno::Reference<drawing::XShape> xChartWall = getShapeByName(xShapes, "CID/DiagramWall="); + CPPUNIT_ASSERT(xChartWall.is()); + + // Check position and size + /*awt::Point aChartWallPosition = xChartWall->getPosition(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aChartWallPosition.X, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aChartWallPosition.Y, INT_EPS); + awt::Size aChartWallSize = xChartWall->getSize(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aChartWallSize.Height, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aChartWallSize.Width, INT_EPS);*/ + + // Check transformation + Reference< beans::XPropertySet > xPropSet(xChartWall, UNO_QUERY_THROW); + /*drawing::HomogenMatrix3 aChartWallTransformation; + xPropSet->getPropertyValue("Transformation") >>= aChartWallTransformation; + CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aChartWallTransformation, INT_EPS);*/ + + // Check fill properties + drawing::FillStyle aChartWallFillStyle; + xPropSet->getPropertyValue(UNO_NAME_FILLSTYLE) >>= aChartWallFillStyle; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aChartWallFillStyle)); + util::Color aChartWallFillColor = 0; + xPropSet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= aChartWallFillColor; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aChartWallFillColor)); + + // Check line properties + // Line type + drawing::LineDash aLineDash; + xPropSet->getPropertyValue("LineDash") >>= aLineDash; + OUString sChartWallLineDash = + OUString::number(static_cast<sal_Int32>(aLineDash.Style)) + ";" + OUString::number(aLineDash.Dots) + ";" + OUString::number(aLineDash.DotLen) + + OUString::number(aLineDash.Dashes) + ";" + OUString::number(aLineDash.DashLen) + ";" + OUString::number(aLineDash.Distance); + CPPUNIT_DUMP_ASSERT_STRINGS_EQUAL(sChartWallLineDash); + // Line color + util::Color aChartWallLineColor = 0; + xPropSet->getPropertyValue("LineColor") >>= aChartWallLineColor; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aChartWallLineColor)); + // Line width + sal_Int32 nChartWallLineWidth = 0; + xPropSet->getPropertyValue("LineWidth") >>= nChartWallLineWidth; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nChartWallLineWidth); + + } +} + +DECLARE_DUMP_TEST(PieChartTest, Chart2DumpTest, false) +{ + const std::vector<OUString> aTestFiles = + { + "normal_pie_chart.ods", + "rotated_pie_chart.ods", + "exploded_pie_chart.ods", + "donut_chart.ods", + "pie_chart_many_slices.ods", + }; + + for (const OUString& sTestFile : aTestFiles) + { + setTestFileName(sTestFile); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromSheet(0, mxComponent), UNO_QUERY_THROW); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + uno::Reference< chart2::XChartDocument > xChartDoc2(xChartDoc, UNO_QUERY_THROW); + Reference<chart2::XChartType> xChartType = getChartTypeFromDoc(xChartDoc2, 0); + CPPUNIT_ASSERT(xChartType.is()); + + std::vector<std::vector<double> > aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType); + size_t nSeriesCount = aDataSeriesYValues.size(); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nSeriesCount); + + for (size_t nSeries = 0; nSeries < nSeriesCount; ++nSeries) + { + uno::Reference<drawing::XShape> xSeriesSlices = getShapeByName(xShapes, "CID/D=0:CS=0:CT=0:Series=" + OUString::number(nSeries)); + if (!xSeriesSlices.is()) + break; // Normal pie chart displays only one series + CPPUNIT_DUMP_ASSERT_NOTE("Series " + OUString::number(nSeries) + " slices"); + + // Check slice count in the series + uno::Reference<container::XIndexAccess> xIndexAccess(xSeriesSlices, UNO_QUERY_THROW); + sal_Int32 nSlicesCountInSeries = xIndexAccess->getCount(); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nSlicesCountInSeries); + + // Check slices properties + for (sal_Int32 nSlice = 0; nSlice < nSlicesCountInSeries; ++nSlice) + { + uno::Reference<drawing::XShape> xSlice(xIndexAccess->getByIndex(nSlice), UNO_QUERY_THROW); + uno::Reference<container::XNamed> xNamedShape(xIndexAccess->getByIndex(nSlice), uno::UNO_QUERY); + OUString sName = xNamedShape->getName(); + CPPUNIT_DUMP_ASSERT_NOTE(sName.copy(sName.lastIndexOf("/D=0"))); + + // Check size and position + awt::Point aSlicePosition = xSlice->getPosition(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aSlicePosition.X, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aSlicePosition.Y, INT_EPS); + awt::Size aSliceSize = xSlice->getSize(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aSliceSize.Height, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aSliceSize.Width, INT_EPS); + + // Check transformation + Reference< beans::XPropertySet > xPropSet(xSlice, UNO_QUERY_THROW); + drawing::HomogenMatrix3 aSliceTransformation; + xPropSet->getPropertyValue("Transformation") >>= aSliceTransformation; + CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aSliceTransformation, INT_EPS); + + // Check slice fill style and color + drawing::FillStyle aSliceFillStyle; + xPropSet->getPropertyValue(UNO_NAME_FILLSTYLE) >>= aSliceFillStyle; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aSliceFillStyle)); + util::Color aSliceFillColor = 0; + xPropSet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= aSliceFillColor; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aSliceFillColor)); + } + } + } +} + +DECLARE_DUMP_TEST(AreaChartTest, Chart2DumpTest, false) +{ + const std::vector<OUString> aTestFiles = + { + "normal_area_chart.ods", + "stacked_area_chart.ods", + "percent_stacked_area_chart.ods" + }; + + for (const OUString& sTestFile : aTestFiles) + { + setTestFileName(sTestFile); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromSheet(0, mxComponent), UNO_QUERY_THROW); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + uno::Reference< chart2::XChartDocument > xChartDoc2(xChartDoc, UNO_QUERY_THROW); + Reference<chart2::XChartType> xChartType = getChartTypeFromDoc(xChartDoc2, 0); + CPPUNIT_ASSERT(xChartType.is()); + + std::vector<std::vector<double> > aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType); + size_t nSeriesCount = aDataSeriesYValues.size(); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nSeriesCount); + + for (size_t nSeries = 0; nSeries < nSeriesCount; ++nSeries) + { + uno::Reference<drawing::XShape> xSeries = getShapeByName(xShapes, "CID/D=0:CS=0:CT=0:Series=" + OUString::number(nSeries)); + CPPUNIT_ASSERT(xSeries.is()); + CPPUNIT_DUMP_ASSERT_NOTE("Series " + OUString::number(nSeries)); + + // One area for one series + uno::Reference<container::XIndexAccess> xIndexAccess(xSeries, UNO_QUERY_THROW); + uno::Reference<container::XIndexAccess> xIndexAccess2(xIndexAccess->getByIndex(0), UNO_QUERY_THROW); // Why this second group shape is here? + uno::Reference<drawing::XShape> xArea(xIndexAccess2->getByIndex(0), UNO_QUERY_THROW); + + // Check size and position + awt::Point aAreaPosition = xArea->getPosition(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aAreaPosition.X, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aAreaPosition.Y, INT_EPS); + awt::Size aAreaSize = xArea->getSize(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aAreaSize.Height, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aAreaSize.Width, INT_EPS); + + // Check transformation + Reference< beans::XPropertySet > xPropSet(xArea, UNO_QUERY_THROW); + drawing::HomogenMatrix3 aAreaTransformation; + xPropSet->getPropertyValue("Transformation") >>= aAreaTransformation; + CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aAreaTransformation, INT_EPS); + + // Check area fill style and color + drawing::FillStyle aAreaFillStyle; + xPropSet->getPropertyValue(UNO_NAME_FILLSTYLE) >>= aAreaFillStyle; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aAreaFillStyle)); + util::Color aAreaFillColor = 0; + xPropSet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= aAreaFillColor; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aAreaFillColor)); + } + } +} + + +DECLARE_DUMP_TEST(PointLineChartTest, Chart2DumpTest, false) +{ + const std::vector<OUString> aTestFiles = + { + "normal_line_chart_lines_only.ods", + "normal_line_chart_points_only.ods", + "normal_line_chart_lines_and_points.ods", + "stacked_line_chart_lines_only.ods", + "stacked_line_chart_points_only.ods", + "stacked_line_chart_lines_and_points.ods", + "percent_stacked_line_chart_lines_only.ods", + "percent_stacked_line_chart_points_only.ods", + "percent_stacked_line_chart_lines_and_points.ods", + "scatter_chart_points_only.ods", + "scatter_chart_lines_only.ods", + "scatter_chart_lines_and_points.ods", + }; + + for (const OUString& sTestFile : aTestFiles) + { + setTestFileName(sTestFile); + load(getTestFileDirName(), getTestFileName()); + uno::Reference< chart::XChartDocument > xChartDoc(getChartDocFromSheet(0, mxComponent), UNO_QUERY_THROW); + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xChartDoc, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference<drawing::XShapes> xShapes(xDrawPage->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xShapes.is()); + + uno::Reference< chart2::XChartDocument > xChartDoc2(xChartDoc, UNO_QUERY_THROW); + Reference<chart2::XChartType> xChartType = getChartTypeFromDoc(xChartDoc2, 0); + CPPUNIT_ASSERT(xChartType.is()); + + std::vector<std::vector<double> > aDataSeriesYValues = getDataSeriesYValuesFromChartType(xChartType); + size_t nSeriesCount = aDataSeriesYValues.size(); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nSeriesCount); + + for (size_t nSeries = 0; nSeries < nSeriesCount; ++nSeries) + { + uno::Reference<drawing::XShape> xSeries = getShapeByName(xShapes, "CID/D=0:CS=0:CT=0:Series=" + OUString::number(nSeries)); + CPPUNIT_ASSERT(xSeries.is()); + CPPUNIT_DUMP_ASSERT_NOTE("Series " + OUString::number(nSeries)); + + uno::Reference<container::XIndexAccess> xIndexAccess(xSeries, UNO_QUERY_THROW); + uno::Reference<container::XIndexAccess> xIndexAccess2(xIndexAccess->getByIndex(0), UNO_QUERY_THROW); + uno::Reference<drawing::XShape> xLine(xIndexAccess2->getByIndex(0), UNO_QUERY_THROW); + Reference< beans::XPropertySet > xPropSet(xLine, UNO_QUERY_THROW); + + // Check whether we have line + drawing::LineStyle aSeriesLineStyle; + xPropSet->getPropertyValue(UNO_NAME_LINESTYLE) >>= aSeriesLineStyle; + if (aSeriesLineStyle != drawing::LineStyle_NONE) + { + CPPUNIT_DUMP_ASSERT_NOTE("Lines are displayed"); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aSeriesLineStyle)); + + // Check line shape geometry + awt::Point aLinePosition = xLine->getPosition(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLinePosition.X, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLinePosition.Y, INT_EPS); + awt::Size aLineSize = xLine->getSize(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLineSize.Height, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aLineSize.Width, INT_EPS); + CPPUNIT_ASSERT(xPropSet.is()); + drawing::HomogenMatrix3 aLineTransformation; + xPropSet->getPropertyValue("Transformation") >>= aLineTransformation; + CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aLineTransformation, INT_EPS); + } + + // Check points of series + if (xIndexAccess->getCount() >= 2) + { + CPPUNIT_DUMP_ASSERT_NOTE("Points are displayed"); + uno::Reference<container::XIndexAccess> xPointsOfSeries(xIndexAccess->getByIndex(1), UNO_QUERY_THROW); + sal_Int32 nPointCountInSeries = xPointsOfSeries->getCount(); + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(nPointCountInSeries); + for (sal_Int32 nPoint = 0; nPoint < nPointCountInSeries; ++nPoint) + { + uno::Reference<container::XIndexAccess> XPointContainer ( + getShapeByName(xShapes, "CID/MultiClick/D=0:CS=0:CT=0:Series=" + OUString::number(nSeries) + ":Point=" + OUString::number(nPoint)), UNO_QUERY_THROW); + uno::Reference<drawing::XShape> XPoint(XPointContainer->getByIndex(0), UNO_QUERY_THROW); + uno::Reference<container::XNamed> xNamedShape(XPointContainer, uno::UNO_QUERY); + CPPUNIT_DUMP_ASSERT_NOTE(xNamedShape->getName()); + + // Check size and position + awt::Point aPointPosition = XPoint->getPosition(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aPointPosition.X, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aPointPosition.Y, INT_EPS); + awt::Size aPointSize = XPoint->getSize(); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aPointSize.Height, INT_EPS); + CPPUNIT_DUMP_ASSERT_DOUBLES_EQUAL(aPointSize.Width, INT_EPS); + + // Check transformation + Reference< beans::XPropertySet > xPointPropSet(XPoint, UNO_QUERY_THROW); + drawing::HomogenMatrix3 aPointTransformation; + xPointPropSet->getPropertyValue("Transformation") >>= aPointTransformation; + CPPUNIT_DUMP_ASSERT_TRANSFORMATIONS_EQUAL(aPointTransformation, INT_EPS); + + // Check fill style and color + drawing::FillStyle aPointFillStyle; + xPointPropSet->getPropertyValue(UNO_NAME_FILLSTYLE) >>= aPointFillStyle; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aPointFillStyle)); + util::Color aPointFillColor = 0; + xPointPropSet->getPropertyValue(UNO_NAME_FILLCOLOR) >>= aPointFillColor; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL(static_cast<sal_Int32>(aPointFillColor)); + } + } + } + } +} + +DECLARE_DUMP_TEST( PivotChartDataButtonTest, Chart2DumpTest, false ) +{ + setTestFileName( "pivotchart_data_button.ods" ); + load( getTestFileDirName(), getTestFileName() ); + + // Check that we have pivot chart in the document + uno::Reference<table::XTablePivotCharts> xTablePivotCharts = getTablePivotChartsFromSheet( 1, mxComponent ); + uno::Reference<container::XIndexAccess> xIndexAccess( xTablePivotCharts, UNO_QUERY_THROW ); + CPPUNIT_ASSERT_EQUAL( sal_Int32(1), xIndexAccess->getCount() ); + + // Get the pivot chart document so we ca access its data + uno::Reference<chart2::XChartDocument> xChartDoc; + xChartDoc.set( getPivotChartDocFromSheet( xTablePivotCharts, 0 ) ); + CPPUNIT_ASSERT( xChartDoc.is() ); + + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier( xChartDoc, uno::UNO_QUERY ); + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference<drawing::XShapes> xShapes( xDrawPage->getByIndex(0), uno::UNO_QUERY ); + CPPUNIT_ASSERT( xShapes.is() ); + + // Get the shape that represents the "Data" button. + uno::Reference<drawing::XShape> xButton = getShapeByName( xShapes, "FieldButton.Row.8", + []( const uno::Reference<drawing::XShape>& xShapeNode ) + { + return xShapeNode->getShapeType() == "com.sun.star.drawing.TextShape"; + } ); + CPPUNIT_ASSERT_MESSAGE( OString( "Cannot find Data button shape" ).getStr(), xButton.is() ); + + // Make sure that there is no arrow shape with the Data button + uno::Reference<drawing::XShape> xArrow = getShapeByName( xShapes, "FieldButton.Row.8", + []( const uno::Reference<drawing::XShape>& xShapeNode ) + { + return xShapeNode->getShapeType() == "com.sun.star.drawing.PolyPolygonShape"; + } ); + CPPUNIT_ASSERT_MESSAGE( OString( "Arrow shape should not be present for the Data button" ).getStr(), !xArrow.is() ); + + // Assert the background color of the Data button + util::Color aButtonFillColor = 0; + uno::Reference<beans::XPropertySet> xPropSet( xButton, UNO_QUERY_THROW ); + xPropSet->getPropertyValue( UNO_NAME_FILLCOLOR ) >>= aButtonFillColor; + CPPUNIT_DUMP_ASSERT_NUMBERS_EQUAL( static_cast<sal_Int32>( aButtonFillColor ) ); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |