/* -*- 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/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <sal/config.h>

#include <string_view>

#include <xmloff/autolayout.hxx>
#include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
#include <xmloff/namespacemap.hxx>
#include <xmloff/xmlnamespace.hxx>
#include <xmloff/xmluconv.hxx>
#include <xmloff/xmltoken.hxx>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/presentation/XPresentationSupplier.hpp>
#include <com/sun/star/presentation/XCustomPresentationSupplier.hpp>
#include <com/sun/star/geometry/RealPoint2D.hpp>
#include <com/sun/star/office/XAnnotationAccess.hpp>
#include <com/sun/star/uno/Any.hxx>
#include "sdxmlexp_impl.hxx"
#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
#include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
#include <com/sun/star/presentation/XHandoutMasterSupplier.hpp>
#include <com/sun/star/container/XIndexContainer.hpp>
#include <com/sun/star/view/PaperOrientation.hpp>
#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>

#include <com/sun/star/form/XFormsSupplier2.hpp>
#include <com/sun/star/presentation/XPresentationPage.hpp>
#include <com/sun/star/drawing/XMasterPageTarget.hpp>
#include <com/sun/star/text/XText.hpp>
#include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
#include <com/sun/star/container/XNamed.hpp>
#include <com/sun/star/util/Duration.hpp>
#include <com/sun/star/util/MeasureUnit.hpp>
#include <rtl/ustrbuf.hxx>
#include <sal/log.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <tools/gen.hxx>
#include <sax/tools/converter.hxx>
#include <xmloff/xmlaustp.hxx>
#include <xmloff/families.hxx>
#include <xmloff/styleexp.hxx>
#include <xmloff/settingsstore.hxx>
#include <xmloff/table/XMLTableExport.hxx>
#include <xmloff/ProgressBarHelper.hxx>
#include "sdpropls.hxx"
#include <xmloff/xmlexppr.hxx>

#include <PropertySetMerger.hxx>
#include "layerexp.hxx"

#include "XMLNumberStylesExport.hxx"

#include <xmloff/animationexport.hxx>

#include <com/sun/star/document/XDocumentProperties.hpp>
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
#include <docmodel/uno/UnoTheme.hxx>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::util;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::drawing;
using namespace ::com::sun::star::office;
using namespace ::com::sun::star::presentation;
using namespace ::com::sun::star::geometry;
using namespace ::com::sun::star::text;
using namespace ::xmloff::token;

class ImpXMLEXPPageMasterInfo
{
    sal_Int32                   mnBorderBottom;
    sal_Int32                   mnBorderLeft;
    sal_Int32                   mnBorderRight;
    sal_Int32                   mnBorderTop;
    sal_Int32                   mnWidth;
    sal_Int32                   mnHeight;
    view::PaperOrientation      meOrientation;
    OUString                    msName;
    OUString                    msMasterPageName;

public:
    ImpXMLEXPPageMasterInfo(const SdXMLExport& rExp, const Reference<XDrawPage>& xPage);
    bool operator==(const ImpXMLEXPPageMasterInfo& rInfo) const;
    void SetName(const OUString& rStr);

    const OUString& GetName() const { return msName; }
    const OUString& GetMasterPageName() const { return msMasterPageName; }

    sal_Int32 GetBorderBottom() const { return mnBorderBottom; }
    sal_Int32 GetBorderLeft() const { return mnBorderLeft; }
    sal_Int32 GetBorderRight() const { return mnBorderRight; }
    sal_Int32 GetBorderTop() const { return mnBorderTop; }
    sal_Int32 GetWidth() const { return mnWidth; }
    sal_Int32 GetHeight() const { return mnHeight; }
    view::PaperOrientation GetOrientation() const { return meOrientation; }
};

ImpXMLEXPPageMasterInfo::ImpXMLEXPPageMasterInfo(
    const SdXMLExport& rExp,
    const Reference<XDrawPage>& xPage)
:   mnBorderBottom(0),
    mnBorderLeft(0),
    mnBorderRight(0),
    mnBorderTop(0),
    mnWidth(0),
    mnHeight(0),
    meOrientation(rExp.IsDraw() ? view::PaperOrientation_PORTRAIT : view::PaperOrientation_LANDSCAPE)
{
    Reference <beans::XPropertySet> xPropSet(xPage, UNO_QUERY);
    if(xPropSet.is())
    {
        Any aAny;

        Reference< beans::XPropertySetInfo > xPropsInfo( xPropSet->getPropertySetInfo() );
        if( xPropsInfo.is() && xPropsInfo->hasPropertyByName(u"BorderBottom"_ustr))
        {
            aAny = xPropSet->getPropertyValue(u"BorderBottom"_ustr);
            aAny >>= mnBorderBottom;

            aAny = xPropSet->getPropertyValue(u"BorderLeft"_ustr);
            aAny >>= mnBorderLeft;

            aAny = xPropSet->getPropertyValue(u"BorderRight"_ustr);
            aAny >>= mnBorderRight;

            aAny = xPropSet->getPropertyValue(u"BorderTop"_ustr);
            aAny >>= mnBorderTop;
        }

        if( xPropsInfo.is() && xPropsInfo->hasPropertyByName(u"Width"_ustr))
        {
            aAny = xPropSet->getPropertyValue(u"Width"_ustr);
            aAny >>= mnWidth;

            aAny = xPropSet->getPropertyValue(u"Height"_ustr);
            aAny >>= mnHeight;
        }

        if( xPropsInfo.is() && xPropsInfo->hasPropertyByName(u"Orientation"_ustr))
        {
            aAny = xPropSet->getPropertyValue(u"Orientation"_ustr);
            aAny >>= meOrientation;
        }
    }

    Reference <container::XNamed> xMasterNamed(xPage, UNO_QUERY);
    if(xMasterNamed.is())
    {
        msMasterPageName = xMasterNamed->getName();
    }
}

bool ImpXMLEXPPageMasterInfo::operator==(const ImpXMLEXPPageMasterInfo& rInfo) const
{
    return ((mnBorderBottom == rInfo.mnBorderBottom)
        && (mnBorderLeft == rInfo.mnBorderLeft)
        && (mnBorderRight == rInfo.mnBorderRight)
        && (mnBorderTop == rInfo.mnBorderTop)
        && (mnWidth == rInfo.mnWidth)
        && (mnHeight == rInfo.mnHeight)
        && (meOrientation == rInfo.meOrientation));
}

void ImpXMLEXPPageMasterInfo::SetName(const OUString& rStr)
{
    msName = rStr;
}

#define IMP_AUTOLAYOUT_INFO_MAX         (35L)

class ImpXMLAutoLayoutInfo
{
    sal_uInt16                  mnType;
    ImpXMLEXPPageMasterInfo*    mpPageMasterInfo;
    OUString                    msLayoutName;
    tools::Rectangle            maTitleRect;
    tools::Rectangle            maPresRect;
    sal_Int32                   mnGapX;
    sal_Int32                   mnGapY;

public:
    ImpXMLAutoLayoutInfo(sal_uInt16 nTyp, ImpXMLEXPPageMasterInfo* pInf);

    sal_uInt16 GetLayoutType() const { return mnType; }
    ImpXMLEXPPageMasterInfo* GetPageMasterInfo() const { return mpPageMasterInfo; }
    sal_Int32 GetGapX() const { return mnGapX; }
    sal_Int32 GetGapY() const { return mnGapY; }

    const OUString& GetLayoutName() const { return msLayoutName; }
    void SetLayoutName(const OUString& rNew) { msLayoutName = rNew; }

    const tools::Rectangle& GetTitleRectangle() const { return maTitleRect; }
    const tools::Rectangle& GetPresRectangle() const { return maPresRect; }

    static bool IsCreateNecessary(sal_uInt16 nTyp);
};

bool ImpXMLAutoLayoutInfo::IsCreateNecessary(sal_uInt16 nTyp)
{
    if(nTyp == 5 /* AUTOLAYOUT_ORG */
        || nTyp == 20 /* AUTOLAYOUT_NONE */
        || nTyp >= IMP_AUTOLAYOUT_INFO_MAX)
        return false;
    return true;
}

ImpXMLAutoLayoutInfo::ImpXMLAutoLayoutInfo(sal_uInt16 nTyp, ImpXMLEXPPageMasterInfo* pInf)
    : mnType(nTyp)
    , mpPageMasterInfo(pInf)
    , mnGapX(0)
    , mnGapY(0)
{
    // create full info (initialize with typical values)
    Point aPagePos(0,0);
    Size aPageSize(28000, 21000);
    Size aPageInnerSize(28000, 21000);

    if(mpPageMasterInfo)
    {
        aPagePos = Point(mpPageMasterInfo->GetBorderLeft(), mpPageMasterInfo->GetBorderTop());
        aPageSize = Size(mpPageMasterInfo->GetWidth(), mpPageMasterInfo->GetHeight());
        aPageInnerSize = aPageSize;
        aPageInnerSize.AdjustWidth(-(mpPageMasterInfo->GetBorderLeft() + mpPageMasterInfo->GetBorderRight()));
        aPageInnerSize.AdjustHeight(-(mpPageMasterInfo->GetBorderTop() + mpPageMasterInfo->GetBorderBottom()));
    }

    // title rectangle aligning
    Point aTitlePos(aPagePos);
    Size aTitleSize(aPageInnerSize);

    if(mnType == 21 /* AUTOLAYOUT_NOTES */)
    {
        aTitleSize.setHeight(static_cast<tools::Long>(aTitleSize.Height() / 2.5));
        Point aPos = aTitlePos;
        aPos.AdjustY( tools::Long( aTitleSize.Height() * 0.083 ) );
        Size aPartArea = aTitleSize;
        Size aSize;

        // scale handout rectangle using actual page size
        double fH = static_cast<double>(aPartArea.Width())  / aPageSize.Width();
        double fV = static_cast<double>(aPartArea.Height()) / aPageSize.Height();

        if ( fH > fV )
            fH = fV;
        aSize.setWidth( static_cast<tools::Long>(fH * aPageSize.Width()) );
        aSize.setHeight( static_cast<tools::Long>(fH * aPageSize.Height()) );

        aPos.AdjustX((aPartArea.Width() - aSize.Width()) / 2);
        aPos.AdjustY((aPartArea.Height()- aSize.Height())/ 2);

        aTitlePos = aPos;
        aTitleSize = aSize;
    }
    else if(mnType == AUTOLAYOUT_VTITLE_VCONTENT_OVER_VCONTENT || mnType == AUTOLAYOUT_VTITLE_VCONTENT)
    {
        Point aClassicTPos(
            aTitlePos.X() + tools::Long( aTitleSize.Width() * 0.0735 ),
            aTitlePos.Y() + tools::Long( aTitleSize.Height() * 0.083 ));
        Size aClassicTSize(
            tools::Long( aTitleSize.Width() * 0.854 ),
            tools::Long( aTitleSize.Height() * 0.167 ));
        Point aLPos(aPagePos);
        Size aLSize(aPageInnerSize);
        Point aClassicLPos(
            aLPos.X() + tools::Long( aLSize.Width() * 0.0735 ),
            aLPos.Y() + tools::Long( aLSize.Height() * 0.472 ));
        Size aClassicLSize(
            tools::Long( aLSize.Width() * 0.854 ),
            tools::Long( aLSize.Height() * 0.444 ));

        aTitlePos.setX( (aClassicTPos.X() + aClassicTSize.Width()) - aClassicTSize.Height() );
        aTitlePos.setY( aClassicTPos.Y() );
        aTitleSize.setWidth( aClassicTSize.Height() );
        aTitleSize.setHeight( (aClassicLPos.Y() + aClassicLSize.Height()) - aClassicTPos.Y() );
    }
    else
    {
        aTitlePos.AdjustX( tools::Long( aTitleSize.Width() * 0.0735 ) );
        aTitlePos.AdjustY( tools::Long( aTitleSize.Height() * 0.083 ) );
        aTitleSize.setWidth( tools::Long( aTitleSize.Width() * 0.854 ) );
        aTitleSize.setHeight( tools::Long( aTitleSize.Height() * 0.167 ) );
    }

    maTitleRect.SetPos(aTitlePos);
    maTitleRect.SetSize(aTitleSize);

    // layout rectangle aligning
    Point aLayoutPos(aPagePos);
    Size aLayoutSize(aPageInnerSize);

    if(mnType == 21 /* AUTOLAYOUT_NOTES */)
    {
        aLayoutPos.AdjustX( tools::Long( aLayoutSize.Width() * 0.0735 ) );
        aLayoutPos.AdjustY( tools::Long( aLayoutSize.Height() * 0.472 ) );
        aLayoutSize.setWidth( tools::Long( aLayoutSize.Width() * 0.854 ) );
        aLayoutSize.setHeight( tools::Long( aLayoutSize.Height() * 0.444 ) );
    }
    else if((mnType >= 22 && mnType <= 26) || (mnType == 31)) // AUTOLAYOUT_HANDOUT*
    {
        // keep info for inner area in maPresRect, put info for gap size
        // to maTitleRect position
        mnGapX = (aPageSize.Width() - aPageInnerSize.Width()) / 2;
        mnGapY = (aPageSize.Height() - aPageInnerSize.Height()) / 2;

        if(!mnGapX)
            mnGapX = aPageSize.Width() / 10;

        if(!mnGapY)
            mnGapY = aPageSize.Height() / 10;

        if(mnGapX < aPageInnerSize.Width() / 10)
            mnGapX = aPageInnerSize.Width() / 10;

        if(mnGapY < aPageInnerSize.Height() / 10)
            mnGapY = aPageInnerSize.Height() / 10;
    }
    else if(mnType == AUTOLAYOUT_VTITLE_VCONTENT_OVER_VCONTENT || mnType == AUTOLAYOUT_VTITLE_VCONTENT)
    {
        Point aClassicTPos(
            aTitlePos.X() + tools::Long( aTitleSize.Width() * 0.0735 ),
            aTitlePos.Y() + tools::Long( aTitleSize.Height() * 0.083 ));
        Size aClassicTSize(
            tools::Long( aTitleSize.Width() * 0.854 ),
            tools::Long( aTitleSize.Height() * 0.167 ));
        Point aClassicLPos(
            aLayoutPos.X() + tools::Long( aLayoutSize.Width() * 0.0735 ),
            aLayoutPos.Y() + tools::Long( aLayoutSize.Height() * 0.472 ));
        Size aClassicLSize(
            tools::Long( aLayoutSize.Width() * 0.854 ),
            tools::Long( aLayoutSize.Height() * 0.444 ));

        aLayoutPos.setX( aClassicLPos.X() );
        aLayoutPos.setY( aClassicTPos.Y() );
        aLayoutSize.setWidth( (aClassicLPos.X() + aClassicLSize.Width())
            - (aClassicTSize.Height() + (aClassicLPos.Y() - (aClassicTPos.Y() + aClassicTSize.Height()))));
        aLayoutSize.setHeight( (aClassicLPos.Y() + aClassicLSize.Height()) - aClassicTPos.Y() );
    }
    else if( mnType == AUTOLAYOUT_ONLY_TEXT )
    {
        aLayoutPos = aTitlePos;
        aLayoutSize.setWidth( aTitleSize.Width() );
        aLayoutSize.setHeight( tools::Long( aLayoutSize.Height() * 0.825 ) );
    }
    else
    {
        aLayoutPos.AdjustX( tools::Long( aLayoutSize.Width() * 0.0735 ) );
        aLayoutPos.AdjustY( tools::Long( aLayoutSize.Height() * 0.278 ) );
        aLayoutSize.setWidth( tools::Long( aLayoutSize.Width() * 0.854 ) );
        aLayoutSize.setHeight( tools::Long( aLayoutSize.Height() * 0.630 ) );
    }

    maPresRect.SetPos(aLayoutPos);
    maPresRect.SetSize(aLayoutSize);
}

