summaryrefslogtreecommitdiffstats
path: root/sd/qa/unit/tiledrendering
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sd/qa/unit/tiledrendering/CallbackRecorder.hxx152
-rw-r--r--sd/qa/unit/tiledrendering/LOKitSearchTest.cxx948
-rw-r--r--sd/qa/unit/tiledrendering/data/2slides.odpbin0 -> 10984 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/MixedTest1.odgbin0 -> 25083 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/MixedTest2.odgbin0 -> 35616 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/OnePDFObject.odgbin0 -> 124632 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/PDFSearch.pdfbin0 -> 14334 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/ReplaceTest.odpbin0 -> 10854 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/TextBoxAndRect.odgbin0 -> 10474 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/cut_selection_change.odpbin0 -> 10983 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/dummy.odgbin0 -> 8183 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/dummy.odpbin0 -> 10763 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/duplicate-undo.odpbin0 -> 11346 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/insert-delete.odpbin0 -> 13178 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/language-all-text.odpbin0 -> 13083 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/notes-view.odpbin0 -> 11184 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/paste-undo.fodp34
-rw-r--r--sd/qa/unit/tiledrendering/data/paste_text_onslide.odpbin0 -> 10587 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/regenerate-diagram.pptxbin0 -> 41813 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/search-all.odpbin0 -> 10974 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/shape.odpbin0 -> 10446 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/table-column.odpbin0 -> 10526 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/table.odpbin0 -> 10559 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/tdf102223.odpbin0 -> 17335 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/tdf103083.fodp932
-rw-r--r--sd/qa/unit/tiledrendering/data/tdf104405.fodp822
-rw-r--r--sd/qa/unit/tiledrendering/data/tdf105502.odpbin0 -> 11629 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/tdf115783.fodp52
-rw-r--r--sd/qa/unit/tiledrendering/data/tdf115873-group.fodp36
-rw-r--r--sd/qa/unit/tiledrendering/data/tdf115873.fodp29
-rw-r--r--sd/qa/unit/tiledrendering/data/tdf118354.odpbin0 -> 14518 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/tdf81754.pptxbin0 -> 35503 bytes
-rw-r--r--sd/qa/unit/tiledrendering/data/title-shape.odpbin0 -> 11406 bytes
-rw-r--r--sd/qa/unit/tiledrendering/tiledrendering.cxx2947
34 files changed, 5952 insertions, 0 deletions
diff --git a/sd/qa/unit/tiledrendering/CallbackRecorder.hxx b/sd/qa/unit/tiledrendering/CallbackRecorder.hxx
new file mode 100644
index 0000000000..ad64f5ab39
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/CallbackRecorder.hxx
@@ -0,0 +1,152 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <cppunit/TestAssert.h>
+
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <boost/property_tree/json_parser.hpp>
+#include <comphelper/string.hxx>
+#include <osl/conditn.hxx>
+#include <sfx2/viewsh.hxx>
+#include <test/lokcallback.hxx>
+#include <o3tl/string_view.hxx>
+
+using namespace css;
+
+namespace
+{
+std::vector<OUString> lcl_convertSeparated(std::u16string_view rString, sal_Unicode nSeparator)
+{
+ std::vector<OUString> aRet;
+
+ sal_Int32 nIndex = 0;
+ do
+ {
+ OUString aToken(o3tl::trim(o3tl::getToken(rString, 0, nSeparator, nIndex)));
+ if (!aToken.isEmpty())
+ aRet.push_back(aToken);
+ } while (nIndex >= 0);
+
+ return aRet;
+}
+
+void lcl_convertRectangle(std::u16string_view rString, tools::Rectangle& rRectangle)
+{
+ uno::Sequence<OUString> aSeq = comphelper::string::convertCommaSeparated(rString);
+ CPPUNIT_ASSERT(aSeq.getLength() == 4 || aSeq.getLength() == 5);
+ rRectangle.SetLeft(aSeq[0].toInt32());
+ rRectangle.SetTop(aSeq[1].toInt32());
+ rRectangle.setWidth(aSeq[2].toInt32());
+ rRectangle.setHeight(aSeq[3].toInt32());
+}
+}
+
+struct CallbackRecorder
+{
+ CallbackRecorder()
+ : m_bFound(true)
+ , m_nPart(0)
+ , m_nSelectionBeforeSearchResult(0)
+ , m_nSelectionAfterSearchResult(0)
+ , m_nSearchResultCount(0)
+ , m_callbackWrapper(&callback, this)
+ {
+ }
+
+ tools::Rectangle m_aInvalidation;
+ std::vector<::tools::Rectangle> m_aSelection;
+ bool m_bFound;
+ sal_Int32 m_nPart;
+ std::vector<OString> m_aSearchResultSelection;
+ std::vector<int> m_aSearchResultPart;
+ int m_nSelectionBeforeSearchResult;
+ int m_nSelectionAfterSearchResult;
+ int m_nSearchResultCount;
+ /// For document size changed callback.
+ osl::Condition m_aDocumentSizeCondition;
+ TestLokCallbackWrapper m_callbackWrapper;
+
+ static void callback(int nType, const char* pPayload, void* pData)
+ {
+ static_cast<CallbackRecorder*>(pData)->processCallback(nType, pPayload);
+ }
+
+ void processCallback(int nType, const char* pPayload)
+ {
+ switch (nType)
+ {
+ case LOK_CALLBACK_INVALIDATE_TILES:
+ {
+ OUString aPayload = OUString::createFromAscii(pPayload);
+ if (aPayload != "EMPTY" && m_aInvalidation.IsEmpty())
+ lcl_convertRectangle(aPayload, m_aInvalidation);
+ }
+ break;
+ case LOK_CALLBACK_TEXT_SELECTION:
+ {
+ OUString aPayload = OUString::createFromAscii(pPayload);
+ m_aSelection.clear();
+ for (const OUString& rString : lcl_convertSeparated(aPayload, u';'))
+ {
+ ::tools::Rectangle aRectangle;
+ lcl_convertRectangle(rString, aRectangle);
+ m_aSelection.push_back(aRectangle);
+ }
+ if (m_aSearchResultSelection.empty())
+ ++m_nSelectionBeforeSearchResult;
+ else
+ ++m_nSelectionAfterSearchResult;
+ }
+ break;
+ case LOK_CALLBACK_SEARCH_NOT_FOUND:
+ {
+ m_bFound = false;
+ }
+ break;
+ case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED:
+ {
+ m_aDocumentSizeCondition.set();
+ }
+ break;
+ case LOK_CALLBACK_SET_PART:
+ {
+ OUString aPayload = OUString::createFromAscii(pPayload);
+ m_nPart = aPayload.toInt32();
+ }
+ break;
+ case LOK_CALLBACK_SEARCH_RESULT_SELECTION:
+ {
+ m_nSearchResultCount++;
+ m_aSearchResultSelection.clear();
+ m_aSearchResultPart.clear();
+ boost::property_tree::ptree aTree;
+ std::stringstream aStream(pPayload);
+ boost::property_tree::read_json(aStream, aTree);
+ for (const boost::property_tree::ptree::value_type& rValue :
+ aTree.get_child("searchResultSelection"))
+ {
+ m_aSearchResultSelection.emplace_back(
+ rValue.second.get<std::string>("rectangles").c_str());
+ m_aSearchResultPart.push_back(
+ std::atoi(rValue.second.get<std::string>("part").c_str()));
+ }
+ }
+ break;
+ }
+ }
+
+ void registerCallbacksFor(SfxViewShell& rViewShell)
+ {
+ rViewShell.setLibreOfficeKitViewCallback(&m_callbackWrapper);
+ }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx b/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx
new file mode 100644
index 0000000000..35b32640b5
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx
@@ -0,0 +1,948 @@
+/* -*- 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 "CallbackRecorder.hxx"
+#include <test/unoapi_test.hxx>
+
+#include <test/helper/transferable.hxx>
+
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/lok.hxx>
+#include <svl/srchitem.hxx>
+#include <vcl/scheduler.hxx>
+#include <ViewShellBase.hxx>
+#include <ViewShell.hxx>
+#include <unomodel.hxx>
+
+#include <DrawDocShell.hxx>
+#include <drawdoc.hxx>
+#include <sdpage.hxx>
+#include <svx/svdograf.hxx>
+#include <vcl/filter/PDFiumLibrary.hxx>
+
+using namespace css;
+
+class LOKitSearchTest : public UnoApiTest
+{
+public:
+ LOKitSearchTest()
+ : UnoApiTest("/sd/qa/unit/tiledrendering/data/")
+ {
+ }
+
+ virtual void setUp() override;
+ virtual void tearDown() override;
+
+ void testSearch();
+ void testSearchAll();
+ void testSearchAllSelections();
+ void testSearchAllNotifications();
+ void testSearchAllFollowedBySearch();
+ void testDontSearchInMasterPages();
+ void testSearchInPDFNonExisting();
+ void testSearchInPDF();
+ void testSearchInPDFOnePDFObject();
+ void testSearchInPDFInMultiplePages();
+ void testSearchInPDFInMultiplePagesBackwards();
+ void testSearchIn2MixedObjects();
+ void testSearchIn6MixedObjects();
+ void testReplace();
+ void testReplaceAll();
+ void testReplaceCombined();
+
+ CPPUNIT_TEST_SUITE(LOKitSearchTest);
+ CPPUNIT_TEST(testSearch);
+ CPPUNIT_TEST(testSearchAll);
+ CPPUNIT_TEST(testSearchAllSelections);
+ CPPUNIT_TEST(testSearchAllNotifications);
+ CPPUNIT_TEST(testSearchAllFollowedBySearch);
+ CPPUNIT_TEST(testDontSearchInMasterPages);
+ CPPUNIT_TEST(testSearchInPDFNonExisting);
+ CPPUNIT_TEST(testSearchInPDF);
+ CPPUNIT_TEST(testSearchInPDFOnePDFObject);
+ CPPUNIT_TEST(testSearchInPDFInMultiplePages);
+ CPPUNIT_TEST(testSearchInPDFInMultiplePagesBackwards);
+ CPPUNIT_TEST(testSearchIn2MixedObjects);
+ CPPUNIT_TEST(testSearchIn6MixedObjects);
+ CPPUNIT_TEST(testReplace);
+ CPPUNIT_TEST(testReplaceAll);
+ CPPUNIT_TEST(testReplaceCombined);
+ CPPUNIT_TEST_SUITE_END();
+
+private:
+ SdXImpressDocument* createDoc(const char* pName,
+ const uno::Sequence<beans::PropertyValue>& rArguments
+ = uno::Sequence<beans::PropertyValue>());
+ void lcl_search(const OUString& rKey, bool bFindAll = false, bool bBackwards = false);
+ void lcl_replace(const OUString& rKey, const OUString& rReplace, bool bAll = false);
+
+ std::unique_ptr<CallbackRecorder> mpCallbackRecorder;
+};
+
+void LOKitSearchTest::setUp()
+{
+ UnoApiTest::setUp();
+
+ // prevent showing warning message box
+ setenv("OOX_NO_SMARTART_WARNING", "1", 1);
+ comphelper::LibreOfficeKit::setActive(true);
+
+ mpCallbackRecorder = std::make_unique<CallbackRecorder>();
+}
+
+void LOKitSearchTest::tearDown()
+{
+ if (mxComponent.is())
+ {
+ mxComponent->dispose();
+ mxComponent.clear();
+ }
+
+ comphelper::LibreOfficeKit::setActive(false);
+
+ UnoApiTest::tearDown();
+}
+
+SdXImpressDocument*
+LOKitSearchTest::createDoc(const char* pName, const uno::Sequence<beans::PropertyValue>& rArguments)
+{
+ loadFromFile(OUString::createFromAscii(pName));
+ SdXImpressDocument* pImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
+ CPPUNIT_ASSERT(pImpressDocument);
+ pImpressDocument->initializeForTiledRendering(rArguments);
+ return pImpressDocument;
+}
+
+void LOKitSearchTest::lcl_search(const OUString& rKey, bool bFindAll, bool bBackwards)
+{
+ Scheduler::ProcessEventsToIdle();
+ SvxSearchCmd eSearch = bFindAll ? SvxSearchCmd::FIND_ALL : SvxSearchCmd::FIND;
+
+ uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence({
+ { "SearchItem.SearchString", uno::Any(rKey) },
+ { "SearchItem.Backward", uno::Any(bBackwards) },
+ { "SearchItem.Command", uno::Any(sal_uInt16(eSearch)) },
+ }));
+
+ dispatchCommand(mxComponent, ".uno:ExecuteSearch", aPropertyValues);
+}
+
+void LOKitSearchTest::lcl_replace(const OUString& rKey, const OUString& rReplace, bool bAll)
+{
+ Scheduler::ProcessEventsToIdle();
+
+ SvxSearchCmd eSearch = bAll ? SvxSearchCmd::REPLACE_ALL : SvxSearchCmd::REPLACE;
+
+ uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence({
+ { "SearchItem.SearchString", uno::Any(rKey) },
+ { "SearchItem.ReplaceString", uno::Any(rReplace) },
+ { "SearchItem.Command", uno::Any(sal_uInt16(eSearch)) },
+ }));
+
+ dispatchCommand(mxComponent, ".uno:ExecuteSearch", aPropertyValues);
+}
+
+namespace
+{
+SdrObject* lclGetSelectedObject(sd::ViewShell* pViewShell)
+{
+ SdrView* pSdrView = pViewShell->GetView();
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ CPPUNIT_ASSERT_EQUAL(size_t(1), rMarkList.GetMarkCount());
+ SdrObject* pObject = rMarkList.GetMark(0)->GetMarkedSdrObj();
+ return pObject;
+}
+
+} // end anonymous namespace
+
+void LOKitSearchTest::testSearch()
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+ uno::Reference<container::XIndexAccess> xDrawPage(
+ pXImpressDocument->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ xShape->setString("Aaa bbb.");
+
+ lcl_search("bbb");
+
+ SdrView* pView = pViewShell->GetView();
+ EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
+ // Did we indeed manage to select the second word?
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), rEditView.GetSelected());
+
+ // Did the selection callback fire?
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), mpCallbackRecorder->m_aSelection.size());
+
+ // Search for something on the second slide, and make sure that the set-part callback fired.
+ lcl_search("bbb");
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), mpCallbackRecorder->m_nPart);
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ // This was 0; should be 1 match for "find".
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1),
+ mpCallbackRecorder->m_aSearchResultSelection.size());
+ // Result is on the second slide.
+ CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_aSearchResultPart[0]);
+
+ // This should trigger the not-found callback.
+ lcl_search("ccc");
+ CPPUNIT_ASSERT_EQUAL(false, mpCallbackRecorder->m_bFound);
+}
+
+void LOKitSearchTest::testSearchAll()
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("search-all.odp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+
+ lcl_search("match", /*bFindAll=*/true);
+
+ // This was empty: find-all did not highlight the first match.
+ CPPUNIT_ASSERT_EQUAL("match"_ostr,
+ apitest::helper::transferable::getTextSelection(
+ pXImpressDocument->getSelection(), "text/plain;charset=utf-8"_ostr));
+
+ // We're on the first slide, search for something on the second slide and make sure we get a SET_PART.
+ mpCallbackRecorder->m_nPart = 0;
+ lcl_search("second", /*bFindAll=*/true);
+ // This was 0: no SET_PART was emitted.
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), mpCallbackRecorder->m_nPart);
+}
+
+void LOKitSearchTest::testSearchAllSelections()
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("search-all.odp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+
+ lcl_search("third", /*bFindAll=*/true);
+ // Make sure this is found on the 3rd slide.
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), mpCallbackRecorder->m_nPart);
+ // This was 1: only the first match was highlighted.
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), mpCallbackRecorder->m_aSelection.size());
+}
+
+void LOKitSearchTest::testSearchAllNotifications()
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("search-all.odp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+
+ lcl_search("third", /*bFindAll=*/true);
+ // Make sure that we get no notifications about selection changes during search.
+ CPPUNIT_ASSERT_EQUAL(0, mpCallbackRecorder->m_nSelectionBeforeSearchResult);
+ // But we do get the selection of the first hit.
+ CPPUNIT_ASSERT(mpCallbackRecorder->m_nSelectionAfterSearchResult > 0);
+}
+
+void LOKitSearchTest::testSearchAllFollowedBySearch()
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("search-all.odp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+
+ lcl_search("third", /*bFindAll=*/true);
+ lcl_search("match" /*,bFindAll=false*/);
+
+ // This used to give wrong result: 'search' after 'search all' still
+ // returned 'third'
+ CPPUNIT_ASSERT_EQUAL("match"_ostr,
+ apitest::helper::transferable::getTextSelection(
+ pXImpressDocument->getSelection(), "text/plain;charset=utf-8"_ostr));
+}
+
+void LOKitSearchTest::testDontSearchInMasterPages()
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+
+ // This should trigger the not-found callback ("date" is present only on
+ // the master page)
+ lcl_search("date");
+ CPPUNIT_ASSERT_EQUAL(false, mpCallbackRecorder->m_bFound);
+}
+
+void LOKitSearchTest::testSearchInPDFNonExisting()
+{
+ auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPdfium)
+ {
+ return;
+ }
+
+ SdXImpressDocument* pXImpressDocument = createDoc("PDFSearch.pdf");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ CPPUNIT_ASSERT(pViewShell);
+ mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+
+ SdPage* pPage = pViewShell->GetActualPage();
+ CPPUNIT_ASSERT(pPage);
+
+ SdrObject* pObject = pPage->GetObj(0);
+ CPPUNIT_ASSERT(pObject);
+
+ SdrGrafObj* pGraphicObject = dynamic_cast<SdrGrafObj*>(pObject);
+ CPPUNIT_ASSERT(pGraphicObject);
+
+ Graphic aGraphic = pGraphicObject->GetGraphic();
+ auto const& pVectorGraphicData = aGraphic.getVectorGraphicData();
+ CPPUNIT_ASSERT(pVectorGraphicData);
+ CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
+
+ lcl_search("NonExisting");
+
+ CPPUNIT_ASSERT_EQUAL(false, mpCallbackRecorder->m_bFound);
+}
+
+void LOKitSearchTest::testSearchInPDF()
+{
+ auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPdfium)
+ {
+ return;
+ }
+
+ SdXImpressDocument* pXImpressDocument = createDoc("PDFSearch.pdf");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ CPPUNIT_ASSERT(pViewShell);
+ mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+
+ SdPage* pPage = pViewShell->GetActualPage();
+ CPPUNIT_ASSERT(pPage);
+
+ SdrObject* pObject = pPage->GetObj(0);
+ CPPUNIT_ASSERT(pObject);
+
+ SdrGrafObj* pGraphicObject = dynamic_cast<SdrGrafObj*>(pObject);
+ CPPUNIT_ASSERT(pGraphicObject);
+
+ Graphic aGraphic = pGraphicObject->GetGraphic();
+ auto const& pVectorGraphicData = aGraphic.getVectorGraphicData();
+ CPPUNIT_ASSERT(pVectorGraphicData);
+ CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
+
+ // Search
+ lcl_search("ABC");
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL("3763, 1331, 1432, 483"_ostr,
+ mpCallbackRecorder->m_aSearchResultSelection[0]);
+ CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(3763, 1331), Size(1433, 484)),
+ mpCallbackRecorder->m_aSelection[0]);
+
+ // Search again - same result
+ lcl_search("ABC");
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(2, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL("3763, 1331, 1432, 483"_ostr,
+ mpCallbackRecorder->m_aSearchResultSelection[0]);
+ CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(3763, 1331), Size(1433, 484)),
+ mpCallbackRecorder->m_aSelection[0]);
+}
+
+void LOKitSearchTest::testSearchInPDFOnePDFObject()
+{
+ auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPdfium)
+ {
+ return;
+ }
+
+ SdXImpressDocument* pXImpressDocument = createDoc("OnePDFObject.odg");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ CPPUNIT_ASSERT(pViewShell);
+ mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+
+ SdPage* pPage = pViewShell->GetActualPage();
+ CPPUNIT_ASSERT(pPage);
+
+ SdrObject* pObject = pPage->GetObj(0);
+ CPPUNIT_ASSERT(pObject);
+
+ SdrGrafObj* pGraphicObject = dynamic_cast<SdrGrafObj*>(pObject);
+ CPPUNIT_ASSERT(pGraphicObject);
+
+ Graphic aGraphic = pGraphicObject->GetGraphic();
+ auto const& pVectorGraphicData = aGraphic.getVectorGraphicData();
+ CPPUNIT_ASSERT(pVectorGraphicData);
+ CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
+
+ // Search down
+ lcl_search("ABC", false, false);
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_nSearchResultCount);
+
+ // Search up
+ lcl_search("ABC", false, true); // This caused a crash
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(2, mpCallbackRecorder->m_nSearchResultCount);
+}
+
+void LOKitSearchTest::testSearchInPDFInMultiplePages()
+{
+ auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPdfium)
+ {
+ return;
+ }
+
+ SdXImpressDocument* pXImpressDocument = createDoc("PDFSearch.pdf");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ CPPUNIT_ASSERT(pViewShell);
+ mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+
+ SdPage* pPage = pViewShell->GetActualPage();
+ CPPUNIT_ASSERT(pPage);
+
+ {
+ SdrObject* pObject = pPage->GetObj(0);
+ CPPUNIT_ASSERT(pObject);
+
+ SdrGrafObj* pGraphicObject = dynamic_cast<SdrGrafObj*>(pObject);
+ CPPUNIT_ASSERT(pGraphicObject);
+
+ Graphic aGraphic = pGraphicObject->GetGraphic();
+ auto const& pVectorGraphicData = aGraphic.getVectorGraphicData();
+ CPPUNIT_ASSERT(pVectorGraphicData);
+ CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
+ }
+
+ // Search for "him"
+ lcl_search("him");
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+
+ CPPUNIT_ASSERT_EQUAL(0, mpCallbackRecorder->m_aSearchResultPart[0]);
+ CPPUNIT_ASSERT_EQUAL("9463, 3382, 1099, 499"_ostr,
+ mpCallbackRecorder->m_aSearchResultSelection[0]);
+
+ // Search for "him"
+ lcl_search("him");
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(2, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+
+ CPPUNIT_ASSERT_EQUAL(0, mpCallbackRecorder->m_aSearchResultPart[0]);
+ CPPUNIT_ASSERT_EQUAL("5592, 5038, 1100, 499"_ostr,
+ mpCallbackRecorder->m_aSearchResultSelection[0]);
+
+ // Search for "him"
+ lcl_search("him");
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(3, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+
+ CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_aSearchResultPart[0]);
+ CPPUNIT_ASSERT_EQUAL("9463, 1308, 1099, 499"_ostr,
+ mpCallbackRecorder->m_aSearchResultSelection[0]);
+
+ // Search for "him"
+ lcl_search("him");
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(4, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+
+ CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_aSearchResultPart[0]);
+ CPPUNIT_ASSERT_EQUAL("5592, 2964, 1100, 499"_ostr,
+ mpCallbackRecorder->m_aSearchResultSelection[0]);
+
+ // Search for "him" - back to start
+ lcl_search("him");
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(5, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+
+ CPPUNIT_ASSERT_EQUAL(0, mpCallbackRecorder->m_aSearchResultPart[0]);
+ CPPUNIT_ASSERT_EQUAL("9463, 3382, 1099, 499"_ostr,
+ mpCallbackRecorder->m_aSearchResultSelection[0]);
+}
+
+void LOKitSearchTest::testSearchInPDFInMultiplePagesBackwards()
+{
+ auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPdfium)
+ {
+ return;
+ }
+
+ SdXImpressDocument* pXImpressDocument = createDoc("PDFSearch.pdf");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ CPPUNIT_ASSERT(pViewShell);
+ mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+
+ SdPage* pPage = pViewShell->GetActualPage();
+ CPPUNIT_ASSERT(pPage);
+
+ {
+ SdrObject* pObject = pPage->GetObj(0);
+ CPPUNIT_ASSERT(pObject);
+
+ SdrGrafObj* pGraphicObject = dynamic_cast<SdrGrafObj*>(pObject);
+ CPPUNIT_ASSERT(pGraphicObject);
+
+ Graphic aGraphic = pGraphicObject->GetGraphic();
+ auto const& pVectorGraphicData = aGraphic.getVectorGraphicData();
+ CPPUNIT_ASSERT(pVectorGraphicData);
+ CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
+ }
+
+ // Expected for backwards search is:
+ // - Start with Page 1
+ // + search backwards through objects
+ // + inside objects search backwards through text
+ // - Switch to Page 2
+ // + search backwards through objects
+ // + inside objects search backwards through text
+
+ // Search for "him"
+ lcl_search("him", /*FindAll*/ false, /*Backwards*/ true);
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+
+ CPPUNIT_ASSERT_EQUAL(0, mpCallbackRecorder->m_aSearchResultPart[0]);
+ CPPUNIT_ASSERT_EQUAL("5592, 5038, 1100, 499"_ostr,
+ mpCallbackRecorder->m_aSearchResultSelection[0]);
+
+ // Search for "him"
+ lcl_search("him", /*FindAll*/ false, /*Backwards*/ true);
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(2, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+
+ CPPUNIT_ASSERT_EQUAL(0, mpCallbackRecorder->m_aSearchResultPart[0]);
+ CPPUNIT_ASSERT_EQUAL("9463, 3382, 1099, 499"_ostr,
+ mpCallbackRecorder->m_aSearchResultSelection[0]);
+
+ // Search for "him"
+ lcl_search("him", /*FindAll*/ false, /*Backwards*/ true);
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(3, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+
+ CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_aSearchResultPart[0]);
+ CPPUNIT_ASSERT_EQUAL("5592, 2964, 1100, 499"_ostr,
+ mpCallbackRecorder->m_aSearchResultSelection[0]);
+
+ // Search for "him"
+ lcl_search("him", /*FindAll*/ false, /*Backwards*/ true);
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(4, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+
+ CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_aSearchResultPart[0]);
+ CPPUNIT_ASSERT_EQUAL("9463, 1308, 1099, 499"_ostr,
+ mpCallbackRecorder->m_aSearchResultSelection[0]);
+
+ // Search for "him" - back to start
+ lcl_search("him", /*FindAll*/ false, /*Backwards*/ true);
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(5, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+
+ CPPUNIT_ASSERT_EQUAL(0, mpCallbackRecorder->m_aSearchResultPart[0]);
+ CPPUNIT_ASSERT_EQUAL("5592, 5038, 1100, 499"_ostr,
+ mpCallbackRecorder->m_aSearchResultSelection[0]);
+}
+
+// Test searching in document with mixed objects.
+// We have 2 objects: 1. Text Object, 2. Graphic Object with PDF
+void LOKitSearchTest::testSearchIn2MixedObjects()
+{
+ auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPdfium)
+ {
+ return;
+ }
+
+ SdXImpressDocument* pXImpressDocument = createDoc("MixedTest1.odg");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ CPPUNIT_ASSERT(pViewShell);
+ SdDrawDocument* pDocument = pXImpressDocument->GetDocShell()->GetDoc();
+ CPPUNIT_ASSERT(pDocument);
+ mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+
+ // Check we have one page
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), pDocument->GetSdPageCount(PageKind::Standard));
+
+ SdPage* pPage = pViewShell->GetActualPage();
+ CPPUNIT_ASSERT(pPage);
+
+ // Check page has 2 objects only
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pPage->GetObjCount());
+
+ // Check Object 1
+ {
+ SdrObject* pObject = pPage->GetObj(0);
+ CPPUNIT_ASSERT(pObject);
+
+ CPPUNIT_ASSERT_EQUAL(SdrObjKind::Text, pObject->GetObjIdentifier());
+ }
+
+ // Check Object 2
+ {
+ SdrObject* pObject = pPage->GetObj(1);
+ CPPUNIT_ASSERT(pObject);
+
+ CPPUNIT_ASSERT_EQUAL(SdrObjKind::Graphic, pObject->GetObjIdentifier());
+
+ SdrGrafObj* pGraphicObject = dynamic_cast<SdrGrafObj*>(pObject);
+ CPPUNIT_ASSERT(pGraphicObject);
+
+ Graphic aGraphic = pGraphicObject->GetGraphic();
+ auto const& pVectorGraphicData = aGraphic.getVectorGraphicData();
+ CPPUNIT_ASSERT(pVectorGraphicData);
+
+ CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
+ }
+
+ // Let's try to search now
+
+ lcl_search("ABC");
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+
+ CPPUNIT_ASSERT_EQUAL("3546, 3174, 738, 402"_ostr,
+ mpCallbackRecorder->m_aSearchResultSelection[0]);
+
+ // Search next
+
+ lcl_search("ABC");
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(2, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+
+ CPPUNIT_ASSERT_EQUAL("8412, 6385, 519, 174"_ostr,
+ mpCallbackRecorder->m_aSearchResultSelection[0]);
+
+ // Search next again - we should get the first object again
+
+ lcl_search("ABC");
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(3, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+
+ CPPUNIT_ASSERT_EQUAL("3546, 3174, 738, 402"_ostr,
+ mpCallbackRecorder->m_aSearchResultSelection[0]);
+}
+
+// Test searching in document with mixed objects. We have 6 objects.
+void LOKitSearchTest::testSearchIn6MixedObjects()
+{
+ auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPdfium)
+ {
+ return;
+ }
+
+ SdXImpressDocument* pXImpressDocument = createDoc("MixedTest2.odg");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ CPPUNIT_ASSERT(pViewShell);
+ SdDrawDocument* pDocument = pXImpressDocument->GetDocShell()->GetDoc();
+ CPPUNIT_ASSERT(pDocument);
+ mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+
+ // Check we have one page
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), pDocument->GetSdPageCount(PageKind::Standard));
+
+ SdPage* pPage = pViewShell->GetActualPage();
+ CPPUNIT_ASSERT(pPage);
+
+ // Check page has 6 objects only
+ CPPUNIT_ASSERT_EQUAL(size_t(6), pPage->GetObjCount());
+
+ // Check we have the right objects that we expect
+
+ // Check Object 1
+ {
+ SdrObject* pObject = pPage->GetObj(0);
+ CPPUNIT_ASSERT(pObject);
+ CPPUNIT_ASSERT_EQUAL(SdrObjKind::Text, pObject->GetObjIdentifier());
+ }
+
+ // Check Object 2
+ {
+ SdrObject* pObject = pPage->GetObj(1);
+ CPPUNIT_ASSERT(pObject);
+ CPPUNIT_ASSERT_EQUAL(SdrObjKind::Graphic, pObject->GetObjIdentifier());
+ SdrGrafObj* pGraphicObject = dynamic_cast<SdrGrafObj*>(pObject);
+ CPPUNIT_ASSERT(pGraphicObject);
+ auto const& pVectorGraphicData = pGraphicObject->GetGraphic().getVectorGraphicData();
+ CPPUNIT_ASSERT(pVectorGraphicData);
+ CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
+ }
+
+ // Check Object 3
+ {
+ SdrObject* pObject = pPage->GetObj(2);
+ CPPUNIT_ASSERT(pObject);
+ CPPUNIT_ASSERT_EQUAL(SdrObjKind::CustomShape, pObject->GetObjIdentifier());
+ }
+
+ // Check Object 4
+ {
+ SdrObject* pObject = pPage->GetObj(3);
+ CPPUNIT_ASSERT(pObject);
+ CPPUNIT_ASSERT_EQUAL(SdrObjKind::CustomShape, pObject->GetObjIdentifier());
+ }
+
+ // Check Object 5
+ {
+ SdrObject* pObject = pPage->GetObj(4);
+ CPPUNIT_ASSERT(pObject);
+ CPPUNIT_ASSERT_EQUAL(SdrObjKind::Graphic, pObject->GetObjIdentifier());
+ SdrGrafObj* pGraphicObject = dynamic_cast<SdrGrafObj*>(pObject);
+ CPPUNIT_ASSERT(pGraphicObject);
+ auto const& pVectorGraphicData = pGraphicObject->GetGraphic().getVectorGraphicData();
+ CPPUNIT_ASSERT(pVectorGraphicData);
+ CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Svg, pVectorGraphicData->getType());
+ }
+
+ // Check Object 6
+ {
+ SdrObject* pObject = pPage->GetObj(5);
+ CPPUNIT_ASSERT(pObject);
+ CPPUNIT_ASSERT_EQUAL(SdrObjKind::Graphic, pObject->GetObjIdentifier());
+ SdrGrafObj* pGraphicObject = dynamic_cast<SdrGrafObj*>(pObject);
+ CPPUNIT_ASSERT(pGraphicObject);
+ auto const& pVectorGraphicData = pGraphicObject->GetGraphic().getVectorGraphicData();
+ CPPUNIT_ASSERT(pVectorGraphicData);
+ CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
+ }
+
+ // Search "ABC" which is in all objects (2 times in Object 3)
+
+ // Object 1
+ lcl_search("ABC");
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(1, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+ CPPUNIT_ASSERT_EQUAL(pPage->GetObj(0), lclGetSelectedObject(pViewShell));
+
+ // Object 2
+ lcl_search("ABC");
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(2, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+ CPPUNIT_ASSERT_EQUAL(pPage->GetObj(1), lclGetSelectedObject(pViewShell));
+
+ // Object 3
+ lcl_search("ABC");
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(3, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+ CPPUNIT_ASSERT_EQUAL(pPage->GetObj(2), lclGetSelectedObject(pViewShell));
+
+ // Object 3 again
+ lcl_search("ABC");
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(4, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+ CPPUNIT_ASSERT_EQUAL(pPage->GetObj(2), lclGetSelectedObject(pViewShell));
+
+ // Object 4
+ lcl_search("ABC");
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(5, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+ CPPUNIT_ASSERT_EQUAL(pPage->GetObj(3), lclGetSelectedObject(pViewShell));
+
+ // Object 5
+ lcl_search("ABC");
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(6, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+ CPPUNIT_ASSERT_EQUAL(pPage->GetObj(4), lclGetSelectedObject(pViewShell));
+
+ // Object 6
+ lcl_search("ABC");
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(7, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+ CPPUNIT_ASSERT_EQUAL(pPage->GetObj(5), lclGetSelectedObject(pViewShell));
+
+ // Loop to Object 1 again
+ lcl_search("ABC");
+
+ CPPUNIT_ASSERT_EQUAL(true, mpCallbackRecorder->m_bFound);
+ CPPUNIT_ASSERT_EQUAL(8, mpCallbackRecorder->m_nSearchResultCount);
+
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultSelection.size());
+ CPPUNIT_ASSERT_EQUAL(size_t(1), mpCallbackRecorder->m_aSearchResultPart.size());
+ CPPUNIT_ASSERT_EQUAL(pPage->GetObj(0), lclGetSelectedObject(pViewShell));
+}
+namespace
+{
+OUString getShapeText(SdXImpressDocument* pXImpressDocument, sal_uInt32 nPage, sal_uInt32 nShape)
+{
+ uno::Reference<container::XIndexAccess> xDrawPage;
+ xDrawPage.set(pXImpressDocument->getDrawPages()->getByIndex(nPage), uno::UNO_QUERY);
+
+ uno::Reference<text::XTextRange> xShape(xDrawPage->getByIndex(nShape), uno::UNO_QUERY);
+ return xShape->getString();
+}
+}
+
+void LOKitSearchTest::testReplace()
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("ReplaceTest.odp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 0, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("Bbb bbb bbb bbb"), getShapeText(pXImpressDocument, 1, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 2, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 3, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 4, 0));
+
+ lcl_replace("bbb", "aaa", false); // select
+
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 0, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("Bbb bbb bbb bbb"), getShapeText(pXImpressDocument, 1, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 2, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 3, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 4, 0));
+
+ lcl_replace("bbb", "aaa", false); // replace
+
+ CPPUNIT_ASSERT_EQUAL(OUString("aaa"), getShapeText(pXImpressDocument, 0, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("Bbb bbb bbb bbb"), getShapeText(pXImpressDocument, 1, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 2, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 3, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 4, 0));
+}
+
+void LOKitSearchTest::testReplaceAll()
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("ReplaceTest.odp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 0, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("Bbb bbb bbb bbb"), getShapeText(pXImpressDocument, 1, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 2, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 3, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 4, 0));
+
+ lcl_replace("bbb", "ccc", true);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("ccc"), getShapeText(pXImpressDocument, 0, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("ccc ccc ccc ccc"), getShapeText(pXImpressDocument, 1, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("ccc"), getShapeText(pXImpressDocument, 2, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("ccc"), getShapeText(pXImpressDocument, 3, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("ccc"), getShapeText(pXImpressDocument, 4, 0));
+
+ lcl_replace("ccc", "bbb", true);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 0, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb bbb bbb bbb"), getShapeText(pXImpressDocument, 1, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 2, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 3, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 4, 0));
+}
+
+void LOKitSearchTest::testReplaceCombined()
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("ReplaceTest.odp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ mpCallbackRecorder->registerCallbacksFor(pViewShell->GetViewShellBase());
+
+ lcl_replace("bbb", "aaa", false); // select
+ lcl_replace("bbb", "aaa", false); // replace
+
+ CPPUNIT_ASSERT_EQUAL(OUString("aaa"), getShapeText(pXImpressDocument, 0, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("Bbb bbb bbb bbb"), getShapeText(pXImpressDocument, 1, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 2, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 3, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), getShapeText(pXImpressDocument, 4, 0));
+
+ lcl_replace("bbb", "ccc", true);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("aaa"), getShapeText(pXImpressDocument, 0, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("ccc ccc ccc ccc"), getShapeText(pXImpressDocument, 1, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("ccc"), getShapeText(pXImpressDocument, 2, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("ccc"), getShapeText(pXImpressDocument, 3, 0));
+ CPPUNIT_ASSERT_EQUAL(OUString("ccc"), getShapeText(pXImpressDocument, 4, 0));
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(LOKitSearchTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/qa/unit/tiledrendering/data/2slides.odp b/sd/qa/unit/tiledrendering/data/2slides.odp
new file mode 100644
index 0000000000..baa42ba9fc
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/2slides.odp
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/MixedTest1.odg b/sd/qa/unit/tiledrendering/data/MixedTest1.odg
new file mode 100644
index 0000000000..db952318c7
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/MixedTest1.odg
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/MixedTest2.odg b/sd/qa/unit/tiledrendering/data/MixedTest2.odg
new file mode 100644
index 0000000000..2709707c1b
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/MixedTest2.odg
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/OnePDFObject.odg b/sd/qa/unit/tiledrendering/data/OnePDFObject.odg
new file mode 100644
index 0000000000..225741c7b5
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/OnePDFObject.odg
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/PDFSearch.pdf b/sd/qa/unit/tiledrendering/data/PDFSearch.pdf
new file mode 100644
index 0000000000..ea8a0919a4
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/PDFSearch.pdf
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/ReplaceTest.odp b/sd/qa/unit/tiledrendering/data/ReplaceTest.odp
new file mode 100644
index 0000000000..9b0fc61aaf
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/ReplaceTest.odp
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/TextBoxAndRect.odg b/sd/qa/unit/tiledrendering/data/TextBoxAndRect.odg
new file mode 100644
index 0000000000..aa1a37b831
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/TextBoxAndRect.odg
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/cut_selection_change.odp b/sd/qa/unit/tiledrendering/data/cut_selection_change.odp
new file mode 100644
index 0000000000..19d3a18480
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/cut_selection_change.odp
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/dummy.odg b/sd/qa/unit/tiledrendering/data/dummy.odg
new file mode 100644
index 0000000000..19ae49d63b
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/dummy.odg
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/dummy.odp b/sd/qa/unit/tiledrendering/data/dummy.odp
new file mode 100644
index 0000000000..83dee413c5
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/dummy.odp
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/duplicate-undo.odp b/sd/qa/unit/tiledrendering/data/duplicate-undo.odp
new file mode 100644
index 0000000000..f66c9f6081
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/duplicate-undo.odp
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/insert-delete.odp b/sd/qa/unit/tiledrendering/data/insert-delete.odp
new file mode 100644
index 0000000000..e388fb60b6
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/insert-delete.odp
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/language-all-text.odp b/sd/qa/unit/tiledrendering/data/language-all-text.odp
new file mode 100644
index 0000000000..a484a6310e
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/language-all-text.odp
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/notes-view.odp b/sd/qa/unit/tiledrendering/data/notes-view.odp
new file mode 100644
index 0000000000..d41bdf9599
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/notes-view.odp
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/paste-undo.fodp b/sd/qa/unit/tiledrendering/data/paste-undo.fodp
new file mode 100644
index 0000000000..2615d1e114
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/paste-undo.fodp
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<office:document xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.presentation">
+ <office:styles>
+ <style:presentation-page-layout style:name="AL1T0">
+ <presentation:placeholder presentation:object="title" svg:x="2.058cm" svg:y="1.743cm" svg:width="23.912cm" svg:height="3.507cm"/>
+ <presentation:placeholder presentation:object="subtitle" svg:x="2.058cm" svg:y="5.838cm" svg:width="23.912cm" svg:height="13.23cm"/>
+ </style:presentation-page-layout>
+ </office:styles>
+ <office:automatic-styles>
+ <style:page-layout style:name="PM0">
+ <style:page-layout-properties fo:margin-top="0cm" fo:margin-bottom="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:page-width="21cm" fo:page-height="29.7cm" style:print-orientation="portrait"/>
+ </style:page-layout>
+ <style:page-layout style:name="PM1">
+ <style:page-layout-properties fo:margin-top="0cm" fo:margin-bottom="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:page-width="28cm" fo:page-height="15.75cm" style:print-orientation="landscape"/>
+ </style:page-layout>
+ <style:style style:name="dp3" style:family="drawing-page">
+ </style:style>
+ <style:style style:name="gr3" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" svg:stroke-color="#000000" draw:fill="none" draw:fill-color="#ffffff" draw:auto-grow-height="true" draw:auto-grow-width="false" fo:max-height="0cm" fo:min-height="0.712cm"/>
+ <style:paragraph-properties style:writing-mode="lr-tb"/>
+ </style:style>
+ </office:automatic-styles>
+ <office:body>
+ <office:presentation>
+ <draw:page draw:name="page1" draw:style-name="dp3" draw:master-page-name="Default" presentation:presentation-page-layout-name="AL1T0">
+ <draw:frame draw:style-name="gr3" draw:text-style-name="P7" draw:layer="layout" svg:width="7.5cm" svg:height="0.962cm" svg:x="3.5cm" svg:y="3.5cm">
+ <draw:text-box>
+ <text:p>world</text:p>
+ </draw:text-box>
+ </draw:frame>
+ </draw:page>
+ </office:presentation>
+ </office:body>
+</office:document>
diff --git a/sd/qa/unit/tiledrendering/data/paste_text_onslide.odp b/sd/qa/unit/tiledrendering/data/paste_text_onslide.odp
new file mode 100644
index 0000000000..c33b7c1102
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/paste_text_onslide.odp
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/regenerate-diagram.pptx b/sd/qa/unit/tiledrendering/data/regenerate-diagram.pptx
new file mode 100644
index 0000000000..97635a5187
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/regenerate-diagram.pptx
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/search-all.odp b/sd/qa/unit/tiledrendering/data/search-all.odp
new file mode 100644
index 0000000000..46ddaf412b
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/search-all.odp
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/shape.odp b/sd/qa/unit/tiledrendering/data/shape.odp
new file mode 100644
index 0000000000..b1ffa54e36
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/shape.odp
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/table-column.odp b/sd/qa/unit/tiledrendering/data/table-column.odp
new file mode 100644
index 0000000000..d2c274e888
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/table-column.odp
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/table.odp b/sd/qa/unit/tiledrendering/data/table.odp
new file mode 100644
index 0000000000..6d92898a00
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/table.odp
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/tdf102223.odp b/sd/qa/unit/tiledrendering/data/tdf102223.odp
new file mode 100644
index 0000000000..6b8570f070
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/tdf102223.odp
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/tdf103083.fodp b/sd/qa/unit/tiledrendering/data/tdf103083.fodp
new file mode 100644
index 0000000000..8de5e37b8f
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/tdf103083.fodp
@@ -0,0 +1,932 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.presentation">
+ <office:meta>
+ <meta:creation-date>2016-10-03T11:33:02.159552013</meta:creation-date>
+ <meta:editing-duration>PT21M51S</meta:editing-duration>
+ <meta:editing-cycles>2</meta:editing-cycles>
+ <meta:generator>LibreOfficeDev/5.3.0.0.alpha0$Linux_X86_64 LibreOffice_project/36b8fd83a57132f486d918e5ab39a6e8898bb630</meta:generator>
+ <dc:date>2016-10-03T11:33:43.592997719</dc:date><meta:document-statistic meta:object-count="27"/></office:meta>
+ <office:settings>
+ <config:config-item-set config:name="ooo:view-settings">
+ <config:config-item config:name="VisibleAreaTop" config:type="int">-275</config:config-item>
+ <config:config-item config:name="VisibleAreaLeft" config:type="int">-1323</config:config-item>
+ <config:config-item config:name="VisibleAreaWidth" config:type="int">28053</config:config-item>
+ <config:config-item config:name="VisibleAreaHeight" config:type="int">19616</config:config-item>
+ <config:config-item-map-indexed config:name="Views">
+ <config:config-item-map-entry>
+ <config:config-item config:name="ViewId" config:type="string">view1</config:config-item>
+ <config:config-item config:name="GridIsVisible" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="GridIsFront" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsSnapToGrid" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsSnapToPageMargins" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsSnapToSnapLines" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsSnapToObjectFrame" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsSnapToObjectPoints" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPlusHandlesAlwaysVisible" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsFrameDragSingles" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="EliminatePolyPointLimitAngle" config:type="int">1500</config:config-item>
+ <config:config-item config:name="IsEliminatePolyPoints" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="VisibleLayers" config:type="base64Binary">//////////////////////////////////////////8=</config:config-item>
+ <config:config-item config:name="PrintableLayers" config:type="base64Binary">//////////////////////////////////////////8=</config:config-item>
+ <config:config-item config:name="LockedLayers" config:type="base64Binary"/>
+ <config:config-item config:name="NoAttribs" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="NoColors" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="SnapLinesDrawing" config:type="string">V2278V23104H18449H578V627V24757H4049H2466H17561</config:config-item>
+ <config:config-item config:name="RulerIsVisible" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="PageKind" config:type="short">0</config:config-item>
+ <config:config-item config:name="SelectedPage" config:type="short">0</config:config-item>
+ <config:config-item config:name="IsLayerMode" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsDoubleClickTextEdit" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsClickChangeRotation" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="SlidesPerRow" config:type="short">4</config:config-item>
+ <config:config-item config:name="EditMode" config:type="int">0</config:config-item>
+ <config:config-item config:name="VisibleAreaTop" config:type="int">-275</config:config-item>
+ <config:config-item config:name="VisibleAreaLeft" config:type="int">-1323</config:config-item>
+ <config:config-item config:name="VisibleAreaWidth" config:type="int">28057</config:config-item>
+ <config:config-item config:name="VisibleAreaHeight" config:type="int">19620</config:config-item>
+ <config:config-item config:name="GridCoarseWidth" config:type="int">2540</config:config-item>
+ <config:config-item config:name="GridCoarseHeight" config:type="int">2540</config:config-item>
+ <config:config-item config:name="GridFineWidth" config:type="int">254</config:config-item>
+ <config:config-item config:name="GridFineHeight" config:type="int">254</config:config-item>
+ <config:config-item config:name="GridSnapWidthXNumerator" config:type="int">254</config:config-item>
+ <config:config-item config:name="GridSnapWidthXDenominator" config:type="int">1</config:config-item>
+ <config:config-item config:name="GridSnapWidthYNumerator" config:type="int">254</config:config-item>
+ <config:config-item config:name="GridSnapWidthYDenominator" config:type="int">1</config:config-item>
+ <config:config-item config:name="IsAngleSnapEnabled" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="SnapAngle" config:type="int">1500</config:config-item>
+ <config:config-item config:name="ZoomOnPage" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">true</config:config-item>
+ </config:config-item-map-entry>
+ </config:config-item-map-indexed>
+ </config:config-item-set>
+ <config:config-item-set config:name="ooo:configuration-settings">
+ <config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="BitmapTableURL" config:type="string">$(inst)/share/palette%3B$(user)/config/standard.sob</config:config-item>
+ <config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item>
+ <config:config-item config:name="ColorTableURL" config:type="string">$(inst)/share/palette%3B$(user)/config/standard.soc</config:config-item>
+ <config:config-item config:name="DashTableURL" config:type="string">$(inst)/share/palette%3B$(user)/config/standard.sod</config:config-item>
+ <config:config-item config:name="DefaultTabStop" config:type="int">1270</config:config-item>
+ <config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item>
+ <config:config-item-map-indexed config:name="ForbiddenCharacters">
+ <config:config-item-map-entry>
+ <config:config-item config:name="Language" config:type="string">de</config:config-item>
+ <config:config-item config:name="Country" config:type="string">DE</config:config-item>
+ <config:config-item config:name="Variant" config:type="string"/>
+ <config:config-item config:name="BeginLine" config:type="string"/>
+ <config:config-item config:name="EndLine" config:type="string"/>
+ </config:config-item-map-entry>
+ <config:config-item-map-entry>
+ <config:config-item config:name="Language" config:type="string">en</config:config-item>
+ <config:config-item config:name="Country" config:type="string">US</config:config-item>
+ <config:config-item config:name="Variant" config:type="string"/>
+ <config:config-item config:name="BeginLine" config:type="string"/>
+ <config:config-item config:name="EndLine" config:type="string"/>
+ </config:config-item-map-entry>
+ <config:config-item-map-entry>
+ <config:config-item config:name="Language" config:type="string">en</config:config-item>
+ <config:config-item config:name="Country" config:type="string">GB</config:config-item>
+ <config:config-item config:name="Variant" config:type="string"/>
+ <config:config-item config:name="BeginLine" config:type="string"/>
+ <config:config-item config:name="EndLine" config:type="string"/>
+ </config:config-item-map-entry>
+ <config:config-item-map-entry>
+ <config:config-item config:name="Language" config:type="string">en</config:config-item>
+ <config:config-item config:name="Country" config:type="string">ZA</config:config-item>
+ <config:config-item config:name="Variant" config:type="string"/>
+ <config:config-item config:name="BeginLine" config:type="string"/>
+ <config:config-item config:name="EndLine" config:type="string"/>
+ </config:config-item-map-entry>
+ </config:config-item-map-indexed>
+ <config:config-item config:name="GradientTableURL" config:type="string">$(inst)/share/palette%3B$(user)/config/standard.sog</config:config-item>
+ <config:config-item config:name="HandoutsHorizontal" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="HatchTableURL" config:type="string">$(inst)/share/palette%3B$(user)/config/standard.soh</config:config-item>
+ <config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPrintBooklet" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPrintBookletBack" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsPrintBookletFront" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsPrintDate" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPrintDrawing" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsPrintFitPage" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPrintHandout" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPrintHiddenPages" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsPrintNotes" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPrintOutline" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPrintPageName" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPrintTilePage" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPrintTime" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="LineEndTableURL" config:type="string">$(inst)/share/palette%3B$(user)/config/standard.soe</config:config-item>
+ <config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="PageNumberFormat" config:type="int">4</config:config-item>
+ <config:config-item config:name="ParagraphSummation" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="PrintQuality" config:type="int">0</config:config-item>
+ <config:config-item config:name="PrinterIndependentLayout" config:type="string">low-resolution</config:config-item>
+ <config:config-item config:name="PrinterName" config:type="string"/>
+ <config:config-item config:name="PrinterSetup" config:type="base64Binary"/>
+ <config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="SlidesPerHandout" config:type="short">6</config:config-item>
+ <config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item>
+ </config:config-item-set>
+ </office:settings>
+ <office:scripts>
+ <office:script script:language="ooo:Basic">
+ <ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"/>
+ </office:script>
+ </office:scripts>
+ <office:font-face-decls>
+ <style:font-face style:name="Arial2" svg:font-family="Arial" style:font-family-generic="swiss"/>
+ <style:font-face style:name="Liberation Sans" svg:font-family="&apos;Liberation Sans&apos;" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Thorndale AMT" svg:font-family="&apos;Thorndale AMT&apos;" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/>
+ <style:font-face style:name="Arial1" svg:font-family="Arial" style:font-adornments="Regular" style:font-family-generic="swiss" style:font-pitch="variable"/>
+ <style:font-face style:name="Calibri" svg:font-family="Calibri" style:font-family-generic="swiss" style:font-pitch="variable"/>
+ <style:font-face style:name="Albany AMT" svg:font-family="&apos;Albany AMT&apos;" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="FreeSans" svg:font-family="FreeSans" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="Mangal" svg:font-family="Mangal" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="Microsoft YaHei" svg:font-family="&apos;Microsoft YaHei&apos;" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="Noto Sans CJK SC Regular" svg:font-family="&apos;Noto Sans CJK SC Regular&apos;" style:font-family-generic="system" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+ <draw:marker draw:name="Arrow" svg:viewBox="0 0 20 30" svg:d="M10 0l-10 30h20z"/>
+ <draw:stroke-dash draw:name="Dashed_20__28_var_29__20_2" draw:display-name="Dashed (var) 2" draw:style="rect" draw:dots1="1" draw:dots1-length="0.02cm" draw:dots2="1" draw:dots2-length="0.02cm" draw:distance="0.02cm"/>
+ <style:default-style style:family="graphic">
+ <style:graphic-properties svg:stroke-color="#000000" draw:fill-color="#99ccff" fo:wrap-option="no-wrap"/>
+ <style:paragraph-properties style:text-autospace="ideograph-alpha" style:punctuation-wrap="simple" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false">
+ <style:tab-stops/>
+ </style:paragraph-properties>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Thorndale AMT" fo:font-size="24pt" fo:language="en" fo:country="US" style:font-name-asian="Albany AMT" style:font-size-asian="24pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Albany AMT" style:font-size-complex="24pt" style:language-complex="hi" style:country-complex="IN"/>
+ </style:default-style>
+ <style:style style:name="standard" style:family="graphic">
+ <style:graphic-properties draw:stroke="solid" draw:stroke-dash="Dashed_20__28_var_29__20_2" svg:stroke-width="0.076cm" svg:stroke-color="#454c51" draw:marker-start-width="0.406cm" draw:marker-start-center="false" draw:marker-end-width="0.406cm" draw:marker-end-center="false" draw:fill="solid" draw:fill-color="#e4e5e6" draw:fill-image-width="0cm" draw:fill-image-height="0cm" draw:auto-grow-width="true" fo:padding-top="0.125cm" fo:padding-bottom="0.125cm" fo:padding-left="0.25cm" fo:padding-right="0.25cm" draw:shadow="hidden" draw:shadow-offset-x="0.305cm" draw:shadow-offset-y="0.305cm" draw:shadow-color="#808080">
+ <text:list-style style:name="standard">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="●">
+ <style:list-level-properties/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="●">
+ <style:list-level-properties text:space-before="5.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ </style:graphic-properties>
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" fo:line-height="100%" fo:text-indent="0cm"/>
+ <style:text-properties style:use-window-font-color="true" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Arial1" fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="18pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" style:letter-kerning="true" style:font-name-asian="Microsoft YaHei" style:font-family-asian="&apos;Microsoft YaHei&apos;" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="18pt" style:font-style-asian="normal" style:font-weight-asian="normal" style:font-name-complex="Mangal" style:font-family-complex="Mangal" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="18pt" style:font-style-complex="normal" style:font-weight-complex="normal" style:text-emphasize="none" style:font-relief="none"/>
+ </style:style>
+ <style:style style:name="objectwitharrow" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="solid" svg:stroke-width="0.15cm" svg:stroke-color="#000000" draw:marker-start="Arrow" draw:marker-start-width="0.7cm" draw:marker-start-center="true" draw:marker-end-width="0.3cm"/>
+ </style:style>
+ <style:style style:name="objectwithshadow" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:shadow="visible" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:shadow-color="#808080"/>
+ </style:style>
+ <style:style style:name="objectwithoutfill" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:fill="none"/>
+ </style:style>
+ <style:style style:name="Object_20_with_20_no_20_fill_20_and_20_no_20_line" style:display-name="Object with no fill and no line" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ </style:style>
+ <style:style style:name="text" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ </style:style>
+ <style:style style:name="textbody" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:text-properties fo:font-size="16pt"/>
+ </style:style>
+ <style:style style:name="textbodyjustfied" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:paragraph-properties fo:text-align="justify"/>
+ </style:style>
+ <style:style style:name="textbodyindent" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0.6cm"/>
+ </style:style>
+ <style:style style:name="title" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:text-properties fo:font-size="40pt"/>
+ </style:style>
+ <style:style style:name="title1" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="solid" draw:fill-color="#008080" draw:shadow="visible" draw:shadow-offset-x="0.2cm" draw:shadow-offset-y="0.2cm" draw:shadow-color="#808080"/>
+ <style:paragraph-properties fo:text-align="center"/>
+ <style:text-properties fo:font-size="24pt"/>
+ </style:style>
+ <style:style style:name="title2" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties svg:stroke-width="0.05cm" draw:fill-color="#ffcc99" draw:shadow="visible" draw:shadow-offset-x="0.2cm" draw:shadow-offset-y="0.2cm" draw:shadow-color="#808080"/>
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0.2cm" fo:margin-top="0.1cm" fo:margin-bottom="0.1cm" fo:text-align="center" fo:text-indent="0cm"/>
+ <style:text-properties fo:font-size="32pt"/>
+ </style:style>
+ <style:style style:name="headline" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:paragraph-properties fo:margin-top="0.42cm" fo:margin-bottom="0.21cm"/>
+ <style:text-properties fo:font-size="24pt"/>
+ </style:style>
+ <style:style style:name="headline1" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:paragraph-properties fo:margin-top="0.42cm" fo:margin-bottom="0.21cm"/>
+ <style:text-properties fo:font-size="18pt" fo:font-weight="bold"/>
+ </style:style>
+ <style:style style:name="headline2" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:paragraph-properties fo:margin-top="0.42cm" fo:margin-bottom="0.21cm"/>
+ <style:text-properties fo:font-size="14pt" fo:font-style="normal" fo:font-weight="normal"/>
+ </style:style>
+ <style:style style:name="measure" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="solid" draw:marker-start="Arrow" draw:marker-start-width="0.2cm" draw:marker-end="Arrow" draw:marker-end-width="0.2cm" draw:fill="none" draw:show-unit="true"/>
+ <style:text-properties fo:font-size="12pt"/>
+ </style:style>
+ <style:style style:name="Normal" style:family="graphic">
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0.623cm" fo:line-height="115%" fo:text-align="start" fo:text-indent="0cm" style:text-autospace="ideograph-alpha"/>
+ <style:text-properties style:font-name="Arial1" fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="11pt" fo:language="en" fo:country="US" style:font-name-asian="Calibri" style:font-family-asian="Calibri" style:font-family-generic-asian="swiss" style:font-pitch-asian="variable" style:font-size-asian="11pt" style:language-asian="en" style:country-asian="US" style:font-name-complex="Calibri" style:font-family-complex="Calibri" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="11pt" style:language-complex="ar" style:country-complex="SA"/>
+ </style:style>
+ <style:style style:name="Default_20_Paragraph_20_Font" style:display-name="Default Paragraph Font" style:family="graphic">
+ <style:paragraph-properties style:text-autospace="none"/>
+ <style:text-properties style:font-name="Arial1" fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable"/>
+ </style:style>
+ <style:style style:name="No-Logo_20_Content-background" style:display-name="No-Logo Content-background" style:family="presentation">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-image-width="0cm" draw:fill-image-height="0cm"/>
+ <style:text-properties style:letter-kerning="true"/>
+ </style:style>
+ <style:style style:name="No-Logo_20_Content-backgroundobjects" style:display-name="No-Logo Content-backgroundobjects" style:family="presentation">
+ <style:graphic-properties draw:shadow="hidden" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:shadow-color="#808080"/>
+ <style:text-properties style:font-name="Arial1" fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" style:letter-kerning="true"/>
+ </style:style>
+ <style:style style:name="No-Logo_20_Content-notes" style:display-name="No-Logo Content-notes" style:family="presentation">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:paragraph-properties fo:margin-left="0.6cm" fo:margin-right="0cm" fo:text-indent="0cm"/>
+ <style:text-properties style:use-window-font-color="true" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Arial2" fo:font-family="Arial" style:font-family-generic="swiss" fo:font-size="14pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" style:letter-kerning="true" style:font-name-asian="Microsoft YaHei" style:font-family-asian="&apos;Microsoft YaHei&apos;" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="14pt" style:font-style-asian="normal" style:font-weight-asian="normal" style:font-name-complex="Mangal" style:font-family-complex="Mangal" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="14pt" style:font-style-complex="normal" style:font-weight-complex="normal" style:text-emphasize="none" style:font-relief="none"/>
+ </style:style>
+ <style:style style:name="No-Logo_20_Content-outline1" style:display-name="No-Logo Content-outline1" style:family="presentation">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:textarea-horizontal-align="left" draw:auto-grow-height="false" draw:fit-to-size="false">
+ <text:list-style style:name="No-Logo_20_Content-outline1" style:display-name="No-Logo Content-outline1">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="•">
+ <style:list-level-properties text:space-before="0.008cm" text:min-label-width="0.47cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="‒">
+ <style:list-level-properties text:space-before="0.766cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="‒">
+ <style:list-level-properties text:space-before="1.515cm" text:min-label-width="0.452cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="‒">
+ <style:list-level-properties text:space-before="2.028cm" text:min-label-width="0.47cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="‒">
+ <style:list-level-properties text:space-before="2.786cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="‒">
+ <style:list-level-properties text:space-before="3.561cm" text:min-label-width="0.505cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="‒">
+ <style:list-level-properties text:space-before="4.061cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="‒">
+ <style:list-level-properties text:space-before="9.119cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="‒">
+ <style:list-level-properties text:space-before="10.312cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="‒">
+ <style:list-level-properties text:space-before="11.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ </style:graphic-properties>
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0.405cm" fo:text-indent="0cm"/>
+ <style:text-properties fo:color="#000000" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Arial1" fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="24pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" style:letter-kerning="true" style:font-name-asian="Microsoft YaHei" style:font-family-asian="&apos;Microsoft YaHei&apos;" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="32pt" style:font-style-asian="normal" style:font-weight-asian="normal" style:font-name-complex="Mangal" style:font-family-complex="Mangal" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="32pt" style:font-style-complex="normal" style:font-weight-complex="normal" style:text-emphasize="none" style:font-relief="none"/>
+ </style:style>
+ <style:style style:name="No-Logo_20_Content-outline2" style:display-name="No-Logo Content-outline2" style:family="presentation" style:parent-style-name="No-Logo_20_Content-outline1">
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0.406cm" fo:text-indent="0cm"/>
+ <style:text-properties fo:color="#000000" fo:font-size="20pt" style:font-size-asian="28pt" style:font-size-complex="28pt"/>
+ </style:style>
+ <style:style style:name="No-Logo_20_Content-outline3" style:display-name="No-Logo Content-outline3" style:family="presentation" style:parent-style-name="No-Logo_20_Content-outline2">
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0.406cm" fo:text-indent="0cm"/>
+ <style:text-properties fo:color="#000000" fo:font-size="16pt" style:font-size-asian="24pt" style:font-size-complex="24pt"/>
+ </style:style>
+ <style:style style:name="No-Logo_20_Content-outline4" style:display-name="No-Logo Content-outline4" style:family="presentation" style:parent-style-name="No-Logo_20_Content-outline3">
+ <style:paragraph-properties fo:margin-left="0.266cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0.406cm" fo:text-indent="0cm"/>
+ <style:text-properties fo:color="#000000" fo:font-size="14pt" style:font-size-asian="20pt" style:font-size-complex="20pt"/>
+ </style:style>
+ <style:style style:name="No-Logo_20_Content-outline5" style:display-name="No-Logo Content-outline5" style:family="presentation" style:parent-style-name="No-Logo_20_Content-outline4">
+ <style:paragraph-properties fo:margin-left="0.265cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0.406cm" fo:text-indent="0cm"/>
+ <style:text-properties fo:color="#000000" fo:font-size="12pt" style:font-size-asian="20pt" style:font-size-complex="20pt"/>
+ </style:style>
+ <style:style style:name="No-Logo_20_Content-outline6" style:display-name="No-Logo Content-outline6" style:family="presentation" style:parent-style-name="No-Logo_20_Content-outline5">
+ <style:paragraph-properties fo:margin-left="0.239cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0.406cm" fo:text-indent="0cm"/>
+ <style:text-properties fo:color="#000000" fo:font-size="12pt" style:font-size-asian="20pt" style:font-size-complex="20pt"/>
+ </style:style>
+ <style:style style:name="No-Logo_20_Content-outline7" style:display-name="No-Logo Content-outline7" style:family="presentation" style:parent-style-name="No-Logo_20_Content-outline6">
+ <style:paragraph-properties fo:margin-left="0.505cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0.406cm" fo:text-indent="0cm"/>
+ <style:text-properties fo:color="#000000" fo:font-size="12pt" style:font-size-asian="20pt" style:font-size-complex="20pt"/>
+ </style:style>
+ <style:style style:name="No-Logo_20_Content-outline8" style:display-name="No-Logo Content-outline8" style:family="presentation" style:parent-style-name="No-Logo_20_Content-outline7">
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0.406cm" fo:text-indent="0cm"/>
+ <style:text-properties fo:color="#000000" fo:font-size="12pt" style:font-size-asian="20pt" style:font-size-complex="20pt"/>
+ </style:style>
+ <style:style style:name="No-Logo_20_Content-outline9" style:display-name="No-Logo Content-outline9" style:family="presentation" style:parent-style-name="No-Logo_20_Content-outline8">
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0.406cm" fo:text-indent="0cm"/>
+ <style:text-properties fo:color="#000000" fo:font-size="12pt" style:font-size-asian="20pt" style:font-size-complex="20pt"/>
+ </style:style>
+ <style:style style:name="No-Logo_20_Content-subtitle" style:display-name="No-Logo Content-subtitle" style:family="presentation">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:textarea-vertical-align="middle">
+ <text:list-style style:name="No-Logo_20_Content-subtitle" style:display-name="No-Logo Content-subtitle">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="●">
+ <style:list-level-properties/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="●">
+ <style:list-level-properties text:space-before="5.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ </style:graphic-properties>
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-align="center" fo:text-indent="0cm"/>
+ <style:text-properties style:use-window-font-color="true" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Arial1" fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="20pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" style:letter-kerning="true" style:font-name-asian="Microsoft YaHei" style:font-family-asian="&apos;Microsoft YaHei&apos;" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="32pt" style:font-style-asian="normal" style:font-weight-asian="normal" style:font-name-complex="Mangal" style:font-family-complex="Mangal" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="32pt" style:font-style-complex="normal" style:font-weight-complex="normal" style:text-emphasize="none" style:font-relief="none"/>
+ </style:style>
+ <style:style style:name="No-Logo_20_Content-title" style:display-name="No-Logo Content-title" style:family="presentation">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:textarea-vertical-align="middle">
+ <text:list-style style:name="No-Logo_20_Content-title" style:display-name="No-Logo Content-title">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="●">
+ <style:list-level-properties/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="●">
+ <style:list-level-properties text:space-before="5.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ </style:graphic-properties>
+ <style:paragraph-properties fo:text-align="start"/>
+ <style:text-properties fo:color="#000000" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Arial1" fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="32pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="bold" style:letter-kerning="true" style:font-name-asian="Microsoft YaHei" style:font-family-asian="&apos;Microsoft YaHei&apos;" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="44pt" style:font-style-asian="normal" style:font-weight-asian="bold" style:font-name-complex="Mangal" style:font-family-complex="Mangal" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="44pt" style:font-style-complex="normal" style:font-weight-complex="bold" style:text-emphasize="none" style:font-relief="none"/>
+ </style:style>
+ <style:presentation-page-layout style:name="AL0T26">
+ <presentation:placeholder presentation:object="handout" svg:x="2.058cm" svg:y="1.743cm" svg:width="10.556cm" svg:height="-0.233cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="15.414cm" svg:y="1.743cm" svg:width="10.556cm" svg:height="-0.233cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="2.058cm" svg:y="3.612cm" svg:width="10.556cm" svg:height="-0.233cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="15.414cm" svg:y="3.612cm" svg:width="10.556cm" svg:height="-0.233cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="2.058cm" svg:y="5.481cm" svg:width="10.556cm" svg:height="-0.233cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="15.414cm" svg:y="5.481cm" svg:width="10.556cm" svg:height="-0.233cm"/>
+ </style:presentation-page-layout>
+ <style:presentation-page-layout style:name="AL1T1">
+ <presentation:placeholder presentation:object="title" svg:x="2.058cm" svg:y="1.743cm" svg:width="23.912cm" svg:height="3.507cm"/>
+ <presentation:placeholder presentation:object="outline" svg:x="2.058cm" svg:y="5.838cm" svg:width="23.912cm" svg:height="13.23cm"/>
+ </style:presentation-page-layout>
+ </office:styles>
+ <office:automatic-styles>
+ <style:page-layout style:name="PM0">
+ <style:page-layout-properties fo:margin-top="0cm" fo:margin-bottom="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:page-width="21.59cm" fo:page-height="27.94cm" style:print-orientation="portrait"/>
+ </style:page-layout>
+ <style:page-layout style:name="PM1">
+ <style:page-layout-properties fo:margin-top="0cm" fo:margin-bottom="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:page-width="25.4cm" fo:page-height="19.05cm" style:print-orientation="landscape"/>
+ </style:page-layout>
+ <style:style style:name="dp1" style:family="drawing-page">
+ <style:drawing-page-properties draw:background-size="border" draw:fill="none" draw:fill-image-width="0cm" draw:fill-image-height="0cm"/>
+ </style:style>
+ <style:style style:name="dp2" style:family="drawing-page">
+ <style:drawing-page-properties presentation:display-header="true" presentation:display-footer="true" presentation:display-page-number="false" presentation:display-date-time="true"/>
+ </style:style>
+ <style:style style:name="dp3" style:family="drawing-page">
+ <style:drawing-page-properties presentation:background-visible="true" presentation:background-objects-visible="true" presentation:display-footer="true" presentation:display-page-number="false" presentation:display-date-time="true"/>
+ </style:style>
+ <style:style style:name="gr1" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:auto-grow-height="false" fo:min-height="1.397cm" fo:min-width="4.236cm"/>
+ </style:style>
+ <style:style style:name="gr2" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:auto-grow-height="false" fo:min-height="1.397cm" fo:min-width="5.234cm"/>
+ </style:style>
+ <style:style style:name="gr3" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:textarea-vertical-align="bottom" draw:auto-grow-height="false" fo:min-height="1.397cm" fo:min-width="3.694cm"/>
+ </style:style>
+ <style:style style:name="gr4" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:textarea-vertical-align="bottom" draw:auto-grow-height="false" fo:min-height="1.397cm" fo:min-width="4.506cm"/>
+ </style:style>
+ <style:style style:name="gr5" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:textarea-horizontal-align="center" draw:textarea-vertical-align="middle" draw:color-mode="standard" draw:luminance="0%" draw:contrast="0%" draw:gamma="100%" draw:red="0%" draw:green="0%" draw:blue="0%" fo:clip="rect(0cm, 0cm, 0cm, 0cm)" draw:image-opacity="100%" style:mirror="none"/>
+ </style:style>
+ <style:style style:name="gr6" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" svg:stroke-width="0.076cm" draw:stroke-linejoin="round" draw:fill="none" draw:textarea-vertical-align="top" draw:auto-grow-height="false" fo:padding-top="0.13cm" fo:padding-bottom="0.13cm" fo:padding-left="0.25cm" fo:padding-right="0.25cm" fo:wrap-option="wrap"/>
+ </style:style>
+ <style:style style:name="gr7" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:textarea-vertical-align="middle" draw:auto-grow-width="true" fo:min-height="0.952cm" fo:min-width="1.78cm"/>
+ </style:style>
+ <style:style style:name="gr8" style:family="graphic">
+ <style:graphic-properties style:protect="size"/>
+ </style:style>
+ <style:style style:name="pr1" style:family="presentation" style:parent-style-name="No-Logo_20_Content-backgroundobjects">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:auto-grow-height="false" fo:min-height="1.397cm" fo:min-width="8.869cm"/>
+ </style:style>
+ <style:style style:name="pr2" style:family="presentation" style:parent-style-name="No-Logo_20_Content-backgroundobjects">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:textarea-vertical-align="bottom" draw:auto-grow-height="false" fo:min-height="1.397cm" fo:min-width="8.869cm"/>
+ </style:style>
+ <style:style style:name="pr3" style:family="presentation" style:parent-style-name="No-Logo_20_Content-title">
+ <style:graphic-properties draw:auto-grow-height="true" fo:min-height="2.743cm" fo:min-width="21.058cm"/>
+ </style:style>
+ <style:style style:name="pr4" style:family="presentation" style:parent-style-name="No-Logo_20_Content-outline1">
+ <style:graphic-properties draw:fit-to-size="false" fo:min-height="10.799cm" fo:min-width="10.066cm"/>
+ </style:style>
+ <style:style style:name="pr5" style:family="presentation" style:parent-style-name="No-Logo_20_Content-notes">
+ <style:graphic-properties draw:fill-color="#ffffff" draw:auto-grow-height="true" fo:min-height="12.572cm" fo:min-width="16.771cm"/>
+ </style:style>
+ <style:style style:name="P1" style:family="paragraph">
+ <style:text-properties fo:font-size="14pt" style:font-size-asian="14pt" style:font-size-complex="14pt"/>
+ </style:style>
+ <style:style style:name="P2" style:family="paragraph">
+ <loext:graphic-properties draw:fill="none" draw:fill-color="#ffffff"/>
+ <style:text-properties fo:font-size="14pt" style:font-size-asian="14pt" style:font-size-complex="14pt"/>
+ </style:style>
+ <style:style style:name="P3" style:family="paragraph">
+ <style:paragraph-properties fo:text-align="end"/>
+ <style:text-properties fo:font-size="14pt" style:font-size-asian="14pt" style:font-size-complex="14pt"/>
+ </style:style>
+ <style:style style:name="P4" style:family="paragraph">
+ <loext:graphic-properties draw:fill="none" draw:fill-color="#ffffff"/>
+ <style:paragraph-properties fo:text-align="end"/>
+ <style:text-properties fo:font-size="14pt" style:font-size-asian="14pt" style:font-size-complex="14pt"/>
+ </style:style>
+ <style:style style:name="P5" style:family="paragraph">
+ <loext:graphic-properties draw:fill="none"/>
+ <style:paragraph-properties fo:text-align="center"/>
+ </style:style>
+ <style:style style:name="P6" style:family="paragraph">
+ <loext:graphic-properties draw:fill="none"/>
+ <style:paragraph-properties fo:text-align="start"/>
+ <style:text-properties fo:font-size="18pt"/>
+ </style:style>
+ <style:style style:name="P7" style:family="paragraph">
+ <style:paragraph-properties fo:text-align="center"/>
+ </style:style>
+ <style:style style:name="P8" style:family="paragraph">
+ <loext:graphic-properties draw:fill="none" draw:fill-color="#ffffff"/>
+ </style:style>
+ <style:style style:name="P9" style:family="paragraph">
+ <loext:graphic-properties draw:fill-color="#ffffff"/>
+ </style:style>
+ <style:style style:name="T1" style:family="text">
+ <style:text-properties fo:font-size="14pt" style:font-size-asian="14pt" style:font-size-complex="14pt"/>
+ </style:style>
+ <style:style style:name="T2" style:family="text">
+ <style:text-properties fo:color="#ffffff" style:font-name="Arial" fo:font-size="11pt" style:font-size-asian="11pt" style:font-size-complex="11pt"/>
+ </style:style>
+ <style:style style:name="T3" style:family="text">
+ <style:text-properties style:text-position="super 58%"/>
+ </style:style>
+ <text:list-style style:name="L1">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="●">
+ <style:list-level-properties/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="●">
+ <style:list-level-properties text:space-before="5.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ <text:list-style style:name="L2">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="●">
+ <style:list-level-properties text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="●">
+ <style:list-level-properties text:space-before="5.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ <text:list-style style:name="L3">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="•">
+ <style:list-level-properties text:space-before="0.008cm" text:min-label-width="0.47cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="‒">
+ <style:list-level-properties text:space-before="0.766cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="‒">
+ <style:list-level-properties text:space-before="1.515cm" text:min-label-width="0.452cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="‒">
+ <style:list-level-properties text:space-before="2.028cm" text:min-label-width="0.47cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="‒">
+ <style:list-level-properties text:space-before="2.786cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="‒">
+ <style:list-level-properties text:space-before="3.561cm" text:min-label-width="0.505cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="‒">
+ <style:list-level-properties text:space-before="4.061cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="‒">
+ <style:list-level-properties text:space-before="9.119cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="‒">
+ <style:list-level-properties text:space-before="10.312cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="‒">
+ <style:list-level-properties text:space-before="11.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" fo:color="#000000" fo:font-size="65%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ <text:list-style style:name="L4">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="●">
+ <style:list-level-properties text:space-before="-0.005cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.766cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.51cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.285cm" text:min-label-width="0.505cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3.056cm" text:min-label-width="0.505cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3.806cm" text:min-label-width="0.473cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.576cm" text:min-label-width="0.473cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="●">
+ <style:list-level-properties text:space-before="9.127cm" text:min-label-width="0.473cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="●">
+ <style:list-level-properties text:space-before="10.312cm" text:min-label-width="0.473cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="●">
+ <style:list-level-properties text:space-before="11.405cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ <text:list-style style:name="L5">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.008cm" text:min-label-width="0.47cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.766cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.515cm" text:min-label-width="0.452cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.028cm" text:min-label-width="0.47cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.786cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3.561cm" text:min-label-width="0.505cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.061cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="●">
+ <style:list-level-properties text:space-before="9.119cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="●">
+ <style:list-level-properties text:space-before="10.312cm" text:min-label-width="0.483cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="●">
+ <style:list-level-properties text:space-before="11.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ </office:automatic-styles>
+ <office:master-styles>
+ <draw:layer-set>
+ <draw:layer draw:name="layout"/>
+ <draw:layer draw:name="background"/>
+ <draw:layer draw:name="backgroundobjects"/>
+ <draw:layer draw:name="controls"/>
+ <draw:layer draw:name="measurelines"/>
+ </draw:layer-set>
+ <style:handout-master presentation:presentation-page-layout-name="AL0T26" style:page-layout-name="PM0" draw:style-name="dp2">
+ <draw:frame draw:style-name="gr1" draw:text-style-name="P2" draw:layer="backgroundobjects" svg:width="7.133cm" svg:height="1.396cm" svg:x="1.119cm" svg:y="0cm" presentation:class="header">
+ <draw:text-box>
+ <text:p text:style-name="P1"><text:span text:style-name="T1"><presentation:header/></text:span><text:span text:style-name="T1"> </text:span><text:span text:style-name="T1"><presentation:header/></text:span><text:span text:style-name="T1"> </text:span><presentation:header/></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame draw:style-name="gr2" draw:text-style-name="P4" draw:layer="backgroundobjects" svg:width="8.63cm" svg:height="1.396cm" svg:x="12.589cm" svg:y="0cm" presentation:class="date-time">
+ <draw:text-box>
+ <text:p text:style-name="P3"><text:span text:style-name="T1"><presentation:date-time/></text:span><text:span text:style-name="T1"> </text:span><text:span text:style-name="T1"><presentation:date-time/></text:span><text:span text:style-name="T1"> </text:span><presentation:date-time/></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame draw:style-name="gr3" draw:text-style-name="P2" draw:layer="backgroundobjects" svg:width="6.32cm" svg:height="1.396cm" svg:x="1.525cm" svg:y="26.543cm" presentation:class="footer">
+ <draw:text-box>
+ <text:p text:style-name="P1"><text:span text:style-name="T1"><presentation:footer/></text:span><text:span text:style-name="T1"> </text:span><text:span text:style-name="T1"><presentation:footer/></text:span><text:span text:style-name="T1"> </text:span><presentation:footer/></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame draw:style-name="gr4" draw:text-style-name="P4" draw:layer="backgroundobjects" svg:width="7.538cm" svg:height="1.396cm" svg:x="13.135cm" svg:y="26.543cm" presentation:class="page-number">
+ <draw:text-box>
+ <text:p text:style-name="P3"><text:span text:style-name="T1"><text:page-number>&lt;number&gt;</text:page-number></text:span><text:span text:style-name="T1"> </text:span><text:span text:style-name="T1"><text:page-number>&lt;number&gt;</text:page-number></text:span><text:span text:style-name="T1"> </text:span><text:page-number>&lt;number&gt;</text:page-number></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="9.294cm" svg:height="6.97cm" svg:x="1cm" svg:y="2.435cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="9.294cm" svg:height="6.97cm" svg:x="1cm" svg:y="10.483cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="9.294cm" svg:height="6.97cm" svg:x="1cm" svg:y="18.531cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="9.294cm" svg:height="6.97cm" svg:x="11.295cm" svg:y="2.435cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="9.294cm" svg:height="6.97cm" svg:x="11.295cm" svg:y="10.483cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="9.294cm" svg:height="6.97cm" svg:x="11.295cm" svg:y="18.531cm"/>
+ </style:handout-master>
+ <style:master-page style:name="No-Logo_20_Content" style:display-name="No-Logo Content" style:page-layout-name="PM1" draw:style-name="dp1">
+ <draw:frame draw:style-name="gr5" draw:text-style-name="P5" draw:layer="backgroundobjects" svg:width="24.125cm" svg:height="0.792cm" svg:x="0.626cm" svg:y="18.269cm">
+ </draw:frame>
+ <draw:frame presentation:style-name="No-Logo_20_Content-title" draw:layer="backgroundobjects" svg:width="20.93cm" svg:height="2.743cm" svg:x="2.286cm" svg:y="0.711cm" presentation:class="title" presentation:placeholder="true">
+ <draw:text-box/>
+ </draw:frame>
+ <draw:frame presentation:style-name="No-Logo_20_Content-outline1" draw:layer="backgroundobjects" svg:width="22.859cm" svg:height="11.048cm" svg:x="1.27cm" svg:y="4.457cm" presentation:class="outline" presentation:placeholder="true">
+ <draw:text-box/>
+ </draw:frame>
+ <draw:frame presentation:style-name="No-Logo_20_Content-outline1" draw:layer="backgroundobjects" svg:width="20.93cm" svg:height="11.049cm" svg:x="2.286cm" svg:y="4.039cm" presentation:class="outline" presentation:placeholder="true">
+ <draw:text-box/>
+ </draw:frame>
+ <draw:custom-shape draw:name="Text Box 4" draw:style-name="gr6" draw:text-style-name="P6" draw:layer="backgroundobjects" svg:width="16.024cm" svg:height="0.656cm" svg:x="2.403cm" svg:y="18.318cm">
+ <text:p/>
+ <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:type="rectangle" draw:enhanced-path="M 0 0 L 21600 0 21600 21600 0 21600 0 0 Z N"/>
+ </draw:custom-shape>
+ <draw:frame draw:style-name="gr7" draw:text-style-name="P8" draw:layer="backgroundobjects" svg:width="2.39cm" svg:height="1.202cm" svg:x="0.305cm" svg:y="18.102cm">
+ <draw:text-box>
+ <text:p text:style-name="P7"><text:span text:style-name="T2"><text:page-number>&lt;number&gt;</text:page-number></text:span><text:span text:style-name="T2"> </text:span></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <presentation:notes style:page-layout-name="PM0">
+ <draw:page-thumbnail presentation:style-name="No-Logo_20_Content-title" draw:layer="backgroundobjects" svg:width="13.97cm" svg:height="10.465cm" svg:x="3.81cm" svg:y="2.134cm" presentation:class="page"/>
+ <draw:frame presentation:style-name="No-Logo_20_Content-notes" draw:layer="backgroundobjects" svg:width="17.271cm" svg:height="12.572cm" svg:x="2.159cm" svg:y="13.271cm" presentation:class="notes" presentation:placeholder="true">
+ <draw:text-box/>
+ </draw:frame>
+ <draw:frame presentation:style-name="No-Logo_20_Content-notes" draw:layer="backgroundobjects" svg:width="17.271cm" svg:height="12.572cm" svg:x="2.159cm" svg:y="13.271cm" presentation:class="notes" presentation:placeholder="true">
+ <draw:text-box/>
+ </draw:frame>
+ <draw:frame presentation:style-name="pr1" draw:text-style-name="P2" draw:layer="backgroundobjects" svg:width="9.369cm" svg:height="1.396cm" svg:x="0cm" svg:y="0cm" presentation:class="header">
+ <draw:text-box>
+ <text:p text:style-name="P1"><text:span text:style-name="T1"><presentation:header/></text:span><text:span text:style-name="T1"> </text:span><text:span text:style-name="T1"><presentation:header/></text:span><text:span text:style-name="T1"> </text:span><presentation:header/></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame presentation:style-name="pr1" draw:text-style-name="P4" draw:layer="backgroundobjects" svg:width="9.369cm" svg:height="1.396cm" svg:x="12.22cm" svg:y="0cm" presentation:class="date-time">
+ <draw:text-box>
+ <text:p text:style-name="P3"><text:span text:style-name="T1"><presentation:date-time/></text:span><text:span text:style-name="T1"> </text:span><text:span text:style-name="T1"><presentation:date-time/></text:span><text:span text:style-name="T1"> </text:span><presentation:date-time/></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame presentation:style-name="pr2" draw:text-style-name="P2" draw:layer="backgroundobjects" svg:width="9.369cm" svg:height="1.396cm" svg:x="0cm" svg:y="26.543cm" presentation:class="footer">
+ <draw:text-box>
+ <text:p text:style-name="P1"><text:span text:style-name="T1"><presentation:footer/></text:span><text:span text:style-name="T1"> </text:span><text:span text:style-name="T1"><presentation:footer/></text:span><text:span text:style-name="T1"> </text:span><presentation:footer/></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame presentation:style-name="pr2" draw:text-style-name="P4" draw:layer="backgroundobjects" svg:width="9.369cm" svg:height="1.396cm" svg:x="12.22cm" svg:y="26.543cm" presentation:class="page-number">
+ <draw:text-box>
+ <text:p text:style-name="P3"><text:span text:style-name="T1"><text:page-number>&lt;number&gt;</text:page-number></text:span><text:span text:style-name="T1"> </text:span><text:span text:style-name="T1"><text:page-number>&lt;number&gt;</text:page-number></text:span><text:span text:style-name="T1"> </text:span><text:page-number>&lt;number&gt;</text:page-number></text:p>
+ </draw:text-box>
+ </draw:frame>
+ </presentation:notes>
+ </style:master-page>
+ </office:master-styles>
+ <office:body>
+ <office:presentation>
+ <draw:page draw:name="page1" draw:style-name="dp3" draw:master-page-name="No-Logo_20_Content" presentation:presentation-page-layout-name="AL1T1">
+ <office:forms form:automatic-focus="false" form:apply-design-mode="false"/>
+ <draw:frame presentation:style-name="pr3" draw:layer="layout" svg:width="20.93cm" svg:height="2.743cm" svg:x="2.286cm" svg:y="0.711cm" presentation:class="title" presentation:user-transformed="true">
+ <draw:text-box>
+ <text:p>How to reproduce</text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame presentation:style-name="pr4" draw:layer="layout" svg:width="20.93cm" svg:height="13.487cm" svg:x="2.286cm" svg:y="4.039cm" presentation:class="outline" presentation:user-transformed="true">
+ <draw:text-box>
+ <text:list text:style-name="L3">
+ <text:list-item>
+ <text:p>This is the 1<text:span text:style-name="T3">st</text:span> level</text:p>
+ </text:list-item>
+ </text:list>
+ <text:list text:style-name="L4">
+ <text:list-item>
+ <text:list>
+ <text:list-item>
+ <text:p>These are the 4 bullet points we are focussing on</text:p>
+ </text:list-item>
+ </text:list>
+ </text:list-item>
+ </text:list>
+ <text:list text:style-name="L5">
+ <text:list-item>
+ <text:list>
+ <text:list-item>
+ <text:p>They have all the same formatting</text:p>
+ </text:list-item>
+ </text:list>
+ </text:list-item>
+ </text:list>
+ <text:list text:style-name="L4">
+ <text:list-item>
+ <text:list>
+ <text:list-item>
+ <text:p>Simply cut (CTRL+X) and paste (CTRL+V) a line</text:p>
+ </text:list-item>
+ <text:list-item>
+ <text:p>And see what happens. But bullet point changes format</text:p>
+ </text:list-item>
+ </text:list>
+ </text:list-item>
+ </text:list>
+ </draw:text-box>
+ </draw:frame>
+ <presentation:notes draw:style-name="dp2">
+ <draw:page-thumbnail draw:style-name="gr8" draw:layer="layout" svg:width="13.97cm" svg:height="10.465cm" svg:x="3.81cm" svg:y="2.134cm" draw:page-number="1" presentation:class="page"/>
+ <draw:frame presentation:style-name="pr5" draw:text-style-name="P9" draw:layer="layout" svg:width="17.271cm" svg:height="12.572cm" svg:x="2.159cm" svg:y="13.271cm" presentation:class="notes" presentation:placeholder="true" presentation:user-transformed="true">
+ <draw:text-box/>
+ </draw:frame>
+ </presentation:notes>
+ </draw:page>
+ <presentation:settings presentation:mouse-visible="false"/>
+ </office:presentation>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sd/qa/unit/tiledrendering/data/tdf104405.fodp b/sd/qa/unit/tiledrendering/data/tdf104405.fodp
new file mode 100644
index 0000000000..d902f177d5
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/tdf104405.fodp
@@ -0,0 +1,822 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.presentation">
+ <office:meta><meta:creation-date>2016-11-16T15:27:08.222708354</meta:creation-date><dc:date>2016-11-16T15:30:23.342583235</dc:date><meta:editing-duration>PT3M18S</meta:editing-duration><meta:editing-cycles>1</meta:editing-cycles><meta:document-statistic meta:object-count="26"/><meta:generator>LibreOfficeDev/5.3.0.0.alpha1$Linux_X86_64 LibreOffice_project/f0c20dc458d8fe9e86b323c8c24df2f3d31610ad</meta:generator></office:meta>
+ <office:settings>
+ <config:config-item-set config:name="ooo:view-settings">
+ <config:config-item config:name="VisibleAreaTop" config:type="int">0</config:config-item>
+ <config:config-item config:name="VisibleAreaLeft" config:type="int">0</config:config-item>
+ <config:config-item config:name="VisibleAreaWidth" config:type="int">14099</config:config-item>
+ <config:config-item config:name="VisibleAreaHeight" config:type="int">9999</config:config-item>
+ <config:config-item-map-indexed config:name="Views">
+ <config:config-item-map-entry>
+ <config:config-item config:name="ViewId" config:type="string">view1</config:config-item>
+ <config:config-item config:name="GridIsVisible" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="GridIsFront" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsSnapToGrid" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsSnapToPageMargins" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsSnapToSnapLines" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsSnapToObjectFrame" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsSnapToObjectPoints" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPlusHandlesAlwaysVisible" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsFrameDragSingles" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="EliminatePolyPointLimitAngle" config:type="int">1500</config:config-item>
+ <config:config-item config:name="IsEliminatePolyPoints" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="VisibleLayers" config:type="base64Binary">//////////////////////////////////////////8=</config:config-item>
+ <config:config-item config:name="PrintableLayers" config:type="base64Binary">//////////////////////////////////////////8=</config:config-item>
+ <config:config-item config:name="LockedLayers" config:type="base64Binary"/>
+ <config:config-item config:name="NoAttribs" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="NoColors" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="RulerIsVisible" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="PageKind" config:type="short">0</config:config-item>
+ <config:config-item config:name="SelectedPage" config:type="short">0</config:config-item>
+ <config:config-item config:name="IsLayerMode" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsDoubleClickTextEdit" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsClickChangeRotation" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="SlidesPerRow" config:type="short">4</config:config-item>
+ <config:config-item config:name="EditMode" config:type="int">0</config:config-item>
+ <config:config-item config:name="VisibleAreaTop" config:type="int">-310</config:config-item>
+ <config:config-item config:name="VisibleAreaLeft" config:type="int">-2139</config:config-item>
+ <config:config-item config:name="VisibleAreaWidth" config:type="int">32314</config:config-item>
+ <config:config-item config:name="VisibleAreaHeight" config:type="int">21646</config:config-item>
+ <config:config-item config:name="GridCoarseWidth" config:type="int">2000</config:config-item>
+ <config:config-item config:name="GridCoarseHeight" config:type="int">2000</config:config-item>
+ <config:config-item config:name="GridFineWidth" config:type="int">200</config:config-item>
+ <config:config-item config:name="GridFineHeight" config:type="int">200</config:config-item>
+ <config:config-item config:name="GridSnapWidthXNumerator" config:type="int">200</config:config-item>
+ <config:config-item config:name="GridSnapWidthXDenominator" config:type="int">1</config:config-item>
+ <config:config-item config:name="GridSnapWidthYNumerator" config:type="int">200</config:config-item>
+ <config:config-item config:name="GridSnapWidthYDenominator" config:type="int">1</config:config-item>
+ <config:config-item config:name="IsAngleSnapEnabled" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="SnapAngle" config:type="int">1500</config:config-item>
+ <config:config-item config:name="ZoomOnPage" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">false</config:config-item>
+ </config:config-item-map-entry>
+ </config:config-item-map-indexed>
+ </config:config-item-set>
+ <config:config-item-set config:name="ooo:configuration-settings">
+ <config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="BitmapTableURL" config:type="string">$(inst)/share/palette%3B$(user)/config/standard.sob</config:config-item>
+ <config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item>
+ <config:config-item config:name="ColorTableURL" config:type="string">$(inst)/share/palette%3B$(user)/config/standard.soc</config:config-item>
+ <config:config-item config:name="DashTableURL" config:type="string">$(inst)/share/palette%3B$(user)/config/standard.sod</config:config-item>
+ <config:config-item config:name="DefaultTabStop" config:type="int">1250</config:config-item>
+ <config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item>
+ <config:config-item-map-indexed config:name="ForbiddenCharacters">
+ <config:config-item-map-entry>
+ <config:config-item config:name="Language" config:type="string">en</config:config-item>
+ <config:config-item config:name="Country" config:type="string">ZA</config:config-item>
+ <config:config-item config:name="Variant" config:type="string"/>
+ <config:config-item config:name="BeginLine" config:type="string"/>
+ <config:config-item config:name="EndLine" config:type="string"/>
+ </config:config-item-map-entry>
+ </config:config-item-map-indexed>
+ <config:config-item config:name="GradientTableURL" config:type="string">$(inst)/share/palette%3B$(user)/config/standard.sog</config:config-item>
+ <config:config-item config:name="HandoutsHorizontal" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="HatchTableURL" config:type="string">$(inst)/share/palette%3B$(user)/config/standard.soh</config:config-item>
+ <config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPrintBooklet" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPrintBookletBack" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsPrintBookletFront" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsPrintDate" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPrintDrawing" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsPrintFitPage" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPrintHandout" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPrintHiddenPages" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsPrintNotes" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPrintOutline" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPrintPageName" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPrintTilePage" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPrintTime" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="LineEndTableURL" config:type="string">$(inst)/share/palette%3B$(user)/config/standard.soe</config:config-item>
+ <config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="PageNumberFormat" config:type="int">4</config:config-item>
+ <config:config-item config:name="ParagraphSummation" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="PrintQuality" config:type="int">0</config:config-item>
+ <config:config-item config:name="PrinterIndependentLayout" config:type="string">low-resolution</config:config-item>
+ <config:config-item config:name="PrinterName" config:type="string"/>
+ <config:config-item config:name="PrinterSetup" config:type="base64Binary"/>
+ <config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="SlidesPerHandout" config:type="short">6</config:config-item>
+ <config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item>
+ </config:config-item-set>
+ </office:settings>
+ <office:scripts>
+ <office:script script:language="ooo:Basic">
+ <ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"/>
+ </office:script>
+ </office:scripts>
+ <office:font-face-decls>
+ <style:font-face style:name="Liberation Sans" svg:font-family="&apos;Liberation Sans&apos;" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Liberation Serif" svg:font-family="&apos;Liberation Serif&apos;" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="DejaVu Sans" svg:font-family="&apos;DejaVu Sans&apos;" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="FreeSans" svg:font-family="FreeSans" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="Noto Sans CJK SC Regular" svg:font-family="&apos;Noto Sans CJK SC Regular&apos;" style:font-family-generic="system" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+ <draw:marker draw:name="Arrow" svg:viewBox="0 0 20 30" svg:d="M10 0l-10 30h20z"/>
+ <style:default-style style:family="graphic">
+ <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap"/>
+ <style:paragraph-properties style:text-autospace="ideograph-alpha" style:punctuation-wrap="simple" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false">
+ <style:tab-stops/>
+ </style:paragraph-properties>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="24pt" fo:language="en" fo:country="ZA" style:font-name-asian="DejaVu Sans" style:font-size-asian="24pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="DejaVu Sans" style:font-size-complex="24pt" style:language-complex="hi" style:country-complex="IN"/>
+ </style:default-style>
+ <style:style style:name="standard" style:family="graphic">
+ <style:graphic-properties draw:stroke="solid" svg:stroke-width="0cm" svg:stroke-color="#3465a4" draw:marker-start-width="0.2cm" draw:marker-start-center="false" draw:marker-end-width="0.2cm" draw:marker-end-center="false" draw:fill="solid" draw:fill-color="#729fcf" draw:textarea-horizontal-align="justify" fo:padding-top="0.125cm" fo:padding-bottom="0.125cm" fo:padding-left="0.25cm" fo:padding-right="0.25cm" draw:shadow="hidden" draw:shadow-offset-x="0.2cm" draw:shadow-offset-y="0.2cm" draw:shadow-color="#808080">
+ <text:list-style style:name="standard">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="●">
+ <style:list-level-properties text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="●">
+ <style:list-level-properties text:space-before="5.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ </style:graphic-properties>
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" fo:line-height="100%" fo:text-indent="0cm"/>
+ <style:text-properties fo:font-variant="normal" fo:text-transform="none" style:use-window-font-color="true" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Liberation Sans" fo:font-family="&apos;Liberation Sans&apos;" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="18pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" style:letter-kerning="true" style:font-name-asian="Noto Sans CJK SC Regular" style:font-family-asian="&apos;Noto Sans CJK SC Regular&apos;" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="18pt" style:font-style-asian="normal" style:font-weight-asian="normal" style:font-name-complex="FreeSans" style:font-family-complex="FreeSans" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="18pt" style:font-style-complex="normal" style:font-weight-complex="normal" style:text-emphasize="none" style:font-relief="none" style:text-overline-style="none" style:text-overline-color="font-color"/>
+ </style:style>
+ <style:style style:name="objectwitharrow" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="solid" svg:stroke-width="0.15cm" svg:stroke-color="#000000" draw:marker-start="Arrow" draw:marker-start-width="0.7cm" draw:marker-start-center="true" draw:marker-end-width="0.3cm"/>
+ </style:style>
+ <style:style style:name="objectwithshadow" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:shadow="visible" draw:shadow-offset-x="0.2cm" draw:shadow-offset-y="0.2cm" draw:shadow-color="#808080"/>
+ </style:style>
+ <style:style style:name="objectwithoutfill" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties svg:stroke-color="#000000" draw:fill="none"/>
+ </style:style>
+ <style:style style:name="Object_20_with_20_no_20_fill_20_and_20_no_20_line" style:display-name="Object with no fill and no line" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ </style:style>
+ <style:style style:name="text" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ </style:style>
+ <style:style style:name="textbody" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:text-properties fo:font-size="16pt"/>
+ </style:style>
+ <style:style style:name="textbodyjustfied" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:paragraph-properties fo:text-align="justify"/>
+ </style:style>
+ <style:style style:name="textbodyindent" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0.6cm"/>
+ </style:style>
+ <style:style style:name="title" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:text-properties fo:font-size="44pt"/>
+ </style:style>
+ <style:style style:name="title1" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="solid" draw:fill-color="#008080" draw:shadow="visible" draw:shadow-offset-x="0.2cm" draw:shadow-offset-y="0.2cm" draw:shadow-color="#808080"/>
+ <style:paragraph-properties fo:text-align="center"/>
+ <style:text-properties fo:font-size="24pt"/>
+ </style:style>
+ <style:style style:name="title2" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties svg:stroke-width="0.05cm" draw:fill-color="#ffcc99" draw:shadow="visible" draw:shadow-offset-x="0.2cm" draw:shadow-offset-y="0.2cm" draw:shadow-color="#808080"/>
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0.2cm" fo:margin-top="0.1cm" fo:margin-bottom="0.1cm" fo:text-align="center" fo:text-indent="0cm"/>
+ <style:text-properties fo:font-size="36pt"/>
+ </style:style>
+ <style:style style:name="headline" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:paragraph-properties fo:margin-top="0.42cm" fo:margin-bottom="0.21cm"/>
+ <style:text-properties fo:font-size="24pt"/>
+ </style:style>
+ <style:style style:name="headline1" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:paragraph-properties fo:margin-top="0.42cm" fo:margin-bottom="0.21cm"/>
+ <style:text-properties fo:font-size="18pt" fo:font-weight="bold"/>
+ </style:style>
+ <style:style style:name="headline2" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:paragraph-properties fo:margin-top="0.42cm" fo:margin-bottom="0.21cm"/>
+ <style:text-properties fo:font-size="14pt" fo:font-style="italic" fo:font-weight="bold"/>
+ </style:style>
+ <style:style style:name="measure" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="solid" svg:stroke-color="#000000" draw:marker-start="Arrow" draw:marker-start-width="0.2cm" draw:marker-end="Arrow" draw:marker-end-width="0.2cm" draw:fill="none" draw:show-unit="true"/>
+ <style:text-properties fo:font-size="12pt"/>
+ </style:style>
+ <style:style style:name="default" style:family="table-cell">
+ <loext:graphic-properties draw:fill="solid" draw:fill-color="#ccccff" draw:textarea-horizontal-align="left" draw:textarea-vertical-align="top" fo:padding-top="0.13cm" fo:padding-bottom="0.13cm" fo:padding-left="0.25cm" fo:padding-right="0.25cm"/>
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" fo:line-height="100%" fo:text-indent="0cm" fo:border="0.03pt solid #ffffff"/>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Sans" fo:font-family="&apos;Liberation Sans&apos;" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="18pt" style:letter-kerning="true" style:font-name-asian="Noto Sans CJK SC Regular" style:font-family-asian="&apos;Noto Sans CJK SC Regular&apos;" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="18pt" style:font-name-complex="FreeSans" style:font-family-complex="FreeSans" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="18pt"/>
+ </style:style>
+ <style:style style:name="gray1" style:family="table-cell" style:parent-style-name="default">
+ <loext:graphic-properties draw:fill="solid" draw:fill-color="#e6e6e6"/>
+ </style:style>
+ <style:style style:name="gray2" style:family="table-cell" style:parent-style-name="default">
+ <loext:graphic-properties draw:fill="solid" draw:fill-color="#cccccc"/>
+ </style:style>
+ <style:style style:name="gray3" style:family="table-cell" style:parent-style-name="default">
+ <loext:graphic-properties draw:fill="solid" draw:fill-color="#b3b3b3"/>
+ </style:style>
+ <table:table-template text:style-name="default">
+ <table:first-row table:style-name="gray3"/>
+ <table:last-row table:style-name="gray3"/>
+ <table:first-column table:style-name="gray3"/>
+ <table:last-column table:style-name="gray3"/>
+ <table:body table:style-name="gray1"/>
+ <table:odd-rows table:style-name="gray2"/>
+ <table:odd-columns table:style-name="gray2"/>
+ </table:table-template>
+ <style:style style:name="Default-background" style:family="presentation">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:text-properties style:letter-kerning="true"/>
+ </style:style>
+ <style:style style:name="Default-backgroundobjects" style:family="presentation">
+ <style:graphic-properties draw:textarea-horizontal-align="justify" draw:shadow="hidden" draw:shadow-offset-x="0.2cm" draw:shadow-offset-y="0.2cm" draw:shadow-color="#808080"/>
+ <style:text-properties style:letter-kerning="true"/>
+ </style:style>
+ <style:style style:name="Default-notes" style:family="presentation">
+ <style:graphic-properties draw:stroke="none" draw:fill="none"/>
+ <style:paragraph-properties fo:margin-left="0.6cm" fo:margin-right="0cm" fo:text-indent="-0.6cm"/>
+ <style:text-properties fo:font-variant="normal" fo:text-transform="none" style:use-window-font-color="true" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Liberation Sans" fo:font-family="&apos;Liberation Sans&apos;" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="20pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" style:letter-kerning="true" fo:background-color="transparent" style:font-name-asian="Noto Sans CJK SC Regular" style:font-family-asian="&apos;Noto Sans CJK SC Regular&apos;" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="20pt" style:font-style-asian="normal" style:font-weight-asian="normal" style:font-name-complex="FreeSans" style:font-family-complex="FreeSans" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="20pt" style:font-style-complex="normal" style:font-weight-complex="normal" style:text-emphasize="none" style:font-relief="none" style:text-overline-style="none" style:text-overline-color="font-color"/>
+ </style:style>
+ <style:style style:name="Default-outline1" style:family="presentation">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:auto-grow-height="false" draw:fit-to-size="shrink-to-fit">
+ <text:list-style style:name="Default-outline1">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.3cm" text:min-label-width="0.9cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="–">
+ <style:list-level-properties text:space-before="1.5cm" text:min-label-width="0.9cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="75%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.8cm" text:min-label-width="0.8cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="–">
+ <style:list-level-properties text:space-before="4.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="75%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="●">
+ <style:list-level-properties text:space-before="5.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="●">
+ <style:list-level-properties text:space-before="6.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="●">
+ <style:list-level-properties text:space-before="7.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="●">
+ <style:list-level-properties text:space-before="9cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="●">
+ <style:list-level-properties text:space-before="10.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="●">
+ <style:list-level-properties text:space-before="11.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ </style:graphic-properties>
+ <style:paragraph-properties fo:margin-top="0.5cm" fo:margin-bottom="0cm"/>
+ <style:text-properties fo:font-variant="normal" fo:text-transform="none" style:use-window-font-color="true" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Liberation Sans" fo:font-family="&apos;Liberation Sans&apos;" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="32pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" style:letter-kerning="true" fo:background-color="transparent" style:font-name-asian="Noto Sans CJK SC Regular" style:font-family-asian="&apos;Noto Sans CJK SC Regular&apos;" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="32pt" style:font-style-asian="normal" style:font-weight-asian="normal" style:font-name-complex="FreeSans" style:font-family-complex="FreeSans" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="32pt" style:font-style-complex="normal" style:font-weight-complex="normal" style:text-emphasize="none" style:font-relief="none" style:text-overline-style="none" style:text-overline-color="font-color"/>
+ </style:style>
+ <style:style style:name="Default-outline2" style:family="presentation" style:parent-style-name="Default-outline1">
+ <style:paragraph-properties fo:margin-top="0.4cm" fo:margin-bottom="0cm"/>
+ <style:text-properties fo:font-size="28pt" style:font-size-asian="28pt" style:font-size-complex="28pt"/>
+ </style:style>
+ <style:style style:name="Default-outline3" style:family="presentation" style:parent-style-name="Default-outline2">
+ <style:paragraph-properties fo:margin-top="0.3cm" fo:margin-bottom="0cm"/>
+ <style:text-properties fo:font-size="24pt" style:font-size-asian="24pt" style:font-size-complex="24pt"/>
+ </style:style>
+ <style:style style:name="Default-outline4" style:family="presentation" style:parent-style-name="Default-outline3">
+ <style:paragraph-properties fo:margin-top="0.2cm" fo:margin-bottom="0cm"/>
+ <style:text-properties fo:font-size="20pt" style:font-size-asian="20pt" style:font-size-complex="20pt"/>
+ </style:style>
+ <style:style style:name="Default-outline5" style:family="presentation" style:parent-style-name="Default-outline4">
+ <style:paragraph-properties fo:margin-top="0.1cm" fo:margin-bottom="0cm"/>
+ <style:text-properties fo:font-size="20pt" style:font-size-asian="20pt" style:font-size-complex="20pt"/>
+ </style:style>
+ <style:style style:name="Default-outline6" style:family="presentation" style:parent-style-name="Default-outline5">
+ <style:paragraph-properties fo:margin-top="0.1cm" fo:margin-bottom="0cm"/>
+ <style:text-properties fo:font-size="20pt" style:font-size-asian="20pt" style:font-size-complex="20pt"/>
+ </style:style>
+ <style:style style:name="Default-outline7" style:family="presentation" style:parent-style-name="Default-outline6">
+ <style:paragraph-properties fo:margin-top="0.1cm" fo:margin-bottom="0cm"/>
+ <style:text-properties fo:font-size="20pt" style:font-size-asian="20pt" style:font-size-complex="20pt"/>
+ </style:style>
+ <style:style style:name="Default-outline8" style:family="presentation" style:parent-style-name="Default-outline7">
+ <style:paragraph-properties fo:margin-top="0.1cm" fo:margin-bottom="0cm"/>
+ <style:text-properties fo:font-size="20pt" style:font-size-asian="20pt" style:font-size-complex="20pt"/>
+ </style:style>
+ <style:style style:name="Default-outline9" style:family="presentation" style:parent-style-name="Default-outline8">
+ <style:paragraph-properties fo:margin-top="0.1cm" fo:margin-bottom="0cm"/>
+ <style:text-properties fo:font-size="20pt" style:font-size-asian="20pt" style:font-size-complex="20pt"/>
+ </style:style>
+ <style:style style:name="Default-subtitle" style:family="presentation">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:textarea-vertical-align="middle">
+ <text:list-style style:name="Default-subtitle">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="●">
+ <style:list-level-properties text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="●">
+ <style:list-level-properties text:space-before="5.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ </style:graphic-properties>
+ <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-align="center" fo:text-indent="0cm"/>
+ <style:text-properties fo:font-variant="normal" fo:text-transform="none" style:use-window-font-color="true" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Liberation Sans" fo:font-family="&apos;Liberation Sans&apos;" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="32pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" style:letter-kerning="true" fo:background-color="transparent" style:font-name-asian="Noto Sans CJK SC Regular" style:font-family-asian="&apos;Noto Sans CJK SC Regular&apos;" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="32pt" style:font-style-asian="normal" style:font-weight-asian="normal" style:font-name-complex="FreeSans" style:font-family-complex="FreeSans" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="32pt" style:font-style-complex="normal" style:font-weight-complex="normal" style:text-emphasize="none" style:font-relief="none" style:text-overline-style="none" style:text-overline-color="font-color"/>
+ </style:style>
+ <style:style style:name="Default-title" style:family="presentation">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:textarea-vertical-align="middle">
+ <text:list-style style:name="Default-title">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="●">
+ <style:list-level-properties text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="●">
+ <style:list-level-properties text:space-before="5.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ </style:graphic-properties>
+ <style:paragraph-properties fo:text-align="center"/>
+ <style:text-properties fo:font-variant="normal" fo:text-transform="none" style:use-window-font-color="true" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Liberation Sans" fo:font-family="&apos;Liberation Sans&apos;" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="44pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" style:letter-kerning="true" fo:background-color="transparent" style:font-name-asian="Noto Sans CJK SC Regular" style:font-family-asian="&apos;Noto Sans CJK SC Regular&apos;" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="44pt" style:font-style-asian="normal" style:font-weight-asian="normal" style:font-name-complex="FreeSans" style:font-family-complex="FreeSans" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="44pt" style:font-style-complex="normal" style:font-weight-complex="normal" style:text-emphasize="none" style:font-relief="none" style:text-overline-style="none" style:text-overline-color="font-color"/>
+ </style:style>
+ <style:presentation-page-layout style:name="AL0T26">
+ <presentation:placeholder presentation:object="handout" svg:x="2.058cm" svg:y="1.743cm" svg:width="10.556cm" svg:height="-0.233cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="15.414cm" svg:y="1.743cm" svg:width="10.556cm" svg:height="-0.233cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="2.058cm" svg:y="3.612cm" svg:width="10.556cm" svg:height="-0.233cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="15.414cm" svg:y="3.612cm" svg:width="10.556cm" svg:height="-0.233cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="2.058cm" svg:y="5.481cm" svg:width="10.556cm" svg:height="-0.233cm"/>
+ <presentation:placeholder presentation:object="handout" svg:x="15.414cm" svg:y="5.481cm" svg:width="10.556cm" svg:height="-0.233cm"/>
+ </style:presentation-page-layout>
+ <style:presentation-page-layout style:name="AL1T0">
+ <presentation:placeholder presentation:object="title" svg:x="2.058cm" svg:y="1.743cm" svg:width="23.912cm" svg:height="3.507cm"/>
+ <presentation:placeholder presentation:object="subtitle" svg:x="2.058cm" svg:y="5.838cm" svg:width="23.912cm" svg:height="13.23cm"/>
+ </style:presentation-page-layout>
+ </office:styles>
+ <office:automatic-styles>
+ <style:page-layout style:name="PM0">
+ <style:page-layout-properties fo:margin-top="0cm" fo:margin-bottom="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:page-width="21cm" fo:page-height="29.7cm" style:print-orientation="portrait"/>
+ </style:page-layout>
+ <style:page-layout style:name="PM1">
+ <style:page-layout-properties fo:margin-top="0cm" fo:margin-bottom="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:page-width="28cm" fo:page-height="21cm" style:print-orientation="landscape"/>
+ </style:page-layout>
+ <style:style style:name="dp1" style:family="drawing-page">
+ <style:drawing-page-properties draw:background-size="border" draw:fill="none"/>
+ </style:style>
+ <style:style style:name="dp2" style:family="drawing-page">
+ <style:drawing-page-properties presentation:display-header="true" presentation:display-footer="true" presentation:display-page-number="false" presentation:display-date-time="true"/>
+ </style:style>
+ <style:style style:name="dp3" style:family="drawing-page">
+ <style:drawing-page-properties presentation:background-visible="true" presentation:background-objects-visible="true" presentation:display-footer="true" presentation:display-page-number="false" presentation:display-date-time="true"/>
+ </style:style>
+ <style:style style:name="gr1" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:auto-grow-height="false" fo:min-height="1.485cm"/>
+ </style:style>
+ <style:style style:name="gr2" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:textarea-vertical-align="bottom" draw:auto-grow-height="false" fo:min-height="1.485cm"/>
+ </style:style>
+ <style:style style:name="gr3" style:family="graphic">
+ <style:graphic-properties style:protect="size"/>
+ </style:style>
+ <style:style style:name="pr1" style:family="presentation" style:parent-style-name="Default-backgroundobjects">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:auto-grow-height="false" fo:min-height="1.449cm"/>
+ </style:style>
+ <style:style style:name="pr2" style:family="presentation" style:parent-style-name="Default-backgroundobjects">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:auto-grow-height="false" fo:min-height="1.485cm"/>
+ </style:style>
+ <style:style style:name="pr3" style:family="presentation" style:parent-style-name="Default-backgroundobjects">
+ <style:graphic-properties draw:stroke="none" draw:fill="none" draw:fill-color="#ffffff" draw:textarea-vertical-align="bottom" draw:auto-grow-height="false" fo:min-height="1.485cm"/>
+ </style:style>
+ <style:style style:name="pr4" style:family="presentation" style:parent-style-name="Default-title">
+ <style:graphic-properties fo:min-height="3.506cm"/>
+ </style:style>
+ <style:style style:name="pr5" style:family="presentation" style:parent-style-name="Default-subtitle">
+ <style:graphic-properties draw:fill-color="#ffffff" fo:min-height="12.179cm"/>
+ </style:style>
+ <style:style style:name="pr6" style:family="presentation" style:parent-style-name="Default-notes">
+ <style:graphic-properties draw:fill-color="#ffffff" fo:min-height="13.364cm"/>
+ </style:style>
+ <style:style style:name="co1" style:family="table-column">
+ <style:table-column-properties style:column-width="4.758cm" style:use-optimal-column-width="false"/>
+ </style:style>
+ <style:style style:name="co2" style:family="table-column">
+ <style:table-column-properties style:column-width="4.767cm" style:use-optimal-column-width="false"/>
+ </style:style>
+ <style:style style:name="ro1" style:family="table-row">
+ <style:table-row-properties style:row-height="2.848cm"/>
+ </style:style>
+ <style:style style:name="ro2" style:family="table-row">
+ <style:table-row-properties style:row-height="2.855cm"/>
+ </style:style>
+ <style:style style:name="ce1" style:family="table-cell">
+ <style:paragraph-properties fo:text-align="center"/>
+ </style:style>
+ <style:style style:name="ce2" style:family="table-cell">
+ <loext:graphic-properties draw:textarea-vertical-align="bottom"/>
+ <style:paragraph-properties fo:text-align="center"/>
+ </style:style>
+ <style:style style:name="P1" style:family="paragraph">
+ <style:text-properties fo:font-size="14pt" style:font-size-asian="14pt" style:font-size-complex="14pt"/>
+ </style:style>
+ <style:style style:name="P2" style:family="paragraph">
+ <loext:graphic-properties draw:fill="none" draw:fill-color="#ffffff"/>
+ <style:text-properties fo:font-size="14pt" style:font-size-asian="14pt" style:font-size-complex="14pt"/>
+ </style:style>
+ <style:style style:name="P3" style:family="paragraph">
+ <style:paragraph-properties fo:text-align="end"/>
+ <style:text-properties fo:font-size="14pt" style:font-size-asian="14pt" style:font-size-complex="14pt"/>
+ </style:style>
+ <style:style style:name="P4" style:family="paragraph">
+ <loext:graphic-properties draw:fill="none" draw:fill-color="#ffffff"/>
+ <style:paragraph-properties fo:text-align="end"/>
+ <style:text-properties fo:font-size="14pt" style:font-size-asian="14pt" style:font-size-complex="14pt"/>
+ </style:style>
+ <style:style style:name="P5" style:family="paragraph">
+ <style:paragraph-properties fo:text-align="center"/>
+ <style:text-properties fo:font-size="14pt" style:font-size-asian="14pt" style:font-size-complex="14pt"/>
+ </style:style>
+ <style:style style:name="P6" style:family="paragraph">
+ <loext:graphic-properties draw:fill="none" draw:fill-color="#ffffff"/>
+ <style:paragraph-properties fo:text-align="center"/>
+ <style:text-properties fo:font-size="14pt" style:font-size-asian="14pt" style:font-size-complex="14pt"/>
+ </style:style>
+ <style:style style:name="P7" style:family="paragraph">
+ <loext:graphic-properties draw:fill-color="#ffffff"/>
+ </style:style>
+ <style:style style:name="P8" style:family="paragraph">
+ <style:paragraph-properties fo:text-align="center"/>
+ </style:style>
+ <text:list-style style:name="L1">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="●">
+ <style:list-level-properties text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="●">
+ <style:list-level-properties text:space-before="5.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ <text:list-style style:name="L2">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="●">
+ <style:list-level-properties text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:bullet-char="●">
+ <style:list-level-properties text:space-before="0.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:bullet-char="●">
+ <style:list-level-properties text:space-before="1.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:bullet-char="●">
+ <style:list-level-properties text:space-before="2.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:bullet-char="●">
+ <style:list-level-properties text:space-before="3.6cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.2cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:bullet-char="●">
+ <style:list-level-properties text:space-before="4.8cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:bullet-char="●">
+ <style:list-level-properties text:space-before="5.4cm" text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="StarSymbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ </office:automatic-styles>
+ <office:master-styles>
+ <draw:layer-set>
+ <draw:layer draw:name="layout"/>
+ <draw:layer draw:name="background"/>
+ <draw:layer draw:name="backgroundobjects"/>
+ <draw:layer draw:name="controls"/>
+ <draw:layer draw:name="measurelines"/>
+ </draw:layer-set>
+ <style:handout-master presentation:presentation-page-layout-name="AL0T26" style:page-layout-name="PM0" draw:style-name="dp2">
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="8.999cm" svg:height="6.749cm" svg:x="1cm" svg:y="2.898cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="8.999cm" svg:height="6.749cm" svg:x="1cm" svg:y="11.474cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="8.999cm" svg:height="6.749cm" svg:x="1cm" svg:y="20.05cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="8.999cm" svg:height="6.749cm" svg:x="11cm" svg:y="2.898cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="8.999cm" svg:height="6.749cm" svg:x="11cm" svg:y="11.474cm"/>
+ <draw:page-thumbnail draw:layer="backgroundobjects" svg:width="8.999cm" svg:height="6.749cm" svg:x="11cm" svg:y="20.05cm"/>
+ <draw:frame draw:style-name="gr1" draw:text-style-name="P2" draw:layer="backgroundobjects" svg:width="9.113cm" svg:height="1.484cm" svg:x="0cm" svg:y="0cm" presentation:class="header">
+ <draw:text-box>
+ <text:p text:style-name="P1"><presentation:header/></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame draw:style-name="gr1" draw:text-style-name="P4" draw:layer="backgroundobjects" svg:width="9.113cm" svg:height="1.484cm" svg:x="11.886cm" svg:y="0cm" presentation:class="date-time">
+ <draw:text-box>
+ <text:p text:style-name="P3"><presentation:date-time/></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame draw:style-name="gr2" draw:text-style-name="P2" draw:layer="backgroundobjects" svg:width="9.113cm" svg:height="1.484cm" svg:x="0cm" svg:y="28.215cm" presentation:class="footer">
+ <draw:text-box>
+ <text:p text:style-name="P1"><presentation:footer/></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame draw:style-name="gr2" draw:text-style-name="P4" draw:layer="backgroundobjects" svg:width="9.113cm" svg:height="1.484cm" svg:x="11.886cm" svg:y="28.215cm" presentation:class="page-number">
+ <draw:text-box>
+ <text:p text:style-name="P3"><text:page-number>&lt;number&gt;</text:page-number></text:p>
+ </draw:text-box>
+ </draw:frame>
+ </style:handout-master>
+ <style:master-page style:name="Default" style:page-layout-name="PM1" draw:style-name="dp1">
+ <draw:frame presentation:style-name="Default-title" draw:layer="backgroundobjects" svg:width="25.199cm" svg:height="3.506cm" svg:x="1.4cm" svg:y="0.837cm" presentation:class="title" presentation:placeholder="true">
+ <draw:text-box/>
+ </draw:frame>
+ <draw:frame presentation:style-name="Default-outline1" draw:layer="backgroundobjects" svg:width="25.199cm" svg:height="12.179cm" svg:x="1.4cm" svg:y="4.914cm" presentation:class="outline" presentation:placeholder="true">
+ <draw:text-box/>
+ </draw:frame>
+ <draw:frame presentation:style-name="pr1" draw:text-style-name="P2" draw:layer="backgroundobjects" svg:width="6.523cm" svg:height="1.448cm" svg:x="1.4cm" svg:y="19.131cm" presentation:class="date-time">
+ <draw:text-box>
+ <text:p text:style-name="P1"><presentation:date-time/></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame presentation:style-name="pr1" draw:text-style-name="P6" draw:layer="backgroundobjects" svg:width="8.875cm" svg:height="1.448cm" svg:x="9.576cm" svg:y="19.131cm" presentation:class="footer">
+ <draw:text-box>
+ <text:p text:style-name="P5"><presentation:footer/></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame presentation:style-name="pr1" draw:text-style-name="P4" draw:layer="backgroundobjects" svg:width="6.523cm" svg:height="1.448cm" svg:x="20.076cm" svg:y="19.131cm" presentation:class="page-number">
+ <draw:text-box>
+ <text:p text:style-name="P3"><text:page-number>&lt;number&gt;</text:page-number></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <presentation:notes style:page-layout-name="PM0">
+ <draw:page-thumbnail presentation:style-name="Default-title" draw:layer="backgroundobjects" svg:width="14.848cm" svg:height="11.136cm" svg:x="3.075cm" svg:y="2.257cm" presentation:class="page"/>
+ <draw:frame presentation:style-name="Default-notes" draw:layer="backgroundobjects" svg:width="16.799cm" svg:height="13.364cm" svg:x="2.1cm" svg:y="14.107cm" presentation:class="notes" presentation:placeholder="true">
+ <draw:text-box/>
+ </draw:frame>
+ <draw:frame presentation:style-name="pr2" draw:text-style-name="P2" draw:layer="backgroundobjects" svg:width="9.113cm" svg:height="1.484cm" svg:x="0cm" svg:y="0cm" presentation:class="header">
+ <draw:text-box>
+ <text:p text:style-name="P1"><presentation:header/></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame presentation:style-name="pr2" draw:text-style-name="P4" draw:layer="backgroundobjects" svg:width="9.113cm" svg:height="1.484cm" svg:x="11.886cm" svg:y="0cm" presentation:class="date-time">
+ <draw:text-box>
+ <text:p text:style-name="P3"><presentation:date-time/></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame presentation:style-name="pr3" draw:text-style-name="P2" draw:layer="backgroundobjects" svg:width="9.113cm" svg:height="1.484cm" svg:x="0cm" svg:y="28.215cm" presentation:class="footer">
+ <draw:text-box>
+ <text:p text:style-name="P1"><presentation:footer/></text:p>
+ </draw:text-box>
+ </draw:frame>
+ <draw:frame presentation:style-name="pr3" draw:text-style-name="P4" draw:layer="backgroundobjects" svg:width="9.113cm" svg:height="1.484cm" svg:x="11.886cm" svg:y="28.215cm" presentation:class="page-number">
+ <draw:text-box>
+ <text:p text:style-name="P3"><text:page-number>&lt;number&gt;</text:page-number></text:p>
+ </draw:text-box>
+ </draw:frame>
+ </presentation:notes>
+ </style:master-page>
+ </office:master-styles>
+ <office:body>
+ <office:presentation>
+ <draw:page draw:name="page1" draw:style-name="dp3" draw:master-page-name="Default" presentation:presentation-page-layout-name="AL1T0">
+ <draw:frame presentation:style-name="pr4" draw:layer="layout" svg:width="25.199cm" svg:height="3.506cm" svg:x="1.4cm" svg:y="0.837cm" presentation:class="title" presentation:placeholder="true">
+ <draw:text-box/>
+ </draw:frame>
+ <draw:frame presentation:style-name="pr5" draw:text-style-name="P7" draw:layer="layout" svg:width="25.199cm" svg:height="12.179cm" svg:x="1.4cm" svg:y="4.914cm" presentation:class="subtitle" presentation:placeholder="true">
+ <draw:text-box/>
+ </draw:frame>
+ <draw:frame draw:style-name="standard" draw:layer="layout" svg:width="23.798cm" svg:height="11.398cm" svg:x="1.8cm" svg:y="5.4cm">
+ <table:table table:template-name="default" table:use-first-row-styles="true" table:use-banding-rows-styles="true">
+ <table:table-column table:style-name="co1"/>
+ <table:table-column table:style-name="co1"/>
+ <table:table-column table:style-name="co1"/>
+ <table:table-column table:style-name="co1"/>
+ <table:table-column table:style-name="co2"/>
+ <table:table-row table:style-name="ro1" table:default-cell-style-name="gray3">
+ <table:table-cell>
+ <text:p>aaa</text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p>aa</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="ce1">
+ <text:p text:style-name="P8">aaaa</text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p>aaaaa</text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p>aaaa</text:p>
+ </table:table-cell>
+ </table:table-row>
+ <table:table-row table:style-name="ro1" table:default-cell-style-name="gray2">
+ <table:table-cell>
+ <text:p>aaa</text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p>aaa</text:p>
+ </table:table-cell>
+ <table:table-cell table:style-name="ce2">
+ <text:p text:style-name="P8">aaa</text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p>aaa</text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p>aaaaaa</text:p>
+ </table:table-cell>
+ </table:table-row>
+ <table:table-row table:style-name="ro1" table:default-cell-style-name="gray1">
+ <table:table-cell>
+ <text:p>aaa</text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p>aaaaa</text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p>aaa</text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p>aaaa</text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p>aaaaaa</text:p>
+ </table:table-cell>
+ </table:table-row>
+ <table:table-row table:style-name="ro2" table:default-cell-style-name="gray2">
+ <table:table-cell>
+ <text:p>aaa</text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p>aaaaaa</text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p>aaa</text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p>aaa</text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p>aaa</text:p>
+ </table:table-cell>
+ </table:table-row>
+ </table:table><draw:image>
+ <office:binary-data>iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAAEElEQVR4nGJgAQAAAP//AwAA
+ BgAFV7+r1AAAAABJRU5ErkJggg==
+ </office:binary-data>
+ </draw:image>
+ </draw:frame>
+ <presentation:notes draw:style-name="dp2">
+ <draw:page-thumbnail draw:style-name="gr3" draw:layer="layout" svg:width="14.848cm" svg:height="11.136cm" svg:x="3.075cm" svg:y="2.257cm" draw:page-number="1" presentation:class="page"/>
+ <draw:frame presentation:style-name="pr6" draw:text-style-name="P7" draw:layer="layout" svg:width="16.799cm" svg:height="13.364cm" svg:x="2.1cm" svg:y="14.107cm" presentation:class="notes" presentation:placeholder="true">
+ <draw:text-box/>
+ </draw:frame>
+ </presentation:notes>
+ </draw:page>
+ <presentation:settings presentation:mouse-visible="false"/>
+ </office:presentation>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sd/qa/unit/tiledrendering/data/tdf105502.odp b/sd/qa/unit/tiledrendering/data/tdf105502.odp
new file mode 100644
index 0000000000..2150f1152b
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/tdf105502.odp
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/tdf115783.fodp b/sd/qa/unit/tiledrendering/data/tdf115783.fodp
new file mode 100644
index 0000000000..d9ada63ad1
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/tdf115783.fodp
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.presentation">
+ <office:font-face-decls>
+ <style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:automatic-styles>
+ <style:style style:name="co1" style:family="table-column">
+ <style:table-column-properties style:column-width="4.3cm" style:use-optimal-column-width="false"/>
+ </style:style>
+ <style:style style:name="co2" style:family="table-column">
+ <style:table-column-properties style:column-width="6.241cm" style:use-optimal-column-width="false"/>
+ </style:style>
+ <style:style style:name="co3" style:family="table-column">
+ <style:table-column-properties style:column-width="4.909cm" style:use-optimal-column-width="false"/>
+ </style:style>
+ <style:style style:name="ro1" style:family="table-row">
+ <style:table-row-properties style:row-height="1.364cm"/>
+ </style:style>
+ <style:style style:name="ce1" style:family="table-cell">
+ <loext:graphic-properties draw:fill="none" style:repeat="repeat"/>
+ <style:paragraph-properties fo:border="0.03pt solid #000000"/>
+ <style:text-properties style:font-name="Arial" fo:font-size="12pt"/>
+ </style:style>
+ <style:style style:name="T1" style:family="text">
+ <style:text-properties style:font-name="Arial" fo:font-size="12pt"/>
+ </style:style>
+ </office:automatic-styles>
+ <office:body>
+ <office:presentation>
+ <draw:page draw:name="page1">
+ <draw:frame draw:style-name="standard" draw:layer="layout" svg:width="15.449cm" svg:height="1.363cm" svg:x="2.179cm" svg:y="3.302cm">
+ <table:table table:template-name="default">
+ <table:table-column table:style-name="co1"/>
+ <table:table-column table:style-name="co2"/>
+ <table:table-column table:style-name="co3"/>
+ <table:table-row table:style-name="ro1" table:default-cell-style-name="ce1">
+ <table:table-cell>
+ <text:p><text:span text:style-name="T1">before</text:span></text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p><text:span text:style-name="T1">hello</text:span></text:p>
+ </table:table-cell>
+ <table:table-cell>
+ <text:p><text:span text:style-name="T1">after</text:span></text:p>
+ </table:table-cell>
+ </table:table-row>
+ </table:table>
+ </draw:frame>
+ </draw:page>
+ </office:presentation>
+ </office:body>
+</office:document>
diff --git a/sd/qa/unit/tiledrendering/data/tdf115873-group.fodp b/sd/qa/unit/tiledrendering/data/tdf115873-group.fodp
new file mode 100644
index 0000000000..603ec4c7e5
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/tdf115873-group.fodp
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.presentation">
+ <office:automatic-styles>
+ <style:style style:name="dp1" style:family="drawing-page">
+ </style:style>
+ <style:style style:name="gr1" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:textarea-horizontal-align="justify" draw:textarea-vertical-align="middle" draw:auto-grow-height="false" fo:min-height="2.15cm" fo:min-width="1.3cm"/>
+ </style:style>
+ <style:style style:name="gr2" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:textarea-horizontal-align="justify" draw:textarea-vertical-align="middle" draw:auto-grow-height="false" fo:min-height="1.55cm" fo:min-width="1.3cm"/>
+ </style:style>
+ <style:style style:name="gr3" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:textarea-horizontal-align="justify" draw:textarea-vertical-align="middle" draw:auto-grow-height="false" fo:min-height="1.55cm" fo:min-width="2.1cm"/>
+ </style:style>
+ </office:automatic-styles>
+ <office:body>
+ <office:presentation>
+ <draw:page draw:name="page1" draw:style-name="dp1">
+ <draw:g draw:name="Group 1">
+ <draw:custom-shape draw:name="Rectangle 1" draw:style-name="gr1" draw:layer="layout" svg:width="1.8cm" svg:height="2.4cm" svg:x="2.8cm" svg:y="2.8cm">
+ <text:p/>
+ <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:type="rectangle" draw:enhanced-path="M 0 0 L 21600 0 21600 21600 0 21600 0 0 Z N"/>
+ </draw:custom-shape>
+ <draw:custom-shape draw:name="Rectangle 2" draw:style-name="gr2" draw:layer="layout" svg:width="1.8cm" svg:height="1.8cm" svg:x="6cm" svg:y="3.2cm">
+ <text:p/>
+ <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:type="rectangle" draw:enhanced-path="M 0 0 L 21600 0 21600 21600 0 21600 0 0 Z N"/>
+ </draw:custom-shape>
+ </draw:g>
+ <draw:custom-shape draw:name="Rectangle 3" draw:style-name="gr3" draw:layer="layout" svg:width="2.6cm" svg:height="1.8cm" svg:x="4.6cm" svg:y="7.4cm">
+ <text:p/>
+ <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:type="rectangle" draw:enhanced-path="M 0 0 L 21600 0 21600 21600 0 21600 0 0 Z N"/>
+ </draw:custom-shape>
+ </draw:page>
+ </office:presentation>
+ </office:body>
+</office:document>
diff --git a/sd/qa/unit/tiledrendering/data/tdf115873.fodp b/sd/qa/unit/tiledrendering/data/tdf115873.fodp
new file mode 100644
index 0000000000..1633a04714
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/tdf115873.fodp
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.presentation">
+ <office:font-face-decls>
+ <style:font-face style:name="Liberation Sans" svg:font-family="&apos;Liberation Sans&apos;" style:font-family-generic="roman" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+ <style:default-style style:family="graphic">
+ <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap"/>
+ <style:paragraph-properties style:text-autospace="ideograph-alpha" style:punctuation-wrap="simple" style:line-break="strict" style:font-independent-line-spacing="false">
+ <style:tab-stops/>
+ </style:paragraph-properties>
+ <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Sans" fo:font-size="24pt" fo:language="en" fo:country="US" style:font-size-asian="24pt" style:language-asian="zh" style:country-asian="CN" style:font-size-complex="24pt" style:language-complex="hi" style:country-complex="IN"/>
+ </style:default-style>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="gr1" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:textarea-horizontal-align="justify" draw:textarea-vertical-align="middle" draw:auto-grow-height="false" fo:min-height="2.544cm" fo:min-width="4.58cm"/>
+ </style:style>
+ </office:automatic-styles>
+ <office:body>
+ <office:presentation>
+ <draw:page draw:name="page1">
+ <draw:custom-shape draw:name="Rectangle" draw:style-name="gr1" draw:layer="layout" svg:width="5.08cm" svg:height="2.794cm" svg:x="12.954cm" svg:y="7.62cm">
+ <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:type="rectangle" draw:enhanced-path="M 0 0 L 21600 0 21600 21600 0 21600 0 0 Z N"/>
+ </draw:custom-shape>
+ </draw:page>
+ </office:presentation>
+ </office:body>
+</office:document>
diff --git a/sd/qa/unit/tiledrendering/data/tdf118354.odp b/sd/qa/unit/tiledrendering/data/tdf118354.odp
new file mode 100644
index 0000000000..beb132c7e3
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/tdf118354.odp
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/tdf81754.pptx b/sd/qa/unit/tiledrendering/data/tdf81754.pptx
new file mode 100644
index 0000000000..8a1fa1dcfd
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/tdf81754.pptx
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/data/title-shape.odp b/sd/qa/unit/tiledrendering/data/title-shape.odp
new file mode 100644
index 0000000000..15d39d68e1
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/data/title-shape.odp
Binary files differ
diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx b/sd/qa/unit/tiledrendering/tiledrendering.cxx
new file mode 100644
index 0000000000..31d61c1fb1
--- /dev/null
+++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx
@@ -0,0 +1,2947 @@
+/* -*- 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 <test/unoapixml_test.hxx>
+
+#include <app.hrc>
+#include <test/helper/transferable.hxx>
+#include <boost/property_tree/json_parser.hpp>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <sal/log.hxx>
+#include <sfx2/lokhelper.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/string.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/editids.hrc>
+#include <editeng/editobj.hxx>
+#include <editeng/editview.hxx>
+#include <editeng/numitem.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/outlobj.hxx>
+#include <osl/conditn.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/stritem.hxx>
+#include <svl/intitem.hxx>
+#include <comphelper/lok.hxx>
+#include <svx/svdotable.hxx>
+#include <svx/svdoutl.hxx>
+#include <unotools/datetime.hxx>
+#include <test/lokcallback.hxx>
+
+#include <DrawDocShell.hxx>
+#include <ViewShellBase.hxx>
+#include <ViewShell.hxx>
+#include <sdpage.hxx>
+#include <unomodel.hxx>
+#include <drawdoc.hxx>
+#include <undo/undomanager.hxx>
+#include <sfx2/request.hxx>
+#include <svx/svxids.hrc>
+#include <pres.hxx>
+#include <navigatr.hxx>
+#include <vcl/cursor.hxx>
+#include <vcl/scheduler.hxx>
+#include <vcl/vclevent.hxx>
+#include <vcl/BitmapReadAccess.hxx>
+#include <vcl/virdev.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <chrono>
+#include <cstdlib>
+#include <string_view>
+
+using namespace css;
+
+static std::ostream& operator<<(std::ostream& os, ViewShellId id)
+{
+ os << static_cast<sal_Int32>(id);
+ return os;
+}
+
+class SdTiledRenderingTest : public UnoApiXmlTest
+{
+public:
+ SdTiledRenderingTest();
+ virtual void setUp() override;
+ virtual void tearDown() override;
+
+protected:
+ SdXImpressDocument* createDoc(const char* pName, const uno::Sequence<beans::PropertyValue>& rArguments = uno::Sequence<beans::PropertyValue>());
+ void setupLibreOfficeKitViewCallback(SfxViewShell& pViewShell);
+ static void callback(int nType, const char* pPayload, void* pData);
+ void callbackImpl(int nType, const char* pPayload);
+ xmlDocUniquePtr parseXmlDump();
+
+ ::tools::Rectangle m_aInvalidation;
+ std::vector<::tools::Rectangle> m_aSelection;
+ bool m_bFound;
+ sal_Int32 m_nPart;
+ std::vector<OString> m_aSearchResultSelection;
+ std::vector<int> m_aSearchResultPart;
+ int m_nSelectionBeforeSearchResult;
+ int m_nSelectionAfterSearchResult;
+
+ /// For document size changed callback.
+ osl::Condition m_aDocumentSizeCondition;
+ xmlBufferPtr m_pXmlBuffer;
+ TestLokCallbackWrapper m_callbackWrapper;
+};
+
+SdTiledRenderingTest::SdTiledRenderingTest()
+ : UnoApiXmlTest("/sd/qa/unit/tiledrendering/data/"),
+ m_bFound(true),
+ m_nPart(0),
+ m_nSelectionBeforeSearchResult(0),
+ m_nSelectionAfterSearchResult(0),
+ m_pXmlBuffer(nullptr),
+ m_callbackWrapper(&callback, this)
+{
+}
+
+void SdTiledRenderingTest::setUp()
+{
+ UnoApiXmlTest::setUp();
+
+ // prevent showing warning message box
+ setenv("OOX_NO_SMARTART_WARNING", "1", 1);
+ comphelper::LibreOfficeKit::setActive(true);
+}
+
+void SdTiledRenderingTest::tearDown()
+{
+ if (mxComponent.is())
+ {
+ mxComponent->dispose();
+ mxComponent.clear();
+ }
+
+ if (m_pXmlBuffer)
+ xmlBufferFree(m_pXmlBuffer);
+
+ m_callbackWrapper.clear();
+ comphelper::LibreOfficeKit::setActive(false);
+
+ UnoApiXmlTest::tearDown();
+}
+
+SdXImpressDocument* SdTiledRenderingTest::createDoc(const char* pName, const uno::Sequence<beans::PropertyValue>& rArguments)
+{
+ loadFromFile(OUString::createFromAscii(pName));
+ SdXImpressDocument* pImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
+ CPPUNIT_ASSERT(pImpressDocument);
+ pImpressDocument->initializeForTiledRendering(rArguments);
+ return pImpressDocument;
+}
+
+void SdTiledRenderingTest::setupLibreOfficeKitViewCallback(SfxViewShell& pViewShell)
+{
+ pViewShell.setLibreOfficeKitViewCallback(&m_callbackWrapper);
+ m_callbackWrapper.setLOKViewId(SfxLokHelper::getView(&pViewShell));
+}
+
+void SdTiledRenderingTest::callback(int nType, const char* pPayload, void* pData)
+{
+ static_cast<SdTiledRenderingTest*>(pData)->callbackImpl(nType, pPayload);
+}
+
+namespace
+{
+
+std::vector<OUString> lcl_convertSeparated(std::u16string_view rString, sal_Unicode nSeparator)
+{
+ std::vector<OUString> aRet;
+
+ sal_Int32 nIndex = 0;
+ do
+ {
+ OUString aToken( o3tl::trim(o3tl::getToken(rString, 0, nSeparator, nIndex)) );
+ if (!aToken.isEmpty())
+ aRet.push_back(aToken);
+ }
+ while (nIndex >= 0);
+
+ return aRet;
+}
+
+void lcl_convertRectangle(std::u16string_view rString, ::tools::Rectangle& rRectangle)
+{
+ uno::Sequence<OUString> aSeq = comphelper::string::convertCommaSeparated(rString);
+ CPPUNIT_ASSERT(aSeq.getLength() == 4 || aSeq.getLength() == 5);
+ rRectangle.SetLeft(aSeq[0].toInt32());
+ rRectangle.SetTop(aSeq[1].toInt32());
+ rRectangle.setWidth(aSeq[2].toInt32());
+ rRectangle.setHeight(aSeq[3].toInt32());
+}
+
+} // end anonymous namespace
+
+void SdTiledRenderingTest::callbackImpl(int nType, const char* pPayload)
+{
+ switch (nType)
+ {
+ case LOK_CALLBACK_INVALIDATE_TILES:
+ {
+ OUString aPayload = OUString::createFromAscii(pPayload);
+ if (aPayload != "EMPTY" && m_aInvalidation.IsEmpty())
+ lcl_convertRectangle(aPayload, m_aInvalidation);
+ }
+ break;
+ case LOK_CALLBACK_TEXT_SELECTION:
+ {
+ OUString aPayload = OUString::createFromAscii(pPayload);
+ m_aSelection.clear();
+ for (const OUString& rString : lcl_convertSeparated(aPayload, u';'))
+ {
+ ::tools::Rectangle aRectangle;
+ lcl_convertRectangle(rString, aRectangle);
+ m_aSelection.push_back(aRectangle);
+ }
+ if (m_aSearchResultSelection.empty())
+ ++m_nSelectionBeforeSearchResult;
+ else
+ ++m_nSelectionAfterSearchResult;
+ }
+ break;
+ case LOK_CALLBACK_SEARCH_NOT_FOUND:
+ {
+ m_bFound = false;
+ }
+ break;
+ case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED:
+ {
+ m_aDocumentSizeCondition.set();
+ }
+ break;
+ case LOK_CALLBACK_SET_PART:
+ {
+ OUString aPayload = OUString::createFromAscii(pPayload);
+ m_nPart = aPayload.toInt32();
+ }
+ break;
+ case LOK_CALLBACK_SEARCH_RESULT_SELECTION:
+ {
+ m_aSearchResultSelection.clear();
+ m_aSearchResultPart.clear();
+ boost::property_tree::ptree aTree;
+ std::stringstream aStream(pPayload);
+ boost::property_tree::read_json(aStream, aTree);
+ for (const boost::property_tree::ptree::value_type& rValue : aTree.get_child("searchResultSelection"))
+ {
+ m_aSearchResultSelection.emplace_back(rValue.second.get<std::string>("rectangles").c_str());
+ m_aSearchResultPart.push_back(std::atoi(rValue.second.get<std::string>("part").c_str()));
+ }
+ }
+ break;
+ }
+}
+
+xmlDocUniquePtr SdTiledRenderingTest::parseXmlDump()
+{
+ if (m_pXmlBuffer)
+ xmlBufferFree(m_pXmlBuffer);
+
+ // Create the xml writer.
+ m_pXmlBuffer = xmlBufferCreate();
+ xmlTextWriterPtr pXmlWriter = xmlNewTextWriterMemory(m_pXmlBuffer, 0);
+ (void)xmlTextWriterStartDocument(pXmlWriter, nullptr, nullptr, nullptr);
+
+ // Create the dump.
+ SdXImpressDocument* pImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
+ CPPUNIT_ASSERT(pImpressDocument);
+ pImpressDocument->GetDoc()->dumpAsXml(pXmlWriter);
+
+ // Delete the xml writer.
+ (void)xmlTextWriterEndDocument(pXmlWriter);
+ xmlFreeTextWriter(pXmlWriter);
+
+ auto pCharBuffer = xmlBufferContent(m_pXmlBuffer);
+ SAL_INFO("test", "SdTiledRenderingTest::parseXmlDump: pCharBuffer is '" << pCharBuffer << "'");
+ return xmlDocUniquePtr(xmlParseDoc(pCharBuffer));
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCreateDestroy)
+{
+ createDoc("dummy.odp");
+ // Nothing to do, the tearDown call should cleanup.
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCreateView)
+{
+ createDoc("dummy.odp");
+
+ SfxLokHelper::createView();
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testRegisterCallback)
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
+
+ // Start text edit of the empty title shape.
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(0);
+ SdrView* pView = pViewShell->GetView();
+ pView->SdrBeginTextEdit(pObject);
+ CPPUNIT_ASSERT(pView->GetTextEditObject());
+
+ // Check that the top left 256x256px tile would be invalidated.
+ CPPUNIT_ASSERT(!m_aInvalidation.IsEmpty());
+ ::tools::Rectangle aTopLeft(0, 0, 256*15, 256*15); // 1 px = 15 twips, assuming 96 DPI.
+ CPPUNIT_ASSERT(m_aInvalidation.Overlaps(aTopLeft));
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testPostKeyEvent)
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(0);
+ CPPUNIT_ASSERT_EQUAL(SdrObjKind::TitleText, pObject->GetObjIdentifier());
+ SdrTextObj* pTextObj = static_cast<SdrTextObj*>(pObject);
+ SdrView* pView = pViewShell->GetView();
+ pView->MarkObj(pTextObj, pView->GetSdrPageView());
+ SfxStringItem aInputString(SID_ATTR_CHAR, "x");
+ pViewShell->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR,
+ SfxCallMode::SYNCHRON, { &aInputString });
+
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT(pView->GetTextEditObject());
+ EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
+ // Did we manage to enter a second character?
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), rEditView.GetSelection().nStartPos);
+ ESelection aWordSelection(0, 0, 0, 2); // start para, start char, end para, end char.
+ rEditView.SetSelection(aWordSelection);
+ // Did we enter the expected character?
+ CPPUNIT_ASSERT_EQUAL(OUString("xx"), rEditView.GetSelected());
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testPostMouseEvent)
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(0);
+ CPPUNIT_ASSERT_EQUAL(SdrObjKind::TitleText, pObject->GetObjIdentifier());
+ SdrTextObj* pTextObj = static_cast<SdrTextObj*>(pObject);
+ SdrView* pView = pViewShell->GetView();
+ pView->MarkObj(pTextObj, pView->GetSdrPageView());
+ SfxStringItem aInputString(SID_ATTR_CHAR, "x");
+ pViewShell->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR,
+ SfxCallMode::SYNCHRON, { &aInputString });
+ CPPUNIT_ASSERT(pView->GetTextEditObject());
+ EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
+ // Did we manage to go after the first character?
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), rEditView.GetSelection().nStartPos);
+
+ vcl::Cursor* pCursor = rEditView.GetCursor();
+ Point aPosition(pCursor->GetPos().getX(), pCursor->GetPos().getY() + pCursor->GetSize().Height() / 2);
+ aPosition.setX(aPosition.getX() - 1000);
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
+ o3tl::toTwips(aPosition.getX(), o3tl::Length::mm100), o3tl::toTwips(aPosition.getY(), o3tl::Length::mm100),
+ 1, MOUSE_LEFT, 0);
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
+ o3tl::toTwips(aPosition.getX(), o3tl::Length::mm100), o3tl::toTwips(aPosition.getY(), o3tl::Length::mm100),
+ 1, MOUSE_LEFT, 0);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT(pView->GetTextEditObject());
+ // The new cursor position must be before the first word.
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), rEditView.GetSelection().nStartPos);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSetTextSelection)
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ uno::Reference<container::XIndexAccess> xDrawPage(pXImpressDocument->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ xShape->setString("Aaa bbb.");
+ // Create a selection on the second word.
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(0);
+ SdrView* pView = pViewShell->GetView();
+ pView->SdrBeginTextEdit(pObject);
+ CPPUNIT_ASSERT(pView->GetTextEditObject());
+ EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
+ ESelection aWordSelection(0, 4, 0, 7);
+ rEditView.SetSelection(aWordSelection);
+ // Did we indeed manage to select the second word?
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), rEditView.GetSelected());
+
+ // Now use setTextSelection() to move the end of the selection 1000 twips right.
+ vcl::Cursor* pCursor = rEditView.GetCursor();
+ Point aEnd = pCursor->GetPos();
+ aEnd.setX(aEnd.getX() + 1000);
+ pXImpressDocument->setTextSelection(LOK_SETTEXTSELECTION_END, aEnd.getX(), aEnd.getY());
+ // The new selection must include the ending dot, too -- but not the first word.
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb."), rEditView.GetSelected());
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testGetTextSelection)
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ uno::Reference<container::XIndexAccess> xDrawPage(pXImpressDocument->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ xShape->setString("Shape");
+ // Create a selection on the shape text.
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(0);
+ SdrView* pView = pViewShell->GetView();
+ pView->SdrBeginTextEdit(pObject);
+ CPPUNIT_ASSERT(pView->GetTextEditObject());
+ EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
+ ESelection aWordSelection(0, 0, 0, 5);
+ rEditView.SetSelection(aWordSelection);
+ // Did we indeed manage to copy the selected text?
+ CPPUNIT_ASSERT_EQUAL("Shape"_ostr, apitest::helper::transferable::getTextSelection(pXImpressDocument->getSelection(), "text/plain;charset=utf-8"_ostr));
+
+ // Make sure returned RTF is not empty.
+ CPPUNIT_ASSERT(!apitest::helper::transferable::getTextSelection(pXImpressDocument->getSelection(), "text/rtf"_ostr).isEmpty());
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSetGraphicSelection)
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pPage->GetObj(0);
+ SdrHdlList handleList(nullptr);
+ pObject->AddToHdlList(handleList);
+ // Make sure the rectangle has 8 handles: at each corner and at the center of each edge.
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(8), handleList.GetHdlCount());
+ // Take the bottom center one.
+ SdrHdl* pHdl = handleList.GetHdl(6);
+ CPPUNIT_ASSERT_EQUAL(int(SdrHdlKind::Lower), static_cast<int>(pHdl->GetKind()));
+ ::tools::Rectangle aShapeBefore = pObject->GetSnapRect();
+ // Resize.
+ pXImpressDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_START, o3tl::toTwips(pHdl->GetPos().getX(), o3tl::Length::mm100), o3tl::toTwips(pHdl->GetPos().getY(), o3tl::Length::mm100));
+ pXImpressDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_END, o3tl::toTwips(pHdl->GetPos().getX(), o3tl::Length::mm100), o3tl::toTwips(pHdl->GetPos().getY() + 1000, o3tl::Length::mm100));
+
+ // Assert that view shell ID tracking works.
+ sal_Int32 nView1 = SfxLokHelper::getView();
+ SdDrawDocument* pDocument = pXImpressDocument->GetDoc();
+ sd::UndoManager* pUndoManager = pDocument->GetUndoManager();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pUndoManager->GetUndoActionCount());
+ auto pListAction = dynamic_cast<SfxListUndoAction*>(pUndoManager->GetUndoAction());
+ CPPUNIT_ASSERT(pListAction);
+ for (size_t i = 0; i < pListAction->maUndoActions.size(); ++i)
+ // The second item was -1 here, view shell ID wasn't known.
+ CPPUNIT_ASSERT_EQUAL(ViewShellId(nView1), pListAction->GetUndoAction(i)->GetViewShellId());
+
+ ::tools::Rectangle aShapeAfter = pObject->GetSnapRect();
+ // Check that a resize happened, but aspect ratio is not kept.
+ CPPUNIT_ASSERT_EQUAL(aShapeBefore.getOpenWidth(), aShapeAfter.getOpenWidth());
+ CPPUNIT_ASSERT(aShapeBefore.getOpenHeight() < aShapeAfter.getOpenHeight());
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testUndoShells)
+{
+ // Load a document and set the page size.
+ SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
+ uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
+ {
+ {"AttributePageSize.Width", uno::Any(static_cast<sal_Int32>(10000))},
+ {"AttributePageSize.Height", uno::Any(static_cast<sal_Int32>(10000))},
+ }));
+ dispatchCommand(mxComponent, ".uno:AttributePageSize", aPropertyValues);
+
+ // Assert that view shell ID tracking works for SdUndoAction subclasses.
+ SdDrawDocument* pDocument = pXImpressDocument->GetDoc();
+ sd::UndoManager* pUndoManager = pDocument->GetUndoManager();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pUndoManager->GetUndoActionCount());
+ sal_Int32 nView1 = SfxLokHelper::getView();
+ // This was -1, SdUndoGroup did not track what view shell created it.
+ CPPUNIT_ASSERT_EQUAL(ViewShellId(nView1), pUndoManager->GetUndoAction()->GetViewShellId());
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testResetSelection)
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ uno::Reference<container::XIndexAccess> xDrawPage(pXImpressDocument->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ xShape->setString("Aaa bbb.");
+ // Create a selection on the second word.
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(0);
+ SdrView* pView = pViewShell->GetView();
+ pView->SdrBeginTextEdit(pObject);
+ CPPUNIT_ASSERT(pView->GetTextEditObject());
+ EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
+ ESelection aWordSelection(0, 4, 0, 7);
+ rEditView.SetSelection(aWordSelection);
+ // Did we indeed manage to select the second word?
+ CPPUNIT_ASSERT_EQUAL(OUString("bbb"), rEditView.GetSelected());
+
+ // Now use resetSelection() to reset the selection.
+ pXImpressDocument->resetSelection();
+ CPPUNIT_ASSERT(!pView->GetTextEditObject());
+}
+
+namespace
+{
+
+std::vector<OUString> getCurrentParts(SdXImpressDocument* pDocument)
+{
+ int parts = pDocument->getParts();
+ std::vector<OUString> result;
+
+ result.reserve(parts);
+ for (int i = 0; i < parts; i++)
+ {
+ result.push_back(pDocument->getPartName(i));
+ }
+
+ return result;
+}
+
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testInsertDeletePage)
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("insert-delete.odp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
+
+ SdDrawDocument* pDoc = pXImpressDocument->GetDocShell()->GetDoc();
+ CPPUNIT_ASSERT(pDoc);
+
+ std::vector<OUString> aInserted =
+ {
+ "Slide 1", "Slide 2", "Slide 3", "Slide 4", "Slide 5",
+ "Slide 6", "Slide 7", "Slide 8", "Slide 9", "Slide 10", "Slide 11"
+ };
+
+ std::vector<OUString> aDeleted =
+ {
+ "Slide 1"
+ };
+
+ // the document has 1 slide
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(1), pDoc->GetSdPageCount(PageKind::Standard));
+
+ uno::Sequence<beans::PropertyValue> aArgs;
+
+ // Insert slides
+ m_aDocumentSizeCondition.reset();
+ for (unsigned it = 1; it <= 10; it++)
+ dispatchCommand(mxComponent, ".uno:InsertPage", aArgs);
+
+ osl::Condition::Result aResult = m_aDocumentSizeCondition.wait(std::chrono::seconds(2));
+ CPPUNIT_ASSERT_EQUAL(osl::Condition::result_ok, aResult);
+
+ // Verify inserted slides
+ std::vector<OUString> aPageList(getCurrentParts(pXImpressDocument));
+ CPPUNIT_ASSERT_EQUAL(aPageList.size(), aInserted.size());
+
+ for (auto it1 = aPageList.begin(), it2 = aInserted.begin(); it1 != aPageList.end(); ++it1, ++it2)
+ {
+ CPPUNIT_ASSERT_EQUAL(*it1, *it2);
+ }
+
+ // Delete slides
+ m_aDocumentSizeCondition.reset();
+ for (unsigned it = 1; it <= 10; it++)
+ dispatchCommand(mxComponent, ".uno:DeletePage", aArgs);
+
+ aResult = m_aDocumentSizeCondition.wait(std::chrono::seconds(2));
+ CPPUNIT_ASSERT_EQUAL(osl::Condition::result_ok, aResult);
+
+ // Verify deleted slides
+ aPageList = getCurrentParts(pXImpressDocument);
+ CPPUNIT_ASSERT_EQUAL(aPageList.size(), aDeleted.size());
+ for (auto it1 = aPageList.begin(), it2 = aDeleted.begin(); it1 != aPageList.end(); ++it1, ++it2)
+ {
+ CPPUNIT_ASSERT_EQUAL(*it1, *it2);
+ }
+
+ // Undo deleted slides
+ m_aDocumentSizeCondition.reset();
+ for (unsigned it = 1; it <= 10; it++)
+ dispatchCommand(mxComponent, ".uno:Undo", aArgs);
+
+ aResult = m_aDocumentSizeCondition.wait(std::chrono::seconds(2));
+ CPPUNIT_ASSERT_EQUAL(osl::Condition::result_ok, aResult);
+
+ // Verify inserted slides
+ aPageList = getCurrentParts(pXImpressDocument);
+ CPPUNIT_ASSERT_EQUAL(aPageList.size(), aInserted.size());
+ for (auto it1 = aPageList.begin(), it2 = aInserted.begin(); it1 != aPageList.end(); ++it1, ++it2)
+ {
+ CPPUNIT_ASSERT_EQUAL(*it1, *it2);
+ }
+
+ // Redo deleted slides
+ m_aDocumentSizeCondition.reset();
+ for (unsigned it = 1; it <= 10; it++)
+ dispatchCommand(mxComponent, ".uno:Redo", aArgs);
+
+ aResult = m_aDocumentSizeCondition.wait(std::chrono::seconds(2));
+ CPPUNIT_ASSERT_EQUAL(osl::Condition::result_ok, aResult);
+
+ // Verify deleted slides
+ aPageList = getCurrentParts(pXImpressDocument);
+ CPPUNIT_ASSERT_EQUAL(aPageList.size(), aDeleted.size());
+ for (auto it1 = aPageList.begin(), it2 = aDeleted.begin(); it1 != aPageList.end(); ++it1, ++it2)
+ {
+ CPPUNIT_ASSERT_EQUAL(*it1, *it2);
+ }
+
+ // the document has 1 slide
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(1), pDoc->GetSdPageCount(PageKind::Standard));
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testInsertTable)
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+
+ uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
+ {
+ { "Rows", uno::Any(sal_Int32(3)) },
+ { "Columns", uno::Any(sal_Int32(5)) }
+ }));
+
+ dispatchCommand(mxComponent, ".uno:InsertTable", aArgs);
+
+ // get the table
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(1);
+ CPPUNIT_ASSERT(pObject);
+
+ // check that the table is not in the top left corner
+ Point aPos(pObject->GetRelativePos());
+
+ CPPUNIT_ASSERT(aPos.X() != 0);
+ CPPUNIT_ASSERT(aPos.Y() != 0);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testDeleteTable)
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+
+ uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
+ {
+ { "Rows", uno::Any(sal_Int32(3)) },
+ { "Columns", uno::Any(sal_Int32(5)) }
+ }));
+
+ dispatchCommand(mxComponent, ".uno:InsertTable", aArgs);
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdrView* pSdrView = pViewShell->GetView();
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ CPPUNIT_ASSERT(rMarkList.GetMarkCount());
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_MOD1 | awt::Key::A);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_MOD1 | awt::Key::A);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_DELETE);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_DELETE);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT(!rMarkList.GetMarkCount());
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testPartHash)
+{
+ SdXImpressDocument* pDoc = createDoc("dummy.odp");
+
+ int nParts = pDoc->getParts();
+ for (int it = 0; it < nParts; it++)
+ {
+ CPPUNIT_ASSERT(!pDoc->getPartHash(it).isEmpty());
+ }
+
+ // check part that it does not exists
+ CPPUNIT_ASSERT(pDoc->getPartHash(100).isEmpty());
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testResizeTable)
+{
+ // Load the document.
+ SdXImpressDocument* pXImpressDocument = createDoc("table.odp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(0);
+ auto pTableObject = dynamic_cast<sdr::table::SdrTableObj*>(pObject);
+ CPPUNIT_ASSERT(pTableObject);
+
+ // Select the table by marking it + starting and ending text edit.
+ SdrView* pView = pViewShell->GetView();
+ pView->MarkObj(pObject, pView->GetSdrPageView());
+ pView->SdrBeginTextEdit(pObject);
+ pView->SdrEndTextEdit();
+
+ // Remember the original row heights.
+ uno::Reference<table::XColumnRowRange> xTable = pTableObject->getTable();
+ uno::Reference<container::XIndexAccess> xRows = xTable->getRows();
+ uno::Reference<beans::XPropertySet> xRow1(xRows->getByIndex(0), uno::UNO_QUERY);
+ sal_Int32 nExpectedRow1 = xRow1->getPropertyValue("Size").get<sal_Int32>();
+ uno::Reference<beans::XPropertySet> xRow2(xRows->getByIndex(1), uno::UNO_QUERY);
+ sal_Int32 nExpectedRow2 = xRow2->getPropertyValue("Size").get<sal_Int32>();
+
+ // Resize the upper row, decrease its height by 1 cm.
+ Point aInnerRowEdge = pObject->GetSnapRect().Center();
+ pXImpressDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_START, o3tl::toTwips(aInnerRowEdge.getX(), o3tl::Length::mm100), o3tl::toTwips(aInnerRowEdge.getY(), o3tl::Length::mm100));
+ pXImpressDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_END, o3tl::toTwips(aInnerRowEdge.getX(), o3tl::Length::mm100), o3tl::toTwips(aInnerRowEdge.getY() - 1000, o3tl::Length::mm100));
+
+ // Remember the resized row heights.
+ sal_Int32 nResizedRow1 = xRow1->getPropertyValue("Size").get<sal_Int32>();
+ CPPUNIT_ASSERT(nResizedRow1 < nExpectedRow1);
+ sal_Int32 nResizedRow2 = xRow2->getPropertyValue("Size").get<sal_Int32>();
+ CPPUNIT_ASSERT_EQUAL(nExpectedRow2, nResizedRow2);
+
+ // Now undo the resize.
+ pXImpressDocument->GetDocShell()->GetUndoManager()->Undo();
+
+ // Check the undo result.
+ sal_Int32 nActualRow1 = xRow1->getPropertyValue("Size").get<sal_Int32>();
+ CPPUNIT_ASSERT_EQUAL(nExpectedRow1, nActualRow1);
+ sal_Int32 nActualRow2 = xRow2->getPropertyValue("Size").get<sal_Int32>();
+ // Expected was 4000, actual was 4572, i.e. the second row after undo was larger than expected.
+ CPPUNIT_ASSERT_EQUAL(nExpectedRow2, nActualRow2);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testResizeTableColumn)
+{
+ // Load the document.
+ SdXImpressDocument* pXImpressDocument = createDoc("table-column.odp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(0);
+ auto pTableObject = dynamic_cast<sdr::table::SdrTableObj*>(pObject);
+ CPPUNIT_ASSERT(pTableObject);
+
+ // Select the table by marking it + starting and ending text edit.
+ SdrView* pView = pViewShell->GetView();
+ pView->MarkObj(pObject, pView->GetSdrPageView());
+ pView->SdrBeginTextEdit(pObject);
+ pView->SdrEndTextEdit();
+
+ // Remember the original cell widths.
+ xmlDocUniquePtr pXmlDoc = parseXmlDump();
+ OString aPrefix = "/SdDrawDocument/SdrModel/maPages/SdPage/SdrPage/SdrObjList/SdrTableObj/SdrTableObjImpl/TableLayouter/columns/"_ostr;
+ sal_Int32 nExpectedColumn1 = getXPath(pXmlDoc, aPrefix + "TableLayouter_Layout[1]", "size"_ostr).toInt32();
+ sal_Int32 nExpectedColumn2 = getXPath(pXmlDoc, aPrefix + "TableLayouter_Layout[2]", "size"_ostr).toInt32();
+ pXmlDoc = nullptr;
+
+ // Resize the left column, decrease its width by 1 cm.
+ Point aInnerRowEdge = pObject->GetSnapRect().Center();
+ pXImpressDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_START, o3tl::toTwips(aInnerRowEdge.getX(), o3tl::Length::mm100), o3tl::toTwips(aInnerRowEdge.getY(), o3tl::Length::mm100));
+ pXImpressDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_END, o3tl::toTwips(aInnerRowEdge.getX() - 1000, o3tl::Length::mm100), o3tl::toTwips(aInnerRowEdge.getY(), o3tl::Length::mm100));
+
+ // Remember the resized column widths.
+ pXmlDoc = parseXmlDump();
+ sal_Int32 nResizedColumn1 = getXPath(pXmlDoc, aPrefix + "TableLayouter_Layout[1]", "size"_ostr).toInt32();
+ CPPUNIT_ASSERT(nResizedColumn1 < nExpectedColumn1);
+ sal_Int32 nResizedColumn2 = getXPath(pXmlDoc, aPrefix + "TableLayouter_Layout[2]", "size"_ostr).toInt32();
+ CPPUNIT_ASSERT(nResizedColumn2 > nExpectedColumn2);
+ pXmlDoc = nullptr;
+
+ // Now undo the resize.
+ pXImpressDocument->GetDocShell()->GetUndoManager()->Undo();
+
+ // Check the undo result.
+ pXmlDoc = parseXmlDump();
+ sal_Int32 nActualColumn1 = getXPath(pXmlDoc, aPrefix + "TableLayouter_Layout[1]", "size"_ostr).toInt32();
+ // Expected was 7049, actual was 6048, i.e. the first column width after undo was 1cm smaller than expected.
+ CPPUNIT_ASSERT_EQUAL(nExpectedColumn1, nActualColumn1);
+ sal_Int32 nActualColumn2 = getXPath(pXmlDoc, aPrefix + "TableLayouter_Layout[2]", "size"_ostr).toInt32();
+ CPPUNIT_ASSERT_EQUAL(nExpectedColumn2, nActualColumn2);
+ pXmlDoc = nullptr;
+}
+
+namespace {
+
+/// A view callback tracks callbacks invoked on one specific view.
+class ViewCallback final
+{
+ SfxViewShell* mpViewShell;
+ int mnView;
+public:
+ bool m_bGraphicSelectionInvalidated;
+ bool m_bGraphicViewSelectionInvalidated;
+ /// Our current part, to be able to decide if a view cursor/selection is relevant for us.
+ int m_nPart;
+ bool m_bCursorVisibleChanged;
+ bool m_bCursorVisible;
+ bool m_bViewLock;
+ bool m_bTilesInvalidated;
+ std::vector<tools::Rectangle> m_aInvalidations;
+ std::map<int, bool> m_aViewCursorInvalidations;
+ std::map<int, bool> m_aViewCursorVisibilities;
+ bool m_bViewSelectionSet;
+ boost::property_tree::ptree m_aCommentCallbackResult;
+ OString m_ShapeSelection;
+ TestLokCallbackWrapper m_callbackWrapper;
+
+ ViewCallback()
+ : m_bGraphicSelectionInvalidated(false),
+ m_bGraphicViewSelectionInvalidated(false),
+ m_nPart(0),
+ m_bCursorVisibleChanged(false),
+ m_bCursorVisible(false),
+ m_bViewLock(false),
+ m_bTilesInvalidated(false),
+ m_bViewSelectionSet(false),
+ m_callbackWrapper(&callback, this)
+ {
+ mpViewShell = SfxViewShell::Current();
+ mpViewShell->setLibreOfficeKitViewCallback(&m_callbackWrapper);
+ mnView = SfxLokHelper::getView();
+ m_callbackWrapper.setLOKViewId( mnView );
+ }
+
+ ~ViewCallback()
+ {
+ SfxLokHelper::setView(mnView);
+ mpViewShell->setLibreOfficeKitViewCallback(nullptr);
+ }
+
+ static void callback(int nType, const char* pPayload, void* pData)
+ {
+ static_cast<ViewCallback*>(pData)->callbackImpl(nType, pPayload);
+ }
+
+ void callbackImpl(int nType, const char* pPayload)
+ {
+ switch (nType)
+ {
+ case LOK_CALLBACK_INVALIDATE_TILES:
+ {
+ m_bTilesInvalidated = true;
+ OString text(pPayload);
+ if (!text.startsWith("EMPTY"))
+ {
+ uno::Sequence<OUString> aSeq = comphelper::string::convertCommaSeparated(OUString::createFromAscii(pPayload));
+ CPPUNIT_ASSERT(aSeq.getLength() == 4 || aSeq.getLength() == 5);
+ tools::Rectangle aInvalidationRect;
+ aInvalidationRect.SetLeft(aSeq[0].toInt32());
+ aInvalidationRect.SetTop(aSeq[1].toInt32());
+ aInvalidationRect.setWidth(aSeq[2].toInt32());
+ aInvalidationRect.setHeight(aSeq[3].toInt32());
+ m_aInvalidations.push_back(aInvalidationRect);
+ }
+ }
+ break;
+ case LOK_CALLBACK_GRAPHIC_SELECTION:
+ {
+ m_bGraphicSelectionInvalidated = true;
+ m_ShapeSelection = OString(pPayload);
+ }
+ break;
+ case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION:
+ {
+ std::stringstream aStream(pPayload);
+ boost::property_tree::ptree aTree;
+ boost::property_tree::read_json(aStream, aTree);
+ if (aTree.get_child("part").get_value<int>() == m_nPart)
+ // Ignore callbacks which are for a different part.
+ m_bGraphicViewSelectionInvalidated = true;
+ }
+ break;
+ case LOK_CALLBACK_CURSOR_VISIBLE:
+ {
+ m_bCursorVisibleChanged = true;
+ m_bCursorVisible = (std::string_view("true") == pPayload);
+ }
+ break;
+ case LOK_CALLBACK_VIEW_LOCK:
+ {
+ std::stringstream aStream(pPayload);
+ boost::property_tree::ptree aTree;
+ boost::property_tree::read_json(aStream, aTree);
+ m_bViewLock = aTree.get_child("rectangle").get_value<std::string>() != "EMPTY";
+ }
+ break;
+ case LOK_CALLBACK_INVALIDATE_VIEW_CURSOR:
+ {
+ std::stringstream aStream(pPayload);
+ boost::property_tree::ptree aTree;
+ boost::property_tree::read_json(aStream, aTree);
+ int nViewId = aTree.get_child("viewId").get_value<int>();
+ m_aViewCursorInvalidations[nViewId] = true;
+ }
+ break;
+ case LOK_CALLBACK_VIEW_CURSOR_VISIBLE:
+ {
+ std::stringstream aStream(pPayload);
+ boost::property_tree::ptree aTree;
+ boost::property_tree::read_json(aStream, aTree);
+ const int nViewId = aTree.get_child("viewId").get_value<int>();
+ m_aViewCursorVisibilities[nViewId] = std::string_view("true") == pPayload;
+ }
+ break;
+ case LOK_CALLBACK_TEXT_VIEW_SELECTION:
+ {
+ m_bViewSelectionSet = true;
+ }
+ break;
+ case LOK_CALLBACK_COMMENT:
+ {
+ m_aCommentCallbackResult.clear();
+ std::stringstream aStream(pPayload);
+ boost::property_tree::read_json(aStream, m_aCommentCallbackResult);
+ m_aCommentCallbackResult = m_aCommentCallbackResult.get_child("comment");
+ }
+ break;
+ }
+ }
+};
+
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testViewCursors)
+{
+ // Create two views.
+ SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
+ ViewCallback aView1;
+ SfxLokHelper::createView();
+ ViewCallback aView2;
+
+ // Select the shape in the second view.
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(0);
+ SdrView* pView = pViewShell->GetView();
+ pView->MarkObj(pObject, pView->GetSdrPageView());
+ Scheduler::ProcessEventsToIdle();
+
+ // First view notices that there was a selection change in the other view.
+ CPPUNIT_ASSERT(aView1.m_bGraphicViewSelectionInvalidated);
+ // Second view notices that there was a selection change in its own view.
+ CPPUNIT_ASSERT(aView2.m_bGraphicSelectionInvalidated);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testViewCursorParts)
+{
+ // Create two views.
+ SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
+ ViewCallback aView1;
+ SfxLokHelper::createView();
+ pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
+ ViewCallback aView2;
+
+ // Select the shape in the second view.
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(0);
+ SdrView* pView = pViewShell->GetView();
+ pView->MarkObj(pObject, pView->GetSdrPageView());
+ Scheduler::ProcessEventsToIdle();
+ // First view notices that there was a selection change in the other view.
+ CPPUNIT_ASSERT(aView1.m_bGraphicViewSelectionInvalidated);
+ pView->UnmarkAllObj(pView->GetSdrPageView());
+
+ // Now switch to the second part in the second view.
+ pXImpressDocument->setPart(1);
+ aView2.m_nPart = 1;
+ aView1.m_bGraphicViewSelectionInvalidated = false;
+ pActualPage = pViewShell->GetActualPage();
+ pObject = pActualPage->GetObj(0);
+ pView->MarkObj(pObject, pView->GetSdrPageView());
+ Scheduler::ProcessEventsToIdle();
+ // First view ignores view selection, as it would be for part 1, and it's in part 0.
+ // This failed when the "part" was always 0 in the callback.
+ CPPUNIT_ASSERT(!aView1.m_bGraphicViewSelectionInvalidated);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCursorViews)
+{
+ // Create the first view.
+ SdXImpressDocument* pXImpressDocument = createDoc("title-shape.odp");
+ int nView1 = SfxLokHelper::getView();
+ ViewCallback aView1;
+
+ // Begin text edit on the only object on the slide.
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdrView* pView = pViewShell->GetView();
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT(pView->IsTextEdit());
+
+ // Make sure that cursor state is not changed just because we create a second view.
+ aView1.m_bCursorVisibleChanged = false;
+ SfxLokHelper::createView();
+ pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT(!aView1.m_bCursorVisibleChanged);
+
+ // Make sure that typing in the first view causes an invalidation in the
+ // second view as well, even if the second view was created after begin
+ // text edit in the first view.
+ ViewCallback aView2;
+ // This failed: the second view didn't get a lock notification, even if the
+ // first view already started text edit.
+ CPPUNIT_ASSERT(aView2.m_bViewLock);
+ SfxLokHelper::setView(nView1);
+ aView2.m_bTilesInvalidated = false;
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
+ Scheduler::ProcessEventsToIdle();
+ // This failed: the second view was not invalidated when pressing a key in
+ // the first view.
+ CPPUNIT_ASSERT(aView2.m_bTilesInvalidated);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCursorVisibility_SingleClick)
+{
+ // Single-clicking in a text box enters editing only
+ // when it's on the text, even if it's the default text.
+
+ // Load doc.
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ ViewCallback aView1;
+
+ // Begin text edit on the only object on the slide.
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject1 = pActualPage->GetObj(0);
+ CPPUNIT_ASSERT(pObject1 != nullptr);
+ CPPUNIT_ASSERT_EQUAL(SdrObjKind::TitleText, pObject1->GetObjIdentifier());
+ SdrTextObj* pTextObject = static_cast<SdrTextObj*>(pObject1);
+
+ // Click once outside of the text (in the first quartile) => no editing.
+ const ::tools::Rectangle aRect = pTextObject->GetCurrentBoundRect();
+ const auto cornerX = o3tl::toTwips(aRect.Left() + (aRect.getOpenWidth() / 4), o3tl::Length::mm100);
+ const auto cornerY = o3tl::toTwips(aRect.Top() + (aRect.getOpenHeight() / 4), o3tl::Length::mm100);
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
+ cornerX, cornerY,
+ 1, MOUSE_LEFT, 0);
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
+ cornerX, cornerY,
+ 1, MOUSE_LEFT, 0);
+ Scheduler::ProcessEventsToIdle();
+
+ // No editing.
+ CPPUNIT_ASSERT(!pViewShell->GetView()->IsTextEdit());
+ CPPUNIT_ASSERT(!aView1.m_bCursorVisible);
+
+ // Click again, now on the text, in the center, to start editing.
+ const auto centerX = o3tl::toTwips(aRect.Left() + (aRect.getOpenWidth() / 2), o3tl::Length::mm100);
+ const auto centerY = o3tl::toTwips(aRect.Top() + (aRect.getOpenHeight() / 2), o3tl::Length::mm100);
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
+ centerX, centerY,
+ 1, MOUSE_LEFT, 0);
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
+ centerX, centerY,
+ 1, MOUSE_LEFT, 0);
+ Scheduler::ProcessEventsToIdle();
+
+ // We must be in text editing mode and have cursor visible.
+ CPPUNIT_ASSERT(pViewShell->GetView()->IsTextEdit());
+ CPPUNIT_ASSERT(aView1.m_bCursorVisible);
+}
+
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCursorVisibility_DoubleClick)
+{
+ // Double-clicking anywhere in the TextBox should start editing.
+
+ // Create the first view.
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ ViewCallback aView1;
+
+ // Begin text edit on the only object on the slide.
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject1 = pActualPage->GetObj(0);
+ CPPUNIT_ASSERT(pObject1 != nullptr);
+ CPPUNIT_ASSERT_EQUAL(SdrObjKind::TitleText, pObject1->GetObjIdentifier());
+ SdrTextObj* pTextObject = static_cast<SdrTextObj*>(pObject1);
+
+ // Double-click outside the text to enter edit mode.
+ const ::tools::Rectangle aRect = pTextObject->GetCurrentBoundRect();
+ const auto cornerX = o3tl::toTwips(aRect.Left() + (aRect.getOpenWidth() / 4), o3tl::Length::mm100);
+ const auto cornerY = o3tl::toTwips(aRect.Top() + (aRect.getOpenHeight() / 4), o3tl::Length::mm100);
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
+ cornerX, cornerY,
+ 2, MOUSE_LEFT, 0);
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
+ cornerX, cornerY,
+ 2, MOUSE_LEFT, 0);
+ Scheduler::ProcessEventsToIdle();
+
+ // We must be in text editing mode and have cursor visible.
+ CPPUNIT_ASSERT(pViewShell->GetView()->IsTextEdit());
+ CPPUNIT_ASSERT(aView1.m_bCursorVisible);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCursorVisibility_MultiView)
+{
+ // Create the first view.
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ const int nView1 = SfxLokHelper::getView();
+ ViewCallback aView1;
+
+ // Begin text edit on the only object on the slide.
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject1 = pActualPage->GetObj(0);
+ CPPUNIT_ASSERT(pObject1);
+ CPPUNIT_ASSERT_EQUAL(SdrObjKind::TitleText, pObject1->GetObjIdentifier());
+ SdrTextObj* pTextObject = static_cast<SdrTextObj*>(pObject1);
+
+ // Make sure that cursor state is not changed just because we create a second view.
+ SfxLokHelper::createView();
+ pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
+ const int nView2 = SfxLokHelper::getView();
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL(false, aView1.m_bCursorVisibleChanged);
+ CPPUNIT_ASSERT_EQUAL(false, aView1.m_aViewCursorVisibilities[nView2]);
+
+ // Also check that the second view gets the notifications.
+ ViewCallback aView2;
+
+ SfxLokHelper::setView(nView1);
+
+ ::tools::Rectangle aRect = pTextObject->GetCurrentBoundRect();
+ const auto centerX = o3tl::toTwips(aRect.Left() + (aRect.getOpenWidth() / 2), o3tl::Length::mm100);
+ const auto centerY = o3tl::toTwips(aRect.Top() + (aRect.getOpenHeight() / 2), o3tl::Length::mm100);
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
+ centerX, centerY,
+ 2, MOUSE_LEFT, 0);
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
+ centerX, centerY,
+ 2, MOUSE_LEFT, 0);
+ Scheduler::ProcessEventsToIdle();
+
+ // We must be in text editing mode and have cursor visible.
+ CPPUNIT_ASSERT(pViewShell->GetView()->IsTextEdit());
+ CPPUNIT_ASSERT(aView1.m_bCursorVisible);
+ CPPUNIT_ASSERT_EQUAL(false, aView1.m_aViewCursorVisibilities[nView2]);
+
+ CPPUNIT_ASSERT_EQUAL(false, aView2.m_bCursorVisible);
+ CPPUNIT_ASSERT_EQUAL(false, aView2.m_aViewCursorVisibilities[nView1]);
+ CPPUNIT_ASSERT_EQUAL(false, aView2.m_aViewCursorVisibilities[nView2]);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCursorVisibility_Escape)
+{
+ // Load doc.
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ ViewCallback aView1;
+
+ // Begin text edit on the only object on the slide.
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject1 = pActualPage->GetObj(0);
+ CPPUNIT_ASSERT(pObject1 != nullptr);
+ CPPUNIT_ASSERT_EQUAL(SdrObjKind::TitleText, pObject1->GetObjIdentifier());
+ SdrTextObj* pTextObject = static_cast<SdrTextObj*>(pObject1);
+
+ // Click once on the text to start editing.
+ const ::tools::Rectangle aRect = pTextObject->GetCurrentBoundRect();
+ const auto centerX = o3tl::toTwips(aRect.Left() + (aRect.getOpenWidth() / 2), o3tl::Length::mm100);
+ const auto centerY = o3tl::toTwips(aRect.Top() + (aRect.getOpenHeight() / 2), o3tl::Length::mm100);
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
+ centerX, centerY,
+ 1, MOUSE_LEFT, 0);
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
+ centerX, centerY,
+ 1, MOUSE_LEFT, 0);
+ Scheduler::ProcessEventsToIdle();
+
+ // We must be in text editing mode and have cursor visible.
+ CPPUNIT_ASSERT(pViewShell->GetView()->IsTextEdit());
+ CPPUNIT_ASSERT(aView1.m_bCursorVisible);
+
+ // End editing by pressing the escape key.
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::ESCAPE);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE);
+ Scheduler::ProcessEventsToIdle();
+
+ // We must be in text editing mode and have cursor visible.
+ CPPUNIT_ASSERT(!pViewShell->GetView()->IsTextEdit());
+ CPPUNIT_ASSERT_EQUAL(false, aView1.m_bCursorVisible);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testViewLock)
+{
+ // Load a document that has a shape and create two views.
+ SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
+ ViewCallback aView1;
+ SfxLokHelper::createView();
+ pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
+
+ // Begin text edit in the second view and assert that the first gets a lock
+ // notification.
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(0);
+ SdrView* pView = pViewShell->GetView();
+ aView1.m_bViewLock = false;
+ pView->SdrBeginTextEdit(pObject);
+ CPPUNIT_ASSERT(aView1.m_bViewLock);
+
+ // End text edit in the second view, and assert that the lock is removed in
+ // the first view.
+ pView->SdrEndTextEdit();
+ CPPUNIT_ASSERT(!aView1.m_bViewLock);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testUndoLimiting)
+{
+ // Create the first view.
+ SdXImpressDocument* pXImpressDocument = createDoc("title-shape.odp");
+ sd::ViewShell* pViewShell1 = pXImpressDocument->GetDocShell()->GetViewShell();
+ int nView1 = SfxLokHelper::getView();
+ SfxLokHelper::createView();
+ sd::ViewShell* pViewShell2 = pXImpressDocument->GetDocShell()->GetViewShell();
+ CPPUNIT_ASSERT(pViewShell1 != pViewShell2);
+
+ // Begin text edit on the only object on the slide.
+ SfxLokHelper::setView(nView1);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT(pViewShell1->GetView()->IsTextEdit());
+
+ // View2 UNDO stack should be empty
+ {
+ SfxRequest aReq2(SID_UNDO, SfxCallMode::SLOT, pXImpressDocument->GetDocShell()->GetDoc()->GetPool());
+ aReq2.AppendItem(SfxUInt16Item(SID_UNDO, 1));
+ pViewShell2->ExecuteSlot(aReq2);
+ const auto* pReturnValue = aReq2.GetReturnValue().getItem();
+ CPPUNIT_ASSERT(!pReturnValue);
+ }
+
+ // View1 can UNDO
+ {
+ SfxRequest aReq1(SID_UNDO, SfxCallMode::SLOT, pXImpressDocument->GetDocShell()->GetDoc()->GetPool());
+ aReq1.AppendItem(SfxUInt16Item(SID_UNDO, 1));
+ pViewShell1->ExecuteSlot(aReq1);
+ CPPUNIT_ASSERT(aReq1.IsDone());
+ }
+
+ // View1 can REDO
+ {
+ SfxRequest aReq1(SID_REDO, SfxCallMode::SLOT, pXImpressDocument->GetDocShell()->GetDoc()->GetPool());
+ aReq1.AppendItem(SfxUInt16Item(SID_REDO, 1));
+ pViewShell1->ExecuteSlot(aReq1);
+ CPPUNIT_ASSERT(aReq1.IsDone());
+ }
+
+ // Exit text edit mode
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::ESCAPE);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE);
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT(!pViewShell1->GetView()->IsTextEdit());
+
+ // Now check view2 cannot undo actions.
+ {
+ SfxRequest aReq2(SID_UNDO, SfxCallMode::SLOT, pXImpressDocument->GetDocShell()->GetDoc()->GetPool());
+ aReq2.AppendItem(SfxUInt16Item(SID_UNDO, 1));
+ pViewShell2->ExecuteSlot(aReq2);
+ const SfxUInt32Item* pUInt32Item = dynamic_cast<const SfxUInt32Item*>(aReq2.GetReturnValue().getItem());
+ CPPUNIT_ASSERT(pUInt32Item);
+ CPPUNIT_ASSERT_EQUAL(static_cast< sal_uInt32 >(SID_REPAIRPACKAGE), pUInt32Item->GetValue());
+ }
+
+ // Now check view1 can undo action
+ {
+ SfxRequest aReq1(SID_UNDO, SfxCallMode::SLOT, pXImpressDocument->GetDocShell()->GetDoc()->GetPool());
+ aReq1.AppendItem(SfxUInt16Item(SID_UNDO, 1));
+ pViewShell1->ExecuteSlot(aReq1);
+ CPPUNIT_ASSERT(aReq1.IsDone());
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCreateViewGraphicSelection)
+{
+ // Load a document and register a callback.
+ SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
+ ViewCallback aView1;
+
+ // Select the only shape in the document and assert that the graphic selection is changed.
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(0);
+ SdrView* pView = pViewShell->GetView();
+ aView1.m_bGraphicSelectionInvalidated = false;
+ pView->MarkObj(pObject, pView->GetSdrPageView());
+ CPPUNIT_ASSERT(aView1.m_bGraphicSelectionInvalidated);
+
+ // Now create a new view.
+ aView1.m_bGraphicSelectionInvalidated = false;
+ SfxLokHelper::createView();
+ pXImpressDocument->initializeForTiledRendering({});
+ // This failed, creating a new view affected the graphic selection of an
+ // existing view.
+ CPPUNIT_ASSERT(!aView1.m_bGraphicSelectionInvalidated);
+
+ // Check that when the first view has a shape selected and we register a
+ // callback on the second view, then it gets a "graphic view selection".
+ ViewCallback aView2;
+ // This failed, the created new view had no "view selection" of the first
+ // view's selected shape.
+ CPPUNIT_ASSERT(aView2.m_bGraphicViewSelectionInvalidated);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCreateViewTextCursor)
+{
+ // Load a document and register a callback.
+ SdXImpressDocument* pXImpressDocument = createDoc("title-shape.odp");
+ ViewCallback aView1;
+
+ // Begin text edit.
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
+ Scheduler::ProcessEventsToIdle();
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdrView* pSdrView = pViewShell->GetView();
+ CPPUNIT_ASSERT(pSdrView->IsTextEdit());
+
+ // Create an editeng text selection.
+ EditView& rEditView = pSdrView->GetTextEditOutlinerView()->GetEditView();
+ // 0th para, 0th char -> 0th para, 1st char.
+ ESelection aWordSelection(0, 0, 0, 1);
+ rEditView.SetSelection(aWordSelection);
+
+ // Make sure that creating a new view either doesn't affect the previous
+ // one, or at least the effect is not visible at the end.
+ aView1.m_aViewCursorInvalidations.clear();
+ aView1.m_aViewCursorVisibilities.clear();
+ SfxLokHelper::createView();
+ pXImpressDocument->initializeForTiledRendering({});
+ ViewCallback aView2;
+ bool bFoundCursor = false;
+ for (const auto& rInvalidation : aView1.m_aViewCursorInvalidations)
+ {
+ auto itVisibility = aView1.m_aViewCursorVisibilities.find(rInvalidation.first);
+ // For each cursor invalidation: if there is no visibility or the visibility is true, that's a problem.
+ if (itVisibility == aView1.m_aViewCursorVisibilities.end() || itVisibility->second)
+ {
+ bFoundCursor = true;
+ break;
+ }
+ }
+ // This failed: the second view created an unexpected view cursor in the
+ // first view.
+ CPPUNIT_ASSERT(!bFoundCursor);
+ // This failed: the text view selection of the first view wasn't seen by
+ // the second view.
+ CPPUNIT_ASSERT(aView2.m_bViewSelectionSet);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testTdf102223)
+{
+ // Load the document.
+ SdXImpressDocument* pXImpressDocument = createDoc("tdf102223.odp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ auto pTableObject = dynamic_cast<sdr::table::SdrTableObj*>(pActualPage->GetObj(2));
+ CPPUNIT_ASSERT(pTableObject);
+ SdrView* pView = pViewShell->GetView();
+
+ // select contents of cell
+ ::tools::Rectangle aRect = pTableObject->GetCurrentBoundRect();
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
+ o3tl::toTwips(aRect.Left() + 2, o3tl::Length::mm100), o3tl::toTwips(aRect.Top() + 2, o3tl::Length::mm100),
+ 1, MOUSE_LEFT, 0);
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
+ o3tl::toTwips(aRect.Left() + 2, o3tl::Length::mm100), o3tl::toTwips(aRect.Top() + 2, o3tl::Length::mm100),
+ 1, MOUSE_LEFT, 0);
+ Scheduler::ProcessEventsToIdle();
+ pView->SdrBeginTextEdit(pTableObject);
+ CPPUNIT_ASSERT(pView->GetTextEditObject());
+ EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
+ rEditView.SetSelection(ESelection(0, 0, 0, 3)); // start para, start char, end para, end char.
+ CPPUNIT_ASSERT_EQUAL(OUString("Red"), rEditView.GetSelected());
+ CPPUNIT_ASSERT_EQUAL(
+ int(1411), static_cast<int>(rEditView.GetAttribs().Get(EE_CHAR_FONTHEIGHT).GetHeight()));
+
+ // cut contents of cell
+ uno::Sequence<beans::PropertyValue> aArgs;
+ dispatchCommand(mxComponent, ".uno:Cut", aArgs);
+
+ pView->SdrEndTextEdit(false);
+ pView->SdrBeginTextEdit(pTableObject);
+ CPPUNIT_ASSERT(pView->GetTextEditObject());
+ EditView& rEditView2 = pView->GetTextEditOutlinerView()->GetEditView();
+ rEditView2.SetSelection(ESelection(0, 0, 0, 1)); // start para, start char, end para, end char.
+ CPPUNIT_ASSERT_EQUAL(
+ int(1411), static_cast<int>(rEditView2.GetAttribs().Get(EE_CHAR_FONTHEIGHT).GetHeight()));
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testTdf118354)
+{
+ // Load the document.
+ SdXImpressDocument* pXImpressDocument = createDoc("tdf118354.odp");
+
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), pActualPage->GetObjCount());
+
+ auto pTableObject = dynamic_cast<sdr::table::SdrTableObj*>(pActualPage->GetObj(0));
+ CPPUNIT_ASSERT(pTableObject);
+
+ // Without the fix, it would crash here
+ ::tools::Rectangle aRect = pTableObject->GetCurrentBoundRect();
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
+ o3tl::toTwips(aRect.Left() + 2, o3tl::Length::mm100), o3tl::toTwips(aRect.Top() + 2, o3tl::Length::mm100),
+ 1, MOUSE_LEFT, 0);
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
+ o3tl::toTwips(aRect.Left() + 2, o3tl::Length::mm100), o3tl::toTwips(aRect.Top() + 2, o3tl::Length::mm100),
+ 1, MOUSE_LEFT, 0);
+ Scheduler::ProcessEventsToIdle();
+
+ SdrView* pView = pViewShell->GetView();
+ auto pMarkedObj = dynamic_cast<sdr::table::SdrTableObj*>(pView->GetMarkedObjectByIndex(0));
+ CPPUNIT_ASSERT_EQUAL(pMarkedObj, pTableObject);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testPostKeyEventInvalidation)
+{
+ // Load a document and begin text edit on the first slide.
+ SdXImpressDocument* pXImpressDocument = createDoc("2slides.odp");
+ CPPUNIT_ASSERT_EQUAL(0, pXImpressDocument->getPart());
+ ViewCallback aView1;
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdrView* pView = pViewShell->GetView();
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_F2);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_F2);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT(pView->GetTextEditObject());
+
+ // Create a second view and begin text edit there as well, in parallel.
+ SfxLokHelper::createView();
+ pXImpressDocument->initializeForTiledRendering({});
+ ViewCallback aView2;
+ pXImpressDocument->setPart(1);
+ sd::ViewShell* pViewShell2 = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdrView* pView2 = pViewShell2->GetView();
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_F2);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_F2);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT(pView2->GetTextEditObject());
+
+ // Now go left with the cursor in the second view and watch for
+ // invalidations.
+ aView2.m_bTilesInvalidated = false;
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT);
+ Scheduler::ProcessEventsToIdle();
+ // This failed: moving the cursor caused unexpected invalidation.
+ CPPUNIT_ASSERT(!aView2.m_bTilesInvalidated);
+}
+
+/**
+ * tests a cut/paste bug around bullet items in a list
+ */
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testTdf103083)
+{
+ // Load the document.
+ SdXImpressDocument* pXImpressDocument = createDoc("tdf103083.fodp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+
+ SdrObject* pObject1 = pActualPage->GetObj(1);
+ CPPUNIT_ASSERT_EQUAL(SdrObjKind::OutlineText, pObject1->GetObjIdentifier());
+ SdrTextObj* pTextObject = static_cast<SdrTextObj*>(pObject1);
+
+ SdrView* pView = pViewShell->GetView();
+
+ // select contents of bullet item
+ ::tools::Rectangle aRect = pTextObject->GetCurrentBoundRect();
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
+ o3tl::toTwips(aRect.Left() + 2, o3tl::Length::mm100), o3tl::toTwips(aRect.Top() + 2, o3tl::Length::mm100),
+ 1, MOUSE_LEFT, 0);
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
+ o3tl::toTwips(aRect.Left() + 2, o3tl::Length::mm100), o3tl::toTwips(aRect.Top() + 2, o3tl::Length::mm100),
+ 1, MOUSE_LEFT, 0);
+ Scheduler::ProcessEventsToIdle();
+ pView->SdrBeginTextEdit(pTextObject);
+ CPPUNIT_ASSERT(pView->GetTextEditObject());
+ EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
+ rEditView.SetSelection(ESelection(2, 0, 2, 33)); // start para, start char, end para, end char.
+ CPPUNIT_ASSERT_EQUAL(OUString("They have all the same formatting"), rEditView.GetSelected());
+ SdrOutliner* pOutliner = pView->GetTextEditOutliner();
+ CPPUNIT_ASSERT_EQUAL(OUString("No-Logo Content~LT~Gliederung 2"),
+ pOutliner->GetStyleSheet(2)->GetName());
+ const EditTextObject& aEdit = pTextObject->GetOutlinerParaObject()->GetTextObject();
+ const SvxNumBulletItem* pNumFmt = aEdit.GetParaAttribs(2).GetItem(EE_PARA_NUMBULLET);
+ SvxNumberFormat aNumFmt(pNumFmt->GetNumRule().GetLevel(2));
+
+ // cut contents of bullet item
+ dispatchCommand(mxComponent, ".uno:Cut", uno::Sequence<beans::PropertyValue>());
+
+ CPPUNIT_ASSERT(pView->GetTextEditObject());
+ EditView& rEditView2 = pView->GetTextEditOutlinerView()->GetEditView();
+ rEditView2.SetSelection(ESelection(2, 0, 2, 10)); // start para, start char, end para, end char.
+ CPPUNIT_ASSERT_EQUAL(OUString(), rEditView2.GetSelected());
+
+ // paste contents of bullet item
+ dispatchCommand(mxComponent, ".uno:Paste", uno::Sequence<beans::PropertyValue>());
+
+ // send an ESC key to trigger the commit of the edit to the main model
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::ESCAPE);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE);
+ Scheduler::ProcessEventsToIdle();
+
+ pView->SdrBeginTextEdit(pTextObject);
+ CPPUNIT_ASSERT(pView->GetTextEditObject());
+ pOutliner = pView->GetTextEditOutliner();
+ EditView& rEditView3 = pView->GetTextEditOutlinerView()->GetEditView();
+ rEditView3.SetSelection(ESelection(2, 0, 2, 33)); // start para, start char, end para, end char.
+ CPPUNIT_ASSERT_EQUAL(OUString("They have all the same formatting"), rEditView3.GetSelected());
+ CPPUNIT_ASSERT_EQUAL(OUString("No-Logo Content~LT~Gliederung 2"),
+ pOutliner->GetStyleSheet(2)->GetName());
+
+ const EditTextObject& aEdit2 = pTextObject->GetOutlinerParaObject()->GetTextObject();
+ const SvxNumBulletItem* pNumFmt2 = aEdit2.GetParaAttribs(2).GetItem(EE_PARA_NUMBULLET);
+ SvxNumberFormat aNumFmt2(pNumFmt2->GetNumRule().GetLevel(2));
+
+ bool bEqual(aNumFmt2 == aNumFmt);
+ CPPUNIT_ASSERT_MESSAGE("Bullet properties changed after paste", bEqual);
+}
+
+/**
+ * tests a clone-formatting bug around table cell attributes
+ */
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testTdf104405)
+{
+ // Load the document.
+ SdXImpressDocument* pXImpressDocument = createDoc("tdf104405.fodp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(2);
+ auto pTableObject = dynamic_cast<sdr::table::SdrTableObj*>(pObject);
+ CPPUNIT_ASSERT(pTableObject);
+
+ // select the middle cell
+ SdrView* pView = pViewShell->GetView();
+ pView->MarkObj(pTableObject, pView->GetSdrPageView());
+ pTableObject->setActiveCell(sdr::table::CellPos(2,1));
+ pView->SdrBeginTextEdit(pTableObject);
+ EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
+ rEditView.SetSelection(ESelection(0, 0, 0, 3)); // start para, start char, end para, end char.
+
+ // trigger the clone-formatting/paintbrush command to copy formatting contents of cell
+ uno::Sequence aArgs{ comphelper::makePropertyValue("PersistentCopy", true) };
+ dispatchCommand(mxComponent, ".uno:FormatPaintbrush", aArgs);
+
+ // now click on the table
+ pView->MarkObj(pTableObject, pView->GetSdrPageView());
+ pTableObject->setActiveCell(sdr::table::CellPos(0,0));
+ pView->SdrEndTextEdit(false);
+ pView->SdrBeginTextEdit(pTableObject);
+ EditView& rEditView2 = pView->GetTextEditOutlinerView()->GetEditView();
+ rEditView2.SetSelection(ESelection(0, 0, 0, 3)); // start para, start char, end para, end char.
+ ::tools::Rectangle aRect = pTableObject->GetCurrentBoundRect();
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
+ o3tl::toTwips(aRect.Left(), o3tl::Length::mm100), o3tl::toTwips(aRect.Top(), o3tl::Length::mm100),
+ 1, MOUSE_LEFT, 0);
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
+ o3tl::toTwips(aRect.Left(), o3tl::Length::mm100), o3tl::toTwips(aRect.Top(), o3tl::Length::mm100),
+ 1, MOUSE_LEFT, 0);
+
+ Scheduler::ProcessEventsToIdle();
+
+ // check that the first cell has acquired the resulting vertical style
+ xmlDocUniquePtr pXmlDoc = parseXmlDump();
+ // the following name has a compiler-dependent part
+ CPPUNIT_ASSERT_EQUAL(
+ OUString("2"),
+ getXPath(
+ pXmlDoc,
+ "/SdDrawDocument/SdrModel/maPages/SdPage/SdrPage/SdrObjList/SdrTableObj/SdrTableObjImpl"
+ "/TableModel/Cell[1]/DefaultProperties/SfxItemSet/SdrTextVertAdjustItem"_ostr,
+ "value"_ostr));
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testTdf81754)
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("tdf81754.pptx");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(1);
+
+ SdrTextObj* pTextObj = static_cast<SdrTextObj*>(pObject);
+ SdrView* pView = pViewShell->GetView();
+ pView->MarkObj(pTextObj, pView->GetSdrPageView());
+ SfxStringItem aInputString(SID_ATTR_CHAR, "x");
+ pViewShell->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR,
+ SfxCallMode::SYNCHRON, { &aInputString });
+
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
+ Scheduler::ProcessEventsToIdle();
+
+ // now save, reload, and assert that we did not lose the edit
+ saveAndReload("Impress Office Open XML");
+
+ uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0),
+ uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xShape(xPage->getByIndex(1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(u"Somethingxx"_ustr, xShape->getString());
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testTdf105502)
+{
+ // Load the document.
+ SdXImpressDocument* pXImpressDocument = createDoc("tdf105502.odp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ sd::Window* pWindow = pViewShell->GetActiveWindow();
+ CPPUNIT_ASSERT(pWindow);
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(0);
+ auto pTableObject = dynamic_cast<sdr::table::SdrTableObj*>(pObject);
+ CPPUNIT_ASSERT(pTableObject);
+
+ // Select the first row.
+ sd::View* pView = pViewShell->GetView();
+ pView->MarkObj(pObject, pView->GetSdrPageView());
+ pView->SdrBeginTextEdit(pObject);
+ rtl::Reference<sdr::SelectionController> xSelectionController(pView->getSelectionController());
+ CPPUNIT_ASSERT(xSelectionController.is());
+ SfxRequest aRequest(*pViewShell->GetViewFrame(), SID_TABLE_SELECT_ROW);
+ xSelectionController->Execute(aRequest);
+
+ // Assert that the A1:B1 selection succeeded.
+ CPPUNIT_ASSERT(xSelectionController->hasSelectedCells());
+ sdr::table::CellPos aFirstCell;
+ sdr::table::CellPos aLastCell;
+ xSelectionController->getSelectedCells(aFirstCell, aLastCell);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aFirstCell.mnCol);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aFirstCell.mnRow);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aLastCell.mnCol);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aLastCell.mnRow);
+
+ // Grow font size for the selection.
+ dispatchCommand(mxComponent, ".uno:Grow", {});
+
+ // Assert that the selected A1 has now a larger font than the unselected
+ // A2.
+ xmlDocUniquePtr pXmlDoc = parseXmlDump();
+ sal_Int32 nA1Height = getXPath(pXmlDoc, "//Cell[1]/SdrText/OutlinerParaObject/EditTextObject/ContentInfo/SfxItemSet/SvxFontHeightItem[1]"_ostr, "height"_ostr).toInt32();
+ sal_Int32 nA2Height = getXPath(pXmlDoc, "//Cell[3]/SdrText/OutlinerParaObject/EditTextObject/ContentInfo/attribs[1]/SvxFontHeightItem"_ostr, "height"_ostr).toInt32();
+ // This failed when FuText::ChangeFontSize() never did "continue" in the
+ // text loop, instead of doing so depending on what IsInSelection() returns.
+ CPPUNIT_ASSERT(nA1Height > nA2Height);
+
+ // Check that selection remains the same
+ CPPUNIT_ASSERT(xSelectionController->hasSelectedCells());
+ xSelectionController->getSelectedCells(aFirstCell, aLastCell);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aFirstCell.mnCol);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aFirstCell.mnRow);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), aLastCell.mnCol);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aLastCell.mnRow);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCommentCallbacks)
+{
+ // Load the document.
+ // Set the tiled annotations off
+ comphelper::LibreOfficeKit::setTiledAnnotations(false);
+
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp", comphelper::InitPropertySequence(
+ {
+ {".uno:Author", uno::Any(OUString("LOK User1"))},
+ }));
+ ViewCallback aView1;
+ int nView1 = SfxLokHelper::getView();
+
+ SfxLokHelper::createView();
+ uno::Sequence<beans::PropertyValue> aArgs(comphelper::InitPropertySequence(
+ {
+ {".uno:Author", uno::Any(OUString("LOK User2"))},
+ }));
+ pXImpressDocument->initializeForTiledRendering(aArgs);
+ ViewCallback aView2;
+ int nView2 = SfxLokHelper::getView();
+
+ SfxLokHelper::setView(nView1);
+
+ // Add a new comment
+ aArgs = comphelper::InitPropertySequence(
+ {
+ {"Text", uno::Any(OUString("Comment"))},
+ });
+ dispatchCommand(mxComponent, ".uno:InsertAnnotation", aArgs);
+
+ // We received a LOK_CALLBACK_COMMENT callback with comment 'Add' action
+ CPPUNIT_ASSERT_EQUAL(std::string("Add"), aView1.m_aCommentCallbackResult.get<std::string>("action"));
+ CPPUNIT_ASSERT_EQUAL(std::string("Add"), aView2.m_aCommentCallbackResult.get<std::string>("action"));
+ int nComment1 = aView1.m_aCommentCallbackResult.get<int>("id");
+ CPPUNIT_ASSERT_EQUAL(nComment1, aView2.m_aCommentCallbackResult.get<int>("id"));
+ css::util::DateTime aDateTime;
+ OUString aDateTimeString = OUString::createFromAscii(aView1.m_aCommentCallbackResult.get<std::string>("dateTime"));
+ CPPUNIT_ASSERT(utl::ISO8601parseDateTime(aDateTimeString, aDateTime));
+ CPPUNIT_ASSERT_EQUAL(std::string("LOK User1"), aView1.m_aCommentCallbackResult.get<std::string>("author"));
+ CPPUNIT_ASSERT_EQUAL(std::string("LOK User1"), aView2.m_aCommentCallbackResult.get<std::string>("author"));
+ CPPUNIT_ASSERT_EQUAL(std::string("Comment"), aView1.m_aCommentCallbackResult.get<std::string>("text"));
+ CPPUNIT_ASSERT_EQUAL(std::string("Comment"), aView2.m_aCommentCallbackResult.get<std::string>("text"));
+ CPPUNIT_ASSERT(!aView1.m_aCommentCallbackResult.get<std::string>("parthash").empty());
+ CPPUNIT_ASSERT(!aView2.m_aCommentCallbackResult.get<std::string>("parthash").empty());
+
+ // Reply to a just added comment
+ SfxLokHelper::setView(nView2);
+ aArgs = comphelper::InitPropertySequence(
+ {
+ {"Id", uno::Any(OUString::number(nComment1))},
+ {"Text", uno::Any(OUString("Reply to comment"))},
+ });
+ dispatchCommand(mxComponent, ".uno:ReplyToAnnotation", aArgs);
+
+ // We received a LOK_CALLBACK_COMMENT callback with comment 'Modify' action
+ CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView1.m_aCommentCallbackResult.get<std::string>("action"));
+ CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView2.m_aCommentCallbackResult.get<std::string>("action"));
+ CPPUNIT_ASSERT_EQUAL(nComment1, aView1.m_aCommentCallbackResult.get<int>("id"));
+ CPPUNIT_ASSERT_EQUAL(nComment1, aView2.m_aCommentCallbackResult.get<int>("id"));
+ CPPUNIT_ASSERT_EQUAL(std::string("LOK User2"), aView1.m_aCommentCallbackResult.get<std::string>("author"));
+ CPPUNIT_ASSERT_EQUAL(std::string("LOK User2"), aView2.m_aCommentCallbackResult.get<std::string>("author"));
+ OUString aReplyTextView1 = OUString::createFromAscii(aView1.m_aCommentCallbackResult.get<std::string>("text"));
+ OUString aReplyTextView2 = OUString::createFromAscii(aView2.m_aCommentCallbackResult.get<std::string>("text"));
+ CPPUNIT_ASSERT(aReplyTextView1.startsWith("Reply to LOK User1"));
+ CPPUNIT_ASSERT(aReplyTextView1.endsWith("Reply to comment"));
+ CPPUNIT_ASSERT(aReplyTextView2.startsWith("Reply to LOK User1"));
+ CPPUNIT_ASSERT(aReplyTextView2.endsWith("Reply to comment"));
+ CPPUNIT_ASSERT(!aView1.m_aCommentCallbackResult.get<std::string>("parthash").empty());
+ CPPUNIT_ASSERT(!aView2.m_aCommentCallbackResult.get<std::string>("parthash").empty());
+
+ // Edit this annotation now
+ aArgs = comphelper::InitPropertySequence(
+ {
+ {"Id", uno::Any(OUString::number(nComment1))},
+ {"Text", uno::Any(OUString("Edited comment"))},
+ });
+ dispatchCommand(mxComponent, ".uno:EditAnnotation", aArgs);
+
+ // We received a LOK_CALLBACK_COMMENT callback with comment 'Modify' action
+ CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView1.m_aCommentCallbackResult.get<std::string>("action"));
+ CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView2.m_aCommentCallbackResult.get<std::string>("action"));
+ CPPUNIT_ASSERT_EQUAL(nComment1, aView1.m_aCommentCallbackResult.get<int>("id"));
+ CPPUNIT_ASSERT_EQUAL(nComment1, aView2.m_aCommentCallbackResult.get<int>("id"));
+ CPPUNIT_ASSERT(!aView1.m_aCommentCallbackResult.get<std::string>("parthash").empty());
+ CPPUNIT_ASSERT(!aView2.m_aCommentCallbackResult.get<std::string>("parthash").empty());
+ CPPUNIT_ASSERT_EQUAL(std::string("Edited comment"), aView1.m_aCommentCallbackResult.get<std::string>("text"));
+ CPPUNIT_ASSERT_EQUAL(std::string("Edited comment"), aView2.m_aCommentCallbackResult.get<std::string>("text"));
+
+ // Delete the comment
+ aArgs = comphelper::InitPropertySequence(
+ {
+ {"Id", uno::Any(OUString::number(nComment1))},
+ });
+ dispatchCommand(mxComponent, ".uno:DeleteAnnotation", aArgs);
+
+ // We received a LOK_CALLBACK_COMMENT callback with comment 'Remove' action
+ CPPUNIT_ASSERT_EQUAL(std::string("Remove"), aView1.m_aCommentCallbackResult.get<std::string>("action"));
+ CPPUNIT_ASSERT_EQUAL(std::string("Remove"), aView2.m_aCommentCallbackResult.get<std::string>("action"));
+ CPPUNIT_ASSERT_EQUAL(nComment1, aView1.m_aCommentCallbackResult.get<int>("id"));
+ CPPUNIT_ASSERT_EQUAL(nComment1, aView2.m_aCommentCallbackResult.get<int>("id"));
+
+ comphelper::LibreOfficeKit::setTiledAnnotations(true);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCommentChangeImpress)
+{
+ uno::Sequence<beans::PropertyValue> aArgs;
+
+ // Load the document.
+ // Set the tiled annotations off
+ comphelper::LibreOfficeKit::setTiledAnnotations(false);
+
+ createDoc("dummy.odp", comphelper::InitPropertySequence(
+ {
+ {".uno:Author", uno::Any(OUString("LOK User1"))},
+ }));
+
+ ViewCallback aView1;
+
+ // Add a new comment
+ aArgs = comphelper::InitPropertySequence(
+ {
+ {"Text", uno::Any(OUString("Comment"))},
+ });
+ dispatchCommand(mxComponent, ".uno:InsertAnnotation", aArgs);
+
+ CPPUNIT_ASSERT_EQUAL(std::string("Add"), aView1.m_aCommentCallbackResult.get<std::string>("action"));
+
+ int nComment1 = aView1.m_aCommentCallbackResult.get<int>("id");
+
+ CPPUNIT_ASSERT(!aView1.m_aCommentCallbackResult.get<std::string>("parthash").empty());
+ CPPUNIT_ASSERT_EQUAL(std::string("Comment"), aView1.m_aCommentCallbackResult.get<std::string>("text"));
+ CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 0, 0"), aView1.m_aCommentCallbackResult.get<std::string>("rectangle"));
+
+ // Edit this annotation now
+ aArgs = comphelper::InitPropertySequence(
+ {
+ {"Id", uno::Any(OUString::number(nComment1))},
+ {"PositionX", uno::Any(sal_Int32(10))},
+ {"PositionY", uno::Any(sal_Int32(20))}
+ });
+ dispatchCommand(mxComponent, ".uno:EditAnnotation", aArgs);
+
+ CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView1.m_aCommentCallbackResult.get<std::string>("action"));
+ CPPUNIT_ASSERT_EQUAL(std::string("Comment"), aView1.m_aCommentCallbackResult.get<std::string>("text"));
+ CPPUNIT_ASSERT_EQUAL(std::string("10, 20, 0, 0"), aView1.m_aCommentCallbackResult.get<std::string>("rectangle"));
+
+ comphelper::LibreOfficeKit::setTiledAnnotations(true);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCommentChangeDraw)
+{
+ uno::Sequence<beans::PropertyValue> aArgs;
+
+ // Load the document.
+ // Set the tiled annotations off
+ comphelper::LibreOfficeKit::setTiledAnnotations(false);
+
+ createDoc("dummy.odg", comphelper::InitPropertySequence(
+ {
+ {".uno:Author", uno::Any(OUString("LOK User1"))},
+ }));
+
+ ViewCallback aView1;
+
+ // Add a new comment
+ aArgs = comphelper::InitPropertySequence(
+ {
+ {"Text", uno::Any(OUString("Comment"))},
+ });
+ dispatchCommand(mxComponent, ".uno:InsertAnnotation", aArgs);
+
+ CPPUNIT_ASSERT_EQUAL(std::string("Add"), aView1.m_aCommentCallbackResult.get<std::string>("action"));
+
+ int nComment1 = aView1.m_aCommentCallbackResult.get<int>("id");
+
+ CPPUNIT_ASSERT(!aView1.m_aCommentCallbackResult.get<std::string>("parthash").empty());
+ CPPUNIT_ASSERT_EQUAL(std::string("Comment"), aView1.m_aCommentCallbackResult.get<std::string>("text"));
+ CPPUNIT_ASSERT_EQUAL(std::string("0, 0, 0, 0"), aView1.m_aCommentCallbackResult.get<std::string>("rectangle"));
+
+ // Edit this annotation now
+ aArgs = comphelper::InitPropertySequence(
+ {
+ {"Id", uno::Any(OUString::number(nComment1))},
+ {"PositionX", uno::Any(sal_Int32(10))},
+ {"PositionY", uno::Any(sal_Int32(20))}
+ });
+ dispatchCommand(mxComponent, ".uno:EditAnnotation", aArgs);
+
+ CPPUNIT_ASSERT_EQUAL(std::string("Modify"), aView1.m_aCommentCallbackResult.get<std::string>("action"));
+ CPPUNIT_ASSERT_EQUAL(std::string("Comment"), aView1.m_aCommentCallbackResult.get<std::string>("text"));
+ CPPUNIT_ASSERT_EQUAL(std::string("10, 20, 0, 0"), aView1.m_aCommentCallbackResult.get<std::string>("rectangle"));
+
+ comphelper::LibreOfficeKit::setTiledAnnotations(true);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testMultiViewInsertDeletePage)
+{
+ // Load the document.
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ ViewCallback aView1;
+ int nView1 = SfxLokHelper::getView();
+ uno::Sequence<beans::PropertyValue> aArgs;
+ SdDrawDocument* pDoc = pXImpressDocument->GetDocShell()->GetDoc();
+
+ // Create second view
+ SfxLokHelper::createView();
+ pXImpressDocument->initializeForTiledRendering(aArgs);
+ ViewCallback aView2;
+ int nView2 = SfxLokHelper::getView();
+
+ // the document has 8 slides
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(8), pDoc->GetSdPageCount(PageKind::Standard));
+
+ // Switch to 5th page in 2nd view
+ pXImpressDocument->setPart(4);
+
+ // Insert slide in 1st view
+ SfxLokHelper::setView(nView1);
+ dispatchCommand(mxComponent, ".uno:InsertPage", aArgs);
+
+ // See if the current slide number changed in 2nd view too
+ SfxLokHelper::setView(nView2);
+ CPPUNIT_ASSERT_EQUAL(5, pXImpressDocument->getPart());
+
+ // Delete the page in 1st view now
+ SfxLokHelper::setView(nView1);
+ dispatchCommand(mxComponent, ".uno:DeletePage", aArgs);
+
+ // See if current slide number changed in 2nd view too
+ SfxLokHelper::setView(nView2);
+ CPPUNIT_ASSERT_EQUAL(4, pXImpressDocument->getPart());
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testMultiViewInsertDeletePage2)
+{
+ // Load the document.
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ ViewCallback aView1;
+ int nView1 = SfxLokHelper::getView();
+ uno::Sequence<beans::PropertyValue> aArgs;
+ SdDrawDocument* pDoc = pXImpressDocument->GetDocShell()->GetDoc();
+
+ // Create second view
+ SfxLokHelper::createView();
+ pXImpressDocument->initializeForTiledRendering(aArgs);
+ ViewCallback aView2;
+ int nView2 = SfxLokHelper::getView();
+
+ // the document has 8 slides
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(8), pDoc->GetSdPageCount(PageKind::Standard));
+
+ // Switch to 5th page in 2nd view
+ pXImpressDocument->setPart(4);
+
+ // Begin text edit on the only object on the slide.
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject1 = pActualPage->GetObj(0);
+ CPPUNIT_ASSERT(pObject1 != nullptr);
+ CPPUNIT_ASSERT_EQUAL(SdrObjKind::TitleText, pObject1->GetObjIdentifier());
+ SdrTextObj* pTextObject = static_cast<SdrTextObj*>(pObject1);
+
+ // Double-click outside the text to enter edit mode.
+ const ::tools::Rectangle aRect = pTextObject->GetCurrentBoundRect();
+ const auto cornerX = o3tl::toTwips(aRect.Left() + (aRect.getOpenWidth() / 4), o3tl::Length::mm100);
+ const auto cornerY = o3tl::toTwips(aRect.Top() + (aRect.getOpenHeight() / 4), o3tl::Length::mm100);
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN,
+ cornerX, cornerY,
+ 2, MOUSE_LEFT, 0);
+ pXImpressDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP,
+ cornerX, cornerY,
+ 2, MOUSE_LEFT, 0);
+ Scheduler::ProcessEventsToIdle();
+
+ // We must be in text editing mode and have cursor visible.
+ CPPUNIT_ASSERT(pViewShell->GetView()->IsTextEdit());
+
+ // Insert slide in 1st view
+ SfxLokHelper::setView(nView1);
+ dispatchCommand(mxComponent, ".uno:InsertPage", aArgs);
+
+ // See if the current slide number changed in 2nd view too
+ SfxLokHelper::setView(nView2);
+ CPPUNIT_ASSERT_EQUAL(5, pXImpressDocument->getPart());
+
+ // Delete the page in 1st view now
+ SfxLokHelper::setView(nView1);
+ dispatchCommand(mxComponent, ".uno:DeletePage", aArgs);
+
+ // See if current slide number changed in 2nd view too
+ SfxLokHelper::setView(nView2);
+ CPPUNIT_ASSERT_EQUAL(4, pXImpressDocument->getPart());
+
+ // We must be still in text editing mode and have cursor visible.
+ CPPUNIT_ASSERT(pViewShell->GetView()->IsTextEdit());
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testDisableUndoRepair)
+{
+ // Load the document.
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+
+ // Create View 1
+ SfxViewShell* pView1 = SfxViewShell::Current();
+ sd::ViewShell* pViewShell1 = pXImpressDocument->GetDocShell()->GetViewShell();
+ int nView1 = SfxLokHelper::getView();
+
+ // Create View 2
+ SfxLokHelper::createView();
+ SfxViewShell* pView2 = SfxViewShell::Current();
+ sd::ViewShell* pViewShell2 = pXImpressDocument->GetDocShell()->GetViewShell();
+ int nView2 = SfxLokHelper::getView();
+
+ // Check UNDO is disabled
+ {
+ std::unique_ptr<SfxPoolItem> pItem1;
+ std::unique_ptr<SfxPoolItem> pItem2;
+ CPPUNIT_ASSERT_EQUAL(SfxItemState::DISABLED, pView1->GetViewFrame().GetBindings().QueryState(SID_UNDO, pItem1));
+ CPPUNIT_ASSERT_EQUAL(SfxItemState::DISABLED, pView2->GetViewFrame().GetBindings().QueryState(SID_UNDO, pItem2));
+ }
+
+ // Insert a character in the first view.
+ SfxLokHelper::setView(nView1);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'h', 0);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'h', 0);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT(pViewShell1->GetView()->IsTextEdit());
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::ESCAPE);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT(!pViewShell1->GetView()->IsTextEdit());
+
+ // Check
+ {
+ std::unique_ptr<SfxPoolItem> xItem1;
+ pView1->GetViewFrame().GetBindings().QueryState(SID_UNDO, xItem1);
+ const auto* pUInt32Item1 = dynamic_cast<const SfxUInt32Item*>(xItem1.get());
+ CPPUNIT_ASSERT(!pUInt32Item1);
+
+ std::unique_ptr<SfxPoolItem> xItem2;
+ pView2->GetViewFrame().GetBindings().QueryState(SID_UNDO, xItem2);
+ const auto* pUInt32Item2 = dynamic_cast<const SfxUInt32Item*>(xItem2.get());
+ CPPUNIT_ASSERT(pUInt32Item2);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(SID_REPAIRPACKAGE), pUInt32Item2->GetValue());
+ }
+
+ // Insert a character in the second view.
+ SfxLokHelper::setView(nView2);
+ pXImpressDocument->setPart(1);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'c', 0);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'c', 0);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT(pViewShell2->GetView()->IsTextEdit());
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::ESCAPE);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT(!pViewShell2->GetView()->IsTextEdit());
+
+ // Check
+ {
+ std::unique_ptr<SfxPoolItem> xItem1;
+ pView1->GetViewFrame().GetBindings().QueryState(SID_UNDO, xItem1);
+ const SfxUInt32Item* pUInt32Item = dynamic_cast<const SfxUInt32Item*>(xItem1.get());
+ CPPUNIT_ASSERT(pUInt32Item);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(SID_REPAIRPACKAGE), pUInt32Item->GetValue());
+
+ std::unique_ptr<SfxPoolItem> xItem2;
+ pView2->GetViewFrame().GetBindings().QueryState(SID_UNDO, xItem2);
+ CPPUNIT_ASSERT(!dynamic_cast< const SfxUInt32Item* >(xItem2.get()));
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testDocumentRepair)
+{
+ // Create two views.
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ CPPUNIT_ASSERT(pXImpressDocument);
+
+ // view #1
+ SfxViewShell* pView1 = SfxViewShell::Current();
+
+ // view #2
+ SfxLokHelper::createView();
+ SfxViewShell* pView2 = SfxViewShell::Current();
+ int nView2 = SfxLokHelper::getView();
+ sd::ViewShell* pViewShell2 = pXImpressDocument->GetDocShell()->GetViewShell();
+
+ CPPUNIT_ASSERT(pView1 != pView2);
+ {
+ std::unique_ptr<SfxBoolItem> pItem1;
+ pView1->GetViewFrame().GetBindings().QueryState(SID_DOC_REPAIR, pItem1);
+ CPPUNIT_ASSERT(pItem1);
+ CPPUNIT_ASSERT_EQUAL(false, pItem1->GetValue());
+
+ std::unique_ptr<SfxBoolItem> pItem2;
+ pView2->GetViewFrame().GetBindings().QueryState(SID_DOC_REPAIR, pItem2);
+ CPPUNIT_ASSERT(pItem2);
+ CPPUNIT_ASSERT_EQUAL(false, pItem2->GetValue());
+ }
+
+ // Insert a character in the second view.
+ SfxLokHelper::setView(nView2);
+ pXImpressDocument->setPart(1);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'c', 0);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'c', 0);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT(pViewShell2->GetView()->IsTextEdit());
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::ESCAPE);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT(!pViewShell2->GetView()->IsTextEdit());
+
+ {
+ std::unique_ptr<SfxBoolItem> pItem1;
+ pView1->GetViewFrame().GetBindings().QueryState(SID_DOC_REPAIR, pItem1);
+ CPPUNIT_ASSERT(pItem1);
+ CPPUNIT_ASSERT_EQUAL(true, pItem1->GetValue());
+
+ std::unique_ptr<SfxBoolItem> pItem2;
+ pView2->GetViewFrame().GetBindings().QueryState(SID_DOC_REPAIR, pItem2);
+ CPPUNIT_ASSERT(pItem2);
+ CPPUNIT_ASSERT_EQUAL(true, pItem2->GetValue());
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testLanguageStatus)
+{
+ // Load the document.
+ createDoc("dummy.odp");
+ SfxViewShell* pView1 = SfxViewShell::Current();
+ SfxLokHelper::createView();
+ SfxViewShell* pView2 = SfxViewShell::Current();
+ {
+ std::unique_ptr<SfxPoolItem> xItem1;
+ std::unique_ptr<SfxPoolItem> xItem2;
+ pView1->GetViewFrame().GetBindings().QueryState(SID_LANGUAGE_STATUS, xItem1);
+ pView2->GetViewFrame().GetBindings().QueryState(SID_LANGUAGE_STATUS, xItem2);
+ auto pStringItem = dynamic_cast<const SfxStringItem*>(xItem1.get());
+ CPPUNIT_ASSERT(pStringItem);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("English (USA);en-US"), pStringItem->GetValue());
+
+ CPPUNIT_ASSERT(dynamic_cast< const SfxStringItem* >(xItem2.get()));
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testLanguageAllText)
+{
+ // Load the document, which has a single shape, with Hungarian text.
+ createDoc("language-all-text.odp");
+
+ // Set the language to English for all text.
+ uno::Sequence<beans::PropertyValue> aArgs = comphelper::InitPropertySequence({
+ { "Language", uno::Any(OUString("Default_English (USA)")) },
+ });
+ dispatchCommand(mxComponent, ".uno:LanguageStatus", aArgs);
+
+ // Assert that the shape text language was changed.
+ uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0),
+ uno::UNO_QUERY);
+ uno::Reference<text::XTextRange> xShape(xPage->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xRun(xShape, uno::UNO_QUERY_THROW);
+ lang::Locale aLocale;
+ xRun->getPropertyValue("CharLocale") >>= aLocale;
+ // Without the accompanying fix in place, this test would have failed with 'Expected: en;
+ // Actual: hu', as the shape text language was not set.
+ CPPUNIT_ASSERT_EQUAL(OUString("en"), aLocale.Language);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testDefaultView)
+{
+ // Load the document with notes view.
+ SdXImpressDocument* pXImpressDocument = createDoc("notes-view.odp");
+ sd::ViewShell* pView = pXImpressDocument->GetDocShell()->GetViewShell();
+ {
+ std::unique_ptr<SfxBoolItem> pImpressView;
+ std::unique_ptr<SfxBoolItem> pNotesView;
+ pView->GetViewFrame()->GetBindings().QueryState(SID_NORMAL_MULTI_PANE_GUI, pImpressView);
+ pView->GetViewFrame()->GetBindings().QueryState(SID_NOTES_MODE, pNotesView);
+ CPPUNIT_ASSERT(pImpressView);
+ CPPUNIT_ASSERT(pNotesView);
+ CPPUNIT_ASSERT_EQUAL(true, pImpressView->GetValue());
+ CPPUNIT_ASSERT_EQUAL(false, pNotesView->GetValue());
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testIMESupport)
+{
+ // Load the document with notes view.
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ VclPtr<vcl::Window> pDocWindow = pXImpressDocument->getDocWindow();
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdrObject* pObject = pViewShell->GetActualPage()->GetObj(0);
+ SdrTextObj* pTextObj = static_cast<SdrTextObj*>(pObject);
+ SdrView* pView = pViewShell->GetView();
+ pView->MarkObj(pTextObj, pView->GetSdrPageView());
+ SfxStringItem aInputString(SID_ATTR_CHAR, "x");
+ pViewShell->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR,
+ SfxCallMode::SYNCHRON, { &aInputString });
+
+ // sequence of chinese IME compositions when 'nihao' is typed in an IME
+ const std::vector<OString> aUtf8Inputs{ "年"_ostr, "你"_ostr, "你好"_ostr, "你哈"_ostr, "你好"_ostr, "你好"_ostr };
+ std::vector<OUString> aInputs;
+ std::transform(aUtf8Inputs.begin(), aUtf8Inputs.end(),
+ std::back_inserter(aInputs), [](OString aInput) {
+ return OUString::fromUtf8(aInput);
+ });
+ for (const auto& aInput: aInputs)
+ {
+ pDocWindow->PostExtTextInputEvent(VclEventId::ExtTextInput, aInput);
+ }
+ pDocWindow->PostExtTextInputEvent(VclEventId::EndExtTextInput, "");
+
+ // the cursor should be at position 3rd
+ EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), rEditView.GetSelection().nStartPos);
+
+ ESelection aWordSelection(0, 0, 0, 3); // start para, start char, end para, end char.
+ rEditView.SetSelection(aWordSelection);
+ // content contains only the last IME composition, not all
+ CPPUNIT_ASSERT_EQUAL(OUString("x" + aInputs[aInputs.size() - 1]), rEditView.GetSelected());
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testTdf115783)
+{
+ // Load the document.
+ SdXImpressDocument* pXImpressDocument = createDoc("tdf115783.fodp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(0);
+ auto pTableObject = dynamic_cast<sdr::table::SdrTableObj*>(pObject);
+ CPPUNIT_ASSERT(pTableObject);
+ SdrView* pView = pViewShell->GetView();
+ pView->MarkObj(pTableObject, pView->GetSdrPageView());
+
+ // Create a cell selection and set font height.
+ // Go to the end of the B1 cell.
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT);
+ // Create a B1->C1 cell selection.
+ const int nShiftRight = KEY_SHIFT + KEY_RIGHT;
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, nShiftRight);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, nShiftRight);
+ uno::Sequence<beans::PropertyValue> aArgs = comphelper::InitPropertySequence({
+ { "FontHeight.Height", uno::Any(static_cast<float>(12)) },
+ });
+ dispatchCommand(mxComponent, ".uno:FontHeight", aArgs);
+
+ // Create a text selection on the B1 cell.
+ pTableObject->setActiveCell(sdr::table::CellPos(1, 0));
+ pView->SdrBeginTextEdit(pTableObject);
+ EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
+ // Start para, start char, end para, end char.
+ rEditView.SetSelection(ESelection(0, 0, 0, 5));
+ CPPUNIT_ASSERT_EQUAL(OUString("hello"), rEditView.GetSelected());
+
+ // Copy selection, paste at the start of the cell.
+ aArgs = {};
+ dispatchCommand(mxComponent, ".uno:Copy", aArgs);
+ rEditView.SetSelection(ESelection(0, 0, 0, 0));
+ aArgs = {};
+ dispatchCommand(mxComponent, ".uno:Paste", aArgs);
+ pView->SdrEndTextEdit();
+
+ // And now verify that the cell has the correct font size.
+ uno::Reference<table::XCellRange> xTable = pTableObject->getTable();
+ CPPUNIT_ASSERT(xTable.is());
+ uno::Reference<text::XTextRange> xCell(xTable->getCellByPosition(1, 0), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xCell.is());
+ uno::Reference<container::XEnumerationAccess> xText(xCell->getText(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xText.is());
+ uno::Reference<container::XEnumerationAccess> xParagraph(
+ xText->createEnumeration()->nextElement(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xParagraph.is());
+ uno::Reference<text::XTextRange> xPortion(xParagraph->createEnumeration()->nextElement(),
+ uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xPortion.is());
+ // This failed, it was only "hello" as the paragraph had 2 portions: a
+ // "hello" with 12pt size and a "hello" with 18pt.
+ CPPUNIT_ASSERT_EQUAL(OUString("hellohello"), xPortion->getString());
+ uno::Reference<beans::XPropertySet> xPropertySet(xPortion, uno::UNO_QUERY);
+ int nHeight = xPropertySet->getPropertyValue("CharHeight").get<float>();
+ // Make sure that the single font size for the cell is the expected one.
+ CPPUNIT_ASSERT_EQUAL(12, nHeight);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testPasteTextOnSlide)
+{
+ // Load the document.
+ SdXImpressDocument* pXImpressDocument = createDoc("paste_text_onslide.odp");
+ CPPUNIT_ASSERT(pXImpressDocument);
+
+ // select second text object
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
+ Scheduler::ProcessEventsToIdle();
+
+ // step into text editing
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, '1', 0);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, '1', 0);
+ Scheduler::ProcessEventsToIdle();
+
+ // select full text
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT | KEY_SHIFT);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT | KEY_SHIFT);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT | KEY_SHIFT);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT | KEY_SHIFT);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT | KEY_SHIFT);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT | KEY_SHIFT);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT | KEY_SHIFT);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT | KEY_SHIFT);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT | KEY_SHIFT);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT | KEY_SHIFT);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT | KEY_SHIFT);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT | KEY_SHIFT);
+ Scheduler::ProcessEventsToIdle();
+
+ // Copy some text
+ dispatchCommand(mxComponent, ".uno:Copy", uno::Sequence<beans::PropertyValue>());
+
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::ESCAPE);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE);
+ Scheduler::ProcessEventsToIdle();
+
+ // Paste onto the slide
+ dispatchCommand(mxComponent, ".uno:Paste", uno::Sequence<beans::PropertyValue>());
+
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::ESCAPE);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE);
+ Scheduler::ProcessEventsToIdle();
+
+ // Check the position of the newly added text shape, created for pasted text
+ SdPage* pActualPage = pXImpressDocument->GetDocShell()->GetViewShell()->GetActualPage();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pActualPage->GetObjCount());
+ SdrObject* pObject = pActualPage->GetObj(2);
+ CPPUNIT_ASSERT(pObject);
+ SdrTextObj* pTextObj = DynCastSdrTextObj(pObject);
+ CPPUNIT_ASSERT(pTextObj);
+ CPPUNIT_ASSERT_EQUAL(SdrObjKind::Text, pTextObj->GetObjIdentifier());
+ const Point aPos = pTextObj->GetLastBoundRect().TopLeft();
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(0), aPos.getX());
+ CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(0), aPos.getY());
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testTdf115873)
+{
+ // Initialize the navigator.
+ SdXImpressDocument* pXImpressDocument = createDoc("tdf115873.fodp");
+ SfxViewShell* pViewShell = SfxViewShell::Current();
+ CPPUNIT_ASSERT(pViewShell);
+ SfxBindings& rBindings = pViewShell->GetViewFrame().GetBindings();
+ auto xNavigator = std::make_unique<SdNavigatorWin>(nullptr, &rBindings, nullptr);
+ xNavigator->InitTreeLB(pXImpressDocument->GetDoc());
+ SdPageObjsTLV& rObjects = xNavigator->GetObjects();
+ rObjects.SelectEntry(u"Slide 1");
+ rObjects.Select();
+ sd::ViewShell* pSdViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdrView* pSdrView = pSdViewShell->GetView();
+ pSdrView->UnmarkAllObj(pSdrView->GetSdrPageView());
+
+ // Make sure that no shapes are selected.
+ const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), rMarkList.GetMarkCount());
+
+ // Single-click with the mouse.
+ MouseEvent aMouseEvent(Point(0, 0), /*nClicks=*/1, MouseEventModifiers::NONE, MOUSE_LEFT);
+ rObjects.MousePressHdl(aMouseEvent);
+ rObjects.SelectEntry(u"Rectangle");
+ rObjects.Select();
+ rObjects.MouseReleaseHdl(aMouseEvent);
+ Scheduler::ProcessEventsToIdle();
+ // This failed, single-click did not result in a shape selection (only
+ // double-click did).
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rMarkList.GetMarkCount());
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testTdf115873Group)
+{
+ // Initialize the navigator.
+ SdXImpressDocument* pXImpressDocument = createDoc("tdf115873-group.fodp");
+ SfxViewShell* pViewShell = SfxViewShell::Current();
+ CPPUNIT_ASSERT(pViewShell);
+ SfxBindings& rBindings = pViewShell->GetViewFrame().GetBindings();
+ auto xNavigator = std::make_unique<SdNavigatorWin>(nullptr, &rBindings, nullptr);
+ xNavigator->InitTreeLB(pXImpressDocument->GetDoc());
+ SdPageObjsTLV& rObjects = xNavigator->GetObjects();
+ // This failed, Fill() and IsEqualToDoc() were out of sync for group
+ // shapes.
+ CPPUNIT_ASSERT(rObjects.IsEqualToDoc(pXImpressDocument->GetDoc()));
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testCutSelectionChange)
+{
+ // Load the document.
+ SdXImpressDocument* pXImpressDocument = createDoc("cut_selection_change.odp");
+ CPPUNIT_ASSERT(pXImpressDocument);
+
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ setupLibreOfficeKitViewCallback(pViewShell->GetViewShellBase());
+ Scheduler::ProcessEventsToIdle();
+
+ // Select first text object
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
+ Scheduler::ProcessEventsToIdle();
+
+ // step into text editing
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, '1', 0);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, '1', 0);
+ Scheduler::ProcessEventsToIdle();
+
+ // select some text
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT | KEY_SHIFT);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT | KEY_SHIFT);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_LEFT | KEY_SHIFT);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_LEFT | KEY_SHIFT);
+ Scheduler::ProcessEventsToIdle();
+
+ // Check that we have a selection before cutting
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), m_aSelection.size());
+
+ // Cut the selected text
+ dispatchCommand(mxComponent, ".uno:Cut", uno::Sequence<beans::PropertyValue>());
+
+ // Selection is removed
+ CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(0), m_aSelection.size());
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testGetViewRenderState)
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ int nFirstViewId = SfxLokHelper::getView();
+ ViewCallback aView1;
+ CPPUNIT_ASSERT_EQUAL(";Default"_ostr, pXImpressDocument->getViewRenderState());
+ // Create a second view
+ SfxLokHelper::createView();
+ ViewCallback aView2;
+ CPPUNIT_ASSERT_EQUAL(";Default"_ostr, pXImpressDocument->getViewRenderState());
+ // Set to dark scheme
+ {
+ uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence(
+ {
+ { "NewTheme", uno::Any(OUString("Dark")) },
+ }
+ );
+ dispatchCommand(mxComponent, ".uno:ChangeTheme", aPropertyValues);
+ }
+ CPPUNIT_ASSERT_EQUAL(";Dark"_ostr, pXImpressDocument->getViewRenderState());
+ // Switch back to the first view, and check that the options string is the same
+ SfxLokHelper::setView(nFirstViewId);
+ CPPUNIT_ASSERT_EQUAL(";Default"_ostr, pXImpressDocument->getViewRenderState());
+}
+
+// Helper function to get a tile to a bitmap and check the pixel color
+static void assertTilePixelColor(SdXImpressDocument* pXImpressDocument, int nPixelX, int nPixelY, Color aColor)
+{
+ size_t nCanvasSize = 1024;
+ size_t nTileSize = 256;
+ std::vector<unsigned char> aPixmap(nCanvasSize * nCanvasSize * 4, 0);
+ ScopedVclPtrInstance<VirtualDevice> pDevice(DeviceFormat::WITHOUT_ALPHA);
+ pDevice->SetBackground(Wallpaper(COL_TRANSPARENT));
+ pDevice->SetOutputSizePixelScaleOffsetAndLOKBuffer(Size(nCanvasSize, nCanvasSize),
+ Fraction(1.0), Point(), aPixmap.data());
+ pXImpressDocument->paintTile(*pDevice, nCanvasSize, nCanvasSize, 0, 0, 15360, 7680);
+ pDevice->EnableMapMode(false);
+ Bitmap aBitmap = pDevice->GetBitmap(Point(0, 0), Size(nTileSize, nTileSize));
+ BitmapScopedReadAccess pAccess(aBitmap);
+ Color aActualColor(pAccess->GetPixel(nPixelX, nPixelY));
+ CPPUNIT_ASSERT_EQUAL(aColor, aActualColor);
+}
+
+// Test that changing the theme in one view doesn't change it in the other view
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testThemeViewSeparation)
+{
+ Color aDarkColor(0x1c, 0x1c, 0x1c);
+ // Add a minimal dark scheme
+ {
+ svtools::EditableColorConfig aColorConfig;
+ svtools::ColorConfigValue aValue;
+ aValue.bIsVisible = true;
+ aValue.nColor = aDarkColor;
+ aColorConfig.SetColorValue(svtools::DOCCOLOR, aValue);
+ aColorConfig.AddScheme(u"Dark"_ustr);
+ }
+ // Add a minimal light scheme
+ {
+ svtools::EditableColorConfig aColorConfig;
+ svtools::ColorConfigValue aValue;
+ aValue.bIsVisible = true;
+ aValue.nColor = COL_WHITE;
+ aColorConfig.SetColorValue(svtools::DOCCOLOR, aValue);
+ aColorConfig.AddScheme(u"Light"_ustr);
+ }
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ int nFirstViewId = SfxLokHelper::getView();
+ ViewCallback aView1;
+ // Switch first view to light scheme
+ {
+ uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence(
+ {
+ { "NewTheme", uno::Any(OUString("Light")) },
+ }
+ );
+ dispatchCommand(mxComponent, ".uno:ChangeTheme", aPropertyValues);
+ }
+ // First view is at light scheme
+ assertTilePixelColor(pXImpressDocument, 255, 255, COL_WHITE);
+ // Create second view
+ SfxLokHelper::createView();
+ int nSecondViewId = SfxLokHelper::getView();
+ ViewCallback aView2;
+ // Set second view to dark scheme
+ {
+ uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence(
+ {
+ { "NewTheme", uno::Any(OUString("Dark")) },
+ }
+ );
+ dispatchCommand(mxComponent, ".uno:ChangeTheme", aPropertyValues);
+ }
+ assertTilePixelColor(pXImpressDocument, 255, 255, aDarkColor);
+ // First view still in light scheme
+ SfxLokHelper::setView(nFirstViewId);
+ assertTilePixelColor(pXImpressDocument, 255, 255, COL_WHITE);
+ // Second view still in dark scheme
+ SfxLokHelper::setView(nSecondViewId);
+ assertTilePixelColor(pXImpressDocument, 255, 255, Color(0x1c, 0x1c, 0x1c));
+ // Switch second view back to light scheme
+ {
+ uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence(
+ {
+ { "NewTheme", uno::Any(OUString("Light")) },
+ }
+ );
+ dispatchCommand(mxComponent, ".uno:ChangeTheme", aPropertyValues);
+ }
+ // Now in light scheme
+ assertTilePixelColor(pXImpressDocument, 255, 255, COL_WHITE);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testRegenerateDiagram)
+{
+ // Load the document.
+ SdXImpressDocument* pXImpressDocument = createDoc("regenerate-diagram.pptx");
+ CPPUNIT_ASSERT(pXImpressDocument);
+
+ SdPage* pActualPage = pXImpressDocument->GetDocShell()->GetViewShell()->GetActualPage();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), pActualPage->GetObj(0)->GetSubList()->GetObjCount());
+
+ // For new Diagram functionality entering group using UI is not allowed as long
+ // as the group shape is a diagram. Do the same as before done by triggering UI
+ // events directly in the model
+ // Remove and free top-left entry (Box showing "A")
+ pActualPage->GetObj(0)->GetSubList()->RemoveObject(1);
+
+ // select diagram
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pActualPage->GetObj(0)->GetSubList()->GetObjCount());
+
+ // regenerate diagram
+ dispatchCommand(mxComponent, ".uno:RegenerateDiagram", uno::Sequence<beans::PropertyValue>());
+
+ // diagram content (child shape count) should be the same as in the beginning
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), pActualPage->GetObj(0)->GetSubList()->GetObjCount());
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testInsertDeletePageInvalidation)
+{
+ // Load the document.
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ ViewCallback aView1;
+ CPPUNIT_ASSERT_EQUAL(8, pXImpressDocument->getParts());
+
+ // Insert slide
+ aView1.m_bTilesInvalidated = false;
+ aView1.m_aInvalidations.clear();
+ dispatchCommand(mxComponent, ".uno:InsertPage", uno::Sequence<beans::PropertyValue>());
+ CPPUNIT_ASSERT(aView1.m_bTilesInvalidated);
+ CPPUNIT_ASSERT_EQUAL(9, pXImpressDocument->getParts());
+ CPPUNIT_ASSERT_EQUAL(size_t(9), aView1.m_aInvalidations.size());
+
+ // Delete slide
+ aView1.m_bTilesInvalidated = false;
+ aView1.m_aInvalidations.clear();
+ dispatchCommand(mxComponent, ".uno:DeletePage", uno::Sequence<beans::PropertyValue>());
+ CPPUNIT_ASSERT(aView1.m_bTilesInvalidated);
+ CPPUNIT_ASSERT_EQUAL(8, pXImpressDocument->getParts());
+ CPPUNIT_ASSERT_EQUAL(size_t(8), aView1.m_aInvalidations.size());
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSpellOnlineRenderParameter)
+{
+ // Load the document.
+ SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+ bool bSet = pXImpressDocument->GetDoc()->GetOnlineSpell();
+
+ uno::Sequence<beans::PropertyValue> aPropertyValues =
+ {
+ comphelper::InitPropertySequence({ { ".uno:SpellOnline", uno::Any(!bSet) } }),
+ };
+ pXImpressDocument->initializeForTiledRendering(aPropertyValues);
+ CPPUNIT_ASSERT_EQUAL(!bSet, pXImpressDocument->GetDoc()->GetOnlineSpell());
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testSlideDuplicateUndo)
+{
+ // Create two views.
+ SdXImpressDocument* pXImpressDocument = createDoc("duplicate-undo.odp");
+ int nView0 = SfxLokHelper::getView();
+ SfxLokHelper::createView();
+ pXImpressDocument->initializeForTiledRendering({});
+ int nView1 = SfxLokHelper::getView();
+ SfxLokHelper::setView(nView0);
+
+ // Switch to the 3rd slide on view 0, and start text editing.
+ {
+ pXImpressDocument->setPart(2);
+ sd::ViewShell* pViewShell0 = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdrView* pView = pViewShell0->GetView();
+ SdPage* pActualPage = pViewShell0->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(1);
+ SdrTextObj* pTextObj = static_cast<SdrTextObj*>(pObject);
+ pView->MarkObj(pTextObj, pView->GetSdrPageView());
+ SfxStringItem aInputString(SID_ATTR_CHAR, "x");
+ pViewShell0->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR,
+ SfxCallMode::SYNCHRON, { &aInputString });
+ CPPUNIT_ASSERT(pView->IsTextEdit());
+ CPPUNIT_ASSERT(pView->GetTextEditPageView());
+ }
+
+ // Duplicate the first slide on view 1 and undo it.
+ SfxLokHelper::setView(nView1);
+ dispatchCommand(mxComponent, ".uno:DuplicatePage", {});
+ pXImpressDocument->setPart(0, /*bAllowChangeFocus=*/false);
+ pXImpressDocument->setPart(1, /*bAllowChangeFocus=*/false);
+ SfxLokHelper::setView(nView0);
+ pXImpressDocument->setPart(0, /*bAllowChangeFocus=*/false);
+ pXImpressDocument->setPart(3, /*bAllowChangeFocus=*/false);
+ SfxLokHelper::setView(nView1);
+ pXImpressDocument->getUndoManager()->undo();
+ // Without the accompanying fix in place, this would have tried to access the outdated page view
+ // pointer, potentially leading to a crash.
+ pXImpressDocument->setPart(2, /*bAllowChangeFocus=*/false);
+
+ // Make sure that view 0 now doesn't have an outdated page view pointer.
+ SfxLokHelper::setView(nView0);
+ sd::ViewShell* pViewShell0 = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdrView* pView0 = pViewShell0->GetView();
+ CPPUNIT_ASSERT(!pView0->GetTextEditPageView());
+}
+
+namespace
+{
+
+void lcl_extractHandleParameters(std::string_view selection, sal_uInt32& id, sal_uInt32& x, sal_uInt32& y)
+{
+ OString extraInfo( selection.substr(selection.find("{")) );
+ std::stringstream aStream((std::string(extraInfo)));
+ boost::property_tree::ptree aTree;
+ boost::property_tree::read_json(aStream, aTree);
+ boost::property_tree::ptree
+ handle0 = aTree
+ .get_child("handles")
+ .get_child("kinds")
+ .get_child("rectangle")
+ .get_child("1")
+ .begin()->second;
+ id = handle0.get_child("id").get_value<int>();
+ x = handle0.get_child("point").get_child("x").get_value<int>();
+ y = handle0.get_child("point").get_child("y").get_value<int>();
+}
+
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testMoveShapeHandle)
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("shape.odp");
+ ViewCallback aView1;
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pPage->GetObj(0);
+ SdrView* pView = pViewShell->GetView();
+ pView->MarkObj(pObject, pView->GetSdrPageView());
+ Scheduler::ProcessEventsToIdle();
+
+ CPPUNIT_ASSERT(!aView1.m_ShapeSelection.isEmpty());
+ {
+ sal_uInt32 id, x, y;
+ lcl_extractHandleParameters(aView1.m_ShapeSelection, id, x ,y);
+ sal_uInt32 oldX = x;
+ sal_uInt32 oldY = y;
+ uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
+ {
+ {"HandleNum", uno::Any(id)},
+ {"NewPosX", uno::Any(x+1)},
+ {"NewPosY", uno::Any(y+1)}
+ }));
+ dispatchCommand(mxComponent, ".uno:MoveShapeHandle", aPropertyValues);
+ CPPUNIT_ASSERT(!aView1.m_ShapeSelection.isEmpty());
+ lcl_extractHandleParameters(aView1.m_ShapeSelection, id, x ,y);
+ CPPUNIT_ASSERT_EQUAL(x-1, oldX);
+ CPPUNIT_ASSERT_EQUAL(y-1, oldY);
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testPasteUndo)
+{
+ // Given a document with a textbox, containing "world":
+ SdXImpressDocument* pXImpressDocument = createDoc("paste-undo.fodp");
+ sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdPage* pActualPage = pViewShell->GetActualPage();
+ SdrObject* pObject = pActualPage->GetObj(0);
+ SdrView* pView = pViewShell->GetView();
+ pView->MarkObj(pObject, pView->GetSdrPageView());
+ pView->SdrBeginTextEdit(pObject);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_HOME);
+ pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_HOME);
+ EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView();
+ ESelection aWordSelection(0, 0, 0, 1); // "w" of "world"
+ rEditView.SetSelection(aWordSelection);
+ dispatchCommand(mxComponent, ".uno:Cut", {});
+
+ // When undoing a paste:
+ dispatchCommand(mxComponent, ".uno:Paste", {});
+ dispatchCommand(mxComponent, ".uno:Undo", {});
+
+ // Then make sure the cursor position is still at the beginning:
+ ESelection aSelection = rEditView.GetSelection();
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 0
+ // - Actual : 4
+ // i.e. the cursor position after undo was at the end of the line, not at the start, as
+ // expected.
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aSelection.nStartPos);
+}
+
+CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, testShapeEditInMultipleViews)
+{
+ SdXImpressDocument* pXImpressDocument = createDoc("TextBoxAndRect.odg");
+ pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
+ SdDrawDocument* pDocument = pXImpressDocument->GetDoc();
+
+ // Create view 1
+ const int nView1 = SfxLokHelper::getView();
+ sd::ViewShell* pViewShell1 = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdrView* pView1 = pViewShell1->GetView();
+ Scheduler::ProcessEventsToIdle();
+
+ // Create view 2
+ SfxLokHelper::createView();
+ const int nView2 = SfxLokHelper::getView();
+ CPPUNIT_ASSERT(nView1 != nView2);
+
+ sd::ViewShell* pViewShell2 = pXImpressDocument->GetDocShell()->GetViewShell();
+ SdrView* pView2 = pViewShell2->GetView();
+ Scheduler::ProcessEventsToIdle();
+
+ // Switch to view 1
+ SfxLokHelper::setView(nView1);
+
+ SdPage* pPage1 = pViewShell1->GetActualPage();
+
+ SdrObject* pTextBoxObject = pPage1->GetObj(0);
+ CPPUNIT_ASSERT_EQUAL(OUString("Text Box"), pTextBoxObject->GetName());
+
+ SdrObject* pRectangleObject = pPage1->GetObj(1);
+ CPPUNIT_ASSERT_EQUAL(OUString("Rect"), pRectangleObject->GetName());
+
+ SdrObject* pTableObject = pPage1->GetObj(2);
+ CPPUNIT_ASSERT_EQUAL(OUString("Table1"), pTableObject->GetName());
+
+ // Scenario 1
+ // 2 shapes - "Text Box" and "Rect"
+ // View1 - "Text Box" enters text edit mode, View 2 - moves the "Rect" around
+ {
+ sd::UndoManager* pUndoManager = pDocument->GetUndoManager();
+ CPPUNIT_ASSERT_EQUAL(size_t(0), pUndoManager->GetUndoActionCount());
+
+ pView1->SdrBeginTextEdit(pTextBoxObject);
+ CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit());
+ CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+
+ // Local undo count for View1 is 0
+ CPPUNIT_ASSERT_EQUAL(size_t(0), pView1->getViewLocalUndoManager()->GetUndoActionCount());
+ // Write 'test' in View1
+ SfxStringItem aInputString(SID_ATTR_CHAR, "test");
+ pViewShell1->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR, SfxCallMode::SYNCHRON, { &aInputString });
+ // Local undo count for View1 is now 1
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pView1->getViewLocalUndoManager()->GetUndoActionCount());
+
+ // Mark rectangle object
+ pView2->MarkObj(pRectangleObject, pView2->GetSdrPageView());
+
+ // Check the initial position of the object
+ tools::Rectangle aRectangle = pRectangleObject->GetLogicRect();
+ CPPUNIT_ASSERT_EQUAL(6250L, aRectangle.TopLeft().X());
+ CPPUNIT_ASSERT_EQUAL(7000L, aRectangle.TopLeft().Y());
+ CPPUNIT_ASSERT_EQUAL(6501L, aRectangle.GetWidth());
+ CPPUNIT_ASSERT_EQUAL(4501L, aRectangle.GetHeight());
+
+ // On View2 - Move handle 0 on the shape to a new position - resize
+ Point aNewPosition = aRectangle.TopLeft() + Point(-1250, -1000);
+ pView2->MoveShapeHandle(0, aNewPosition, -1);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pUndoManager->GetUndoActionCount());
+
+ // Check the object has a new size
+ aRectangle = pRectangleObject->GetLogicRect();
+ CPPUNIT_ASSERT_EQUAL(5000L, aRectangle.TopLeft().X());
+ CPPUNIT_ASSERT_EQUAL(6000L, aRectangle.TopLeft().Y());
+ CPPUNIT_ASSERT_EQUAL(7751L, aRectangle.GetWidth());
+ CPPUNIT_ASSERT_EQUAL(5501L, aRectangle.GetHeight());
+
+ // View1 is still in text edit mode...
+ CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit());
+ CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+
+ // On View2 - relative move the shape to a different position
+ pView2->MoveMarkedObj(Size(1000, 2000), /*bCopy=*/false);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pUndoManager->GetUndoActionCount());
+
+ // Check the object is at a different position
+ aRectangle = pRectangleObject->GetLogicRect();
+ CPPUNIT_ASSERT_EQUAL(6000L, aRectangle.TopLeft().X());
+ CPPUNIT_ASSERT_EQUAL(8000L, aRectangle.TopLeft().Y());
+ CPPUNIT_ASSERT_EQUAL(7751L, aRectangle.GetWidth());
+ CPPUNIT_ASSERT_EQUAL(5501L, aRectangle.GetHeight());
+
+ // View1 is still in text edit mode...
+ CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit());
+ CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+
+ // End Text edit - check undo count increase from 2 -> 3
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pUndoManager->GetUndoActionCount());
+ pView1->SdrEndTextEdit();
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL(size_t(3), pUndoManager->GetUndoActionCount());
+
+ // Check that both views exited the text edit mode
+ CPPUNIT_ASSERT_EQUAL(false, pView1->IsTextEdit());
+ CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+ }
+
+ // Scenario 2
+ // 1 shapes - "Text Box"
+ // View1 - "Text Box" enters text edit mode, View 2 - moves the "Text Box" around
+ {
+ sd::UndoManager* pUndoManager = pDocument->GetUndoManager();
+ CPPUNIT_ASSERT_EQUAL(size_t(3), pUndoManager->GetUndoActionCount());
+
+ pView1->SdrBeginTextEdit(pTextBoxObject);
+ CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit());
+ CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+
+ // Local undo count for View1 is 0
+ CPPUNIT_ASSERT_EQUAL(size_t(0), pView1->getViewLocalUndoManager()->GetUndoActionCount());
+ // Write 'test' in View1
+ SfxStringItem aInputString(SID_ATTR_CHAR, "test");
+ pViewShell1->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR, SfxCallMode::SYNCHRON, { &aInputString });
+ // Local undo count for View1 is now 1
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pView1->getViewLocalUndoManager()->GetUndoActionCount());
+
+ // Mark rectangle object
+ pView2->MarkObj(pTextBoxObject, pView2->GetSdrPageView());
+
+ // Check the initial position of the object
+ tools::Rectangle aRectangle = pTextBoxObject->GetLogicRect();
+ CPPUNIT_ASSERT_EQUAL(2250L, aRectangle.TopLeft().X());
+ CPPUNIT_ASSERT_EQUAL(2000L, aRectangle.TopLeft().Y());
+ CPPUNIT_ASSERT_EQUAL(4501L, aRectangle.GetWidth());
+ CPPUNIT_ASSERT_EQUAL(2001L, aRectangle.GetHeight());
+
+ // On View2 - Move handle 0 on the shape to a new position - resize
+ Point aNewPosition = aRectangle.TopLeft() + Point(-1250, -1000);
+ pView2->MoveShapeHandle(0, aNewPosition, -1);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL(size_t(4), pUndoManager->GetUndoActionCount());
+
+ // Check the object has a new size
+ aRectangle = pTextBoxObject->GetLogicRect();
+ CPPUNIT_ASSERT_EQUAL(1000L, aRectangle.TopLeft().X());
+ CPPUNIT_ASSERT_EQUAL(1000L, aRectangle.TopLeft().Y());
+ CPPUNIT_ASSERT_EQUAL(4990L, aRectangle.GetWidth());
+ CPPUNIT_ASSERT_EQUAL(2175L, aRectangle.GetHeight());
+
+ // View1 is still in text edit mode...
+ CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit());
+ CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+
+ // On View2 - relative move the shape to a different position
+ pView2->MoveMarkedObj(Size(1000, 2000), /*bCopy=*/false);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL(size_t(5), pUndoManager->GetUndoActionCount());
+
+ // Check the object is at a different position
+ aRectangle = pTextBoxObject->GetLogicRect();
+ CPPUNIT_ASSERT_EQUAL(2000L, aRectangle.TopLeft().X());
+ CPPUNIT_ASSERT_EQUAL(3000L, aRectangle.TopLeft().Y());
+ CPPUNIT_ASSERT_EQUAL(4990L, aRectangle.GetWidth());
+ CPPUNIT_ASSERT_EQUAL(2175L, aRectangle.GetHeight());
+
+ // View1 is still in text edit mode...
+ CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit());
+ CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+
+ // End Text edit - check undo count increase from 5 -> 6
+ CPPUNIT_ASSERT_EQUAL(size_t(5), pUndoManager->GetUndoActionCount());
+ pView1->SdrEndTextEdit();
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL(size_t(6), pUndoManager->GetUndoActionCount());
+
+ // Check that both views exited the text edit mode
+ CPPUNIT_ASSERT_EQUAL(false, pView1->IsTextEdit());
+ CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+ }
+
+ // Scenario 3
+ // 1 shapes - "Table1"
+ // View1 - "Table1" enters text edit mode, View 2 - moves the "Table1" around
+ {
+ sd::UndoManager* pUndoManager = pDocument->GetUndoManager();
+ CPPUNIT_ASSERT_EQUAL(size_t(6), pUndoManager->GetUndoActionCount());
+
+ pView1->SdrBeginTextEdit(pTableObject);
+ CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit());
+ CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+
+ // Local undo count for View1 is 0
+ CPPUNIT_ASSERT_EQUAL(size_t(0), pView1->getViewLocalUndoManager()->GetUndoActionCount());
+ // Write 'test' in View1
+ SfxStringItem aInputString(SID_ATTR_CHAR, "test");
+ pViewShell1->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR, SfxCallMode::SYNCHRON, { &aInputString });
+ // Local undo count for View1 is now 1
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pView1->getViewLocalUndoManager()->GetUndoActionCount());
+
+ // Mark rectangle object
+ pView2->MarkObj(pTableObject, pView2->GetSdrPageView());
+
+ // Check the initial position of the table
+ tools::Rectangle aRectangle = pTableObject->GetLogicRect();
+ CPPUNIT_ASSERT_EQUAL(2919L, aRectangle.TopLeft().X());
+ CPPUNIT_ASSERT_EQUAL(18063L, aRectangle.TopLeft().Y());
+ CPPUNIT_ASSERT_EQUAL(14099L, aRectangle.GetWidth());
+ CPPUNIT_ASSERT_EQUAL(5999L, aRectangle.GetHeight());
+
+ // On View2 - relative move the shape to a different position
+ pView2->MoveMarkedObj(Size(1000, 2000), /*bCopy=*/false);
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL(size_t(7), pUndoManager->GetUndoActionCount());
+
+ // Check the object is at a different position
+ aRectangle = pTableObject->GetLogicRect();
+ CPPUNIT_ASSERT_EQUAL(3919L, aRectangle.TopLeft().X());
+ CPPUNIT_ASSERT_EQUAL(20063L, aRectangle.TopLeft().Y());
+ CPPUNIT_ASSERT_EQUAL(14099L, aRectangle.GetWidth());
+ CPPUNIT_ASSERT_EQUAL(5999L, aRectangle.GetHeight());
+
+ // View1 is still in text edit mode...
+ CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit());
+ CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+
+ // End Text edit - check undo count increase from 7 -> 8
+ CPPUNIT_ASSERT_EQUAL(size_t(7), pUndoManager->GetUndoActionCount());
+ pView1->SdrEndTextEdit();
+ Scheduler::ProcessEventsToIdle();
+ CPPUNIT_ASSERT_EQUAL(size_t(8), pUndoManager->GetUndoActionCount());
+
+ // Check that both views exited the text edit mode
+ CPPUNIT_ASSERT_EQUAL(false, pView1->IsTextEdit());
+ CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+ }
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */