/* -*- 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()
{
    bool bEmbedFonts = false;
    bool bEmbedUsedOnly = false;
    bool bEmbedLatinScript = true;
    bool bEmbedAsianScript = true;
    bool bEmbedComplexScript = true;
 
    if (getExportFlags() & SvXMLExportFlags::CONTENT)
    {
        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) >>= bEmbedFonts;
                if (xInfo->hasPropertyByName(u"EmbedOnlyUsedFonts"_ustr))
                    xProps->getPropertyValue(u"EmbedOnlyUsedFonts"_ustr) >>= bEmbedUsedOnly;
                if (xInfo->hasPropertyByName(u"EmbedLatinScriptFonts"_ustr))
                    xProps->getPropertyValue(u"EmbedLatinScriptFonts"_ustr) >>= bEmbedLatinScript;
                if (xInfo->hasPropertyByName(u"EmbedAsianScriptFonts"_ustr))
                    xProps->getPropertyValue(u"EmbedAsianScriptFonts"_ustr) >>= bEmbedAsianScript;
                if (xInfo->hasPropertyByName(u"EmbedComplexScriptFonts"_ustr))
                    xProps->getPropertyValue(u"EmbedComplexScriptFonts"_ustr) >>= bEmbedComplexScript;
            }
        } 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, bEmbedFonts );
    pPool->setEmbedOnlyUsedFonts(bEmbedUsedOnly);
    pPool->setEmbedFontScripts(bEmbedLatinScript, bEmbedAsianScript, bEmbedComplexScript);
 
    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: */

V530 The return value of function 'append' is required to be utilized.

V530 The return value of function 'append' is required to be utilized.

V530 The return value of function 'Add' is required to be utilized.

V519 The 'aAny' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 153, 155.

V519 The 'bHasAttr' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 1889, 1895.

V547 Expression '!bFixed' is always true.

V547 Expression '!bTemp' is always true.

V547 Expression 'bTemp' is always false.

V547 Expression '!bTemp' is always true.

V547 Expression 'bTemp' is always false.

V547 Expression 'bTemp' is always false.

V547 Expression '!bTemp' is always true.

V547 Expression 'bTemp' is always false.

V547 Expression 'bTemp' is always false.

V547 Expression 'bTemp' is always false.

V547 Expression '!bTemp' is always true.

V547 Expression 'bTemp' is always false.

V560 A part of conditional expression is always true: !bFixed.

V1048 The 'bHasAttr' variable was assigned the same value.

V1048 The 'bHasAttr' variable was assigned the same value.

V1048 The 'bHasAttr' variable was assigned the same value.