constexpr OUString gsPageLayoutNames( u"PageLayoutNames"_ustr );

SdXMLExport::SdXMLExport(
    const css::uno::Reference< css::uno::XComponentContext >& xContext,
    OUString const & implementationName,
    bool bIsDraw, SvXMLExportFlags nExportFlags )
:   SvXMLExport( xContext, implementationName, util::MeasureUnit::CM,
        bIsDraw ? XML_GRAPHICS : XML_PRESENTATION, nExportFlags ),
    mnDocMasterPageCount(0),
    mnDocDrawPageCount(0),
    mnObjectCount(0),
    mpHandoutPageMaster(nullptr),
    mbIsDraw(bIsDraw)
{

}

// XExporter
void SAL_CALL SdXMLExport::setSourceDocument( const Reference< lang::XComponent >& xDoc )
{
    SvXMLExport::setSourceDocument( xDoc );

    // prepare factory parts
    mpSdPropHdlFactory = new XMLSdPropHdlFactory( GetModel(), *this );

    // construct PropertySetMapper
    rtl::Reference < XMLPropertySetMapper > xMapper = new XMLShapePropertySetMapper( mpSdPropHdlFactory, true);

    // get or create text paragraph export
    GetTextParagraphExport();
    mpPropertySetMapper = new XMLShapeExportPropertyMapper( xMapper, *this );

    // chain text attributes
    mpPropertySetMapper->ChainExportMapper(XMLTextParagraphExport::CreateParaExtPropMapper(*this));

    // construct PresPagePropsMapper
    xMapper = new XMLPropertySetMapper(aXMLSDPresPageProps, mpSdPropHdlFactory, true);

    mpPresPagePropsMapper = new XMLPageExportPropertyMapper( xMapper, *this  );

    // add family name
    GetAutoStylePool()->AddFamily(
        XmlStyleFamily::SD_GRAPHICS_ID,
        XML_STYLE_FAMILY_SD_GRAPHICS_NAME,
          GetPropertySetMapper(),
          XML_STYLE_FAMILY_SD_GRAPHICS_PREFIX);
    GetAutoStylePool()->AddFamily(
        XmlStyleFamily::SD_PRESENTATION_ID,
        XML_STYLE_FAMILY_SD_PRESENTATION_NAME,
          GetPropertySetMapper(),
          XML_STYLE_FAMILY_SD_PRESENTATION_PREFIX);
    GetAutoStylePool()->AddFamily(
        XmlStyleFamily::SD_DRAWINGPAGE_ID,
        XML_STYLE_FAMILY_SD_DRAWINGPAGE_NAME,
          GetPresPagePropsMapper(),
          XML_STYLE_FAMILY_SD_DRAWINGPAGE_PREFIX);
    // prepare access to styles
    Reference< style::XStyleFamiliesSupplier > xFamSup( GetModel(), UNO_QUERY );
    if(xFamSup.is())
    {
        mxDocStyleFamilies = xFamSup->getStyleFamilies();
    }

    // prepare access to master pages
    Reference < drawing::XMasterPagesSupplier > xMasterPagesSupplier(GetModel(), UNO_QUERY);
    if(xMasterPagesSupplier.is())
    {
        mxDocMasterPages = xMasterPagesSupplier->getMasterPages();
        if(mxDocMasterPages.is())
        {
            mnDocMasterPageCount = mxDocMasterPages->getCount();
            maMasterPagesStyleNames.insert( maMasterPagesStyleNames.begin(), mnDocMasterPageCount, u""_ustr );
        }
    }

    // prepare access to draw pages
    Reference <XDrawPagesSupplier> xDrawPagesSupplier(GetModel(), UNO_QUERY);
    if(xDrawPagesSupplier.is())
    {
        mxDocDrawPages = xDrawPagesSupplier->getDrawPages();
        if(mxDocDrawPages.is())
        {
            mnDocDrawPageCount = mxDocDrawPages->getCount();
            maDrawPagesStyleNames.insert( maDrawPagesStyleNames.begin(), mnDocDrawPageCount, u""_ustr );
            maDrawNotesPagesStyleNames.insert( maDrawNotesPagesStyleNames.begin(), mnDocDrawPageCount, u""_ustr );
            if( !mbIsDraw )
                maDrawPagesAutoLayoutNames.realloc( mnDocDrawPageCount + 1 );

            HeaderFooterPageSettingsImpl aEmptySettings;
            maDrawPagesHeaderFooterSettings.insert( maDrawPagesHeaderFooterSettings.begin(), mnDocDrawPageCount, aEmptySettings );
            maDrawNotesPagesHeaderFooterSettings.insert( maDrawNotesPagesHeaderFooterSettings.begin(), mnDocDrawPageCount, aEmptySettings );
        }
    }

    // #82003# count all draw objects for use with progress bar.
    // #88245# init mnObjectCount once, use counter itself as flag. It
    // is initialized to 0.
    if(!mnObjectCount)
    {
        if( IsImpress() )
        {
             // #91587# add handout master count
            Reference<presentation::XHandoutMasterSupplier> xHandoutSupp(GetModel(), UNO_QUERY);
            if(xHandoutSupp.is())
            {
                Reference<XDrawPage> xHandoutPage(xHandoutSupp->getHandoutMasterPage());
                if(xHandoutPage.is() && xHandoutPage->getCount())
                    mnObjectCount += ImpRecursiveObjectCount(xHandoutPage);
            }
        }

        if(mxDocMasterPages.is())
        {
            for(sal_Int32 a(0); a < mnDocMasterPageCount; a++)
            {
                Any aAny(mxDocMasterPages->getByIndex(a));
                Reference< drawing::XShapes > xMasterPage;

                if((aAny >>= xMasterPage) && xMasterPage.is())
                {
                    mnObjectCount += ImpRecursiveObjectCount(xMasterPage);
                }

                if( IsImpress() )
                {
                    // #91587# take notes pages from master pages into account
                    Reference<presentation::XPresentationPage> xPresPage;
                    if((aAny >>= xPresPage) && xPresPage.is())
                    {
                        Reference<XDrawPage> xNotesPage(xPresPage->getNotesPage());
                        if(xNotesPage.is() && xNotesPage->getCount())
                            mnObjectCount += ImpRecursiveObjectCount(xNotesPage);
                    }
                }
            }
        }

        if(mxDocDrawPages.is())
        {
            for(sal_Int32 a(0); a < mnDocDrawPageCount; a++)
            {
                Any aAny(mxDocDrawPages->getByIndex(a));
                Reference< drawing::XShapes > xPage;

                if((aAny >>= xPage) && xPage.is())
                {
                    mnObjectCount += ImpRecursiveObjectCount(xPage);
                }

                if( IsImpress() )
                {
                    // #91587# take notes pages from draw pages into account
                    Reference<presentation::XPresentationPage> xPresPage;
                    if((aAny >>= xPresPage) && xPresPage.is())
                    {
                        Reference<XDrawPage> xNotesPage(xPresPage->getNotesPage());
                        if(xNotesPage.is() && xNotesPage->getCount())
                            mnObjectCount += ImpRecursiveObjectCount(xNotesPage);
                    }
                }
            }
        }

        // #82003# init progress bar
        GetProgressBarHelper()->SetReference(mnObjectCount);
    }

    // add namespaces
    GetNamespaceMap_().Add(
        GetXMLToken(XML_NP_PRESENTATION),
        GetXMLToken(XML_N_PRESENTATION),
        XML_NAMESPACE_PRESENTATION);

    GetNamespaceMap_().Add(
        GetXMLToken(XML_NP_SMIL),
        GetXMLToken(XML_N_SMIL_COMPAT),
        XML_NAMESPACE_SMIL);

    GetNamespaceMap_().Add(
        GetXMLToken(XML_NP_ANIMATION),
        GetXMLToken(XML_N_ANIMATION),
        XML_NAMESPACE_ANIMATION);

    if (getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
    {
        GetNamespaceMap_().Add(
            GetXMLToken(XML_NP_OFFICE_EXT),
            GetXMLToken(XML_N_OFFICE_EXT),
            XML_NAMESPACE_OFFICE_EXT);
    }

    GetShapeExport()->enableLayerExport();

    // #88546# enable progress bar increments
    GetShapeExport()->enableHandleProgressBar();
}

// #82003# helper function for recursive object count
sal_uInt32 SdXMLExport::ImpRecursiveObjectCount(const Reference< drawing::XShapes >& xShapes)
{
    sal_uInt32 nRetval(0);

    if(xShapes.is())
    {
        sal_Int32 nCount = xShapes->getCount();

        for(sal_Int32 a(0); a < nCount; a++)
        {
            Any aAny(xShapes->getByIndex(a));
            Reference< drawing::XShapes > xGroup;

            if((aAny >>= xGroup) && xGroup.is())
            {
                // #93180# count group objects, too.
                nRetval += 1 + ImpRecursiveObjectCount(xGroup);
            }
            else
            {
                nRetval++;
            }
        }
    }

    return nRetval;
}

SdXMLExport::~SdXMLExport()
{
    // cleanup factory, decrease refcount. Should lead to destruction.
    mpSdPropHdlFactory.clear();

    // cleanup mapper, decrease refcount. Should lead to destruction.
    mpPropertySetMapper.clear();

    // cleanup presPage mapper, decrease refcount. Should lead to destruction.
    mpPresPagePropsMapper.clear();

    mvPageMasterInfoList.clear();

    // clear auto-layout infos
    mvAutoLayoutInfoList.clear();
}

void SdXMLExport::ImpPrepAutoLayoutInfos()
{
    if(!IsImpress())
        return;

    OUString aStr;
    auto DrawPagesAutoLayoutNamesRange = asNonConstRange(maDrawPagesAutoLayoutNames);
    Reference< presentation::XHandoutMasterSupplier > xHandoutSupp( GetModel(), UNO_QUERY );
    if( xHandoutSupp.is() )
    {
        Reference< XDrawPage > xHandoutPage( xHandoutSupp->getHandoutMasterPage() );
        if( xHandoutPage.is() )
        {
            if(ImpPrepAutoLayoutInfo(xHandoutPage, aStr))
                DrawPagesAutoLayoutNamesRange[0] = aStr;
        }
    }

    // prepare name creation
    for (sal_Int32 nCnt = 0; nCnt < mnDocDrawPageCount; nCnt++)
    {
        Any aAny(mxDocDrawPages->getByIndex(nCnt));
        Reference<XDrawPage> xDrawPage;

        if((aAny >>= xDrawPage) && xDrawPage.is())
        {
            if(ImpPrepAutoLayoutInfo(xDrawPage, aStr))
                DrawPagesAutoLayoutNamesRange[nCnt+1] = aStr;
        }
    }
}

bool SdXMLExport::ImpPrepAutoLayoutInfo(const Reference<XDrawPage>& xPage, OUString& rName)
{
    rName.clear();
    bool bRetval(false);

    Reference <beans::XPropertySet> xPropSet(xPage, UNO_QUERY);
    if(xPropSet.is())
    {
        sal_uInt16 nType = sal_uInt16();
        Any aAny = xPropSet->getPropertyValue(u"Layout"_ustr);
        if(aAny >>= nType)
        {
            if(ImpXMLAutoLayoutInfo::IsCreateNecessary(nType))
            {
                ImpXMLEXPPageMasterInfo* pInfo = nullptr;

                // get master-page info
                Reference < drawing::XMasterPageTarget > xMasterPageInt(xPage, UNO_QUERY);
                if(xMasterPageInt.is())
                {
                    Reference<XDrawPage> xUsedMasterPage(xMasterPageInt->getMasterPage());
                    if(xUsedMasterPage.is())
                    {
                        Reference < container::XNamed > xMasterNamed(xUsedMasterPage, UNO_QUERY);
                        if(xMasterNamed.is())
                        {
                            OUString sMasterPageName = xMasterNamed->getName();
                            pInfo = ImpGetPageMasterInfoByName(sMasterPageName);
                        }
                    }
                }

                // create entry and look for existence
                ImpXMLAutoLayoutInfo* pNew;
                auto it = std::find_if(mvAutoLayoutInfoList.begin(), mvAutoLayoutInfoList.end(),
                            [=](std::unique_ptr<ImpXMLAutoLayoutInfo> const & rInfo) { return nType == rInfo->GetLayoutType() && pInfo == rInfo->GetPageMasterInfo(); });
                if (it != mvAutoLayoutInfoList.end())
                {
                    pNew = it->get();
                }
                else
                {
                    pNew = new ImpXMLAutoLayoutInfo(nType, pInfo);
                    mvAutoLayoutInfoList.emplace_back( pNew );
                    OUString sNewName =
                        "AL" + OUString::number(mvAutoLayoutInfoList.size() - 1) +
                        "T" + OUString::number(nType);
                    pNew->SetLayoutName(sNewName);
                }

                rName = pNew->GetLayoutName();
                bRetval = true;
            }
        }
    }

    return bRetval;
}

void SdXMLExport::ImpWriteAutoLayoutInfos()
{
    for(const auto & pInfo : mvAutoLayoutInfoList)
    {
        if(pInfo)
        {
            // prepare presentation-page layout attributes, style-name
            AddAttribute(XML_NAMESPACE_STYLE, XML_NAME, pInfo->GetLayoutName());

            // write draw-style attributes
            SvXMLElementExport aDSE(*this, XML_NAMESPACE_STYLE, XML_PRESENTATION_PAGE_LAYOUT, true, true);

            // write presentation placeholders
            switch(pInfo->GetLayoutType())
            {
                case AUTOLAYOUT_TITLE :
                {
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderSubtitle, pInfo->GetPresRectangle());
                    break;
                }
                case AUTOLAYOUT_TITLE_CONTENT :
                {
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderOutline, pInfo->GetPresRectangle());
                    break;
                }
                case AUTOLAYOUT_CHART :
                {
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderChart, pInfo->GetPresRectangle());
                    break;
                }
                case AUTOLAYOUT_TITLE_2CONTENT :
                {
                    tools::Rectangle aLeft(pInfo->GetPresRectangle());
                    aLeft.setWidth(tools::Long(aLeft.GetWidth() * 0.488));
                    tools::Rectangle aRight(aLeft);
                    aRight.AdjustLeft(aRight.GetWidth() * 1.05);

                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderOutline, aLeft);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderOutline, aRight);
                    break;
                }
                case AUTOLAYOUT_TEXTCHART :
                {
                    tools::Rectangle aLeft(pInfo->GetPresRectangle());
                    aLeft.setWidth(tools::Long(aLeft.GetWidth() * 0.488));
                    tools::Rectangle aRight(aLeft);
                    aRight.AdjustLeft(aRight.GetWidth() * 1.05);

                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderOutline, aLeft);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderChart, aRight);
                    break;
                }
                case AUTOLAYOUT_TEXTCLIP :
                {
                    tools::Rectangle aLeft(pInfo->GetPresRectangle());
                    aLeft.setWidth(tools::Long(aLeft.GetWidth() * 0.488));
                    tools::Rectangle aRight(aLeft);
                    aRight.AdjustLeft(aRight.GetWidth() * 1.05);

                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderOutline, aLeft);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderGraphic, aRight);
                    break;
                }
                case AUTOLAYOUT_CHARTTEXT :
                {
                    tools::Rectangle aLeft(pInfo->GetPresRectangle());
                    aLeft.setWidth(tools::Long(aLeft.GetWidth() * 0.488));
                    tools::Rectangle aRight(aLeft);
                    aRight.AdjustLeft(aRight.GetWidth() * 1.05);

                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderChart, aLeft);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderOutline, aRight);
                    break;
                }
                case AUTOLAYOUT_TAB :
                {
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTable, pInfo->GetPresRectangle());
                    break;
                }
                case AUTOLAYOUT_CLIPTEXT :
                {
                    tools::Rectangle aLeft(pInfo->GetPresRectangle());
                    aLeft.setWidth(tools::Long(aLeft.GetWidth() * 0.488));
                    tools::Rectangle aRight(aLeft);
                    aRight.AdjustLeft(aRight.GetWidth() * 1.05);

                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderGraphic, aLeft);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderOutline, aRight);
                    break;
                }
                case AUTOLAYOUT_TEXTOBJ :
                {
                    tools::Rectangle aLeft(pInfo->GetPresRectangle());
                    aLeft.setWidth(tools::Long(aLeft.GetWidth() * 0.488));
                    tools::Rectangle aRight(aLeft);
                    aRight.AdjustLeft(aRight.GetWidth() * 1.05);

                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderOutline, aLeft);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderObject, aRight);
                    break;
                }
                case AUTOLAYOUT_OBJ :
                {
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderObject, pInfo->GetPresRectangle());
                    break;
                }
                case AUTOLAYOUT_TITLE_CONTENT_2CONTENT :
                {
                    tools::Rectangle aLeft(pInfo->GetPresRectangle());
                    aLeft.setWidth(tools::Long(aLeft.GetWidth() * 0.488));
                    tools::Rectangle aRightTop(aLeft);
                    aRightTop.AdjustLeft(aRightTop.GetWidth() * 1.05);
                    aRightTop.setHeight(tools::Long(aRightTop.GetHeight() * 0.477));
                    tools::Rectangle aRightBottom(aRightTop);
                    aRightBottom.AdjustTop(aRightBottom.GetHeight() * 1.095);

                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderOutline, aLeft);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderObject, aRightTop);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderObject, aRightBottom);
                    break;
                }
                case AUTOLAYOUT_OBJTEXT :
                {
                    tools::Rectangle aLeft(pInfo->GetPresRectangle());
                    aLeft.setWidth(tools::Long(aLeft.GetWidth() * 0.488));
                    tools::Rectangle aRight(aLeft);
                    aRight.AdjustLeft(aRight.GetWidth() * 1.05);

                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderObject, aLeft);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderOutline, aRight);
                    break;
                }
                case AUTOLAYOUT_TITLE_CONTENT_OVER_CONTENT :
                {
                    tools::Rectangle aTop(pInfo->GetPresRectangle());
                    aTop.setHeight(tools::Long(aTop.GetHeight() * 0.477));
                    tools::Rectangle aBottom(aTop);
                    aBottom.AdjustTop(aBottom.GetHeight() * 1.095);

                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderObject, aTop);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderOutline, aBottom);
                    break;
                }
                case AUTOLAYOUT_TITLE_2CONTENT_CONTENT :
                {
                    tools::Rectangle aLeftTop(pInfo->GetPresRectangle());
                    aLeftTop.setWidth(tools::Long(aLeftTop.GetWidth() * 0.488));
                    tools::Rectangle aRight(aLeftTop);
                    aRight.AdjustLeft(aRight.GetWidth() * 1.05);
                    aLeftTop.setHeight(tools::Long(aLeftTop.GetHeight() * 0.477));
                    tools::Rectangle aLeftBottom(aLeftTop);
                    aLeftBottom.AdjustTop(aLeftBottom.GetHeight() * 1.095);

                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderObject, aLeftTop);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderObject, aLeftBottom);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderOutline, aRight);
                    break;
                }
                case AUTOLAYOUT_TITLE_2CONTENT_OVER_CONTENT :
                {
                    tools::Rectangle aTopLeft(pInfo->GetPresRectangle());
                    aTopLeft.setHeight(tools::Long(aTopLeft.GetHeight() * 0.477));
                    tools::Rectangle aBottom(aTopLeft);
                    aBottom.AdjustTop(aBottom.GetHeight() * 1.095);
                    aTopLeft.setWidth(tools::Long(aTopLeft.GetWidth() * 0.488));
                    tools::Rectangle aTopRight(aTopLeft);
                    aTopRight.AdjustLeft(aTopRight.GetWidth() * 1.05);

                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderObject, aTopLeft);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderObject, aTopRight);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderOutline, aBottom);
                    break;
                }
                case AUTOLAYOUT_TEXTOVEROBJ :
                {
                    tools::Rectangle aTop(pInfo->GetPresRectangle());
                    aTop.setHeight(tools::Long(aTop.GetHeight() * 0.477));
                    tools::Rectangle aBottom(aTop);
                    aBottom.AdjustTop(aBottom.GetHeight() * 1.095);

                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderOutline, aTop);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderObject, aBottom);
                    break;
                }
                case AUTOLAYOUT_TITLE_4CONTENT :
                {
                    tools::Rectangle aTopLeft(pInfo->GetPresRectangle());
                    aTopLeft.setHeight(tools::Long(aTopLeft.GetHeight() * 0.477));
                    aTopLeft.setWidth(tools::Long(aTopLeft.GetWidth() * 0.488));
                    tools::Rectangle aBottomLeft(aTopLeft);
                    aBottomLeft.AdjustTop(aBottomLeft.GetHeight() * 1.095);
                    tools::Rectangle aTopRight(aTopLeft);
                    aTopRight.AdjustLeft(aTopRight.GetWidth() * 1.05);
                    tools::Rectangle aBottomRight(aTopRight);
                    aBottomRight.AdjustTop(aBottomRight.GetHeight() * 1.095);

                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderObject, aTopLeft);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderObject, aTopRight);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderObject, aBottomLeft);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderObject, aBottomRight);
                    break;
                }
                case AUTOLAYOUT_TITLE_ONLY :
                {
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    break;
                }
                case AUTOLAYOUT_NOTES :
                {
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderPage, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderNotes, pInfo->GetPresRectangle());
                    break;
                }
                case AUTOLAYOUT_HANDOUT1 :
                case AUTOLAYOUT_HANDOUT2 :
                case AUTOLAYOUT_HANDOUT3 :
                case AUTOLAYOUT_HANDOUT4 :
                case AUTOLAYOUT_HANDOUT6 :
                case AUTOLAYOUT_HANDOUT9 :
                {
                    sal_Int32 nColCnt, nRowCnt;
                    sal_Int32 nGapX = pInfo->GetGapX();
                    sal_Int32 nGapY = pInfo->GetGapY();

                    switch(pInfo->GetLayoutType())
                    {
                        case 22 : nColCnt = 1; nRowCnt = 1; break;
                        case 23 : nColCnt = 1; nRowCnt = 2; break;
                        case 24 : nColCnt = 1; nRowCnt = 3; break;
                        case 25 : nColCnt = 2; nRowCnt = 2; break;
                        case 26 : nColCnt = 3; nRowCnt = 2; break;
                        case 31 : nColCnt = 3; nRowCnt = 3; break;
                        default:  nColCnt = 0; nRowCnt = 0; break;  // FIXME - What is correct values?
                    }

                    Size aPartSize(pInfo->GetTitleRectangle().GetSize());
                    Point aPartPos(pInfo->GetTitleRectangle().TopLeft());

                    if(aPartSize.Width() > aPartSize.Height())
                    {
                        sal_Int32 nZwi(nColCnt);
                        nColCnt = nRowCnt;
                        nRowCnt = nZwi;
                    }

                    if (nColCnt == 0 || nRowCnt == 0)
                        break;

                    aPartSize.setWidth( (aPartSize.Width() - ((nColCnt - 1) * nGapX)) / nColCnt );
                    aPartSize.setHeight( (aPartSize.Height() - ((nRowCnt - 1) * nGapY)) / nRowCnt );

                    Point aTmpPos(aPartPos);

                    for (sal_Int32 a = 0; a < nRowCnt; a++)
                    {
                        aTmpPos.setX(aPartPos.X());

                        for (sal_Int32 b = 0; b < nColCnt; b++)
                        {
                            tools::Rectangle aTmpRect(aTmpPos, aPartSize);

                            ImpWriteAutoLayoutPlaceholder(XmlPlaceholderHandout, aTmpRect);
                            aTmpPos.AdjustX( aPartSize.Width() + nGapX );
                        }

                        aTmpPos.AdjustY( aPartSize.Height() + nGapY );
                    }
                    break;
                }
                case AUTOLAYOUT_VTITLE_VCONTENT_OVER_VCONTENT :
                {
                    tools::Rectangle aTop(pInfo->GetPresRectangle());
                    aTop.setHeight(tools::Long(aTop.GetHeight() * 0.488));
                    tools::Rectangle aBottom(aTop);
                    aBottom.AdjustTop(aBottom.GetHeight() * 1.05);

                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderVerticalTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderVerticalOutline, aTop);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderChart, aBottom);
                    break;
                }
                case AUTOLAYOUT_VTITLE_VCONTENT :
                {
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderVerticalTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderVerticalOutline, pInfo->GetPresRectangle());
                    break;
                }
                case AUTOLAYOUT_TITLE_VCONTENT :
                {
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderVerticalOutline, pInfo->GetPresRectangle());
                    break;
                }
                case AUTOLAYOUT_TITLE_2VTEXT :
                {
                    tools::Rectangle aLeft(pInfo->GetPresRectangle());
                    aLeft.setWidth(tools::Long(aLeft.GetWidth() * 0.488));
                    tools::Rectangle aRight(aLeft);
                    aRight.AdjustLeft(aRight.GetWidth() * 1.05);

                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderGraphic, aLeft);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderVerticalOutline, aRight);
                    break;
                }
                case AUTOLAYOUT_ONLY_TEXT :
                {
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderSubtitle, pInfo->GetPresRectangle());
                    break;
                }

                case AUTOLAYOUT_4CLIPART :
                {
                    tools::Rectangle aTopLeft(pInfo->GetPresRectangle());
                    aTopLeft.setHeight(tools::Long(aTopLeft.GetHeight() * 0.477));
                    aTopLeft.setWidth(tools::Long(aTopLeft.GetWidth() * 0.488));
                    tools::Rectangle aBottomLeft(aTopLeft);
                    aBottomLeft.AdjustTop(aBottomLeft.GetHeight() * 1.095);
                    tools::Rectangle aTopRight(aTopLeft);
                    aTopRight.AdjustLeft(aTopRight.GetWidth() * 1.05);
                    tools::Rectangle aBottomRight(aTopRight);
                    aBottomRight.AdjustTop(aBottomRight.GetHeight() * 1.095);

                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderGraphic, aTopLeft);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderGraphic, aTopRight);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderGraphic, aBottomLeft);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderGraphic, aBottomRight);
                    break;
                }

                case AUTOLAYOUT_TITLE_6CONTENT :
                {
                    tools::Rectangle aTopLeft(pInfo->GetPresRectangle());
                    aTopLeft.setHeight(tools::Long(aTopLeft.GetHeight() * 0.477));
                    aTopLeft.setWidth(tools::Long(aTopLeft.GetWidth() * 0.322));
                    tools::Rectangle aTopCenter(aTopLeft);
                    aTopCenter.AdjustLeft(aTopCenter.GetWidth() * 1.05);
                    tools::Rectangle aTopRight(aTopLeft);
                    aTopRight.AdjustLeft(aTopRight.GetWidth() * 2 * 1.05);

                    tools::Rectangle aBottomLeft(aTopLeft);
                    aBottomLeft.AdjustTop(aBottomLeft.GetHeight() * 1.095);
                    tools::Rectangle aBottomCenter(aTopCenter);
                    aBottomCenter.AdjustTop(aBottomCenter.GetHeight() * 1.095);
                    tools::Rectangle aBottomRight(aTopRight);
                    aBottomRight.AdjustTop(aBottomRight.GetHeight() * 1.095);

                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderTitle, pInfo->GetTitleRectangle());
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderGraphic, aTopLeft);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderGraphic, aTopCenter);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderGraphic, aTopRight);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderGraphic, aBottomLeft);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderGraphic, aBottomCenter);
                    ImpWriteAutoLayoutPlaceholder(XmlPlaceholderGraphic, aBottomRight);
                    break;
                }
                default:
                {
                    OSL_FAIL("XMLEXP: unknown autolayout export");
                    break;
                }
            }
        }
    }
}

