/* -*- 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 <sdpage.hxx>

#include "sdmodeltestbase.hxx"
#include <tools/color.hxx>

#include <editeng/eeitem.hxx>
#include <editeng/editobj.hxx>
#include <editeng/numitem.hxx>
#include <editeng/unoprnms.hxx>

#include <svx/svdotable.hxx>
#include <svx/xfillit0.hxx>
#include <svx/xfilluseslidebackgrounditem.hxx>
#include <svx/xflclit.hxx>
#include <svx/xlineit0.hxx>
#include <svx/xlnclit.hxx>
#include <svx/sdooitm.hxx>
#include <animations/animationnodehelper.hxx>

#include <com/sun/star/awt/XBitmap.hpp>
#include <com/sun/star/awt/Gradient.hpp>
#include <com/sun/star/document/XEventsSupplier.hpp>
#include <com/sun/star/presentation/ClickAction.hpp>
#include <com/sun/star/presentation/XPresentationPage.hpp>
#include <com/sun/star/presentation/XPresentationSupplier.hpp>
#include <com/sun/star/drawing/BitmapMode.hpp>
#include <com/sun/star/drawing/ColorMode.hpp>
#include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
#include <com/sun/star/drawing/XGluePointsSupplier.hpp>
#include <com/sun/star/drawing/GluePoint2.hpp>
#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
#include <com/sun/star/container/XIdentifierAccess.hpp>
#include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
#include <com/sun/star/animations/XAnimate.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>
#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
#include <com/sun/star/chart2/XChartTypeContainer.hpp>
#include <com/sun/star/style/ParagraphAdjust.hpp>
#include <com/sun/star/style/LineSpacing.hpp>
#include <com/sun/star/style/LineSpacingMode.hpp>
#include <com/sun/star/text/GraphicCrop.hpp>
#include <com/sun/star/text/WritingMode2.hpp>
#include <com/sun/star/text/XTextColumns.hpp>
#include <com/sun/star/xml/dom/XDocument.hpp>

#include <comphelper/sequenceashashmap.hxx>
#include <comphelper/graphicmimetype.hxx>
#include <sfx2/linkmgr.hxx>
#include <vcl/BitmapReadAccess.hxx>
#include <vcl/dibtools.hxx>
#include <sdresid.hxx>
#include <stlpool.hxx>
#include <strings.hrc>

using namespace ::com::sun::star;

class SdImportTest2 : public SdModelTestBase
{
public:
    SdImportTest2()
        : SdModelTestBase(u"/sd/qa/unit/data/"_ustr)
    {
    }

protected:
    bool checkPattern(int nShapeNumber, std::vector<sal_uInt8>& rExpected);
};

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf157529)
{
    createSdImpressDoc("pptx/tdf157529.pptx");

    uno::Reference<beans::XPropertySet> xShape1(getShapeFromPage(0, 0));
    CPPUNIT_ASSERT(xShape1.is());
    sal_Int16 nTransparence1;
    xShape1->getPropertyValue(u"FillTransparence"_ustr) >>= nTransparence1;

    // Without the fix in place, this test would have failed with
    // Expected: transparence value: 100%
    // Actual  : transparence value: 0%
    CPPUNIT_ASSERT_EQUAL(sal_Int16(100), nTransparence1);

    uno::Reference<beans::XPropertySet> xShape2(getShapeFromPage(1, 0));
    CPPUNIT_ASSERT(xShape2.is());
    sal_Int16 nTransparence2;
    xShape2->getPropertyValue(u"FillTransparence"_ustr) >>= nTransparence2;

    // Without the fix in place, this test would have failed with
    // Expected: transparence value: 100%
    // Actual  : transparence value: 0%
    CPPUNIT_ASSERT_EQUAL(sal_Int16(100), nTransparence2);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf160490)
{
    createSdImpressDoc("pptx/tdf160490.pptx");

    uno::Reference<drawing::XShape> xShape1(getShapeFromPage(0, 0), uno::UNO_QUERY);
    CPPUNIT_ASSERT(xShape1.is());
    sal_Int32 nHeight1 = xShape1->getSize().Height;

    // Without the fix in place, this test would have failed with
    // Expected: placeholder height: 3726
    // Actual  : placeholder height: 3476
    CPPUNIT_ASSERT_EQUAL(sal_Int32(3726), nHeight1);

    uno::Reference<drawing::XShape> xShape2(getShapeFromPage(0, 1), uno::UNO_QUERY);
    CPPUNIT_ASSERT(xShape2.is());
    sal_Int32 nHeight2 = xShape2->getSize().Height;

    // Without the fix in place, this test would have failed with
    // Expected: placeholder height: 3365
    // Actual  : placeholder height: 3116
    CPPUNIT_ASSERT_EQUAL(sal_Int32(3365), nHeight2);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf165321)
{
    createSdImpressDoc("pptx/tdf165321.pptx");

    uno::Reference<container::XIndexAccess> xGroupShape(getShapeFromPage(0, 0),
                                                        uno::UNO_QUERY_THROW);
    uno::Reference<drawing::XShape> xShape(xGroupShape->getByIndex(0), uno::UNO_QUERY_THROW);
    CPPUNIT_ASSERT(xShape.is());
    // Without the fix in place, this test would have failed with
    // Expected: shape height: 3597
    // Actual  : shape height: 3
    CPPUNIT_ASSERT_EQUAL(sal_Int32(3597), xShape->getSize().Height);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(6592), xShape->getSize().Width);

    xShape.set(xGroupShape->getByIndex(1), uno::UNO_QUERY_THROW);
    CPPUNIT_ASSERT(xShape.is());
    // Without the fix in place, this test would have failed with
    // Expected: shape height: 3597
    // Actual  : shape height: 3
    CPPUNIT_ASSERT_EQUAL(sal_Int32(3597), xShape->getSize().Height);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(6402), xShape->getSize().Width);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf165341)
{
    createSdImpressDoc("pptx/tdf165341.pptx");

    uno::Reference<drawing::XShape> xShape(getShapeFromPage(0, 0), uno::UNO_QUERY);
    CPPUNIT_ASSERT(xShape.is());
    uno::Reference<beans::XPropertySet> xProp(xShape, uno::UNO_QUERY);
    drawing::TextHorizontalAdjust eHori;
    CPPUNIT_ASSERT(xProp->getPropertyValue(u"TextHorizontalAdjust"_ustr) >>= eHori);
    drawing::TextVerticalAdjust eVert;
    CPPUNIT_ASSERT(xProp->getPropertyValue(u"TextVerticalAdjust"_ustr) >>= eVert);
    CPPUNIT_ASSERT_EQUAL(drawing::TextHorizontalAdjust::TextHorizontalAdjust_CENTER, eHori);
    CPPUNIT_ASSERT_EQUAL(drawing::TextVerticalAdjust::TextVerticalAdjust_TOP, eVert);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf157285)
{
    createSdImpressDoc("pptx/tdf157285.pptx");

    uno::Reference<drawing::XShape> xShape1(getShapeFromPage(0, 0), uno::UNO_QUERY);
    CPPUNIT_ASSERT(xShape1.is());
    sal_Int32 nHeight1 = xShape1->getSize().Height;

    // Without the fix in place, this test would have failed with
    // Expected: placeholder height: 2565
    // Actual  : placeholder height: 3435
    CPPUNIT_ASSERT_EQUAL(sal_Int32(2565), nHeight1);

    uno::Reference<drawing::XShape> xShape2(getShapeFromPage(1, 0), uno::UNO_QUERY);
    CPPUNIT_ASSERT(xShape2.is());
    sal_Int32 nHeight2 = xShape2->getSize().Height;

    // Without the fix in place, this test would have failed with
    // Expected: placeholder height: 1180
    // Actual  : placeholder height: 11303
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1180), nHeight2);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf152186)
{
    createSdImpressDoc("pptx/tdf152186.pptx");
    saveAndReload(TestFilter::PPTX_2007);

    bool bHasShadow = bool();
    const SdrPage* pPage = GetPage(1);
    for (size_t i = 0; i < pPage->GetObjCount(); ++i)
    {
        uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(i, 0));
        CPPUNIT_ASSERT(xShape->getPropertyValue(u"Shadow"_ustr) >>= bHasShadow);
        CPPUNIT_ASSERT(!bHasShadow);
    }
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf93868)
{
    createSdImpressDoc("pptx/tdf93868.pptx");

    const SdrPage* pPage = &(GetPage(1)->TRG_GetMasterPage());
    CPPUNIT_ASSERT_EQUAL(size_t(5), pPage->GetObjCount());
    CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID,
                         pPage->GetObj(0)->GetMergedItem(XATTR_FILLSTYLE).GetValue());

    CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE,
                         pPage->GetObj(1)->GetMergedItem(XATTR_FILLSTYLE).GetValue());
    CPPUNIT_ASSERT_EQUAL(true,
                         pPage->GetObj(1)->GetMergedItem(XATTR_FILLUSESLIDEBACKGROUND).GetValue());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf95932)
{
    createSdImpressDoc("pptx/tdf95932.pptx");

    const SdrPage* pPage = GetPage(1);
    SdrObject* const pObj = pPage->GetObj(1);
    CPPUNIT_ASSERT(pObj);

    const XFillStyleItem& rStyleItem = pObj->GetMergedItem(XATTR_FILLSTYLE);
    CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, rStyleItem.GetValue());
    const XFillColorItem& rColorItem = pObj->GetMergedItem(XATTR_FILLCOLOR);
    CPPUNIT_ASSERT_EQUAL(Color(0x76bf3d), rColorItem.GetColorValue());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf99030)
{
    createSdImpressDoc("pptx/tdf99030.pptx");

    uno::Reference<drawing::XMasterPagesSupplier> xDoc(mxComponent, uno::UNO_QUERY_THROW);
    uno::Reference<drawing::XDrawPage> xPage(xDoc->getMasterPages()->getByIndex(0),
                                             uno::UNO_QUERY_THROW);
    uno::Reference<beans::XPropertySet> xPropSet(xPage, uno::UNO_QUERY);

    Color nFillColor;
    uno::Any aAny = xPropSet->getPropertyValue(u"Background"_ustr);
    if (aAny.hasValue())
    {
        uno::Reference<beans::XPropertySet> xBackgroundPropSet;
        aAny >>= xBackgroundPropSet;
        xBackgroundPropSet->getPropertyValue(u"FillColor"_ustr) >>= nFillColor;
    }
    CPPUNIT_ASSERT_EQUAL(Color(0x676A55), nFillColor);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf49561)
{
    createSdImpressDoc("ppt/tdf49561.ppt");

    uno::Reference<drawing::XMasterPagesSupplier> xDoc(mxComponent, uno::UNO_QUERY_THROW);
    uno::Reference<drawing::XDrawPage> xPage(xDoc->getMasterPages()->getByIndex(0),
                                             uno::UNO_QUERY_THROW);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), xPage->getCount());

    uno::Reference<beans::XPropertySet> xShape(getShape(3, xPage));
    uno::Reference<text::XTextRange> xParagraph(getParagraphFromShape(0, xShape));
    uno::Reference<text::XTextRange> xRun(getRunFromParagraph(0, xParagraph));
    uno::Reference<beans::XPropertySet> xPropSet(xRun, uno::UNO_QUERY_THROW);

    float fCharHeight = 0;
    CPPUNIT_ASSERT(xPropSet->getPropertyValue(u"CharHeight"_ustr) >>= fCharHeight);
    CPPUNIT_ASSERT_EQUAL(12.f, fCharHeight);

    OUString aCharFontName;
    CPPUNIT_ASSERT(xPropSet->getPropertyValue(u"CharFontName"_ustr) >>= aCharFontName);
    CPPUNIT_ASSERT_EQUAL(u"Stencil"_ustr, aCharFontName);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf103473)
{
    createSdImpressDoc("pptx/tdf103473.pptx");

    const SdrPage* pPage = GetPage(1);
    SdrTextObj* const pObj = dynamic_cast<SdrTextObj* const>(pPage->GetObj(0));
    CPPUNIT_ASSERT(pObj);
    ::tools::Rectangle aRect = pObj->GetGeoRect();
    CPPUNIT_ASSERT_EQUAL(tools::Long(3629), aRect.Left());
    CPPUNIT_ASSERT_EQUAL(tools::Long(4431), aRect.Top());
    CPPUNIT_ASSERT_EQUAL(tools::Long(8353), aRect.Right());
    CPPUNIT_ASSERT_EQUAL(tools::Long(9155), aRect.Bottom());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testAoo124143)
{
    createSdDrawDoc("odg/ooo124143-1.odg");

    uno::Reference<beans::XPropertySet> const xImage(getShapeFromPage(0, 0));
    uno::Reference<drawing::XGluePointsSupplier> const xGPS(xImage, uno::UNO_QUERY);
    uno::Reference<container::XIdentifierAccess> const xGluePoints(xGPS->getGluePoints(),
                                                                   uno::UNO_QUERY);

    uno::Sequence<sal_Int32> const ids(xGluePoints->getIdentifiers());
    CPPUNIT_ASSERT_EQUAL(sal_Int32(6), ids.getLength());
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), ids[0]);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), ids[1]);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(2), ids[2]);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(3), ids[3]);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), ids[4]);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(5), ids[5]);

    // interesting ones are custom 4, 5
    drawing::GluePoint2 glue4;
    xGluePoints->getByIdentifier(4) >>= glue4;
    CPPUNIT_ASSERT_EQUAL(sal_Int32(2470), glue4.Position.X);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(-1810), glue4.Position.Y);

    drawing::GluePoint2 glue5;
    xGluePoints->getByIdentifier(5) >>= glue5;
    CPPUNIT_ASSERT_EQUAL(sal_Int32(-2975), glue5.Position.X);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(-2165), glue5.Position.Y);

    // now check connectors
    uno::Reference<beans::XPropertySet> const xEllipse(getShapeFromPage(1, 0));
    uno::Reference<beans::XPropertySet> const xConn1(getShapeFromPage(2, 0));
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1),
                         xConn1->getPropertyValue(u"StartGluePointIndex"_ustr).get<sal_Int32>());
    CPPUNIT_ASSERT_EQUAL(
        xEllipse,
        xConn1->getPropertyValue(u"StartShape"_ustr).get<uno::Reference<beans::XPropertySet>>());
    CPPUNIT_ASSERT_EQUAL(sal_Int32(4),
                         xConn1->getPropertyValue(u"EndGluePointIndex"_ustr).get<sal_Int32>());
    CPPUNIT_ASSERT_EQUAL(
        xImage,
        xConn1->getPropertyValue(u"EndShape"_ustr).get<uno::Reference<beans::XPropertySet>>());
    uno::Reference<beans::XPropertySet> const xConn2(getShapeFromPage(3, 0));
    CPPUNIT_ASSERT_EQUAL(sal_Int32(3),
                         xConn2->getPropertyValue(u"StartGluePointIndex"_ustr).get<sal_Int32>());
    CPPUNIT_ASSERT_EQUAL(
        xEllipse,
        xConn2->getPropertyValue(u"StartShape"_ustr).get<uno::Reference<beans::XPropertySet>>());
    CPPUNIT_ASSERT_EQUAL(sal_Int32(5),
                         xConn2->getPropertyValue(u"EndGluePointIndex"_ustr).get<sal_Int32>());
    CPPUNIT_ASSERT_EQUAL(
        xImage,
        xConn2->getPropertyValue(u"EndShape"_ustr).get<uno::Reference<beans::XPropertySet>>());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf103567)
{
    createSdImpressDoc("odp/tdf103567.odp");
    for (int i = 0; i < 4; ++i)
    {
        uno::Reference<beans::XPropertySet> const xShape(getShapeFromPage(i, 0));
        uno::Reference<document::XEventsSupplier> const xEventsSupplier(xShape, uno::UNO_QUERY);
        uno::Reference<container::XNameAccess> const xEvents(xEventsSupplier->getEvents());
        OString const msg("shape " + OString::number(i) + ": ");

        CPPUNIT_ASSERT(xEvents->hasByName(u"OnClick"_ustr));
        uno::Sequence<beans::PropertyValue> props;
        xEvents->getByName(u"OnClick"_ustr) >>= props;
        comphelper::SequenceAsHashMap const map(props);
        {
            auto iter(map.find(u"EventType"_ustr));
            CPPUNIT_ASSERT_MESSAGE(OString(msg + "no EventType").getStr(), iter != map.end());
            CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.getStr(), u"Presentation"_ustr,
                                         iter->second.get<OUString>());
        }
        {
            auto iter(map.find(u"ClickAction"_ustr));
            CPPUNIT_ASSERT_MESSAGE(OString(msg + "no ClickAction").getStr(), iter != map.end());
            if (i % 2 == 0)
            {
                CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.getStr(), css::presentation::ClickAction_DOCUMENT,
                                             iter->second.get<css::presentation::ClickAction>());
            }
            else
            {
                CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.getStr(), css::presentation::ClickAction_NEXTPAGE,
                                             iter->second.get<css::presentation::ClickAction>());
            }
        }
        if (i % 2 == 0)
        {
            auto iter(map.find(u"Bookmark"_ustr));
            CPPUNIT_ASSERT_MESSAGE(OString(msg + "no Bookmark").getStr(), iter != map.end());
            CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.getStr(), u"http://example.com/"_ustr,
                                         iter->second.get<OUString>());
        }
    }
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf103792)
{
    // Title text shape on the actual slide contained no text neither a placeholder text.

    createSdImpressDoc("pptx/tdf103792.pptx");

    const SdrPage* pPage = GetPage(1);
    CPPUNIT_ASSERT_MESSAGE("No page found", pPage != nullptr);
    SdrObject* pObj = pPage->GetObj(0);
    CPPUNIT_ASSERT_MESSAGE("Wrong object", pObj != nullptr);
    SdrTextObj* pTxtObj = DynCastSdrTextObj(pObj);
    CPPUNIT_ASSERT_MESSAGE("Not a text object", pTxtObj != nullptr);

    const EditTextObject& aEdit = pTxtObj->GetOutlinerParaObject()->GetTextObject();
    CPPUNIT_ASSERT_EQUAL(u"Click to add Title"_ustr, aEdit.GetText(0));
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf148685)
{
    createSdImpressDoc("pptx/tdf148685.pptx");
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(1, 0));

    uno::Reference<text::XTextRange> const xParagraph(getParagraphFromShape(0, xShape));

    uno::Reference<text::XTextRange> xRun(getRunFromParagraph(0, xParagraph));
    CPPUNIT_ASSERT_EQUAL(u"TEXT "_ustr, xRun->getString());

    uno::Reference<beans::XPropertySet> xPropSet(xRun, uno::UNO_QUERY_THROW);

    Color nCharUnderlineColor;
    xPropSet->getPropertyValue(u"CharUnderlineColor"_ustr) >>= nCharUnderlineColor;
    CPPUNIT_ASSERT_EQUAL(Color(0xA1467E), nCharUnderlineColor);

    xRun.set(getRunFromParagraph(1, xParagraph));

    CPPUNIT_ASSERT_EQUAL(u"TE"_ustr, xRun->getString());

    xPropSet.set(xRun, uno::UNO_QUERY_THROW);

    xPropSet->getPropertyValue(u"CharUnderlineColor"_ustr) >>= nCharUnderlineColor;

    // Without the fix in place, this test would have failed with
    // - Expected: Color: R:255 G:255 B:255 A:255
    // - Actual  : Color: R:161 G:70 B:126 A:0
    CPPUNIT_ASSERT_EQUAL(COL_AUTO, nCharUnderlineColor);

    xRun.set(getRunFromParagraph(2, xParagraph));
    CPPUNIT_ASSERT_EQUAL(u"XT"_ustr, xRun->getString());

    xPropSet.set(xRun, uno::UNO_QUERY_THROW);

    xPropSet->getPropertyValue(u"CharUnderlineColor"_ustr) >>= nCharUnderlineColor;
    CPPUNIT_ASSERT_EQUAL(COL_AUTO, nCharUnderlineColor);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf103876)
{
    // Title text shape's placeholder text did not inherit the corresponding text properties

    createSdImpressDoc("pptx/tdf103876.pptx");
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0));

    // Check paragraph alignment
    sal_Int16 nParaAdjust = 0;
    xShape->getPropertyValue(u"ParaAdjust"_ustr) >>= nParaAdjust;
    CPPUNIT_ASSERT_EQUAL(style::ParagraphAdjust_CENTER,
                         static_cast<style::ParagraphAdjust>(nParaAdjust));

    // Check character color
    Color nCharColor;
    xShape->getPropertyValue(u"CharColor"_ustr) >>= nCharColor;
    CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, nCharColor);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf79007)
{
    createSdImpressDoc("pptx/tdf79007.pptx");

    uno::Reference<beans::XPropertySet> xShape1(getShapeFromPage(0, 0));
    CPPUNIT_ASSERT_MESSAGE("Not a shape", xShape1.is());

    // Check we map mso washout to our watermark
    drawing::ColorMode aColorMode1;
    xShape1->getPropertyValue(u"GraphicColorMode"_ustr) >>= aColorMode1;
    CPPUNIT_ASSERT_EQUAL(drawing::ColorMode_WATERMARK, aColorMode1);

    sal_Int16 nContrast1;
    xShape1->getPropertyValue(u"AdjustContrast"_ustr) >>= nContrast1;
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(0), nContrast1);

    sal_Int16 nLuminance1;
    xShape1->getPropertyValue(u"AdjustLuminance"_ustr) >>= nLuminance1;
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(0), nLuminance1);

    uno::Reference<beans::XPropertySet> xShape2(getShapeFromPage(1, 0));
    CPPUNIT_ASSERT_MESSAGE("Not a shape", xShape2.is());

    // Check we map mso grayscale to our grayscale
    drawing::ColorMode aColorMode2;
    xShape2->getPropertyValue(u"GraphicColorMode"_ustr) >>= aColorMode2;
    CPPUNIT_ASSERT_EQUAL(drawing::ColorMode_GREYS, aColorMode2);

    sal_Int16 nContrast2;
    xShape2->getPropertyValue(u"AdjustContrast"_ustr) >>= nContrast2;
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(0), nContrast2);

    sal_Int16 nLuminance2;
    xShape2->getPropertyValue(u"AdjustLuminance"_ustr) >>= nLuminance2;
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(0), nLuminance2);

    uno::Reference<beans::XPropertySet> xShape3(getShapeFromPage(2, 0));
    CPPUNIT_ASSERT_MESSAGE("Not a shape", xShape3.is());

    // Check we map mso black/white to our black/white
    drawing::ColorMode aColorMode3;
    xShape3->getPropertyValue(u"GraphicColorMode"_ustr) >>= aColorMode3;
    CPPUNIT_ASSERT_EQUAL(drawing::ColorMode_MONO, aColorMode3);

    sal_Int16 nContrast3;
    xShape3->getPropertyValue(u"AdjustContrast"_ustr) >>= nContrast3;
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(0), nContrast3);

    sal_Int16 nLuminance3;
    xShape3->getPropertyValue(u"AdjustLuminance"_ustr) >>= nLuminance3;
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(0), nLuminance3);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf119649)
{
    createSdImpressDoc("pptx/tdf119649.pptx");
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(1, 0));

    // Get first paragraph of the text
    uno::Reference<text::XTextRange> const xParagraph(getParagraphFromShape(0, xShape));

    uno::Reference<text::XTextRange> xRun(getRunFromParagraph(0, xParagraph));
    CPPUNIT_ASSERT_EQUAL(u"default_color("_ustr, xRun->getString());

    uno::Reference<beans::XPropertySet> xPropSet(xRun, uno::UNO_QUERY_THROW);

    Color nCharColor;
    xPropSet->getPropertyValue(u"CharColor"_ustr) >>= nCharColor;
    CPPUNIT_ASSERT_EQUAL(COL_AUTO, nCharColor);

    xRun.set(getRunFromParagraph(1, xParagraph));

    // Without the fix in place, this test would have failed with
    // - Expected: colored_text
    // - Actual  : colored_text)
    CPPUNIT_ASSERT_EQUAL(u"colored_text"_ustr, xRun->getString());

    xPropSet.set(xRun, uno::UNO_QUERY_THROW);

    xPropSet->getPropertyValue(u"CharColor"_ustr) >>= nCharColor;
    CPPUNIT_ASSERT_EQUAL(Color(0xCE181E), nCharColor);

    xRun.set(getRunFromParagraph(2, xParagraph));
    CPPUNIT_ASSERT_EQUAL(u")"_ustr, xRun->getString());

    xPropSet.set(xRun, uno::UNO_QUERY_THROW);

    xPropSet->getPropertyValue(u"CharColor"_ustr) >>= nCharColor;
    CPPUNIT_ASSERT_EQUAL(COL_AUTO, nCharColor);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf118776)
{
    createSdImpressDoc("pptx/tdf118776.pptx");
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0));

    // Get first paragraph of the text
    uno::Reference<text::XTextRange> const xParagraph(getParagraphFromShape(0, xShape));

    // Get first run of the paragraph
    uno::Reference<text::XTextRange> xRun(getRunFromParagraph(0, xParagraph));
    uno::Reference<beans::XPropertySet> xPropSet(xRun, uno::UNO_QUERY_THROW);
    sal_Int16 nTransparency = 0;
    xPropSet->getPropertyValue(u"CharTransparence"_ustr) >>= nTransparency;

    // Import noFill color as 99% transparency
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(99), nTransparency);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf129686)
{
    createSdImpressDoc("pptx/tdf129686.pptx");
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0));

    // Get first paragraph of the text
    uno::Reference<text::XTextRange> const xParagraph(getParagraphFromShape(0, xShape));

    // Get first run of the paragraph
    uno::Reference<text::XTextRange> xRun(getRunFromParagraph(0, xParagraph));
    uno::Reference<beans::XPropertySet> xPropSet(xRun, uno::UNO_QUERY_THROW);
    sal_Int16 nTransparency = 0;
    xPropSet->getPropertyValue(u"CharTransparence"_ustr) >>= nTransparency;

    // 0 = no transparency, 100 (default) = completely transparent (unless COL_AUTO)
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(0), nTransparency);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf104015)
{
    // Shape fill, line and effect properties were not inherited from master slide shape

    createSdImpressDoc("pptx/tdf104015.pptx");

    const SdrPage* pPage = GetPage(1);
    CPPUNIT_ASSERT_MESSAGE("No page found", pPage != nullptr);
    SdrObject* const pObj = pPage->GetObj(0);
    CPPUNIT_ASSERT_MESSAGE("Wrong object", pObj != nullptr);
    // Should have a red fill color
    {
        const XFillStyleItem& rStyleItem = pObj->GetMergedItem(XATTR_FILLSTYLE);
        CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, rStyleItem.GetValue());
        const XFillColorItem& rColorItem = pObj->GetMergedItem(XATTR_FILLCOLOR);
        CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, rColorItem.GetColorValue());
    }
    // Should have a blue line
    {
        const XLineStyleItem& rStyleItem = pObj->GetMergedItem(XATTR_LINESTYLE);
        CPPUNIT_ASSERT_EQUAL(drawing::LineStyle_SOLID, rStyleItem.GetValue());

        const XLineColorItem& rColorItem = pObj->GetMergedItem(XATTR_LINECOLOR);
        CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, rColorItem.GetColorValue());
    }
    // Should have some shadow
    {
        const SdrOnOffItem& rShadowItem = pObj->GetMergedItem(SDRATTR_SHADOW);
        CPPUNIT_ASSERT(rShadowItem.GetValue());
    }
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf104201)
{
    // Group shape properties did not overwrite the child shapes' fill

    createSdImpressDoc("pptx/tdf104201.pptx");

    const SdrPage* pPage = GetPage(1);
    CPPUNIT_ASSERT_MESSAGE("No page found", pPage != nullptr);

    // First shape has red fill, but this should be overwritten by green group fill
    {
        SdrObject* const pObj = pPage->GetObj(0);
        CPPUNIT_ASSERT_MESSAGE("Wrong object", pObj != nullptr);
        const XFillStyleItem& rStyleItem = pObj->GetMergedItem(XATTR_FILLSTYLE);
        CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, rStyleItem.GetValue());
        const XFillColorItem& rColorItem = pObj->GetMergedItem(XATTR_FILLCOLOR);
        CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, rColorItem.GetColorValue());
    }
    // Second shape has blue fill, but this should be overwritten by green group fill
    {
        SdrObject* const pObj = pPage->GetObj(0);
        CPPUNIT_ASSERT_MESSAGE("Wrong object", pObj != nullptr);
        const XFillStyleItem& rStyleItem = pObj->GetMergedItem(XATTR_FILLSTYLE);
        CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, rStyleItem.GetValue());
        const XFillColorItem& rColorItem = pObj->GetMergedItem(XATTR_FILLCOLOR);
        CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, rColorItem.GetColorValue());
    }
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf103477)
{
    createSdImpressDoc("pptx/tdf103477.pptx");

    const SdrPage* pPage = GetPage(1);

    SdrTextObj* pTxtObj = DynCastSdrTextObj(pPage->GetObj(6));
    CPPUNIT_ASSERT_MESSAGE("no text object", pTxtObj != nullptr);

    const EditTextObject& aEdit = pTxtObj->GetOutlinerParaObject()->GetTextObject();
    const SvxNumBulletItem* pNumFmt = aEdit.GetParaAttribs(0).GetItem(EE_PARA_NUMBULLET);
    CPPUNIT_ASSERT(pNumFmt);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Bullet's color is wrong!", COL_BLACK,
                                 pNumFmt->GetNumRule().GetLevel(1).GetBulletColor());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf164640)
{
    createSdImpressDoc();

    SdXImpressDocument* pXImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
    CPPUNIT_ASSERT(pXImpressDocument);
    SdDrawDocument* pDoc = pXImpressDocument->GetDoc();

    SdStyleSheetPool* const pPool(pDoc->GetSdStyleSheetPool());

    for (sal_Int32 nLevel = 1; nLevel < 10; nLevel++)
    {
        OString aMsg = "Fails on level " + OString::number(nLevel);

        OUString aStyleName(SdResId(STR_PSEUDOSHEET_OUTLINE) + " " + OUString::number(nLevel));
        SfxStyleSheetBase* pStyleSheet = pPool->Find(aStyleName, SfxStyleFamily::Pseudo);
        CPPUNIT_ASSERT(pStyleSheet);

        const SvxNumBulletItem& rNumFmt = pStyleSheet->GetItemSet().Get(EE_PARA_NUMBULLET);
        sal_UCS4 aBullet1 = rNumFmt.GetNumRule().GetLevel(0).GetBulletChar();
        CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), sal_UCS4(0x25CF), aBullet1);

        sal_UCS4 aBullet2 = rNumFmt.GetNumRule().GetLevel(1).GetBulletChar();
        // Without the fix in place, this test would have failed with
        // - Expected: 8211
        // - Actual  : 9679
        // - Fails on level 2
        CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), sal_UCS4(0x2013), aBullet2);

        sal_UCS4 aBullet3 = rNumFmt.GetNumRule().GetLevel(2).GetBulletChar();
        CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), sal_UCS4(0x25CF), aBullet3);

        sal_UCS4 aBullet4 = rNumFmt.GetNumRule().GetLevel(3).GetBulletChar();
        CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), sal_UCS4(0x2013), aBullet4);

        sal_UCS4 aBullet5 = rNumFmt.GetNumRule().GetLevel(4).GetBulletChar();
        CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), sal_UCS4(0x25CF), aBullet5);

        sal_UCS4 aBullet6 = rNumFmt.GetNumRule().GetLevel(5).GetBulletChar();
        CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), sal_UCS4(0x25CF), aBullet6);

        sal_UCS4 aBullet7 = rNumFmt.GetNumRule().GetLevel(6).GetBulletChar();
        CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), sal_UCS4(0x25CF), aBullet7);

        sal_UCS4 aBullet8 = rNumFmt.GetNumRule().GetLevel(7).GetBulletChar();
        CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), sal_UCS4(0x25CF), aBullet8);

        sal_UCS4 aBullet9 = rNumFmt.GetNumRule().GetLevel(8).GetBulletChar();
        CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), sal_UCS4(0x25CF), aBullet9);

        sal_UCS4 aBullet10 = rNumFmt.GetNumRule().GetLevel(9).GetBulletChar();
        CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), sal_UCS4(0x25CF), aBullet10);
    }
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf105150)
{
    createSdImpressDoc("pptx/tdf105150.pptx");
    const SdrPage* pPage = GetPage(1);
    const SdrObject* pObj = pPage->GetObj(1);
    auto& rFillStyleItem = pObj->GetMergedItem(XATTR_FILLSTYLE);
    // This was drawing::FillStyle_NONE, <p:sp useBgFill="1"> was ignored when
    // the slide didn't have an explicit background fill.
    CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, rFillStyleItem.GetValue());
    auto& rFillBackgroundItem = pObj->GetMergedItem(XATTR_FILLUSESLIDEBACKGROUND);
    CPPUNIT_ASSERT_EQUAL(true, rFillBackgroundItem.GetValue());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf123684)
{
    createSdImpressDoc("pptx/tdf123684.pptx");
    const SdrPage* pPage = GetPage(1);
    const SdrObject* pObj = pPage->GetObj(0);
    auto& rFillStyleItem = pObj->GetMergedItem(XATTR_FILLSTYLE);
    // Without the accompanying fix in place, this test would have failed with 'Expected: 0; Actual:
    // 1', i.e. the shape's fill was FillStyle_SOLID, making the text of the shape unreadable.
    CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, rFillStyleItem.GetValue());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf105150PPT)
{
    createSdImpressDoc("ppt/tdf105150.ppt");
    const SdrPage* pPage = GetPage(1);
    const SdrObject* pObj = pPage->GetObj(1);
    // This was drawing::FillStyle_NONE, the shape's mso_fillBackground was
    // ignored when the slide didn't have an explicit background fill.
    auto& rFillStyleItem = pObj->GetMergedItem(XATTR_FILLSTYLE);
    CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, rFillStyleItem.GetValue());
    auto& rFillBackgroundItem = pObj->GetMergedItem(XATTR_FILLUSESLIDEBACKGROUND);
    CPPUNIT_ASSERT_EQUAL(true, rFillBackgroundItem.GetValue());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf104445)
{
    // Extra bullets were added to the first shape

    createSdImpressDoc("pptx/tdf104445.pptx");

    // First shape should not have bullet
    {
        uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0));
        uno::Reference<text::XText> xText
            = uno::Reference<text::XTextRange>(xShape, uno::UNO_QUERY_THROW)->getText();
        CPPUNIT_ASSERT_MESSAGE("Not a text shape", xText.is());
        uno::Reference<beans::XPropertySet> xPropSet(xText, uno::UNO_QUERY_THROW);

        uno::Reference<container::XIndexAccess> xNumRule;
        xPropSet->getPropertyValue(u"NumberingRules"_ustr) >>= xNumRule;
        uno::Sequence<beans::PropertyValue> aBulletProps;
        xNumRule->getByIndex(0) >>= aBulletProps;

        for (beans::PropertyValue const& rProp : aBulletProps)
        {
            if (rProp.Name == "NumberingType")
                CPPUNIT_ASSERT_EQUAL(sal_Int16(style::NumberingType::NUMBER_NONE),
                                     rProp.Value.get<sal_Int16>());
            if (rProp.Name == "LeftMargin")
                CPPUNIT_ASSERT_EQUAL(sal_Int32(0), rProp.Value.get<sal_Int32>());
        }
    }
    // Second shape should have bullet set
    {
        uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(1, 0));
        uno::Reference<text::XText> xText
            = uno::Reference<text::XTextRange>(xShape, uno::UNO_QUERY_THROW)->getText();
        CPPUNIT_ASSERT_MESSAGE("Not a text shape", xText.is());
        uno::Reference<beans::XPropertySet> xPropSet(xText, uno::UNO_QUERY_THROW);

        uno::Reference<container::XIndexAccess> xNumRule;
        xPropSet->getPropertyValue(u"NumberingRules"_ustr) >>= xNumRule;
        uno::Sequence<beans::PropertyValue> aBulletProps;
        xNumRule->getByIndex(0) >>= aBulletProps;

        for (beans::PropertyValue const& rProp : aBulletProps)
        {
            if (rProp.Name == "NumberingType")
                CPPUNIT_ASSERT_EQUAL(sal_Int16(style::NumberingType::CHAR_SPECIAL),
                                     rProp.Value.get<sal_Int16>());
            if (rProp.Name == "LeftMargin")
                CPPUNIT_ASSERT_EQUAL(sal_Int32(635), rProp.Value.get<sal_Int32>());
        }
    }
}

namespace
{
bool checkPatternValues(std::vector<sal_uInt8>& rExpected, Bitmap& rBitmap)
{
    bool bResult = true;

    const Color aFGColor(COL_LIGHTRED);
    const Color aBGColor(COL_WHITE);

    BitmapScopedReadAccess pAccess(rBitmap);
    for (tools::Long y = 0; y < pAccess->Height(); ++y)
    {
        Scanline pScanline = pAccess->GetScanline(y);
        for (tools::Long x = 0; x < pAccess->Width(); ++x)
        {
            Color aColor = pAccess->GetPixelFromData(pScanline, x);
            sal_uInt8 aValue = rExpected[y * 8 + x];

            if (aValue == 1 && aColor != aFGColor)
                bResult = false;
            else if (aValue == 0 && aColor != aBGColor)
                bResult = false;
        }
    }

    return bResult;
}

} // end anonymous namespace

bool SdImportTest2::checkPattern(int nShapeNumber, std::vector<sal_uInt8>& rExpected)
{
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(nShapeNumber, 0));
    CPPUNIT_ASSERT_MESSAGE("Not a shape", xShape.is());

    Bitmap aBitmap;
    if (xShape.is())
    {
        uno::Any aBitmapAny = xShape->getPropertyValue(u"FillBitmap"_ustr);
        uno::Reference<awt::XBitmap> xBitmap;
        if (aBitmapAny >>= xBitmap)
        {
            uno::Sequence<sal_Int8> aBitmapSequence(xBitmap->getDIB());
            SvMemoryStream aBitmapStream(aBitmapSequence.getArray(), aBitmapSequence.getLength(),
                                         StreamMode::READ);
            ReadDIB(aBitmap, aBitmapStream, true);
        }
    }
    CPPUNIT_ASSERT_EQUAL(tools::Long(8), aBitmap.GetSizePixel().Width());
    CPPUNIT_ASSERT_EQUAL(tools::Long(8), aBitmap.GetSizePixel().Height());
    return checkPatternValues(rExpected, aBitmap);
}

/* Test checks that importing a PPT file with all supported fill patterns is
 * correctly imported as a tiled fill bitmap with the expected pattern.
 */