void SdXMLExport::ImpWriteAutoLayoutPlaceholder(XmlPlaceholder ePl, const tools::Rectangle& rRect)
{
    OUString aStr;
    OUStringBuffer sStringBuffer;

    // prepare presentation-placeholder attributes, presentation:object
    switch(ePl)
    {
        case XmlPlaceholderTitle: aStr = "title"; break;
        case XmlPlaceholderOutline: aStr = "outline"; break;
        case XmlPlaceholderSubtitle: aStr = "subtitle"; break;
        case XmlPlaceholderGraphic: aStr = "graphic"; break;
        case XmlPlaceholderObject: aStr = "object"; break;
        case XmlPlaceholderChart: aStr = "chart"; break;
        case XmlPlaceholderTable: aStr = "table"; break;
        case XmlPlaceholderPage: aStr = "page"; break;
        case XmlPlaceholderNotes: aStr = "notes"; break;
        case XmlPlaceholderHandout: aStr = "handout"; break;
        case XmlPlaceholderVerticalTitle: aStr = "vertical_title"; break;
        case XmlPlaceholderVerticalOutline: aStr = "vertical_outline"; break;
    }

    AddAttribute(XML_NAMESPACE_PRESENTATION, XML_OBJECT, aStr);

    // svg:x,y,width,height
    GetMM100UnitConverter().convertMeasureToXML(sStringBuffer, rRect.Left());
    aStr = sStringBuffer.makeStringAndClear();
    AddAttribute(XML_NAMESPACE_SVG, XML_X, aStr);

    GetMM100UnitConverter().convertMeasureToXML(sStringBuffer, rRect.Top());
    aStr = sStringBuffer.makeStringAndClear();
    AddAttribute(XML_NAMESPACE_SVG, XML_Y, aStr);

    GetMM100UnitConverter().convertMeasureToXML(sStringBuffer,
            rRect.GetWidth());
    aStr = sStringBuffer.makeStringAndClear();
    AddAttribute(XML_NAMESPACE_SVG, XML_WIDTH, aStr);

    GetMM100UnitConverter().convertMeasureToXML(sStringBuffer,
            rRect.GetHeight());
    aStr = sStringBuffer.makeStringAndClear();
    AddAttribute(XML_NAMESPACE_SVG, XML_HEIGHT, aStr);

    // write presentation-placeholder
    SvXMLElementExport aPPL(*this, XML_NAMESPACE_PRESENTATION, XML_PLACEHOLDER, true, true);
}

ImpXMLEXPPageMasterInfo* SdXMLExport::ImpGetOrCreatePageMasterInfo( const Reference< XDrawPage >& xMasterPage )
{
    bool bDoesExist = false;

    ImpXMLEXPPageMasterInfo* pNewInfo = new ImpXMLEXPPageMasterInfo(*this, xMasterPage);

    // compare with prev page-master infos
    for( size_t a = 0; !bDoesExist && a < mvPageMasterInfoList.size(); a++)
    {
        if (   mvPageMasterInfoList.at(a)
           && *mvPageMasterInfoList.at(a) == *pNewInfo
           )
        {
            delete pNewInfo;
            pNewInfo = mvPageMasterInfoList.at(a).get();
            bDoesExist = true;
        }
    }
    // add entry when not found same page-master infos
    if(!bDoesExist)
        mvPageMasterInfoList.emplace_back( pNewInfo );

    return pNewInfo;
}

void SdXMLExport::ImpPrepPageMasterInfos()
{
    if( IsImpress() )
    {
        // create page master info for handout master page

        Reference< XHandoutMasterSupplier > xHMS( GetModel(), UNO_QUERY );
        if( xHMS.is() )
        {
            Reference< XDrawPage > xMasterPage( xHMS->getHandoutMasterPage() );
            if( xMasterPage.is() )
                mpHandoutPageMaster = ImpGetOrCreatePageMasterInfo(xMasterPage);
        }
    }

    // create page master infos for master pages
    if(!mnDocMasterPageCount)
        return;

    // look for needed page-masters, create these
    for (sal_Int32 nMPageId = 0; nMPageId < mnDocMasterPageCount; nMPageId++)
    {
        Reference< XDrawPage > xMasterPage( mxDocMasterPages->getByIndex(nMPageId), UNO_QUERY );
        ImpXMLEXPPageMasterInfo* pNewInfo = nullptr;

        if(xMasterPage.is())
            pNewInfo = ImpGetOrCreatePageMasterInfo(xMasterPage);

        mvPageMasterUsageList.push_back( pNewInfo );

        // look for page master of handout page
        if(IsImpress())
        {
            pNewInfo = nullptr;
            Reference< presentation::XPresentationPage > xPresPage(xMasterPage, UNO_QUERY);
            if(xPresPage.is())
            {
                Reference< XDrawPage > xNotesPage(xPresPage->getNotesPage());
                if(xNotesPage.is())
                {
                    pNewInfo = ImpGetOrCreatePageMasterInfo(xNotesPage);
                }
            }
            mvNotesPageMasterUsageList.push_back( pNewInfo );
        }
    }
}

void SdXMLExport::ImpWritePageMasterInfos()
{
    // write created page-masters, create names for these
    for( size_t nCnt = 0; nCnt < mvPageMasterInfoList.size(); nCnt++)
    {
        ImpXMLEXPPageMasterInfo* pInfo = mvPageMasterInfoList.at(nCnt).get();
        if(pInfo)
        {
            // create name
            OUString sNewName = "PM" + OUString::number(nCnt);
            pInfo->SetName(sNewName);

            // prepare page-master attributes
            OUString sString;
            OUStringBuffer sStringBuffer;

            sString = sNewName;
            AddAttribute(XML_NAMESPACE_STYLE, XML_NAME, sString);

            // write page-layout
            SvXMLElementExport aPME(*this, XML_NAMESPACE_STYLE, XML_PAGE_LAYOUT, true, true);

            // prepare style:properties inside page-master
            GetMM100UnitConverter().convertMeasureToXML(sStringBuffer,
                    pInfo->GetBorderTop());
            sString = sStringBuffer.makeStringAndClear();
            AddAttribute(XML_NAMESPACE_FO, XML_MARGIN_TOP, sString);

            GetMM100UnitConverter().convertMeasureToXML(sStringBuffer,
                    pInfo->GetBorderBottom());
            sString = sStringBuffer.makeStringAndClear();
            AddAttribute(XML_NAMESPACE_FO, XML_MARGIN_BOTTOM, sString);

            GetMM100UnitConverter().convertMeasureToXML(sStringBuffer,
                    pInfo->GetBorderLeft());
            sString = sStringBuffer.makeStringAndClear();
            AddAttribute(XML_NAMESPACE_FO, XML_MARGIN_LEFT, sString);

            GetMM100UnitConverter().convertMeasureToXML(sStringBuffer,
                    pInfo->GetBorderRight());
            sString = sStringBuffer.makeStringAndClear();
            AddAttribute(XML_NAMESPACE_FO, XML_MARGIN_RIGHT, sString);

            GetMM100UnitConverter().convertMeasureToXML(sStringBuffer,
                    pInfo->GetWidth());
            sString = sStringBuffer.makeStringAndClear();
            AddAttribute(XML_NAMESPACE_FO, XML_PAGE_WIDTH, sString);

            GetMM100UnitConverter().convertMeasureToXML(sStringBuffer,
                    pInfo->GetHeight());
            sString = sStringBuffer.makeStringAndClear();
            AddAttribute(XML_NAMESPACE_FO, XML_PAGE_HEIGHT, sString);

            if(pInfo->GetOrientation() == view::PaperOrientation_PORTRAIT)
                AddAttribute(XML_NAMESPACE_STYLE, XML_PRINT_ORIENTATION, XML_PORTRAIT);
            else
                AddAttribute(XML_NAMESPACE_STYLE, XML_PRINT_ORIENTATION, XML_LANDSCAPE);

            // write style:properties
            SvXMLElementExport aPMF(*this, XML_NAMESPACE_STYLE, XML_PAGE_LAYOUT_PROPERTIES, true, true);
        }
    }
}

ImpXMLEXPPageMasterInfo* SdXMLExport::ImpGetPageMasterInfoByName(std::u16string_view rName)
{
    if(!rName.empty())
    {
        for(const auto & pInfo : mvPageMasterInfoList)
        {
            if(pInfo)
            {
                if(!pInfo->GetMasterPageName().isEmpty() && rName == pInfo->GetMasterPageName())
                {
                    return pInfo.get();
                }
            }
        }
    }
    return nullptr;
}

void SdXMLExport::ImpPrepDrawPageInfos()
{
    // create draw:style-name entries for page export
    // containing presentation page attributes AND background attributes
    // fixed family for page-styles is "drawing-page" (XML_STYLE_FAMILY_SD_DRAWINGPAGE_NAME)

    sal_Int32 nCnt;
    for(nCnt = 0; nCnt < mnDocDrawPageCount; nCnt++)
    {
        Reference<XDrawPage> xDrawPage;
        mxDocDrawPages->getByIndex(nCnt) >>= xDrawPage;
        maDrawPagesStyleNames[nCnt] = ImpCreatePresPageStyleName( xDrawPage );

        Reference< presentation::XPresentationPage > xPresPage(xDrawPage, UNO_QUERY);
        if(xPresPage.is())
        {
            maDrawNotesPagesStyleNames[nCnt] = ImpCreatePresPageStyleName( xPresPage->getNotesPage(), false );

            maDrawPagesHeaderFooterSettings[nCnt] = ImpPrepDrawPageHeaderFooterDecls( xDrawPage );
            maDrawNotesPagesHeaderFooterSettings[nCnt] = ImpPrepDrawPageHeaderFooterDecls( xPresPage->getNotesPage() );
        }
    }
}

static OUString findOrAppendImpl( std::vector< OUString >& rVector, const OUString& rText, std::u16string_view pPrefix )
{
    // search rVector if there is already a string that equals rText
    auto aIter = std::find(rVector.begin(), rVector.end(), rText);
    sal_Int32 nIndex = std::distance(rVector.begin(), aIter) + 1;

    // if nothing is found, append the string at the end of rVector
    if( aIter == rVector.end() )
        rVector.push_back( rText );

    // create a reference string with pPrefix and the index of the
    // found or created rText
    return pPrefix + OUString::number( nIndex );
}

static OUString findOrAppendImpl( std::vector< DateTimeDeclImpl >& rVector, const OUString& rText, bool bFixed, sal_Int32 nFormat, std::u16string_view pPrefix )
{
    // search rVector if there is already a DateTimeDeclImpl with rText,bFixed and nFormat
    auto aIter = std::find_if(rVector.begin(), rVector.end(),
        [bFixed, &rText, nFormat](const DateTimeDeclImpl& rDecl) {
            return (rDecl.mbFixed == bFixed) &&
                (!bFixed || (rDecl.maStrText == rText)) &&
                (bFixed || (rDecl.mnFormat == nFormat));
        });
    sal_Int32 nIndex = std::distance(rVector.begin(), aIter) + 1;

    // if nothing is found, append a new DateTimeDeclImpl
    if( aIter == rVector.end() )
    {
        DateTimeDeclImpl aDecl;
        aDecl.maStrText = rText;
        aDecl.mbFixed = bFixed;
        aDecl.mnFormat = nFormat;
        rVector.push_back( aDecl );
    }

    // create a reference string with pPrefix and the index of the
    // found or created DateTimeDeclImpl
    return pPrefix + OUString::number( nIndex );
}

constexpr OUString gpStrHeaderTextPrefix = u"hdr"_ustr;
constexpr OUString gpStrFooterTextPrefix = u"ftr"_ustr;
constexpr OUString gpStrDateTimeTextPrefix = u"dtd"_ustr;

HeaderFooterPageSettingsImpl SdXMLExport::ImpPrepDrawPageHeaderFooterDecls( const Reference<XDrawPage>& xDrawPage )
{
    HeaderFooterPageSettingsImpl aSettings;

    if( xDrawPage.is() ) try
    {
        Reference< XPropertySet > xSet( xDrawPage, UNO_QUERY_THROW );
        Reference< XPropertySetInfo > xInfo( xSet->getPropertySetInfo() );

        OUString aStrText;

        static constexpr OUString aStrHeaderTextProp( u"HeaderText"_ustr );
        if( xInfo->hasPropertyByName( aStrHeaderTextProp ) )
        {
            xSet->getPropertyValue( aStrHeaderTextProp  ) >>= aStrText;
            if( !aStrText.isEmpty() )
                aSettings.maStrHeaderDeclName = findOrAppendImpl( maHeaderDeclsVector, aStrText, gpStrHeaderTextPrefix );
        }

        static constexpr OUString aStrFooterTextProp( u"FooterText"_ustr );
        if( xInfo->hasPropertyByName( aStrFooterTextProp ) )
        {
            xSet->getPropertyValue( aStrFooterTextProp ) >>= aStrText;
            if( !aStrText.isEmpty() )
                aSettings.maStrFooterDeclName = findOrAppendImpl( maFooterDeclsVector, aStrText, gpStrFooterTextPrefix );
        }

        static constexpr OUString aStrDateTimeTextProp( u"DateTimeText"_ustr );
        if( xInfo->hasPropertyByName( aStrDateTimeTextProp ) )
        {
            bool bFixed = false;
            sal_Int32 nFormat = 0;
            xSet->getPropertyValue( aStrDateTimeTextProp ) >>= aStrText;
            xSet->getPropertyValue(u"IsDateTimeFixed"_ustr) >>= bFixed;
            xSet->getPropertyValue(u"DateTimeFormat"_ustr) >>= nFormat;

            if( !bFixed || !aStrText.isEmpty() )
            {
                aSettings.maStrDateTimeDeclName = findOrAppendImpl( maDateTimeDeclsVector, aStrText, bFixed, nFormat, gpStrDateTimeTextPrefix );
                if( !bFixed )
                    addDataStyle( nFormat );
            }
        }
    }
    catch(const Exception&)
    {
        TOOLS_WARN_EXCEPTION("xmloff.draw", "");
    }

    return aSettings;
}