CPPUNIT_TEST_FIXTURE(SdImportTest2, testPatternImport)
{
    createSdImpressDoc("ppt/FillPatterns.ppt");

    std::vector<sal_uInt8> aExpectedPattern1 = {
        1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    };
    std::vector<sal_uInt8> aExpectedPattern2 = {
        1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    };
    std::vector<sal_uInt8> aExpectedPattern3 = {
        1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
        1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    };
    std::vector<sal_uInt8> aExpectedPattern4 = {
        1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0,
        0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0,
        0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0,
    };
    std::vector<sal_uInt8> aExpectedPattern5 = {
        1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0,
        1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0,
        0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1,
    };
    std::vector<sal_uInt8> aExpectedPattern6 = {
        1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0,
        1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1,
        0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1,
    };
    std::vector<sal_uInt8> aExpectedPattern7 = {
        1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0,
        1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1,
        0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1,
    };
    std::vector<sal_uInt8> aExpectedPattern8 = {
        1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0,
        1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1,
        0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1,
    };
    std::vector<sal_uInt8> aExpectedPattern9 = {
        0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1,
        1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1,
        1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1,
    };
    std::vector<sal_uInt8> aExpectedPattern10 = {
        0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
        0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    };
    std::vector<sal_uInt8> aExpectedPattern11 = {
        1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
    };
    std::vector<sal_uInt8> aExpectedPattern12 = {
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
    };
    std::vector<sal_uInt8> aExpectedPatternLine1 = {
        1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0,
        1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
        0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1,
    };
    std::vector<sal_uInt8> aExpectedPatternLine2 = {
        0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1,
        0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0,
        0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
    };
    std::vector<sal_uInt8> aExpectedPatternLine3 = {
        1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0,
        1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0,
        0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1,
    };
    std::vector<sal_uInt8> aExpectedPatternLine4 = {
        0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1,
        0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0,
        0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1,
    };
    std::vector<sal_uInt8> aExpectedPatternLine5 = {
        1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
        0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
        1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1,
    };
    std::vector<sal_uInt8> aExpectedPatternLine6 = {
        1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1,
        1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1,
        0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1,
    };
    std::vector<sal_uInt8> aExpectedPatternLine7 = {
        1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0,
        0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
        1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
    };
    std::vector<sal_uInt8> aExpectedPatternLine8 = {
        1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    };
    std::vector<sal_uInt8> aExpectedPatternLine9 = {
        0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
        0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
        0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
    };
    std::vector<sal_uInt8> aExpectedPatternLine10 = {
        1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
        1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
        0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
    };
    std::vector<sal_uInt8> aExpectedPatternLine11 = {
        1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,
        0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
        1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
    };
    std::vector<sal_uInt8> aExpectedPatternLine12 = {
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    };

    CPPUNIT_ASSERT_MESSAGE("Pattern1 - 5%", checkPattern(0, aExpectedPattern1));
    CPPUNIT_ASSERT_MESSAGE("Pattern2 - 10%", checkPattern(1, aExpectedPattern2));
    CPPUNIT_ASSERT_MESSAGE("Pattern3 - 20%", checkPattern(2, aExpectedPattern3));
    CPPUNIT_ASSERT_MESSAGE("Pattern4 - 25%", checkPattern(3, aExpectedPattern4));
    CPPUNIT_ASSERT_MESSAGE("Pattern5 - 30%", checkPattern(4, aExpectedPattern5));
    CPPUNIT_ASSERT_MESSAGE("Pattern6 - 40%", checkPattern(5, aExpectedPattern6));
    CPPUNIT_ASSERT_MESSAGE("Pattern7 - 50%", checkPattern(6, aExpectedPattern7));
    CPPUNIT_ASSERT_MESSAGE("Pattern8 - 60%", checkPattern(7, aExpectedPattern8));
    CPPUNIT_ASSERT_MESSAGE("Pattern9 - 70%", checkPattern(8, aExpectedPattern9));
    CPPUNIT_ASSERT_MESSAGE("Pattern10 - 75%", checkPattern(9, aExpectedPattern10));
    CPPUNIT_ASSERT_MESSAGE("Pattern11 - 80%", checkPattern(10, aExpectedPattern11));
    CPPUNIT_ASSERT_MESSAGE("Pattern12 - 90%", checkPattern(11, aExpectedPattern12));

    CPPUNIT_ASSERT_MESSAGE("Pattern13 - Light downward diagonal",
                           checkPattern(12, aExpectedPatternLine1));
    CPPUNIT_ASSERT_MESSAGE("Pattern14 - Light upward diagonal",
                           checkPattern(13, aExpectedPatternLine2));
    CPPUNIT_ASSERT_MESSAGE("Pattern15 - Dark downward diagonal",
                           checkPattern(14, aExpectedPatternLine3));
    CPPUNIT_ASSERT_MESSAGE("Pattern16 - Dark upward diagonal",
                           checkPattern(15, aExpectedPatternLine4));
    CPPUNIT_ASSERT_MESSAGE("Pattern17 - Wide downward diagonal",
                           checkPattern(16, aExpectedPatternLine5));
    CPPUNIT_ASSERT_MESSAGE("Pattern18 - Wide upward diagonal",
                           checkPattern(17, aExpectedPatternLine6));

    CPPUNIT_ASSERT_MESSAGE("Pattern19 - Light vertical", checkPattern(18, aExpectedPatternLine7));
    CPPUNIT_ASSERT_MESSAGE("Pattern20 - Light horizontal", checkPattern(19, aExpectedPatternLine8));
    CPPUNIT_ASSERT_MESSAGE("Pattern21 - Narrow vertical", checkPattern(20, aExpectedPatternLine9));
    CPPUNIT_ASSERT_MESSAGE("Pattern22 - Narrow horizontal",
                           checkPattern(21, aExpectedPatternLine10));
    CPPUNIT_ASSERT_MESSAGE("Pattern23 - Dark vertical", checkPattern(22, aExpectedPatternLine11));
    CPPUNIT_ASSERT_MESSAGE("Pattern24 - Dark horizontal", checkPattern(23, aExpectedPatternLine12));

    // TODO: other patterns in the test document
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf100926)
{
    createSdImpressDoc("pptx/tdf100926.pptx");
    const SdrPage* pPage = GetPage(1);
    CPPUNIT_ASSERT(pPage != nullptr);

    sdr::table::SdrTableObj* pTableObj = dynamic_cast<sdr::table::SdrTableObj*>(pPage->GetObj(0));
    CPPUNIT_ASSERT(pTableObj != nullptr);
    uno::Reference<table::XCellRange> xTable(pTableObj->getTable(), uno::UNO_QUERY_THROW);

    sal_Int32 nRotation = 0;
    uno::Reference<beans::XPropertySet> xCell(xTable->getCellByPosition(0, 0),
                                              uno::UNO_QUERY_THROW);
    xCell->getPropertyValue(u"RotateAngle"_ustr) >>= nRotation;
    CPPUNIT_ASSERT_EQUAL(sal_Int32(27000), nRotation);

    xCell.set(xTable->getCellByPosition(1, 0), uno::UNO_QUERY_THROW);
    xCell->getPropertyValue(u"RotateAngle"_ustr) >>= nRotation;
    CPPUNIT_ASSERT_EQUAL(sal_Int32(9000), nRotation);

    xCell.set(xTable->getCellByPosition(2, 0), uno::UNO_QUERY_THROW);
    xCell->getPropertyValue(u"RotateAngle"_ustr) >>= nRotation;
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nRotation);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf89064)
{
    createSdImpressDoc("pptx/tdf89064.pptx");
    uno::Reference<presentation::XPresentationPage> xPage(getPage(0), uno::UNO_QUERY_THROW);
    uno::Reference<drawing::XDrawPage> xNotesPage(xPage->getNotesPage(), uno::UNO_SET_THROW);
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xNotesPage->getCount());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf108925)
{
    // Test document contains bulleting with too small bullet size (1%) which breaks the lower constraint
    // So it should be converted to the lowest allowed value (25%).

    createSdImpressDoc("odp/tdf108925.odp");
    const SdrPage* pPage = GetPage(1);
    SdrTextObj* pTxtObj = DynCastSdrTextObj(pPage->GetObj(0));
    CPPUNIT_ASSERT_MESSAGE("No text object", pTxtObj != nullptr);
    const EditTextObject& aEdit = pTxtObj->GetOutlinerParaObject()->GetTextObject();

    const SvxNumBulletItem* pNumFmt = aEdit.GetParaAttribs(0).GetItem(EE_PARA_NUMBULLET);
    CPPUNIT_ASSERT(pNumFmt);
    CPPUNIT_ASSERT_EQUAL(sal_uInt16(25), pNumFmt->GetNumRule().GetLevel(0).GetBulletRelSize());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf109067)
{
    createSdImpressDoc("pptx/tdf109067.pptx");
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0), uno::UNO_SET_THROW);
    awt::Gradient gradient;
    CPPUNIT_ASSERT(xShape->getPropertyValue(u"FillGradient"_ustr) >>= gradient);
    CPPUNIT_ASSERT_EQUAL(sal_Int16(450), gradient.Angle);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf109187)
{
    createSdImpressDoc("pptx/tdf109187.pptx");
    uno::Reference<beans::XPropertySet> xArrow1(getShapeFromPage(0, 0), uno::UNO_SET_THROW);
    awt::Gradient aGradient1;
    CPPUNIT_ASSERT(xArrow1->getPropertyValue(u"FillGradient"_ustr) >>= aGradient1);
    CPPUNIT_ASSERT_EQUAL(sal_Int16(2250), aGradient1.Angle);
    uno::Reference<beans::XPropertySet> xArrow2(getShapeFromPage(1, 0), uno::UNO_SET_THROW);
    awt::Gradient aGradient2;
    CPPUNIT_ASSERT(xArrow2->getPropertyValue(u"FillGradient"_ustr) >>= aGradient2);
    CPPUNIT_ASSERT_EQUAL(sal_Int16(1350), aGradient2.Angle);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf108926)
{
    createSdImpressDoc("pptx/tdf108926.ppt");
    uno::Reference<presentation::XPresentationPage> xPage(getPage(0), uno::UNO_QUERY_THROW);
    uno::Reference<drawing::XDrawPage> xNotesPage(xPage->getNotesPage(), uno::UNO_SET_THROW);
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xNotesPage->getCount());

    // Second object should be imported as an empty presentation shape
    uno::Reference<beans::XPropertySet> xPresentationShape(xNotesPage->getByIndex(1),
                                                           uno::UNO_QUERY);
    CPPUNIT_ASSERT(xPresentationShape.is());
    bool bIsEmptyPresObject = false;
    xPresentationShape->getPropertyValue(u"IsEmptyPresentationObject"_ustr) >>= bIsEmptyPresObject;
    CPPUNIT_ASSERT(bIsEmptyPresObject);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf100065)
{
    createSdImpressDoc("pptx/tdf100065.pptx");

    uno::Reference<container::XIndexAccess> xGroupShape1(getShapeFromPage(0, 0),
                                                         uno::UNO_QUERY_THROW);
    uno::Reference<beans::XPropertySet> xShape1(xGroupShape1->getByIndex(1), uno::UNO_QUERY_THROW);
    sal_Int32 nAngle1;
    CPPUNIT_ASSERT(xShape1->getPropertyValue(u"RotateAngle"_ustr) >>= nAngle1);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(2000), nAngle1);

    uno::Reference<container::XIndexAccess> xGroupShape2(getShapeFromPage(1, 0),
                                                         uno::UNO_QUERY_THROW);
    uno::Reference<beans::XPropertySet> xShape2(xGroupShape2->getByIndex(0), uno::UNO_QUERY_THROW);
    sal_Int32 nAngle2;
    CPPUNIT_ASSERT(xShape2->getPropertyValue(u"RotateAngle"_ustr) >>= nAngle2);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(18000), nAngle2);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf90626)
{
    createSdImpressDoc("pptx/tdf90626.pptx");
    const SdrPage* pPage = GetPage(1);
    SdrTextObj* pTxtObj = DynCastSdrTextObj(pPage->GetObj(1));
    CPPUNIT_ASSERT_MESSAGE("No text object", pTxtObj != nullptr);
    const EditTextObject& aEdit = pTxtObj->GetOutlinerParaObject()->GetTextObject();
    for (int i = 0; i < 4; i++)
    {
        const SvxNumBulletItem* pNumFmt = aEdit.GetParaAttribs(i).GetItem(EE_PARA_NUMBULLET);
        CPPUNIT_ASSERT(pNumFmt);
        CPPUNIT_ASSERT_DOUBLES_EQUAL(tools::Long(372),
                                     pNumFmt->GetNumRule().GetLevel(0).GetGraphicSize().getHeight(),
                                     tools::Long(1));
    }
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf138148)
{
    createSdImpressDoc("pptx/tdf138148.pptx");
    const SdrPage* pPage = GetPage(1);
    SdrTextObj* pTxtObj = DynCastSdrTextObj(pPage->GetObj(0));
    CPPUNIT_ASSERT_MESSAGE("No text object", pTxtObj != nullptr);
    const EditTextObject& aEdit = pTxtObj->GetOutlinerParaObject()->GetTextObject();
    for (int i = 0; i < 2; i++)
    {
        const SvxNumBulletItem* pNumFmt = aEdit.GetParaAttribs(i).GetItem(EE_PARA_NUMBULLET);
        CPPUNIT_ASSERT(pNumFmt);
        CPPUNIT_ASSERT_DOUBLES_EQUAL(tools::Long(444),
                                     pNumFmt->GetNumRule().GetLevel(0).GetGraphicSize().getHeight(),
                                     tools::Long(1));

        // Without the fix in place, this test would have failed with
        // - Expected: 148
        // - Actual  : 444
        CPPUNIT_ASSERT_DOUBLES_EQUAL(tools::Long(148),
                                     pNumFmt->GetNumRule().GetLevel(0).GetGraphicSize().getWidth(),
                                     tools::Long(1));
    }
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf114488)
{
    // This doc has two images - one WMF and the other PNG (fallback image).
    // When loading this doc, the WMF image should be preferred over the PNG image.

    createSdDrawDoc("odg/tdf114488.fodg");
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0), uno::UNO_SET_THROW);
    uno::Reference<graphic::XGraphic> xGraphic;
    xShape->getPropertyValue(u"Graphic"_ustr) >>= xGraphic;
    CPPUNIT_ASSERT(xGraphic.is());
    OUString sMimeType(comphelper::GraphicMimeTypeHelper::GetMimeTypeForXGraphic(xGraphic));
    CPPUNIT_ASSERT_EQUAL(u"image/x-wmf"_ustr, sMimeType);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf134174)
{
    createSdImpressDoc("pptx/tdf134174.pptx");
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0), uno::UNO_SET_THROW);
    CPPUNIT_ASSERT(xShape.is());

    uno::Reference<graphic::XGraphic> xGraphic;
    xShape->getPropertyValue(u"FillBitmap"_ustr) >>= xGraphic;
    CPPUNIT_ASSERT(xGraphic.is());

    Graphic aGraphic(xGraphic);
    Bitmap aBitmap(aGraphic.GetBitmap());
    CPPUNIT_ASSERT_EQUAL(Color(0x8b21db), aBitmap.GetPixelColor(0, 0));
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf134210)
{
    createSdImpressDoc("pptx/tdf134210.pptx");
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0), uno::UNO_SET_THROW);
    CPPUNIT_ASSERT(xShape.is());

    uno::Reference<graphic::XGraphic> xGraphic;
    xShape->getPropertyValue(u"FillBitmap"_ustr) >>= xGraphic;
    CPPUNIT_ASSERT(xGraphic.is());

    Graphic aGraphic(xGraphic);
    Bitmap aBitmap(aGraphic.GetBitmap());
    CPPUNIT_ASSERT_EQUAL(Color(0x605741), aBitmap.GetPixelColor(0, 0));
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf114913)
{
    createSdImpressDoc("pptx/tdf114913.pptx");
    SdrTextObj* pTxtObj = DynCastSdrTextObj(GetPage(1)->GetObj(1));
    CPPUNIT_ASSERT_MESSAGE("No text object", pTxtObj != nullptr);
    const SvxNumBulletItem* pItem
        = pTxtObj->GetOutlinerParaObject()->GetTextObject().GetParaAttribs(0).GetItem(
            EE_PARA_NUMBULLET);
    CPPUNIT_ASSERT(pItem);
    CPPUNIT_ASSERT_EQUAL(tools::Long(692),
                         pItem->GetNumRule().GetLevel(0).GetGraphicSize().getHeight());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf114821)
{
    css::uno::Any aAny;

    createSdImpressDoc("pptx/tdf114821.pptx");

    uno::Reference<beans::XPropertySet> xPropSet(getShapeFromPage(0, 0));
    aAny = xPropSet->getPropertyValue(u"Model"_ustr);
    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());

    // These Labels have custom position, so the exported LabelPlacement (reference point) by MSO is OUTSIDE/OUTEND
    // Check the first label
    const css::uno::Reference<css::beans::XPropertySet> aPropSet0(
        aSeriesSeq[0]->getDataPointByIndex(0));
    CPPUNIT_ASSERT(aPropSet0.is());
    sal_Int32 aPlacement;
    aPropSet0->getPropertyValue(u"LabelPlacement"_ustr) >>= aPlacement;
    CPPUNIT_ASSERT_EQUAL(css::chart::DataLabelPlacement::OUTSIDE, aPlacement);

    // Check the second label
    const css::uno::Reference<css::beans::XPropertySet> aPropSet1(
        aSeriesSeq[0]->getDataPointByIndex(1));
    CPPUNIT_ASSERT(aPropSet1.is());
    aPropSet1->getPropertyValue(u"LabelPlacement"_ustr) >>= aPlacement;
    CPPUNIT_ASSERT_EQUAL(css::chart::DataLabelPlacement::OUTSIDE, aPlacement);

    // Check the third label
    const css::uno::Reference<css::beans::XPropertySet> aPropSet2(
        aSeriesSeq[0]->getDataPointByIndex(2));
    CPPUNIT_ASSERT(aPropSet2.is());
    aPropSet2->getPropertyValue(u"LabelPlacement"_ustr) >>= aPlacement;
    CPPUNIT_ASSERT_EQUAL(css::chart::DataLabelPlacement::OUTSIDE, aPlacement);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf115394)
{
    createSdImpressDoc("pptx/tdf115394.pptx");
    double fTransitionDuration;

    SdXImpressDocument* pXImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
    CPPUNIT_ASSERT(pXImpressDocument);
    SdDrawDocument* pDoc = pXImpressDocument->GetDoc();

    // Slow in MS formats
    SdPage* pPage1 = pDoc->GetSdPage(0, PageKind::Standard);
    fTransitionDuration = pPage1->getTransitionDuration();
    CPPUNIT_ASSERT_EQUAL(1.0, fTransitionDuration);

    // Medium in MS formats
    SdPage* pPage2 = pDoc->GetSdPage(1, PageKind::Standard);
    fTransitionDuration = pPage2->getTransitionDuration();
    CPPUNIT_ASSERT_EQUAL(0.75, fTransitionDuration);

    // Fast in MS formats
    SdPage* pPage3 = pDoc->GetSdPage(2, PageKind::Standard);
    fTransitionDuration = pPage3->getTransitionDuration();
    CPPUNIT_ASSERT_EQUAL(0.5, fTransitionDuration);

    // Custom values
    SdPage* pPage4 = pDoc->GetSdPage(3, PageKind::Standard);
    fTransitionDuration = pPage4->getTransitionDuration();
    CPPUNIT_ASSERT_EQUAL(0.25, fTransitionDuration);

    SdPage* pPage5 = pDoc->GetSdPage(4, PageKind::Standard);
    fTransitionDuration = pPage5->getTransitionDuration();
    CPPUNIT_ASSERT_EQUAL(4.25, fTransitionDuration);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf115394PPT)
{
    createSdImpressDoc("ppt/tdf115394.ppt");
    double fTransitionDuration;

    SdXImpressDocument* pXImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
    CPPUNIT_ASSERT(pXImpressDocument);
    SdDrawDocument* pDoc = pXImpressDocument->GetDoc();

    // Fast
    SdPage* pPage1 = pDoc->GetSdPage(0, PageKind::Standard);
    fTransitionDuration = pPage1->getTransitionDuration();
    CPPUNIT_ASSERT_EQUAL(0.5, fTransitionDuration);

    // Medium
    SdPage* pPage2 = pDoc->GetSdPage(1, PageKind::Standard);
    fTransitionDuration = pPage2->getTransitionDuration();
    CPPUNIT_ASSERT_EQUAL(0.75, fTransitionDuration);

    // Slow
    SdPage* pPage3 = pDoc->GetSdPage(2, PageKind::Standard);
    fTransitionDuration = pPage3->getTransitionDuration();
    CPPUNIT_ASSERT_EQUAL(1.0, fTransitionDuration);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf51340)
{
    // Line spacing was not inherited from upper levels (slide layout, master slide)

    createSdImpressDoc("pptx/tdf51340.pptx");
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(1, 0));

    // First paragraph has a 90% line spacing set on master slide
    uno::Reference<text::XTextRange> xParagraph(getParagraphFromShape(0, xShape));
    uno::Reference<beans::XPropertySet> xPropSet(xParagraph, uno::UNO_QUERY_THROW);
    css::style::LineSpacing aSpacing;
    xPropSet->getPropertyValue(u"ParaLineSpacing"_ustr) >>= aSpacing;
    CPPUNIT_ASSERT_EQUAL(css::style::LineSpacingMode::PROP, aSpacing.Mode);
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(90), aSpacing.Height);

    // Second paragraph has a 125% line spacing set on slide layout
    xParagraph.set(getParagraphFromShape(1, xShape));
    xPropSet.set(xParagraph, uno::UNO_QUERY_THROW);
    xPropSet->getPropertyValue(u"ParaLineSpacing"_ustr) >>= aSpacing;
    CPPUNIT_ASSERT_EQUAL(css::style::LineSpacingMode::PROP, aSpacing.Mode);
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(125), aSpacing.Height);

    // Third paragraph has a 70% line spacing set directly on normal slide (master slide property is overridden)
    xParagraph.set(getParagraphFromShape(2, xShape));
    xPropSet.set(xParagraph, uno::UNO_QUERY_THROW);
    xPropSet->getPropertyValue(u"ParaLineSpacing"_ustr) >>= aSpacing;
    CPPUNIT_ASSERT_EQUAL(css::style::LineSpacingMode::PROP, aSpacing.Mode);
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(70), aSpacing.Height);

    // Fourth paragraph has a 190% line spacing set directly on normal slide (slide layout property is overridden)
    xParagraph.set(getParagraphFromShape(3, xShape));
    xPropSet.set(xParagraph, uno::UNO_QUERY_THROW);
    xPropSet->getPropertyValue(u"ParaLineSpacing"_ustr) >>= aSpacing;
    CPPUNIT_ASSERT_EQUAL(css::style::LineSpacingMode::PROP, aSpacing.Mode);
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(190), aSpacing.Height);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf116899)
{
    // This is a PPT created in Impress and roundtripped in PP, the key times become [1, -1] in PP,
    //  a time of -1 (-1000) in PPT means key times have to be distributed evenly between 0 and 1

    createSdImpressDoc("ppt/tdf116899.ppt");

    uno::Reference<drawing::XDrawPagesSupplier> xDoc(mxComponent, uno::UNO_QUERY_THROW);
    uno::Reference<drawing::XDrawPage> xPage(xDoc->getDrawPages()->getByIndex(0),
                                             uno::UNO_QUERY_THROW);
    uno::Reference<animations::XAnimationNodeSupplier> xAnimNodeSupplier(xPage,
                                                                         uno::UNO_QUERY_THROW);
    uno::Reference<animations::XAnimationNode> xRootNode(xAnimNodeSupplier->getAnimationNode());
    std::vector<uno::Reference<animations::XAnimationNode>> aAnimVector;
    anim::create_deep_vector(xRootNode, aAnimVector);
    uno::Reference<animations::XAnimate> xNode(aAnimVector[8], uno::UNO_QUERY_THROW);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Number of key times in the animation node isn't 2.",
                                 static_cast<sal_Int32>(2), xNode->getKeyTimes().getLength());
    CPPUNIT_ASSERT_EQUAL_MESSAGE(
        "First key time in the animation node isn't 0, key times aren't normalized.", 0.,
        xNode->getKeyTimes()[0]);
    CPPUNIT_ASSERT_EQUAL_MESSAGE(
        "Second key time in the animation node isn't 1, key times aren't normalized.", 1.,
        xNode->getKeyTimes()[1]);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf77747)
{
    createSdImpressDoc("ppt/tdf77747.ppt");
    SdrTextObj* pTxtObj = DynCastSdrTextObj(GetPage(1)->GetObj(0));
    CPPUNIT_ASSERT_MESSAGE("No text object", pTxtObj != nullptr);
    const SvxNumBulletItem* pNumFmt
        = pTxtObj->GetOutlinerParaObject()->GetTextObject().GetParaAttribs(0).GetItem(
            EE_PARA_NUMBULLET);
    CPPUNIT_ASSERT(pNumFmt);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Bullet's suffix is wrong!", u"-"_ustr,
                                 pNumFmt->GetNumRule().GetLevel(0).GetSuffix());
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Bullet's numbering type is wrong!", SVX_NUM_NUMBER_HEBREW,
                                 pNumFmt->GetNumRule().GetLevel(0).GetNumberingType());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf116266)
{
    createSdImpressDoc("odp/tdf116266.odp");
    SdXImpressDocument* pXImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
    CPPUNIT_ASSERT(pXImpressDocument);
    SdDrawDocument* pDoc = pXImpressDocument->GetDoc();
    sfx2::LinkManager* rLinkManager = pDoc->GetLinkManager();
    // The document contains one SVG stored as a link.
    CPPUNIT_ASSERT_EQUAL(size_t(1), rLinkManager->GetLinks().size());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testPptCrop)
{
    createSdImpressDoc("ppt/crop.ppt");

    uno::Reference<beans::XPropertySet> xPropertySet(getShapeFromPage(/*nShape=*/1, /*nPage=*/0));
    text::GraphicCrop aCrop;
    xPropertySet->getPropertyValue(u"GraphicCrop"_ustr) >>= aCrop;
    // These were all 0, lazy-loading broke cropping.
    CPPUNIT_ASSERT_GREATER(static_cast<sal_Int32>(0), aCrop.Top);
    CPPUNIT_ASSERT_GREATER(static_cast<sal_Int32>(0), aCrop.Bottom);
    CPPUNIT_ASSERT_GREATER(static_cast<sal_Int32>(0), aCrop.Left);
    CPPUNIT_ASSERT_GREATER(static_cast<sal_Int32>(0), aCrop.Right);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf149206)
{
    // Check that the image is cropped
    createSdImpressDoc("pptx/tdf149206.pptx");

    uno::Reference<beans::XPropertySet> xPropertySet(getShapeFromPage(/*nShape=*/0, /*nPage=*/0));
    text::GraphicCrop aCrop;
    xPropertySet->getPropertyValue(u"GraphicCrop"_ustr) >>= aCrop;

    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aCrop.Top);

    // Without the fix in place, this test would have failed with
    // - Expected: 5937
    // - Actual  : 0
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(5937), aCrop.Bottom);
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aCrop.Left);
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aCrop.Right);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testtdf163852)
{
    // Check that the svg image is cropped
    createSdImpressDoc("pptx/tdf163852.pptx");

    uno::Reference<beans::XPropertySet> xPropertySet(getShapeFromPage(/*nShape=*/1, /*nPage=*/0));
    text::GraphicCrop aCrop;
    xPropertySet->getPropertyValue(u"GraphicCrop"_ustr) >>= aCrop;

    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aCrop.Top);
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aCrop.Left);
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aCrop.Right);
    // Without the fix in place, this test would have failed with
    // - Expected: 702
    // - Actual  : 0
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(702), aCrop.Bottom);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf149785)
{
    // Without the fix in place, this test would have failed to load the file
    createSdImpressDoc("pptx/tdf149785.pptx");

    const SdrPage* pPage = GetPage(1);
    CPPUNIT_ASSERT_EQUAL(size_t(1), pPage->GetObjCount());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf149985)
{
    // Without the fix in place, this test would have failed to load the file
    createSdImpressDoc("pptx/tdf149985.pptx");

    const SdrPage* pPage = GetPage(1);
    CPPUNIT_ASSERT_EQUAL(size_t(1), pPage->GetObjCount());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf150770)
{
    // Without the fix in place, this test would have failed to load the file
    createSdImpressDoc("pptx/tdf150770.pptx");
    uno::Reference<drawing::XDrawPagesSupplier> xDoc(mxComponent, uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(4), xDoc->getDrawPages()->getCount());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf120028)
{
    // Check that the text shape has 4 columns.
    createSdImpressDoc("pptx/tdf120028.pptx");
    uno::Reference<drawing::XDrawPagesSupplier> xDoc(mxComponent, uno::UNO_QUERY);
    CPPUNIT_ASSERT(xDoc.is());

    uno::Reference<drawing::XDrawPage> xPage(xDoc->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
    CPPUNIT_ASSERT(xPage.is());

    uno::Reference<beans::XPropertySet> xShape(getShape(0, xPage));
    uno::Reference<text::XTextColumns> xCols(xShape->getPropertyValue(u"TextColumns"_ustr),
                                             uno::UNO_QUERY_THROW);
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(4), xCols->getColumnCount());
    uno::Reference<beans::XPropertySet> xColProps(xCols, uno::UNO_QUERY_THROW);
    CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(0)),
                         xColProps->getPropertyValue(u"AutomaticDistance"_ustr));

    // Check font size in the shape.
    uno::Reference<text::XTextRange> xParagraph(getParagraphFromShape(0, xShape));
    uno::Reference<text::XTextRange> xRun(getRunFromParagraph(0, xParagraph));
    uno::Reference<beans::XPropertySet> xPropSet(xRun, uno::UNO_QUERY_THROW);
    double fCharHeight = 0;
    xPropSet->getPropertyValue(u"CharHeight"_ustr) >>= fCharHeight;
    CPPUNIT_ASSERT_DOUBLES_EQUAL(13.5, fCharHeight, 1E-12);

    double fFontScale = 0.0;
    xShape->getPropertyValue(u"TextFitToSizeFontScale"_ustr) >>= fFontScale;
    CPPUNIT_ASSERT_DOUBLES_EQUAL(92.0, fFontScale, 1E1);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testDescriptionImport)
{
    createSdImpressDoc("pptx/altdescription.pptx");

    uno::Reference<beans::XPropertySet> xPropertySet(getShapeFromPage(/*nShape=*/2, /*nPage=*/0));
    OUString sDesc;

    xPropertySet->getPropertyValue(u"Description"_ustr) >>= sDesc;

    CPPUNIT_ASSERT_EQUAL(u"We Can Do It!"_ustr, sDesc);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf83247)
{
    auto GetPause = [this](const OUString& sSrc) {
        loadFromFile(sSrc);
        uno::Reference<presentation::XPresentationSupplier> xPresentationSupplier(mxComponent,
                                                                                  uno::UNO_QUERY);
        uno::Reference<beans::XPropertySet> xPresentationProps(
            xPresentationSupplier->getPresentation(), uno::UNO_QUERY_THROW);

        auto retVal = xPresentationProps->getPropertyValue(u"Pause"_ustr);
        return retVal.get<sal_Int32>();
    };

    // 1. Check that presentation:pause attribute is imported correctly
    CPPUNIT_ASSERT_EQUAL(sal_Int32(10), GetPause(u"odp/loopPause10.odp"_ustr));

    // 2. ODF compliance: if presentation:pause attribute is absent, it must be treated as 0
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), GetPause(u"odp/loopNoPause.odp"_ustr));

    // 3. Import PPT: pause should be 0
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), GetPause(u"ppt/loopNoPause.ppt"_ustr));
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf47365)
{
    createSdImpressDoc("pptx/loopNoPause.pptx");
    uno::Reference<presentation::XPresentationSupplier> xPresentationSupplier(mxComponent,
                                                                              uno::UNO_QUERY_THROW);
    uno::Reference<beans::XPropertySet> xPresentationProps(xPresentationSupplier->getPresentation(),
                                                           uno::UNO_QUERY_THROW);

    const bool bEndlessVal = xPresentationProps->getPropertyValue(u"IsEndless"_ustr).get<bool>();
    const sal_Int32 nPauseVal
        = xPresentationProps->getPropertyValue(u"Pause"_ustr).get<sal_Int32>();

    // Check that we import "loop" attribute of the presentation, and don't introduce any pauses
    CPPUNIT_ASSERT(bEndlessVal);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nPauseVal);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf122899)
{
    // tdf122899 FILEOPEN: ppt: old kind arc from MS Office 97 is broken
    // Error was, that the path coordinates of a mso_sptArc shape were read as sal_Int16
    // although they are unsigned 16 bit. This leads to wrong positions of start and end
    // point and results to a huge shape width in the test document.
    createSdImpressDoc("ppt/tdf122899_Arc_90_to_91_clockwise.ppt");
    uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent,
                                                                   uno::UNO_QUERY_THROW);
    CPPUNIT_ASSERT_MESSAGE("Could not get XDrawPagesSupplier", xDrawPagesSupplier.is());
    uno::Reference<drawing::XDrawPages> xDrawPages(xDrawPagesSupplier->getDrawPages());
    uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->getByIndex(0), uno::UNO_QUERY_THROW);
    CPPUNIT_ASSERT_MESSAGE("Could not get xDrawPage", xDrawPage.is());
    uno::Reference<drawing::XShape> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
    CPPUNIT_ASSERT_MESSAGE("Could not get xShape", xShape.is());
    awt::Rectangle aFrameRect;
    uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY);
    CPPUNIT_ASSERT_MESSAGE("Could not get the shape properties", xShapeProps.is());
    xShapeProps->getPropertyValue(UNO_NAME_MISC_OBJ_FRAMERECT) >>= aFrameRect;
    // original width is 9cm, add some tolerance
    CPPUNIT_ASSERT_LESS(static_cast<sal_Int32>(9020), aFrameRect.Width);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testOOXTheme)
{
    createSdImpressDoc("pptx/ooxtheme.pptx");

    uno::Reference<beans::XPropertySet> xPropSet(mxComponent, uno::UNO_QUERY_THROW);
    uno::Sequence<beans::PropertyValue> aGrabBag;
    xPropSet->getPropertyValue(u"InteropGrabBag"_ustr) >>= aGrabBag;

    bool bTheme = false;
    for (beans::PropertyValue const& prop : aGrabBag)
    {
        if (prop.Name == "OOXTheme")
        {
            bTheme = true;
            uno::Reference<xml::dom::XDocument> aThemeDom;
            CPPUNIT_ASSERT(prop.Value >>= aThemeDom); // PropertyValue of proper type
            CPPUNIT_ASSERT(aThemeDom); // Reference not empty
        }
    }
    CPPUNIT_ASSERT(bTheme); // Grab Bag has all the expected elements
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testCropToShape)
{
    createSdImpressDoc("pptx/crop-to-shape.pptx");
    uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent,
                                                                   uno::UNO_QUERY_THROW);
    CPPUNIT_ASSERT_MESSAGE("Could not get XDrawPagesSupplier", xDrawPagesSupplier.is());
    uno::Reference<drawing::XDrawPages> xDrawPages(xDrawPagesSupplier->getDrawPages());
    uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->getByIndex(0), uno::UNO_QUERY_THROW);
    CPPUNIT_ASSERT_MESSAGE("Could not get xDrawPage", xDrawPage.is());
    uno::Reference<drawing::XShape> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(u"com.sun.star.drawing.CustomShape"_ustr, xShape->getShapeType());
    CPPUNIT_ASSERT_MESSAGE("Could not get xShape", xShape.is());
    uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY);
    css::drawing::FillStyle fillStyle;
    xShapeProps->getPropertyValue(u"FillStyle"_ustr) >>= fillStyle;
    CPPUNIT_ASSERT_EQUAL(css::drawing::FillStyle_BITMAP, fillStyle);
    css::drawing::BitmapMode bitmapmode;
    xShapeProps->getPropertyValue(u"FillBitmapMode"_ustr) >>= bitmapmode;
    CPPUNIT_ASSERT_EQUAL(css::drawing::BitmapMode_STRETCH, bitmapmode);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf127964)
{
    createSdImpressDoc("pptx/tdf127964.pptx");
    {
        const SdrPage* pPage = GetPage(1);
        const SdrObject* pObj = pPage->GetObj(0);
        auto& rFillStyleItem = pObj->GetMergedItem(XATTR_FILLSTYLE);
        CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, rFillStyleItem.GetValue());
        auto& rFillBackgroundItem = pObj->GetMergedItem(XATTR_FILLUSESLIDEBACKGROUND);
        CPPUNIT_ASSERT_EQUAL(true, rFillBackgroundItem.GetValue());
    }

    saveAndReload(TestFilter::ODP);

    {
        const SdrPage* pPage = GetPage(1);
        const SdrObject* pObj = pPage->GetObj(0);
        auto& rFillStyleItem = pObj->GetMergedItem(XATTR_FILLSTYLE);
        CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, rFillStyleItem.GetValue());
        auto& rFillBackgroundItem = pObj->GetMergedItem(XATTR_FILLUSESLIDEBACKGROUND);
        CPPUNIT_ASSERT_EQUAL(true, rFillBackgroundItem.GetValue());
    }
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf48083)
{
    createSdImpressDoc("ppt/tdf48083.ppt");
    const SdrPage* pPage = GetPage(1);
    CPPUNIT_ASSERT_EQUAL(size_t(2), pPage->GetObjCount());
    const SdrObject* pObj = pPage->GetObj(1);
    auto& rFillStyleItem = pObj->GetMergedItem(XATTR_FILLSTYLE);
    CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, rFillStyleItem.GetValue());
    auto& rFillBackgroundItem = pObj->GetMergedItem(XATTR_FILLUSESLIDEBACKGROUND);
    CPPUNIT_ASSERT_EQUAL(true, rFillBackgroundItem.GetValue());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf106638)
{
    createSdImpressDoc("pptx/tdf106638.pptx");
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0));
    uno::Reference<text::XTextRange> const xPara(getParagraphFromShape(1, xShape));
    uno::Reference<text::XText> xText = xPara->getText();
    uno::Reference<text::XTextCursor> xTextCursor
        = xText->createTextCursorByRange(xPara->getStart());
    uno::Reference<beans::XPropertySet> xPropSet(xTextCursor, uno::UNO_QUERY_THROW);
    OUString aCharFontName;
    CPPUNIT_ASSERT(xTextCursor->goRight(1, true));
    // First character U+f0fe that uses Wingding
    xPropSet->getPropertyValue(u"CharFontName"_ustr) >>= aCharFontName;
    CPPUNIT_ASSERT_EQUAL(u"Wingdings"_ustr, aCharFontName);

    // The rest characters that do not use Wingding.
    CPPUNIT_ASSERT(xTextCursor->goRight(45, true));
    xPropSet->getPropertyValue(u"CharFontName"_ustr) >>= aCharFontName;
    CPPUNIT_ASSERT(aCharFontName != "Wingdings");
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf128684)
{
    createSdImpressDoc("pptx/tdf128684.pptx");
    uno::Reference<drawing::XDrawPagesSupplier> xDoc(mxComponent, uno::UNO_QUERY);
    CPPUNIT_ASSERT(xDoc.is());
    uno::Reference<drawing::XDrawPage> xPage(xDoc->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
    CPPUNIT_ASSERT(xPage.is());
    uno::Reference<beans::XPropertySet> xShapeProperties(getShape(0, xPage));
    CPPUNIT_ASSERT(xShapeProperties.is());
    // Check text direction.
    sal_Int16 eWritingMode(text::WritingMode2::LR_TB);
    if (xShapeProperties->getPropertySetInfo()->hasPropertyByName(u"WritingMode"_ustr))
        xShapeProperties->getPropertyValue(u"WritingMode"_ustr) >>= eWritingMode;
    CPPUNIT_ASSERT_EQUAL(sal_Int16(text::WritingMode2::TB_RL90), eWritingMode);
    // Check shape rotation
    sal_Int32 nRotateAngle = 0;
    if (xShapeProperties->getPropertySetInfo()->hasPropertyByName(u"RotateAngle"_ustr))
        xShapeProperties->getPropertyValue(u"RotateAngle"_ustr) >>= nRotateAngle;
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(9000), nRotateAngle);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf113198)
{
    createSdImpressDoc("pptx/tdf113198.pptx");

    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0));
    sal_Int16 nParaAdjust = -1;
    xShape->getPropertyValue(u"ParaAdjust"_ustr) >>= nParaAdjust;
    CPPUNIT_ASSERT_EQUAL(style::ParagraphAdjust_CENTER,
                         static_cast<style::ParagraphAdjust>(nParaAdjust));
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf49856)
{
    createSdImpressDoc("ppt/tdf49856.ppt");
    const SdrPage* pPage = GetPage(1);
    SdrTextObj* pTxtObj = DynCastSdrTextObj(pPage->GetObj(1));
    CPPUNIT_ASSERT_MESSAGE("No text object", pTxtObj != nullptr);
    const EditTextObject& aEdit = pTxtObj->GetOutlinerParaObject()->GetTextObject();
    const SvxNumBulletItem* pNumFmt = aEdit.GetParaAttribs(2).GetItem(EE_PARA_NUMBULLET);
    CPPUNIT_ASSERT(pNumFmt);
    const sal_UCS4 aBullet = pNumFmt->GetNumRule().GetLevel(0).GetBulletChar();
    CPPUNIT_ASSERT_EQUAL(u"More level 2"_ustr, aEdit.GetText(2));
    CPPUNIT_ASSERT_EQUAL(sal_UCS4(0x2022), aBullet);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testShapeGlowEffectPPTXImpoer)
{
    createSdImpressDoc("pptx/shape-glow-effect.pptx");

    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0));
    sal_Int32 nRadius = -1;
    xShape->getPropertyValue(u"GlowEffectRadius"_ustr) >>= nRadius;
    CPPUNIT_ASSERT_EQUAL(sal_Int32(388), nRadius); // 139700 EMU = 388.0556 mm/100
    Color nColor;
    xShape->getPropertyValue(u"GlowEffectColor"_ustr) >>= nColor;
    CPPUNIT_ASSERT_EQUAL(Color(0xFFC000), nColor);
    sal_Int16 nTransparency;
    xShape->getPropertyValue(u"GlowEffectTransparency"_ustr) >>= nTransparency;
    CPPUNIT_ASSERT_EQUAL(sal_Int16(60), nTransparency);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testShapeTextGlowEffectPPTXImport)
{
    createSdImpressDoc("pptx/shape-text-glow-effect.pptx");

    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0));
    sal_Int32 nRadius = -1;
    xShape->getPropertyValue(u"GlowTextEffectRadius"_ustr) >>= nRadius;
    CPPUNIT_ASSERT_EQUAL(sal_Int32(706), nRadius); // 20 pt = 706 mm/100
    Color nColor;
    xShape->getPropertyValue(u"GlowTextEffectColor"_ustr) >>= nColor;
    CPPUNIT_ASSERT_EQUAL(Color(0x4EA72E), nColor);
    sal_Int16 nTransparency;
    xShape->getPropertyValue(u"GlowTextEffectTransparency"_ustr) >>= nTransparency;
    CPPUNIT_ASSERT_EQUAL(sal_Int16(5), nTransparency);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testShapeBlurPPTXImport)
{
    createSdImpressDoc("pptx/shape-blur-effect.pptx");

    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0));
    bool bHasShadow = false;
    xShape->getPropertyValue(u"Shadow"_ustr) >>= bHasShadow;
    CPPUNIT_ASSERT(bHasShadow);

    sal_Int32 nRadius = -1;
    xShape->getPropertyValue(u"ShadowBlur"_ustr) >>= nRadius;
    CPPUNIT_ASSERT_EQUAL(sal_Int32(388), nRadius); // 584200EMU=46pt - 139700EMU = 388Hmm = 11pt
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testMirroredGraphic)
{
    createSdImpressDoc("pptx/mirrored-graphic.pptx");
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0), uno::UNO_SET_THROW);
    CPPUNIT_ASSERT(xShape.is());
    uno::Reference<graphic::XGraphic> xGraphic;
    xShape->getPropertyValue(u"FillBitmap"_ustr) >>= xGraphic;
    CPPUNIT_ASSERT(xGraphic.is());
    Graphic aGraphic(xGraphic);
    Bitmap aBitmap(aGraphic.GetBitmap());
    CPPUNIT_ASSERT_EQUAL(Color(0x4f4955), aBitmap.GetPixelColor(0, 0));
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf134210CropPosition)
{
    // We are testing crop position of bitmap in custom shapes. We should see only green with proper fix.

    createSdImpressDoc("pptx/crop-position.pptx");
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0), uno::UNO_SET_THROW);
    CPPUNIT_ASSERT(xShape.is());
    uno::Reference<graphic::XGraphic> xGraphic;
    xShape->getPropertyValue(u"FillBitmap"_ustr) >>= xGraphic;
    CPPUNIT_ASSERT(xGraphic.is());
    Graphic aGraphic(xGraphic);
    Bitmap aBitmap(aGraphic.GetBitmap());
    CPPUNIT_ASSERT_EQUAL(Color(0x81d41a), aBitmap.GetPixelColor(0, 0));
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testGreysScaleGraphic)
{
    createSdImpressDoc("pptx/greysscale-graphic.pptx");
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0), uno::UNO_SET_THROW);
    CPPUNIT_ASSERT(xShape.is());
    uno::Reference<graphic::XGraphic> xGraphic;
    xShape->getPropertyValue(u"FillBitmap"_ustr) >>= xGraphic;
    CPPUNIT_ASSERT(xGraphic.is());
    Graphic aGraphic(xGraphic);
    Bitmap aBitmap(aGraphic.GetBitmap());
    CPPUNIT_ASSERT_EQUAL(Color(0x3c3c3c), aBitmap.GetPixelColor(0, 0));
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf103347)
{
    createSdImpressDoc("pptx/tdf103347.pptx");
    uno::Reference<drawing::XDrawPagesSupplier> xDoc(mxComponent, uno::UNO_QUERY_THROW);

    uno::Reference<drawing::XDrawPage> xPage1(xDoc->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
    uno::Reference<container::XNamed> xNamed1(xPage1, uno::UNO_QUERY_THROW);
    CPPUNIT_ASSERT_EQUAL(u"Hello"_ustr, xNamed1->getName());

    uno::Reference<drawing::XDrawPage> xPage2(xDoc->getDrawPages()->getByIndex(1), uno::UNO_QUERY);
    uno::Reference<container::XNamed> xNamed2(xPage2, uno::UNO_QUERY_THROW);
    CPPUNIT_ASSERT_EQUAL(u"Hello (2)"_ustr, xNamed2->getName());

    uno::Reference<drawing::XDrawPage> xPage3(xDoc->getDrawPages()->getByIndex(2), uno::UNO_QUERY);
    uno::Reference<container::XNamed> xNamed3(xPage3, uno::UNO_QUERY_THROW);
    CPPUNIT_ASSERT_EQUAL(u"Hello (3)"_ustr, xNamed3->getName());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testHyperlinksOnShapes)
{
    createSdImpressDoc("pptx/tdf144616.pptx");

    for (sal_Int32 i = 0; i < 7; i++)
    {
        uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(i, 0));
        uno::Reference<document::XEventsSupplier> xEventsSupplier(xShape, uno::UNO_QUERY);
        uno::Reference<container::XNameAccess> xEvents(xEventsSupplier->getEvents());

        uno::Sequence<beans::PropertyValue> props;
        xEvents->getByName(u"OnClick"_ustr) >>= props;
        comphelper::SequenceAsHashMap map(props);
        auto iter(map.find(u"ClickAction"_ustr));
        switch (i)
        {
            case 0:
                CPPUNIT_ASSERT_EQUAL(css::presentation::ClickAction_FIRSTPAGE,
                                     iter->second.get<css::presentation::ClickAction>());
                break;
            case 1:
                CPPUNIT_ASSERT_EQUAL(css::presentation::ClickAction_LASTPAGE,
                                     iter->second.get<css::presentation::ClickAction>());
                break;
            case 2:
                CPPUNIT_ASSERT_EQUAL(css::presentation::ClickAction_NEXTPAGE,
                                     iter->second.get<css::presentation::ClickAction>());
                break;
            case 3:
                CPPUNIT_ASSERT_EQUAL(css::presentation::ClickAction_PREVPAGE,
                                     iter->second.get<css::presentation::ClickAction>());
                break;
            case 4:
            {
                auto iter2(map.find(u"Bookmark"_ustr));
                CPPUNIT_ASSERT_EQUAL(u"Second slide"_ustr, iter2->second.get<OUString>());
            }
            break;
            case 5:
                CPPUNIT_ASSERT_EQUAL(css::presentation::ClickAction_STOPPRESENTATION,
                                     iter->second.get<css::presentation::ClickAction>());
                break;
            case 6:
            {
                auto iter1(map.find(u"Bookmark"_ustr));
                CPPUNIT_ASSERT_EQUAL(u"http://www.example.com/"_ustr,
                                     iter1->second.get<OUString>());
            }
            break;
            default:
                break;
        }
    }
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf112209)
{
    createSdImpressDoc("pptx/tdf112209.pptx");
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0), uno::UNO_SET_THROW);
    CPPUNIT_ASSERT(xShape.is());

    uno::Reference<graphic::XGraphic> xGraphic;
    xShape->getPropertyValue(u"FillBitmap"_ustr) >>= xGraphic;
    CPPUNIT_ASSERT(xGraphic.is());

    Graphic aGraphic(xGraphic);
    Bitmap aBitmap(aGraphic.GetBitmap());

    // Without the accompanying fix in place, this test would have failed with:
    // - Expected: Color: R:132 G:132 B:132 A:0
    // - Actual  : Color: R:21 G:170 B:236 A:0
    // i.e. the image color was blue instead of grey.
    CPPUNIT_ASSERT_EQUAL(Color(0x848484), aBitmap.GetPixelColor(0, 0));
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf128596)
{
    createSdImpressDoc("pptx/tdf128596.pptx");
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0), uno::UNO_SET_THROW);
    CPPUNIT_ASSERT(xShape.is());

    css::drawing::BitmapMode bitmapmode;
    xShape->getPropertyValue(u"FillBitmapMode"_ustr) >>= bitmapmode;
    CPPUNIT_ASSERT_EQUAL(css::drawing::BitmapMode_REPEAT, bitmapmode);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf96389_deftabstopISO29500)
{
    createSdImpressDoc("potx/tdf96389_deftabstopISO29500.potx");

    SdXImpressDocument* pXImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
    CPPUNIT_ASSERT(pXImpressDocument);
    SdDrawDocument* pDoc = pXImpressDocument->GetDoc();

    sal_Int32 nDefTab = pDoc->GetDefaultTabulator();

    CPPUNIT_ASSERT_EQUAL(sal_Int32(2540), nDefTab);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf96389_deftabstopECMA)
{
    createSdImpressDoc("potx/tdf96389_deftabstopECMA.potx");

    SdXImpressDocument* pXImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
    SdDrawDocument* pDoc = pXImpressDocument->GetDoc();

    sal_Int32 nDefTab = pDoc->GetDefaultTabulator();

    CPPUNIT_ASSERT_EQUAL(sal_Int32(2540), nDefTab);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testCropToZero)
{
    // Must not crash because of division by zero
    // Also must not fail assertions because of passing negative value to CropQuotientsFromSrcRect
    createSdImpressDoc("pptx/croppedTo0.pptx");
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf144092TableHeight)
{
    createSdImpressDoc("pptx/tdf144092-tableHeight.pptx");

    uno::Reference<drawing::XShape> xTableShape(getShapeFromPage(0, 0), uno::UNO_QUERY);

    // Without the accompanying fix in place, this test would have failed with:
    // - Expected: 7885
    // - Actual  : 4595
    // i.e. the table height wasn't corrected by expanding less than minimum sized rows.
    CPPUNIT_ASSERT_EQUAL(sal_Int32(7885), xTableShape->getSize().Height);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf89928BlackWhiteThreshold)
{
    // A slide with two graphics, one with color HSV{0,0,74%} and one with HSV{0,0,76%}
    // where both have an applied 75% Black/White Color Effect.

    createSdImpressDoc("pptx/tdf89928-blackWhiteEffectThreshold.pptx");

    // First graphic should appear black
    {
        uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0), uno::UNO_SET_THROW);
        uno::Reference<graphic::XGraphic> xGraphic;
        xShape->getPropertyValue(u"Graphic"_ustr) >>= xGraphic;
        CPPUNIT_ASSERT(xGraphic.is());

        Graphic aGraphic(xGraphic);
        Bitmap aBitmap(aGraphic.GetBitmap());

        // Without the accompanying fix in place, this test would have failed with:
        // - Expected: Color: R:0 G:0 B:0 A:0
        // - Actual  : Color: R:189 G:189 B:189 A:0
        CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0x000000), aBitmap.GetPixelColor(0, 0));
    }

    // Second graphic should appear white
    {
        uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(1, 0), uno::UNO_SET_THROW);
        uno::Reference<graphic::XGraphic> xGraphic;
        xShape->getPropertyValue(u"Graphic"_ustr) >>= xGraphic;
        CPPUNIT_ASSERT(xGraphic.is());

        Graphic aGraphic(xGraphic);
        Bitmap aBitmap(aGraphic.GetBitmap());

        CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0xFFFFFF), aBitmap.GetPixelColor(0, 0));
    }
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf151547TransparentWhiteText)
{
    createSdImpressDoc("pptx/tdf151547-transparent-white-text.pptx");

    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0));
    uno::Reference<text::XTextRange> xParagraph(getParagraphFromShape(0, xShape));
    uno::Reference<text::XTextRange> xRun(getRunFromParagraph(0, xParagraph));
    uno::Reference<beans::XPropertySet> xPropSet(xRun, uno::UNO_QUERY_THROW);

    Color nCharColor;
    xPropSet->getPropertyValue(u"CharColor"_ustr) >>= nCharColor;
    // Without the accompanying fix in place, this test would have failed with:
    // - Expected: Color: R:255 G:255 B:254 A:255
    // - Actual  : Color: R:255 G:255 B:255 A:255
    // i.e. fully transparent white text color was interpreted as COL_AUTO
    CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0xFFFFFFFE), nCharColor);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf149961AutofitIndentation)
{
    createSdImpressDoc("pptx/tdf149961-autofitIndentation.pptx");

    const SdrPage* pPage = GetPage(1);

    {
        SdrTextObj* pTxtObj = DynCastSdrTextObj(pPage->GetObj(0));
        CPPUNIT_ASSERT_MESSAGE("no text object", pTxtObj != nullptr);

        const EditTextObject& aEdit = pTxtObj->GetOutlinerParaObject()->GetTextObject();
        const SvxNumBulletItem* pNumFmt = aEdit.GetParaAttribs(0).GetItem(EE_PARA_NUMBULLET);
        CPPUNIT_ASSERT(pNumFmt);

        CPPUNIT_ASSERT_EQUAL(sal_Int32(3175), pNumFmt->GetNumRule().GetLevel(0).GetAbsLSpace());
        CPPUNIT_ASSERT_EQUAL(sal_Int32(-3175),
                             pNumFmt->GetNumRule().GetLevel(0).GetFirstLineOffset());
    }

    {
        SdrTextObj* pTxtObj = DynCastSdrTextObj(pPage->GetObj(1));
        CPPUNIT_ASSERT_MESSAGE("no text object", pTxtObj != nullptr);

        const EditTextObject& aEdit = pTxtObj->GetOutlinerParaObject()->GetTextObject();
        const SvxNumBulletItem* pNumFmt = aEdit.GetParaAttribs(0).GetItem(EE_PARA_NUMBULLET);
        CPPUNIT_ASSERT(pNumFmt);

        // Spacing doesn't change when it is scaled
        CPPUNIT_ASSERT_EQUAL(sal_Int32(3175), pNumFmt->GetNumRule().GetLevel(0).GetAbsLSpace());
        CPPUNIT_ASSERT_EQUAL(sal_Int32(-3175),
                             pNumFmt->GetNumRule().GetLevel(0).GetFirstLineOffset());
    }
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf149588TransparentSolidFill)
{
    createSdImpressDoc("pptx/tdf149588_transparentSolidFill.pptx");
    saveAndReload(TestFilter::PPTX_2007);

    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(6, 0));
    uno::Reference<text::XTextRange> xParagraph(getParagraphFromShape(0, xShape));
    uno::Reference<text::XTextRange> xRun(getRunFromParagraph(0, xParagraph));
    uno::Reference<beans::XPropertySet> xPropSet(xRun, uno::UNO_QUERY_THROW);

    Color nCharColor;
    xPropSet->getPropertyValue(u"CharColor"_ustr) >>= nCharColor;
    // Without the accompanying fix in place, this test would have failed with:
    // - Expected: Color: R:99 G:99 B:99 A   51  (T:204)
    // - Actual  : Color: R:99 G:99 B:99 A: 255  (T:  0)
    CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0xCC636363), nCharColor);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testOverflowBehaviorClip)
{
    createSdImpressDoc("odp/style-overflow-behavior-clip.fodp");
    {
        uno::Reference<beans::XPropertySet> xPropSet(getShapeFromPage(0, 0));
        // Without the accompanying fix in place, this test would have failed with:
        // - Expected: 1
        // - Actual  : 0
        CPPUNIT_ASSERT_EQUAL(
            true, xPropSet->getPropertyValue(u"TextClipVerticalOverflow"_ustr).get<bool>());
    }

    saveAndReload(TestFilter::ODP);
    {
        uno::Reference<beans::XPropertySet> xPropSet(getShapeFromPage(0, 0));
        CPPUNIT_ASSERT_EQUAL(
            true, xPropSet->getPropertyValue(u"TextClipVerticalOverflow"_ustr).get<bool>());
    }
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testIndentDuplication)
{
    createSdImpressDoc("pptx/formatting-bullet-indent.pptx");
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(2, 0));

    uno::Reference<beans::XPropertySet> const xParagraph1(getParagraphFromShape(0, xShape),
                                                          uno::UNO_QUERY_THROW);
    sal_Int32 nIndent1;
    xParagraph1->getPropertyValue(u"ParaFirstLineIndent"_ustr) >>= nIndent1;
    CPPUNIT_ASSERT_EQUAL(sal_Int32(2500), nIndent1);

    uno::Reference<beans::XPropertySet> const xParagraph2(getParagraphFromShape(1, xShape),
                                                          uno::UNO_QUERY_THROW);
    sal_Int32 nIndent2;
    xParagraph2->getPropertyValue(u"ParaFirstLineIndent"_ustr) >>= nIndent2;
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nIndent2);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, test_srcRect_smallNegBound)
{
    // Given a cropped custom shape, with a srcRect having a small negative value in one of bounds
    createSdImpressDoc("pptx/tdf153008-srcRect-smallNegBound.pptx");

    uno::Reference<graphic::XGraphic> xGraphic(
        getShapeFromPage(0, 0)->getPropertyValue(u"FillBitmap"_ustr), uno::UNO_QUERY_THROW);

    Bitmap aBitmap(Graphic(xGraphic).GetBitmap());

    // Properly cropped bitmap should have black pixels close to left edge, near vertical center.
    // Before the fix, the gear was distorted, and this area was white.
    auto yMiddle = aBitmap.GetSizePixel().Height() / 2;
    auto x5Percent = aBitmap.GetSizePixel().Width() / 20;
    CPPUNIT_ASSERT(aBitmap.GetPixelColor(x5Percent, yMiddle).IsDark());
    // Just in case, check that the corner is bright (it is in fact yellow)
    CPPUNIT_ASSERT(aBitmap.GetPixelColor(0, 0).IsBright());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf153012)
{
    // Given a chart with a data point with solid fill of "Background 1, Darker 15%" color,
    // where the 'bg1' is mapped in the slide to "dk1", but in the chart to "lt1":
    createSdImpressDoc("pptx/chart_pt_color_bg1.pptx");

    uno::Reference<chart2::XChartDocument> xChart2Doc(
        getShapeFromPage(0, 0)->getPropertyValue(u"Model"_ustr), uno::UNO_QUERY_THROW);

    uno::Reference<chart2::XCoordinateSystemContainer> xCooSysCnt(xChart2Doc->getFirstDiagram(),
                                                                  uno::UNO_QUERY_THROW);

    uno::Reference<chart2::XChartTypeContainer> xCTCnt(xCooSysCnt->getCoordinateSystems()[0],
                                                       uno::UNO_QUERY_THROW);

    uno::Reference<chart2::XDataSeriesContainer> xDSCnt(xCTCnt->getChartTypes()[0],
                                                        uno::UNO_QUERY_THROW);

    uno::Sequence<uno::Reference<chart2::XDataSeries>> aSeriesSeq(xDSCnt->getDataSeries());
    CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aSeriesSeq.getLength());

    css::uno::Reference<css::beans::XPropertySet> xPropSet1(aSeriesSeq[0]->getDataPointByIndex(1),
                                                            uno::UNO_SET_THROW);
    Color aFillColor;
    xPropSet1->getPropertyValue(u"FillColor"_ustr) >>= aFillColor;
    // The color must arrive correctly. Without the fix, it would fail:
    // - Expected: rgba[d9d9d9ff]
    // - Actual  : rgba[000000ff]
    CPPUNIT_ASSERT_EQUAL(Color(0xd9d9d9), aFillColor);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testMasterSlides)
{
    createSdImpressDoc("pptx/master-slides.pptx");
    uno::Reference<drawing::XMasterPagesSupplier> xMasterPagesSupplier(mxComponent,
                                                                       uno::UNO_QUERY_THROW);
    uno::Reference<drawing::XDrawPages> xMasterPages(xMasterPagesSupplier->getMasterPages());
    CPPUNIT_ASSERT(xMasterPages.is());
    CPPUNIT_ASSERT_EQUAL(sal_Int32(7), xMasterPages->getCount());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf161023)
{
    // Given a shape with three paragraphs (18pt), all directly assigned a smaller font (10pt)
    createSdImpressDoc("odp/tdf161023.fodp");
    auto shape = getShapeFromPage(0, 0);

    // 1st paragraph, not empty
    {
        auto paragraph(getParagraphFromShape(0, shape));
        CPPUNIT_ASSERT_EQUAL(u"a"_ustr, paragraph->getString());
        auto run(getRunFromParagraph(0, paragraph));
        CPPUNIT_ASSERT_EQUAL(u"a"_ustr, run->getString());
        uno::Reference<beans::XPropertySet> xPropSet(run, uno::UNO_QUERY_THROW);
        double fCharHeight = 0;
        xPropSet->getPropertyValue(u"CharHeight"_ustr) >>= fCharHeight;
        CPPUNIT_ASSERT_EQUAL(10.0, fCharHeight);
        // No more runs
        CPPUNIT_ASSERT_THROW(getRunFromParagraph(1, paragraph), container::NoSuchElementException);
    }

    // Empty 2nd paragraph, consisting of a single span: this span was treated as "paragraph mark"
    {
        auto paragraph(getParagraphFromShape(1, shape));
        CPPUNIT_ASSERT_EQUAL(u""_ustr, paragraph->getString());
        auto run(getRunFromParagraph(0, paragraph));
        CPPUNIT_ASSERT_EQUAL(u""_ustr, run->getString());
        uno::Reference<beans::XPropertySet> xPropSet(run, uno::UNO_QUERY_THROW);
        double fCharHeight = 0;
        xPropSet->getPropertyValue(u"CharHeight"_ustr) >>= fCharHeight;
        // Without the fix, this would fail with
        // - Expected: 10
        // - Actual  : 18
        CPPUNIT_ASSERT_EQUAL(10.0, fCharHeight);
        // No more runs
        CPPUNIT_ASSERT_THROW(getRunFromParagraph(1, paragraph), container::NoSuchElementException);
    }

    // 3rd paragraph, not empty
    {
        auto paragraph(getParagraphFromShape(2, shape));
        CPPUNIT_ASSERT_EQUAL(u"c"_ustr, paragraph->getString());
        auto run(getRunFromParagraph(0, paragraph));
        CPPUNIT_ASSERT_EQUAL(u"c"_ustr, run->getString());
        uno::Reference<beans::XPropertySet> xPropSet(run, uno::UNO_QUERY_THROW);
        double fCharHeight = 0;
        xPropSet->getPropertyValue(u"CharHeight"_ustr) >>= fCharHeight;
        CPPUNIT_ASSERT_EQUAL(10.0, fCharHeight);
        // No more runs
        CPPUNIT_ASSERT_THROW(getRunFromParagraph(1, paragraph), container::NoSuchElementException);
    }
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf161430)
{
    // Without the bug fix this opens with the classic solid 'blue' background used in "Outline 1"
    // as seen in slide 3
    createSdImpressDoc("odp/tdf161430.odp");
    SdXImpressDocument* pXImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
    CPPUNIT_ASSERT(pXImpressDocument);
    SdDrawDocument* pDoc = pXImpressDocument->GetDoc();

    SdStyleSheetPool* const pPool(pDoc->GetSdStyleSheetPool());

    OUString aStyleName(SdResId(STR_PSEUDOSHEET_OUTLINE) + " 1");
    SfxStyleSheetBase* pStyleSheet = pPool->Find(aStyleName, SfxStyleFamily::Pseudo);
    CPPUNIT_ASSERT(pStyleSheet);

    const XFillStyleItem& rFillStyle = pStyleSheet->GetItemSet().Get(XATTR_FILLSTYLE);
    drawing::FillStyle eXFS = rFillStyle.GetValue();
    CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, eXFS);
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, tdf158512)
{
    // First shape on first slide should have no fill to avoid hiding background
    createSdImpressDoc("pptx/tdf158512.pptx");

    const SdrPage* pPage = GetPage(1);
    CPPUNIT_ASSERT_EQUAL(size_t(2), pPage->GetObjCount());
    CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE,
                         pPage->GetObj(0)->GetMergedItem(XATTR_FILLSTYLE).GetValue());
    CPPUNIT_ASSERT_EQUAL(false,
                         pPage->GetObj(0)->GetMergedItem(XATTR_FILLUSESLIDEBACKGROUND).GetValue());
}

CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf169524)
{
    createSdImpressDoc("pptx/tdf169524.pptx");
    uno::Reference<beans::XPropertySet> xShape(getShapeFromPage(0, 0));
    uno::Reference<beans::XPropertySet> const xParagraph(getParagraphFromShape(8, xShape),
                                                         uno::UNO_QUERY_THROW);
    sal_Int32 nLeftMargin;
    xParagraph->getPropertyValue(u"ParaLeftMargin"_ustr) >>= nLeftMargin;
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nLeftMargin);
}

CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