void SdXMLExport::ImpWriteHeaderFooterDecls()
{
    OUStringBuffer sBuffer;

    if( !maHeaderDeclsVector.empty() )
    {
        // export header decls
        const OUString aPrefix( gpStrHeaderTextPrefix );
        sal_Int32 nIndex = 1;
        for( const auto& rDecl : maHeaderDeclsVector )
        {
            sBuffer.append( aPrefix + OUString::number( nIndex ) );
            AddAttribute(XML_NAMESPACE_PRESENTATION, XML_NAME, sBuffer.makeStringAndClear());

            SvXMLElementExport aElem(*this, XML_NAMESPACE_PRESENTATION, XML_HEADER_DECL, true, true);
            Characters(rDecl);
            ++nIndex;
        }
    }

    if( !maFooterDeclsVector.empty() )
    {
        // export footer decls
        const OUString aPrefix( gpStrFooterTextPrefix );
        sal_Int32 nIndex = 1;
        for( const auto& rDecl : maFooterDeclsVector )
        {
            sBuffer.append( aPrefix + OUString::number( nIndex ) );
            AddAttribute(XML_NAMESPACE_PRESENTATION, XML_NAME, sBuffer.makeStringAndClear());

            SvXMLElementExport aElem(*this, XML_NAMESPACE_PRESENTATION, XML_FOOTER_DECL, false, false);
            Characters(rDecl);
            ++nIndex;
        }
    }

    if( maDateTimeDeclsVector.empty() )
        return;

    // export footer decls
    const OUString aPrefix( gpStrDateTimeTextPrefix );
    sal_Int32 nIndex = 1;
    for( const auto& rDecl : maDateTimeDeclsVector )
    {
        sBuffer.append( aPrefix + OUString::number( nIndex ) );
        AddAttribute( XML_NAMESPACE_PRESENTATION, XML_NAME, sBuffer.makeStringAndClear());

        AddAttribute( XML_NAMESPACE_PRESENTATION, XML_SOURCE, rDecl.mbFixed ? XML_FIXED : XML_CURRENT_DATE );

        if( !rDecl.mbFixed )
            AddAttribute( XML_NAMESPACE_STYLE, XML_DATA_STYLE_NAME, getDataStyleName( rDecl.mnFormat ) );

        SvXMLElementExport aElem(*this, XML_NAMESPACE_PRESENTATION, XML_DATE_TIME_DECL, false, false);
        if( rDecl.mbFixed )
            Characters(rDecl.maStrText);

        ++nIndex;
    }
}

void SdXMLExport::ImplExportHeaderFooterDeclAttributes( const HeaderFooterPageSettingsImpl& aSettings )
{
    if( !aSettings.maStrHeaderDeclName.isEmpty() )
        AddAttribute( XML_NAMESPACE_PRESENTATION, XML_USE_HEADER_NAME, aSettings.maStrHeaderDeclName );

    if( !aSettings.maStrFooterDeclName.isEmpty() )
        AddAttribute( XML_NAMESPACE_PRESENTATION, XML_USE_FOOTER_NAME, aSettings.maStrFooterDeclName );

    if( !aSettings.maStrDateTimeDeclName.isEmpty() )
        AddAttribute( XML_NAMESPACE_PRESENTATION, XML_USE_DATE_TIME_NAME, aSettings.maStrDateTimeDeclName );
}

OUString SdXMLExport::ImpCreatePresPageStyleName( const Reference<XDrawPage>& xDrawPage, bool bExportBackground /* = true */ )
{
    // create name
    OUString sStyleName;

    // create style for this page and add to auto style pool

    Reference< beans::XPropertySet > xPropSet1(xDrawPage, UNO_QUERY);
    if(xPropSet1.is())
    {
        Reference< beans::XPropertySet > xPropSet;

        if( bExportBackground )
        {
            // since the background items are in a different propertyset
            // which itself is a property of the pages property set
            // we now merge these two propertysets if possible to simulate
            // a single propertyset with all draw page properties
            static constexpr OUString aBackground(u"Background"_ustr);
            Reference< beans::XPropertySet > xPropSet2;
            Reference< beans::XPropertySetInfo > xInfo( xPropSet1->getPropertySetInfo() );
            if( xInfo.is() && xInfo->hasPropertyByName( aBackground ) )
            {
                Any aAny( xPropSet1->getPropertyValue( aBackground ) );
                aAny >>= xPropSet2;
            }

            if( xPropSet2.is() )
                xPropSet = PropertySetMerger_CreateInstance( xPropSet1, xPropSet2 );
            else
                xPropSet = std::move(xPropSet1);
        }
        else
        {
            xPropSet = std::move(xPropSet1);
        }

        const rtl::Reference< SvXMLExportPropertyMapper > aMapperRef( GetPresPagePropsMapper() );

        std::vector<XMLPropertyState> aPropStates(aMapperRef->Filter(*this, xPropSet));

        if( !aPropStates.empty() )
        {
            // there are filtered properties -> hard attributes
            // try to find this style in AutoStylePool
            sStyleName = GetAutoStylePool()->Find(XmlStyleFamily::SD_DRAWINGPAGE_ID, sStyleName, aPropStates);

            if(sStyleName.isEmpty())
            {
                // Style did not exist, add it to AutoStalePool
                sStyleName = GetAutoStylePool()->Add(XmlStyleFamily::SD_DRAWINGPAGE_ID, sStyleName, std::move(aPropStates));
            }
        }
    }

    return sStyleName;
}

void SdXMLExport::ImpPrepMasterPageInfos()
{
    // create draw:style-name entries for master page export
    // containing only background attributes
    // fixed family for page-styles is "drawing-page" (XML_STYLE_FAMILY_SD_DRAWINGPAGE_NAME)

    sal_Int32 nCnt;
    for( nCnt = 0; nCnt < mnDocMasterPageCount; nCnt++)
    {
        Reference<XDrawPage> xDrawPage;
        mxDocMasterPages->getByIndex(nCnt) >>= xDrawPage;
        maMasterPagesStyleNames[nCnt] = ImpCreatePresPageStyleName( xDrawPage );
    }

    if( !IsImpress() )
        return;

    Reference< presentation::XHandoutMasterSupplier > xHandoutSupp( GetModel(), UNO_QUERY );
    if( xHandoutSupp.is() )
    {
        Reference< XDrawPage > xHandoutPage( xHandoutSupp->getHandoutMasterPage() );
        if( xHandoutPage.is() )
        {
            maHandoutPageHeaderFooterSettings = ImpPrepDrawPageHeaderFooterDecls( xHandoutPage );
            maHandoutMasterStyleName = ImpCreatePresPageStyleName( xHandoutPage, false );
        }
    }
}

void SdXMLExport::ImpWritePresentationStyles()
{
    if(!IsImpress())
        return;

    for (sal_Int32 nCnt = 0; nCnt < mnDocMasterPageCount; nCnt++)
    {
        Any aAny(mxDocMasterPages->getByIndex(nCnt));
        Reference<container::XNamed> xNamed;

        if(aAny >>= xNamed)
        {
            // write presentation styles (ONLY if presentation)
            if(IsImpress() && mxDocStyleFamilies.is() && xNamed.is())
            {
                rtl::Reference<XMLStyleExport> aStEx(new XMLStyleExport(*this, GetAutoStylePool().get()));
                const rtl::Reference< SvXMLExportPropertyMapper > aMapperRef( GetPropertySetMapper() );

                OUString aPrefix( xNamed->getName() + "-" );

                aStEx->exportStyleFamily(xNamed->getName(),
                    XML_STYLE_FAMILY_SD_PRESENTATION_NAME,
                    aMapperRef, false,
                    XmlStyleFamily::SD_PRESENTATION_ID, &aPrefix);
            }
        }
    }
}

void SdXMLExport::ExportMeta_()
{
    uno::Sequence<beans::NamedValue> stats { { u"ObjectCount"_ustr, uno::Any(mnObjectCount) } };

    // update document statistics at the model
    uno::Reference<document::XDocumentPropertiesSupplier> xPropSup(GetModel(),
        uno::UNO_QUERY_THROW);
    uno::Reference<document::XDocumentProperties> xDocProps(
        xPropSup->getDocumentProperties());
    if (xDocProps.is()) {
        xDocProps->setDocumentStatistics(stats);
    }

    // call parent
    SvXMLExport::ExportMeta_();
}

void SdXMLExport::ExportFontDecls_()
{
    GetFontAutoStylePool(); // make sure the pool is created
    SvXMLExport::ExportFontDecls_();
}

void SdXMLExport::ExportContent_()
{
    // export <pres:header-decl>, <pres:footer-decl> and <pres:date-time-decl> elements
    ImpWriteHeaderFooterDecls();

    // page export
    for(sal_Int32 nPageInd(0); nPageInd < mnDocDrawPageCount; nPageInd++)
    {
        uno::Reference<drawing::XDrawPage> xDrawPage( mxDocDrawPages->getByIndex(nPageInd), uno::UNO_QUERY );

        // set progress view
        if(GetStatusIndicator().is())
            GetStatusIndicator()->setValue(((nPageInd + 1) * 100) / mnDocDrawPageCount);

        if(xDrawPage.is())
        {
            // prepare page attributes, name of page
            Reference < container::XNamed > xNamed(xDrawPage, UNO_QUERY);
            if(xNamed.is())
                AddAttribute(XML_NAMESPACE_DRAW, XML_NAME, xNamed->getName());

            // draw:style-name (presentation page attributes AND background attributes)
            if( !maDrawPagesStyleNames[nPageInd].isEmpty() )
                AddAttribute(XML_NAMESPACE_DRAW, XML_STYLE_NAME,
                        maDrawPagesStyleNames[nPageInd]);

            // draw:master-page-name
            Reference < drawing::XMasterPageTarget > xMasterPageInt(xDrawPage, UNO_QUERY);
            if(xMasterPageInt.is())
            {
                Reference<XDrawPage> xUsedMasterPage(xMasterPageInt->getMasterPage());
                if(xUsedMasterPage.is())
                {
                    Reference < container::XNamed > xMasterNamed(xUsedMasterPage, UNO_QUERY);
                    if(xMasterNamed.is())
                    {
                        AddAttribute(XML_NAMESPACE_DRAW, XML_MASTER_PAGE_NAME,
                            EncodeStyleName( xMasterNamed->getName()) );
                    }
                }
            }

            // presentation:page-layout-name
            if( IsImpress() && !maDrawPagesAutoLayoutNames[nPageInd+1].isEmpty())
            {
                AddAttribute(XML_NAMESPACE_PRESENTATION, XML_PRESENTATION_PAGE_LAYOUT_NAME, maDrawPagesAutoLayoutNames[nPageInd+1] );
            }

            Reference< beans::XPropertySet > xProps( xDrawPage, UNO_QUERY );
            if( xProps.is() )
            {
                try
                {
                    OUString aBookmarkURL;
                    xProps->getPropertyValue(u"BookmarkURL"_ustr) >>= aBookmarkURL;

                    if( !aBookmarkURL.isEmpty() )
                    {
                        sal_Int32 nIndex = aBookmarkURL.lastIndexOf( '#' );
                        if( nIndex != -1 )
                        {
                            OUString aFileName( aBookmarkURL.copy( 0, nIndex ) );
                            std::u16string_view aBookmarkName( aBookmarkURL.subView( nIndex+1 ) );

                            aBookmarkURL = GetRelativeReference( aFileName ) + "#" + aBookmarkName;
                        }

                        AddAttribute ( XML_NAMESPACE_XLINK, XML_HREF, aBookmarkURL);
                        AddAttribute ( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
                        AddAttribute ( XML_NAMESPACE_XLINK, XML_SHOW, XML_REPLACE );
                        AddAttribute ( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONREQUEST );
                    }
                }
                catch(const Exception&)
                {
                    OSL_FAIL(" no \"BookmarkURL\" property at page?" );
                }
            }

            if( IsImpress() )
                ImplExportHeaderFooterDeclAttributes( maDrawPagesHeaderFooterSettings[nPageInd] );

            OUString sNavigationOrder( getNavigationOrder( xDrawPage ) );
            if( !sNavigationOrder.isEmpty() )
                AddAttribute ( XML_NAMESPACE_DRAW, XML_NAV_ORDER, sNavigationOrder );

            rtl::Reference< xmloff::AnimationsExporter >  xAnimationsExporter;
            uno::Reference< css::animations::XAnimationNodeSupplier > xAnimNodeSupplier;

            // prepare animation export
            if(IsImpress())
            {
                if( getExportFlags() & SvXMLExportFlags::OASIS )
                {
                    // export new animations for oasis format
                    xAnimNodeSupplier.set( xDrawPage, UNO_QUERY );

                    // prepare animations exporter if impress
                    if(xAnimNodeSupplier.is())
                    {
                        xAnimationsExporter = new xmloff::AnimationsExporter( *this, xProps );
                        xAnimationsExporter->prepare( xAnimNodeSupplier->getAnimationNode() );
                    }
                }
                else
                {
                    // export old animations for ooo format
                    rtl::Reference< XMLAnimationsExporter > xAnimExport = new XMLAnimationsExporter();
                    GetShapeExport()->setAnimationsExporter( xAnimExport );
                }
            }

            // write draw:id
            const OUString aPageId = getInterfaceToIdentifierMapper().getIdentifier( xDrawPage );
            if( !aPageId.isEmpty() )
            {
                AddAttributeIdLegacy(XML_NAMESPACE_DRAW, aPageId);
            }

            // write page
            SvXMLElementExport aDPG(*this, XML_NAMESPACE_DRAW, XML_PAGE, true, true);

            // write optional office:forms
            exportFormsElement( xDrawPage );

            // write graphic objects on this page (if any)
            if(xDrawPage.is() && xDrawPage->getCount())
                GetShapeExport()->exportShapes( xDrawPage );

            // write animations and presentation notes (ONLY if presentation)
            if(IsImpress())
            {
                if(xAnimNodeSupplier.is())
                {
                    xAnimationsExporter->exportAnimations( xAnimNodeSupplier->getAnimationNode() );
                }
                else
                {
                    // animations
                    rtl::Reference< XMLAnimationsExporter > xAnimExport( GetShapeExport()->getAnimationsExporter() );
                    if( xAnimExport.is() )
                        xAnimExport->exportAnimations( *this );

                    xAnimExport = nullptr;
                    GetShapeExport()->setAnimationsExporter( xAnimExport );
                }

                // presentations
                Reference< presentation::XPresentationPage > xPresPage(xDrawPage, UNO_QUERY);
                if(xPresPage.is())
                {
                    Reference< XDrawPage > xNotesPage(xPresPage->getNotesPage());
                    if(xNotesPage.is())
                    {
                        if( !maDrawNotesPagesStyleNames[nPageInd].isEmpty() )
                            AddAttribute(XML_NAMESPACE_DRAW, XML_STYLE_NAME, maDrawNotesPagesStyleNames[nPageInd]);

                        ImplExportHeaderFooterDeclAttributes( maDrawNotesPagesHeaderFooterSettings[nPageInd] );

                        // write presentation notes
                        SvXMLElementExport aPSY(*this, XML_NAMESPACE_PRESENTATION, XML_NOTES, true, true);

                        // write optional office:forms
                        exportFormsElement( xNotesPage );

                        // write shapes per se
                        GetShapeExport()->exportShapes( xNotesPage );
                    }
                }
            }

            exportAnnotations( xDrawPage );
        }
    }

    if( IsImpress() )
        exportPresentationSettings();
}

void SdXMLExport::exportPresentationSettings()
{
    try
    {
        Reference< XPresentationSupplier > xPresSupplier( GetModel(), UNO_QUERY );
        if( !xPresSupplier.is() )
            return;

        Reference< XPropertySet > xPresProps( xPresSupplier->getPresentation(), UNO_QUERY );
        if( !xPresProps.is() )
            return;

        bool bHasAttr = false;

        bool bTemp = false;

        // export range
        xPresProps->getPropertyValue(u"IsShowAll"_ustr) >>= bTemp;
        if( !bTemp )
        {
            OUString aFirstPage;
            xPresProps->getPropertyValue(u"FirstPage"_ustr) >>= aFirstPage;
            if( !aFirstPage.isEmpty() )
            {
                AddAttribute(XML_NAMESPACE_PRESENTATION, XML_START_PAGE, aFirstPage );
                bHasAttr = true;
            }
            else
            {
                OUString aCustomShow;
                xPresProps->getPropertyValue(u"CustomShow"_ustr) >>= aCustomShow;
                if( !aCustomShow.isEmpty() )
                {
                    AddAttribute(XML_NAMESPACE_PRESENTATION, XML_SHOW, aCustomShow );
                    bHasAttr = true;
                }
            }
        }

        xPresProps->getPropertyValue(u"IsEndless"_ustr) >>= bTemp;
        if( bTemp )
        {
            AddAttribute(XML_NAMESPACE_PRESENTATION, XML_ENDLESS, XML_TRUE );
            bHasAttr = true;

            sal_Int32 nPause = 0;
            xPresProps->getPropertyValue(u"Pause"_ustr) >>= nPause;

            util::Duration aDuration;
            aDuration.Seconds = static_cast<sal_uInt16>(nPause);

            OUStringBuffer aOut;
            ::sax::Converter::convertDuration(aOut, aDuration);
            AddAttribute(XML_NAMESPACE_PRESENTATION, XML_PAUSE, aOut.makeStringAndClear() );
        }

        xPresProps->getPropertyValue(u"AllowAnimations"_ustr) >>= bTemp;
        if( !bTemp )
        {
            AddAttribute(XML_NAMESPACE_PRESENTATION, XML_ANIMATIONS, XML_DISABLED );
            bHasAttr = true;
        }

        xPresProps->getPropertyValue(u"IsAlwaysOnTop"_ustr) >>= bTemp;
        if( bTemp )
        {
            AddAttribute(XML_NAMESPACE_PRESENTATION, XML_STAY_ON_TOP, XML_TRUE );
            bHasAttr = true;
        }

        xPresProps->getPropertyValue(u"IsAutomatic"_ustr) >>= bTemp;
        if( bTemp )
        {
            AddAttribute(XML_NAMESPACE_PRESENTATION, XML_FORCE_MANUAL, XML_TRUE );
            bHasAttr = true;
        }

        xPresProps->getPropertyValue(u"IsFullScreen"_ustr) >>= bTemp;
        if( !bTemp )
        {
            AddAttribute(XML_NAMESPACE_PRESENTATION, XML_FULL_SCREEN, XML_FALSE );
            bHasAttr = true;
        }

        // We need to always export this attribute, because the import had the wrong default (tdf#108824)
        xPresProps->getPropertyValue(u"IsMouseVisible"_ustr) >>= bTemp;
        AddAttribute(XML_NAMESPACE_PRESENTATION, XML_MOUSE_VISIBLE, bTemp ? XML_TRUE : XML_FALSE);
        bHasAttr = true;

        xPresProps->getPropertyValue(u"StartWithNavigator"_ustr) >>= bTemp;
        if( bTemp )
        {
            AddAttribute(XML_NAMESPACE_PRESENTATION, XML_START_WITH_NAVIGATOR, XML_TRUE );
            bHasAttr = true;
        }

        xPresProps->getPropertyValue(u"UsePen"_ustr) >>= bTemp;
        if( bTemp )
        {
            AddAttribute(XML_NAMESPACE_PRESENTATION, XML_MOUSE_AS_PEN, XML_TRUE );
            bHasAttr = true;
        }

        xPresProps->getPropertyValue(u"IsTransitionOnClick"_ustr) >>= bTemp;
        if( !bTemp )
        {
            AddAttribute(XML_NAMESPACE_PRESENTATION, XML_TRANSITION_ON_CLICK, XML_DISABLED );
            bHasAttr = true;
        }

        xPresProps->getPropertyValue(u"IsShowLogo"_ustr) >>= bTemp;
        if( bTemp )
        {
            AddAttribute(XML_NAMESPACE_PRESENTATION, XML_SHOW_LOGO, XML_TRUE );
            bHasAttr = true;
        }

        Reference< container::XNameContainer > xShows;
        Sequence< OUString > aShowNames;
        bool bHasNames = false;

        Reference< XCustomPresentationSupplier > xSup( GetModel(), UNO_QUERY );
        if( xSup.is() )
        {
            xShows = xSup->getCustomPresentations();
            if( xShows.is() )
            {
                aShowNames = xShows->getElementNames();
                bHasNames = aShowNames.hasElements();
            }
        }

        if( bHasAttr || bHasNames )
        {
            SvXMLElementExport aSettings(*this, XML_NAMESPACE_PRESENTATION, XML_SETTINGS, true, true);

            if( !bHasNames )
                return;

            Reference< XIndexContainer > xShow;
            Reference< XNamed > xPageName;

            OUStringBuffer sTmp;

            for (const auto& rShowName : aShowNames)
            {
                AddAttribute(XML_NAMESPACE_PRESENTATION, XML_NAME, rShowName );

                xShows->getByName( rShowName ) >>= xShow;
                SAL_WARN_IF( !xShow.is(), "xmloff", "invalid custom show!" );
                if( !xShow.is() )
                    continue;

                const sal_Int32 nPageCount = xShow->getCount();
                for( sal_Int32 nPage = 0; nPage < nPageCount; nPage++ )
                {
                    xShow->getByIndex( nPage ) >>= xPageName;

                    if( !xPageName.is() )
                        continue;

                    if( !sTmp.isEmpty() )
                        sTmp.append(  ',' );
                    sTmp.append( xPageName->getName() );

                }

                if( !sTmp.isEmpty() )
                    AddAttribute(XML_NAMESPACE_PRESENTATION, XML_PAGES, sTmp.makeStringAndClear() );

                SvXMLElementExport aShows(*this, XML_NAMESPACE_PRESENTATION, XML_SHOW, true, true);
            }
        }
    }
    catch(const uno::Exception&)
    {
        TOOLS_WARN_EXCEPTION("xmloff.draw", "while exporting <presentation:settings>");
    }
}

void SdXMLExport::ExportStyles_(bool bUsed)
{
    GetPropertySetMapper()->SetAutoStyles( false );

    // export fill styles
    SvXMLExport::ExportStyles_( bUsed );

    // write draw:style-name for object graphic-styles
    GetShapeExport()->ExportGraphicDefaults();

    // do not export in ODF 1.1 or older
    if (getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012)
        GetShapeExport()->GetShapeTableExport()->exportTableStyles();

    // write presentation styles
    ImpWritePresentationStyles();

    // prepare draw:auto-layout-name for page export
    ImpPrepAutoLayoutInfos();

    // write draw:auto-layout-name for page export
    ImpWriteAutoLayoutInfos();

    Reference< beans::XPropertySet > xInfoSet( getExportInfo() );
    if( xInfoSet.is() )
    {
        Reference< beans::XPropertySetInfo > xInfoSetInfo( xInfoSet->getPropertySetInfo() );

        if( xInfoSetInfo->hasPropertyByName( gsPageLayoutNames ) )
        {
            xInfoSet->setPropertyValue( gsPageLayoutNames, Any(maDrawPagesAutoLayoutNames) );
        }
    }
}

void SdXMLExport::collectAutoStyles()
{
    SvXMLExport::collectAutoStyles();
    if (mbAutoStylesCollected)
        return;

    Reference< beans::XPropertySet > xInfoSet( getExportInfo() );
    if( xInfoSet.is() )
    {
        Reference< beans::XPropertySetInfo > xInfoSetInfo( xInfoSet->getPropertySetInfo() );

        if( xInfoSetInfo->hasPropertyByName( gsPageLayoutNames ) )
        {
            xInfoSet->getPropertyValue( gsPageLayoutNames ) >>= maDrawPagesAutoLayoutNames;
        }
    }

    GetPropertySetMapper()->SetAutoStyles( true );

    if( getExportFlags() & SvXMLExportFlags::STYLES )
    {
        // #80012# PageMaster export moved from _ExportStyles
        // prepare page-master infos
        ImpPrepPageMasterInfos();

        // prepare draw:style-name for master page export
        ImpPrepMasterPageInfos();
    }

    if( getExportFlags() & SvXMLExportFlags::CONTENT )
    {
        // prepare draw:style-name for page export
        ImpPrepDrawPageInfos();
    }

    if( getExportFlags() & SvXMLExportFlags::STYLES )
    {
        // create auto style infos for shapes on master handout page
        if( IsImpress() )
        {
            Reference< presentation::XHandoutMasterSupplier > xHandoutSupp( GetModel(), UNO_QUERY );
            if( xHandoutSupp.is() )
            {
                Reference< XDrawPage > xHandoutPage( xHandoutSupp->getHandoutMasterPage() );
                if( xHandoutPage.is() && xHandoutPage->getCount())
                    GetShapeExport()->collectShapesAutoStyles( xHandoutPage );
            }
        }

        // create auto style infos for objects on master pages
        for(sal_Int32 nMPageId(0); nMPageId < mnDocMasterPageCount; nMPageId++)
        {
            Reference< XDrawPage > xMasterPage(mxDocMasterPages->getByIndex(nMPageId), UNO_QUERY );

            if( xMasterPage.is() )
            {
                // collect layer information
                GetFormExport()->examineForms( xMasterPage );

                // get MasterPage Name
                OUString aMasterPageNamePrefix;
                Reference < container::XNamed > xNamed(xMasterPage, UNO_QUERY);
                if(xNamed.is())
                {
                    aMasterPageNamePrefix = xNamed->getName();
                }
                if(!aMasterPageNamePrefix.isEmpty())
                {
                    aMasterPageNamePrefix += "-";
                }
                GetShapeExport()->setPresentationStylePrefix( aMasterPageNamePrefix );

                if(xMasterPage.is() && xMasterPage->getCount())
                    GetShapeExport()->collectShapesAutoStyles( xMasterPage );

                if(IsImpress())
                {
                    Reference< presentation::XPresentationPage > xPresPage(xMasterPage, UNO_QUERY);
                    if(xPresPage.is())
                    {
                        Reference< XDrawPage > xNotesPage(xPresPage->getNotesPage());
                        if(xNotesPage.is())
                        {
                            // collect layer information
                            GetFormExport()->examineForms( xNotesPage );

                            if(xNotesPage->getCount())
                                GetShapeExport()->collectShapesAutoStyles( xNotesPage );
                        }
                    }
                }
                collectAnnotationAutoStyles(xMasterPage);
            }
        }
    }

    if( getExportFlags() & SvXMLExportFlags::CONTENT )
    {
        // prepare animations exporter if impress
        if(IsImpress() && (!(getExportFlags() & SvXMLExportFlags::OASIS)) )
        {
            rtl::Reference< XMLAnimationsExporter > xAnimExport = new XMLAnimationsExporter();
            GetShapeExport()->setAnimationsExporter( xAnimExport );
        }

        // create auto style infos for objects on pages
        for(sal_Int32 nPageInd(0); nPageInd < mnDocDrawPageCount; nPageInd++)
        {
            Reference<XDrawPage> xDrawPage( mxDocDrawPages->getByIndex(nPageInd), UNO_QUERY );
            if( xDrawPage.is() )
            {
                // collect layer information
                GetFormExport()->examineForms( xDrawPage );

                // get MasterPage Name
                OUString aMasterPageNamePrefix;
                Reference < drawing::XMasterPageTarget > xMasterPageInt(xDrawPage, UNO_QUERY);
                if(xMasterPageInt.is())
                {
                    Reference<XDrawPage> xUsedMasterPage(xMasterPageInt->getMasterPage());
                    if(xUsedMasterPage.is())
                    {
                        Reference < container::XNamed > xMasterNamed(xUsedMasterPage, UNO_QUERY);
                        if(xMasterNamed.is())
                        {
                            aMasterPageNamePrefix = xMasterNamed->getName();
                        }
                    }
                }
                if(!aMasterPageNamePrefix.isEmpty())
                {
                    aMasterPageNamePrefix += "-";
                }

                GetShapeExport()->setPresentationStylePrefix( aMasterPageNamePrefix );

                // prepare object infos
                if(xDrawPage.is() && xDrawPage->getCount())
                    GetShapeExport()->collectShapesAutoStyles( xDrawPage );

                // prepare presentation notes page object infos (ONLY if presentation)
                if(IsImpress())
                {
                    Reference< presentation::XPresentationPage > xPresPage(xDrawPage, UNO_QUERY);
                    if(xPresPage.is())
                    {
                        Reference< XDrawPage > xNotesPage(xPresPage->getNotesPage());
                        if(xNotesPage.is())
                        {
                            // collect layer information
                            GetFormExport()->examineForms( xNotesPage );

                            if(xNotesPage->getCount())
                                GetShapeExport()->collectShapesAutoStyles( xNotesPage );
                        }
                    }
                }

                collectAnnotationAutoStyles( xDrawPage );
            }
        }
        if (IsImpress())
        {
            rtl::Reference< XMLAnimationsExporter > xAnimExport;
            GetShapeExport()->setAnimationsExporter( xAnimExport );
        }
    }

    mbAutoStylesCollected = true;
}

void SdXMLExport::ExportAutoStyles_()
{
    collectAutoStyles();

    if( getExportFlags() & SvXMLExportFlags::STYLES )
    {
        // write page-master infos
        ImpWritePageMasterInfos();
    }

    // export draw-page styles
    GetAutoStylePool()->exportXML( XmlStyleFamily::SD_DRAWINGPAGE_ID );

    exportAutoDataStyles();

    GetShapeExport()->exportAutoStyles();

    SvXMLExportFlags nContentAutostyles = SvXMLExportFlags::CONTENT | SvXMLExportFlags::AUTOSTYLES;
    if ( ( getExportFlags() & nContentAutostyles ) == nContentAutostyles )
        GetFormExport()->exportAutoStyles( );

    // ...for text
    GetTextParagraphExport()->exportTextAutoStyles();
}

void SdXMLExport::ExportMasterStyles_()
{
    // export layer
    SdXMLayerExporter::exportLayer( *this );

    // export handout master page if impress
    if( IsImpress() )
    {
        Reference< presentation::XHandoutMasterSupplier > xHandoutSupp( GetModel(), UNO_QUERY );
        if( xHandoutSupp.is() )
        {
            Reference< XDrawPage > xHandoutPage( xHandoutSupp->getHandoutMasterPage() );
            if( xHandoutPage.is() )
            {
                // presentation:page-layout-name
                if( IsImpress() && !maDrawPagesAutoLayoutNames[0].isEmpty())
                {
                    AddAttribute(XML_NAMESPACE_PRESENTATION, XML_PRESENTATION_PAGE_LAYOUT_NAME, EncodeStyleName( maDrawPagesAutoLayoutNames[0] ));
                }

                ImpXMLEXPPageMasterInfo* pInfo = mpHandoutPageMaster;
                if(pInfo)
                {
                    const OUString& sString = pInfo->GetName();
                    AddAttribute(XML_NAMESPACE_STYLE, XML_PAGE_LAYOUT_NAME, sString );
                }

                // draw:style-name
                if( !maHandoutMasterStyleName.isEmpty() )
                    AddAttribute(XML_NAMESPACE_DRAW, XML_STYLE_NAME, maHandoutMasterStyleName);

                ImplExportHeaderFooterDeclAttributes( maHandoutPageHeaderFooterSettings );

                // write masterpage
                SvXMLElementExport aMPG(*this, XML_NAMESPACE_STYLE, XML_HANDOUT_MASTER, true, true);

                // write graphic objects on this master page (if any)
                if(xHandoutPage.is() && xHandoutPage->getCount())
                    GetShapeExport()->exportShapes( xHandoutPage );
            }
        }
    }

    // export MasterPages in master-styles section
    for (sal_Int32 nMPageId = 0; nMPageId < mnDocMasterPageCount; nMPageId++)
    {
        Reference< XDrawPage > xMasterPage( mxDocMasterPages->getByIndex(nMPageId), UNO_QUERY );
        if(xMasterPage.is())
        {
            // prepare masterpage attributes
            Reference < container::XNamed > xNamed(xMasterPage, UNO_QUERY);
            if(xNamed.is())
            {
                bool bEncoded = false;
                OUString sMasterPageName = xNamed->getName();
                AddAttribute(XML_NAMESPACE_STYLE, XML_NAME,
                    EncodeStyleName( sMasterPageName, &bEncoded ));
                if( bEncoded )
                    AddAttribute(
                        XML_NAMESPACE_STYLE, XML_DISPLAY_NAME,
                        sMasterPageName );
            }

            ImpXMLEXPPageMasterInfo* pInfo = mvPageMasterUsageList.at( nMPageId );
            if(pInfo)
            {
                const OUString& sString = pInfo->GetName();
                AddAttribute(XML_NAMESPACE_STYLE, XML_PAGE_LAYOUT_NAME, sString );
            }

            // draw:style-name (background attributes)
            if( !maMasterPagesStyleNames[nMPageId].isEmpty() )
                AddAttribute(XML_NAMESPACE_DRAW, XML_STYLE_NAME,
                        maMasterPagesStyleNames[nMPageId]);

            // write masterpage
            SvXMLElementExport aMPG(*this, XML_NAMESPACE_STYLE, XML_MASTER_PAGE, true, true);

            // write optional office:forms
            exportFormsElement( xMasterPage );

            // write optional loext:theme
            exportTheme(xMasterPage);

            // write graphic objects on this master page (if any)
            if(xMasterPage.is() && xMasterPage->getCount())
                GetShapeExport()->exportShapes( xMasterPage );

            // write presentation notes (ONLY if presentation)
            if(IsImpress())
            {
                Reference< presentation::XPresentationPage > xPresPage(xMasterPage, UNO_QUERY);
                if(xPresPage.is())
                {
                    Reference< XDrawPage > xNotesPage(xPresPage->getNotesPage());
                    if(xNotesPage.is())
                    {
                        ImpXMLEXPPageMasterInfo* pMasterInfo = mvNotesPageMasterUsageList.at( nMPageId );
                        if(pMasterInfo)
                        {
                            const OUString& sString = pMasterInfo->GetName();
                            AddAttribute(XML_NAMESPACE_STYLE, XML_PAGE_LAYOUT_NAME, sString);
                        }

                        // write presentation notes
                        SvXMLElementExport aPSY(*this, XML_NAMESPACE_PRESENTATION, XML_NOTES, true, true);

                        // write optional office:forms
                        exportFormsElement( xNotesPage );

                        // write shapes per se
                        GetShapeExport()->exportShapes( xNotesPage );
                    }
                }
            }
            exportAnnotations( xMasterPage );
        }
    }
}

void SdXMLExport::exportFormsElement( const Reference< XDrawPage >& xDrawPage )
{
    if( !xDrawPage.is() )
        return;

    Reference< form::XFormsSupplier2 > xFormsSupplier( xDrawPage, UNO_QUERY );
    if ( xFormsSupplier.is() && xFormsSupplier->hasForms() )
    {
        // write masterpage
        ::xmloff::OOfficeFormsExport aForms(*this);
        GetFormExport()->exportForms( xDrawPage );
    }

    if(! GetFormExport()->seekPage( xDrawPage ) )
    {
        OSL_FAIL( "OFormLayerXMLExport::seekPage failed!" );
    }
}

void SdXMLExport::exportTheme(const uno::Reference<drawing::XDrawPage>& xDrawPage)
{
    if ((getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED) == 0)
    {
        // Do not export in standard ODF 1.3 or older.
        return;
    }

    uno::Reference<beans::XPropertySet> xPropertySet(xDrawPage, uno::UNO_QUERY);
    if (!xPropertySet.is())
        return;

    uno::Reference<util::XTheme> xTheme;
    xPropertySet->getPropertyValue(u"Theme"_ustr) >>= xTheme;
    if (!xTheme.is())
        return;

    auto* pUnoTheme = dynamic_cast<UnoTheme*>(xTheme.get());
    if (!pUnoTheme)
        return;

    auto pTheme = pUnoTheme->getTheme();
    if (!pTheme)
        return;

    ExportThemeElement(pTheme);
}

void SdXMLExport::GetViewSettings(uno::Sequence<beans::PropertyValue>& rProps)
{
    Reference< beans::XPropertySet > xPropSet( GetModel(), UNO_QUERY );
    if( !xPropSet.is() )
        return;

    awt::Rectangle aVisArea;
    xPropSet->getPropertyValue(u"VisibleArea"_ustr) >>= aVisArea;

    rProps.realloc(4);
    beans::PropertyValue* pProps = rProps.getArray();

    pProps[0].Name = "VisibleAreaTop";
    pProps[0].Value <<= aVisArea.Y;
    pProps[1].Name = "VisibleAreaLeft";
    pProps[1].Value <<= aVisArea.X;
    pProps[2].Name = "VisibleAreaWidth";
    pProps[2].Value <<= aVisArea.Width;
    pProps[3].Name = "VisibleAreaHeight";
    pProps[3].Value <<= aVisArea.Height;

}

void SdXMLExport::GetConfigurationSettings(uno::Sequence<beans::PropertyValue>& rProps)
{
    Reference< lang::XMultiServiceFactory > xFac( GetModel(), UNO_QUERY );
    if( !xFac.is() )
        return;

    Reference< beans::XPropertySet > xProps( xFac->createInstance(u"com.sun.star.document.Settings"_ustr), UNO_QUERY );
    if( xProps.is() )
        SvXMLUnitConverter::convertPropertySet( rProps, xProps );
    DocumentSettingsSerializer *pFilter(dynamic_cast<DocumentSettingsSerializer *>(xProps.get()));
    if (!pFilter)
        return;
    const uno::Reference< embed::XStorage > xStorage(GetTargetStorage());
    if (!xStorage.is())
        return;
    rProps = pFilter->filterStreamsToStorage(xStorage, rProps);
}

void SdXMLExport::addDataStyle(const sal_Int32 nNumberFormat, bool bTimeFormat )
{
    sal_Int32 nFormat = nNumberFormat;
    if( (nNumberFormat > 1) && (nNumberFormat <= 0x0f) )
        nFormat -= 2;

    if( bTimeFormat )
    {
        maUsedTimeStyles.insert( nFormat );
    }
    else
    {
        maUsedDateStyles.insert( nFormat );
    }
}

void SdXMLExport::exportDataStyles()
{
    // there are no data styles to export in draw/impress yet
}

void SdXMLExport::exportAutoDataStyles()
{
    for( const auto& rUsedDateStyle : maUsedDateStyles )
        SdXMLNumberStylesExporter::exportDateStyle( *this, rUsedDateStyle );

    for( const auto& rUsedTimeStyle : maUsedTimeStyles )
        SdXMLNumberStylesExporter::exportTimeStyle( *this, rUsedTimeStyle );

    if(HasFormExport())
        GetFormExport()->exportAutoControlNumberStyles();
}

OUString SdXMLExport::getDataStyleName(const sal_Int32 nNumberFormat, bool bTimeFormat ) const
{
    if( bTimeFormat )
    {
        return SdXMLNumberStylesExporter::getTimeStyleName( nNumberFormat );
    }
    else
    {
        return SdXMLNumberStylesExporter::getDateStyleName( nNumberFormat );
    }
}

OUString SdXMLExport::getNavigationOrder( const Reference< XDrawPage >& xDrawPage )
{
    OUStringBuffer sNavOrder;
    try
    {
        Reference< XPropertySet > xSet( xDrawPage, UNO_QUERY_THROW );
        Reference< XIndexAccess > xNavOrder( xSet->getPropertyValue(u"NavigationOrder"_ustr), UNO_QUERY_THROW );

        Reference< XIndexAccess > xZOrderAccess = xDrawPage;

        // only export navigation order if it is different from the z-order
        if( (xNavOrder.get() != xZOrderAccess.get()) && (xNavOrder->getCount() == xDrawPage->getCount())  )
        {
            sal_Int32 nIndex;
            const sal_Int32 nCount = xNavOrder->getCount();
            for( nIndex = 0; nIndex < nCount; ++nIndex )
            {
                OUString sId( getInterfaceToIdentifierMapper().registerReference( Reference< XInterface >( xNavOrder->getByIndex( nIndex ), UNO_QUERY ) ) );
                if( !sId.isEmpty() )
                {
                    if( !sNavOrder.isEmpty() )
                        sNavOrder.append( ' ' );
                    sNavOrder.append( sId );
                }
            }
        }
    }
    catch(const Exception&)
    {
    }
    return sNavOrder.makeStringAndClear();
}

void SdXMLExport::collectAnnotationAutoStyles( const Reference<XDrawPage>& xDrawPage )
{
    Reference< XAnnotationAccess > xAnnotationAccess( xDrawPage, UNO_QUERY );
    if( !xAnnotationAccess.is() ) return;

    try
    {
        Reference< XAnnotationEnumeration > xAnnotationEnumeration( xAnnotationAccess->createAnnotationEnumeration() );
        if( xAnnotationEnumeration.is() )
        {
            while( xAnnotationEnumeration->hasMoreElements() )
            {
                Reference< XAnnotation > xAnnotation( xAnnotationEnumeration->nextElement(), UNO_SET_THROW );
                Reference< XText > xText( xAnnotation->getTextRange() );
                if(xText.is() && !xText->getString().isEmpty())
                    GetTextParagraphExport()->collectTextAutoStyles( xText );
            }
        }
    }
    catch(const Exception&)
    {
        TOOLS_WARN_EXCEPTION("xmloff.draw",
                             "exception caught during export of annotation auto styles");
    }
}

void SdXMLExport::exportAnnotations( const Reference<XDrawPage>& xDrawPage )
{
    // do not export in standard ODF 1.3 or older
    if ((getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED) == 0)
    {
        return;
    }

    Reference< XAnnotationAccess > xAnnotationAccess( xDrawPage, UNO_QUERY );
    if( !xAnnotationAccess.is() )
        return;

    try
    {
        Reference< XAnnotationEnumeration > xAnnotationEnumeration( xAnnotationAccess->createAnnotationEnumeration() );
        if( xAnnotationEnumeration.is() && xAnnotationEnumeration->hasMoreElements() )
        {
            bool bRemovePersonalInfo = SvtSecurityOptions::IsOptionSet(
                SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo ) && !SvtSecurityOptions::IsOptionSet(
                    SvtSecurityOptions::EOption::DocWarnKeepNoteAuthorDateInfo);

            OUStringBuffer sStringBuffer;
            do
            {
                Reference< XAnnotation > xAnnotation( xAnnotationEnumeration->nextElement(), UNO_SET_THROW );

                RealPoint2D aPosition( xAnnotation->getPosition() );

                GetMM100UnitConverter().convertMeasureToXML(sStringBuffer,
                        static_cast<sal_Int32>( aPosition.X * 100 ) );
                AddAttribute(XML_NAMESPACE_SVG, XML_X, sStringBuffer.makeStringAndClear());

                GetMM100UnitConverter().convertMeasureToXML(sStringBuffer,
                        static_cast<sal_Int32>( aPosition.Y * 100 ) );
                AddAttribute(XML_NAMESPACE_SVG, XML_Y, sStringBuffer.makeStringAndClear());

                RealSize2D aSize( xAnnotation->getSize() );

                if( aSize.Width || aSize.Height )
                {
                    GetMM100UnitConverter().convertMeasureToXML(sStringBuffer,
                            static_cast<sal_Int32>( aSize.Width * 100 ) );
                    AddAttribute(XML_NAMESPACE_SVG, XML_WIDTH, sStringBuffer.makeStringAndClear());
                    GetMM100UnitConverter().convertMeasureToXML(sStringBuffer,
                            static_cast<sal_Int32>( aSize.Height * 100 ) );
                    AddAttribute(XML_NAMESPACE_SVG, XML_HEIGHT, sStringBuffer.makeStringAndClear());
                }

                // annotation element + content
                SvXMLElementExport aElem(*this, XML_NAMESPACE_OFFICE_EXT, XML_ANNOTATION, false, true);

                // author
                OUString aAuthor( xAnnotation->getAuthor() );
                if( !aAuthor.isEmpty() )
                {
                    SvXMLElementExport aCreatorElem( *this, XML_NAMESPACE_DC, XML_CREATOR, true, false );
                    Characters( bRemovePersonalInfo
                            ? "Author" + OUString::number( SvXMLExport::GetInfoID(aAuthor) )
                            : aAuthor );
                }

                // initials
                OUString aInitials( xAnnotation->getInitials() );
                if( !aInitials.isEmpty() )
                {
                    // OFFICE-3776 export meta:creator-initials for ODF 1.3
                    SvXMLElementExport aInitialsElem( *this,
                            (SvtSaveOptions::ODFSVER_013 <= getSaneDefaultVersion())
                                ? XML_NAMESPACE_META
                                : XML_NAMESPACE_LO_EXT,
                            (SvtSaveOptions::ODFSVER_013 <= getSaneDefaultVersion())
                                ? XML_CREATOR_INITIALS
                                : XML_SENDER_INITIALS,
                            true, false );
                    Characters( bRemovePersonalInfo
                            ? OUString::number( SvXMLExport::GetInfoID(aInitials) )
                            : aInitials );
                }

                {
                    // date time
                    css::util::DateTime aDate( bRemovePersonalInfo
                            ? css::util::DateTime(0, 0, 0, 0, 1, 1, 1970, true) // Epoch time
                            : xAnnotation->getDateTime() );
                    ::sax::Converter::convertDateTime(sStringBuffer, aDate, nullptr, true);
                    SvXMLElementExport aDateElem( *this, XML_NAMESPACE_DC, XML_DATE, true, false );
                    Characters( sStringBuffer.makeStringAndClear() );
                }

                css::uno::Reference < css::text::XText > xText( xAnnotation->getTextRange() );
                if( xText.is() )
                    GetTextParagraphExport()->exportText( xText );
            }
            while( xAnnotationEnumeration->hasMoreElements() );
        }
    }
    catch(const Exception&)
    {
        TOOLS_WARN_EXCEPTION("xmloff.draw", "exception caught during export of annotations");
    }
}

extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
com_sun_star_comp_Impress_XMLOasisExporter_get_implementation(
    uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
{
    return cppu::acquire(new SdXMLExport(
        pCtx, u"XMLImpressExportOasis"_ustr, false,
        SvXMLExportFlags::OASIS | SvXMLExportFlags::META | SvXMLExportFlags::STYLES
            | SvXMLExportFlags::MASTERSTYLES | SvXMLExportFlags::AUTOSTYLES
            | SvXMLExportFlags::CONTENT | SvXMLExportFlags::SCRIPTS | SvXMLExportFlags::SETTINGS
            | SvXMLExportFlags::FONTDECLS | SvXMLExportFlags::EMBEDDED));
}

extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
com_sun_star_comp_Impress_XMLOasisStylesExporter_get_implementation(
    uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
{
    return cppu::acquire(new SdXMLExport(
        pCtx, u"XMLImpressStylesExportOasis"_ustr, false,
        SvXMLExportFlags::OASIS | SvXMLExportFlags::STYLES | SvXMLExportFlags::MASTERSTYLES
            | SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::FONTDECLS));
}

extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
com_sun_star_comp_Impress_XMLOasisContentExporter_get_implementation(
    uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
{
    return cppu::acquire(new SdXMLExport(pCtx, u"XMLImpressContentExportOasis"_ustr, false,
                                         SvXMLExportFlags::OASIS | SvXMLExportFlags::AUTOSTYLES
                                             | SvXMLExportFlags::CONTENT | SvXMLExportFlags::SCRIPTS
                                             | SvXMLExportFlags::FONTDECLS));
}

extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
com_sun_star_comp_Impress_XMLOasisMetaExporter_get_implementation(
    uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
{
    return cppu::acquire(new SdXMLExport(pCtx, u"XMLImpressMetaExportOasis"_ustr, false,
                                         SvXMLExportFlags::OASIS | SvXMLExportFlags::META));
}

extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
com_sun_star_comp_Impress_XMLOasisSettingsExporter_get_implementation(
    uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
{
    return cppu::acquire(new SdXMLExport(pCtx, u"XMLImpressSettingsExportOasis"_ustr, false,
                                         SvXMLExportFlags::OASIS | SvXMLExportFlags::SETTINGS));
}

extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
com_sun_star_comp_Impress_XMLExporter_get_implementation(uno::XComponentContext* pCtx,
                                                         uno::Sequence<uno::Any> const& /*rSeq*/)
{
    return cppu::acquire(new SdXMLExport(
        pCtx, u"XMLImpressExportOOO"_ustr, false,
        SvXMLExportFlags::META | SvXMLExportFlags::STYLES | SvXMLExportFlags::MASTERSTYLES
            | SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::CONTENT | SvXMLExportFlags::SCRIPTS
            | SvXMLExportFlags::SETTINGS | SvXMLExportFlags::FONTDECLS
            | SvXMLExportFlags::EMBEDDED));
}

extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
com_sun_star_comp_Draw_XMLExporter_get_implementation(uno::XComponentContext* pCtx,
                                                      uno::Sequence<uno::Any> const& /*rSeq*/)
{
    return cppu::acquire(new SdXMLExport(
        pCtx, u"XMLDrawExportOOO"_ustr, true,
        SvXMLExportFlags::META | SvXMLExportFlags::STYLES | SvXMLExportFlags::MASTERSTYLES
            | SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::CONTENT | SvXMLExportFlags::SCRIPTS
            | SvXMLExportFlags::SETTINGS | SvXMLExportFlags::FONTDECLS
            | SvXMLExportFlags::EMBEDDED));
}

extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
com_sun_star_comp_Draw_XMLOasisSettingsExporter_get_implementation(
    uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
{
    return cppu::acquire(new SdXMLExport(pCtx, u"XMLDrawSettingsExportOasis"_ustr, true,
                                         SvXMLExportFlags::OASIS | SvXMLExportFlags::SETTINGS));
}

extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
com_sun_star_comp_Draw_XMLOasisMetaExporter_get_implementation(
    uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
{
    return cppu::acquire(new SdXMLExport(pCtx, u"XMLDrawMetaExportOasis"_ustr, true,
                                         SvXMLExportFlags::OASIS | SvXMLExportFlags::META));
}

extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
com_sun_star_comp_Draw_XMLOasisContentExporter_get_implementation(
    uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
{
    return cppu::acquire(new SdXMLExport(pCtx, u"XMLDrawContentExportOasis"_ustr, true,
                                         SvXMLExportFlags::OASIS | SvXMLExportFlags::AUTOSTYLES
                                             | SvXMLExportFlags::CONTENT | SvXMLExportFlags::SCRIPTS
                                             | SvXMLExportFlags::FONTDECLS));
}

extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
com_sun_star_comp_Draw_XMLOasisStylesExporter_get_implementation(
    uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
{
    return cppu::acquire(new SdXMLExport(
        pCtx, u"XMLDrawStylesExportOasis"_ustr, true,
        SvXMLExportFlags::OASIS | SvXMLExportFlags::STYLES | SvXMLExportFlags::MASTERSTYLES
            | SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::FONTDECLS));
}

extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
com_sun_star_comp_Draw_XMLOasisExporter_get_implementation(uno::XComponentContext* pCtx,
                                                           uno::Sequence<uno::Any> const& /*rSeq*/)
{
    return cppu::acquire(new SdXMLExport(
        pCtx, u"XMLDrawExportOasis"_ustr, true,
        SvXMLExportFlags::OASIS | SvXMLExportFlags::META | SvXMLExportFlags::STYLES
            | SvXMLExportFlags::MASTERSTYLES | SvXMLExportFlags::AUTOSTYLES
            | SvXMLExportFlags::CONTENT | SvXMLExportFlags::SCRIPTS | SvXMLExportFlags::SETTINGS
            | SvXMLExportFlags::FONTDECLS | SvXMLExportFlags::EMBEDDED));
}

extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
com_sun_star_comp_DrawingLayer_XMLExporter_get_implementation(
    uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
{
    return cppu::acquire(
        new SdXMLExport(pCtx, u"XMLDrawingLayerExport"_ustr, true,
                        SvXMLExportFlags::OASIS | SvXMLExportFlags::STYLES
                            | SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::CONTENT
                            | SvXMLExportFlags::FONTDECLS | SvXMLExportFlags::EMBEDDED));
}

extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
com_sun_star_comp_Impress_XMLClipboardExporter_get_implementation(
    uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
{
    return cppu::acquire(
        new SdXMLExport(pCtx, u"XMLImpressClipboardExport"_ustr, /*bIsDraw=*/false,
                        SvXMLExportFlags::OASIS | SvXMLExportFlags::STYLES
                            | SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::CONTENT
                            | SvXMLExportFlags::FONTDECLS | SvXMLExportFlags::EMBEDDED));
}

XMLFontAutoStylePool* SdXMLExport::CreateFontAutoStylePool()
{
    try
    {
        Reference<lang::XMultiServiceFactory> xFactory(GetModel(), UNO_QUERY);
        Reference<beans::XPropertySet> xProps;
        Reference<beans::XPropertySetInfo> xInfo;

        if (xFactory.is())
            xProps.set(xFactory->createInstance(u"com.sun.star.document.Settings"_ustr), UNO_QUERY);
        if (xProps.is())
            xInfo =  xProps->getPropertySetInfo();
        if (xInfo.is() && xProps.is())
        {
            if (xInfo->hasPropertyByName(u"EmbedFonts"_ustr))
                xProps->getPropertyValue(u"EmbedFonts"_ustr) >>= mbEmbedFonts;
            if (xInfo->hasPropertyByName(u"EmbedOnlyUsedFonts"_ustr))
                xProps->getPropertyValue(u"EmbedOnlyUsedFonts"_ustr) >>= mbEmbedUsedOnly;
            if (xInfo->hasPropertyByName(u"EmbedLatinScriptFonts"_ustr))
                xProps->getPropertyValue(u"EmbedLatinScriptFonts"_ustr) >>= mbEmbedLatinScript;
            if (xInfo->hasPropertyByName(u"EmbedAsianScriptFonts"_ustr))
                xProps->getPropertyValue(u"EmbedAsianScriptFonts"_ustr) >>= mbEmbedAsianScript;
            if (xInfo->hasPropertyByName(u"EmbedComplexScriptFonts"_ustr))
                xProps->getPropertyValue(u"EmbedComplexScriptFonts"_ustr) >>= mbEmbedComplexScript;
        }
    } catch(...)
    {
        // clipboard document doesn't have shell so throws from getPropertyValue
        // gallery elements may not support com.sun.star.document.Settings so throws from createInstance
    }

    XMLFontAutoStylePool* pPool = new XMLFontAutoStylePool(*this);

    Reference< beans::XPropertySet > xProps( GetModel(), UNO_QUERY );
    if ( xProps.is() ) {
        Sequence<Any> aAnySeq;
        if( xProps->getPropertyValue(u"Fonts"_ustr) >>= aAnySeq )
        {
            if( aAnySeq.getLength() % 5 == 0 )
            {
                int nLen = aAnySeq.getLength() / 5;
                int nSeqIndex = 0;
                for( int i = 0; i < nLen; i++ )
                {
                    OUString sFamilyName, sStyleName;
                    sal_Int16 eFamily(FAMILY_DONTKNOW),
                        ePitch(PITCH_DONTKNOW),
                        eCharSet(RTL_TEXTENCODING_DONTKNOW);

                    aAnySeq[nSeqIndex++] >>= sFamilyName;
                    aAnySeq[nSeqIndex++] >>= sStyleName;
                    aAnySeq[nSeqIndex++] >>= eFamily;
                    aAnySeq[nSeqIndex++] >>= ePitch;
                    aAnySeq[nSeqIndex++] >>= eCharSet;

                    pPool->Add( sFamilyName, sStyleName, FontFamily( eFamily ), FontPitch( ePitch ), rtl_TextEncoding( eCharSet ) );
                }
            }
        }
    }

    return pPool;
}

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