    /* -*- 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 <stdio.h>
    #include <o3tl/any.hxx>
    #include <oox/drawingml/chart/chartconverter.hxx>
    #include <oox/drawingml/clrscheme.hxx>
    #include <oox/token/namespaces.hxx>
    #include <oox/token/tokens.hxx>
    #include <oox/token/relationship.hxx>
    #include <oox/ole/vbaproject.hxx>
    #include "epptooxml.hxx"
    #include "epptdef.hxx"
    #include <oox/export/shapes.hxx>

    #include <comphelper/sequenceashashmap.hxx>
    #include <comphelper/storagehelper.hxx>
    #include <cppuhelper/implementationentry.hxx>
    #include <cppuhelper/factory.hxx>
    #include <sax/fshelper.hxx>
    #include <rtl/ustrbuf.hxx>
    #include <sal/log.hxx>
    #include <filter/msfilter/escherex.hxx>
    #include <tools/poly.hxx>
    #include <com/sun/star/animations/TransitionType.hpp>
    #include <com/sun/star/animations/TransitionSubType.hpp>
    #include <com/sun/star/beans/Property.hpp>
    #include <com/sun/star/beans/XPropertySetInfo.hpp>
    #include <com/sun/star/container/XEnumerationAccess.hpp>
    #include <com/sun/star/drawing/FillStyle.hpp>
    #include <com/sun/star/drawing/RectanglePoint.hpp>
    #include <com/sun/star/drawing/XDrawPages.hpp>
    #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
    #include <com/sun/star/embed/ElementModes.hpp>
    #include <com/sun/star/geometry/RealPoint2D.hpp>
    #include <com/sun/star/office/XAnnotationEnumeration.hpp>
    #include <com/sun/star/office/XAnnotationAccess.hpp>
    #include <com/sun/star/presentation/AnimationSpeed.hpp>
    #include <com/sun/star/util/DateTime.hpp>
    #include <com/sun/star/task/XStatusIndicator.hpp>
    #include <com/sun/star/frame/XModel.hpp>
    #include <com/sun/star/lang/XMultiServiceFactory.hpp>

    #include <oox/export/utils.hxx>
    #include <oox/ppt/pptfilterhelpers.hxx>
    #include <basegfx/polygon/b2dpolypolygontools.hxx>

    #include "pptexanimations.hxx"
    #include "pptx-animations.hxx"
    #include "../ppt/pptanimations.hxx"

    #include <com/sun/star/document/XDocumentProperties.hpp>
    #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
    #include <com/sun/star/document/XStorageBasedDocument.hpp>
    #include <utility>

    // presentation namespaces
    #define PNMSS         FSNS(XML_xmlns, XML_a),   OUStringToOString(this->getNamespaceURL(OOX_NS(dml)), RTL_TEXTENCODING_UTF8).getStr(), \
                          FSNS(XML_xmlns, XML_p),   OUStringToOString(this->getNamespaceURL(OOX_NS(ppt)), RTL_TEXTENCODING_UTF8).getStr(), \
                          FSNS(XML_xmlns, XML_r),   OUStringToOString(this->getNamespaceURL(OOX_NS(officeRel)), RTL_TEXTENCODING_UTF8).getStr(), \
                          FSNS(XML_xmlns, XML_p14), OUStringToOString(this->getNamespaceURL(OOX_NS(p14)), RTL_TEXTENCODING_UTF8).getStr(), \
                          FSNS(XML_xmlns, XML_p15), OUStringToOString(this->getNamespaceURL(OOX_NS(p15)), RTL_TEXTENCODING_UTF8).getStr(), \
                          FSNS(XML_xmlns, XML_mc),  OUStringToOString(this->getNamespaceURL(OOX_NS(mce)), RTL_TEXTENCODING_UTF8).getStr()

    using namespace ::com::sun::star;
    using namespace ::com::sun::star::animations;
    using namespace ::com::sun::star::beans;
    using namespace ::com::sun::star::container;
    using namespace ::com::sun::star::drawing;
    using namespace ::com::sun::star::geometry;
    using namespace ::com::sun::star::presentation;
    using namespace ::com::sun::star::office;
    using namespace ::com::sun::star::text;
    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::util;
    using namespace ::ppt;
    using ::com::sun::star::beans::XPropertySet;
    using ::com::sun::star::beans::XPropertySetInfo;
    using ::com::sun::star::container::XIndexAccess;
    using ::sax_fastparser::FSHelperPtr;
    using namespace oox::drawingml;
    using namespace oox::core;

    #if OSL_DEBUG_LEVEL > 1
    void dump_pset(Reference< XPropertySet > const& rXPropSet);
    #endif

    namespace oox
    {
    namespace core
    {

    class PowerPointShapeExport : public ShapeExport
    {
        PowerPointExport&   mrExport;
        PageType            mePageType;
        bool                mbMaster;
    public:
        PowerPointShapeExport(FSHelperPtr pFS, ShapeHashMap* pShapeMap, PowerPointExport* pFB);
        void                SetMaster(bool bMaster);
        void                SetPageType(PageType ePageType);
        ShapeExport&        WriteNonVisualProperties(const Reference< XShape >& xShape) override;
        ShapeExport&        WriteTextShape(const Reference< XShape >& xShape) override;
        ShapeExport&        WriteUnknownShape(const Reference< XShape >& xShape) override;
        ShapeExport&        WritePlaceholderShape(const Reference< XShape >& xShape, PlaceholderType ePlaceholder);
        ShapeExport&        WritePageShape(const Reference< XShape >& xShape, PageType ePageType, bool bPresObj);

        // helper parts
        bool WritePlaceholder(const Reference< XShape >& xShape, PlaceholderType ePlaceholder, bool bMaster);
    };

    }
    }

    enum PPTXLayout
    {
        LAYOUT_BLANK,
        LAYOUT_TITLE_SLIDE,
        LAYOUT_TITLE_CONTENT,
        LAYOUT_TITLE_2CONTENT,
        LAYOUT_TITLE,
        LAYOUT_CENTERED_TEXT,
        LAYOUT_TITLE_2CONTENT_CONTENT,
        LAYOUT_TITLE_CONTENT_2CONTENT,
        LAYOUT_TITLE_2CONTENT_OVER_CONTENT,
        LAYOUT_TITLE_CONTENT_OVER_CONTENT,
        LAYOUT_TITLE_4CONTENT,
        LAYOUT_TITLE_6CONTENT,
        LAYOUT_SIZE
    };

    struct PPTXLayoutInfo
    {
        int nType;
        const char* sName;
        const char* sType;
    };

    static const PPTXLayoutInfo aLayoutInfo[LAYOUT_SIZE] =
    {
        { 20, "Blank Slide", "blank" },
        { 0, "Title Slide", "tx" },
        { 1, "Title, Content", "obj" },
        { 3, "Title, 2 Content", "twoObj" },
        { 19, "Title Only", "titleOnly" },
        { 32, "Centered Text", "objOnly" },                       // not exactly, but close
        { 15, "Title, 2 Content and Content", "twoObjAndObj" },
        { 12, "Title Content and 2 Content", "objAndTwoObj" },
        { 16, "Title, 2 Content over Content", "twoObjOverTx" },      // not exactly, but close
        { 14, "Title, Content over Content", "objOverTx" },           // not exactly, but close
        { 18, "Title, 4 Content", "fourObj" },
        { 34, "Title, 6 Content", "blank" }                           // not defined => blank
    };

    int PowerPointExport::GetPPTXLayoutId(int nOffset)
    {
        int nId = LAYOUT_BLANK;

        SAL_INFO("sd.eppt", "GetPPTXLayoutId " << nOffset);

        switch (nOffset)
        {
        case 0:
            nId = LAYOUT_TITLE_SLIDE;
            break;
        case 1:
            nId = LAYOUT_TITLE_CONTENT;
            break;
        case 3:
            nId = LAYOUT_TITLE_2CONTENT;
            break;
        case 19:
            nId = LAYOUT_TITLE;
            break;
        case 15:
            nId = LAYOUT_TITLE_2CONTENT_CONTENT;
            break;
        case 12:
            nId = LAYOUT_TITLE_CONTENT_2CONTENT;
            break;
        case 16:
            nId = LAYOUT_TITLE_2CONTENT_OVER_CONTENT;
            break;
        case 14:
            nId = LAYOUT_TITLE_CONTENT_OVER_CONTENT;
            break;
        case 18:
            nId = LAYOUT_TITLE_4CONTENT;
            break;
        case 32:
            nId = LAYOUT_CENTERED_TEXT;
            break;
        case 34:
            nId = LAYOUT_TITLE_6CONTENT;
            break;
        case 20:
        default:
            nId = LAYOUT_BLANK;
            break;
        }

        return nId;
    }

    PowerPointShapeExport::PowerPointShapeExport(FSHelperPtr pFS, ShapeHashMap* pShapeMap,
            PowerPointExport* pFB)
        : ShapeExport(XML_p, std::move(pFS), pShapeMap, pFB)
        , mrExport(*pFB)
        , mePageType(UNDEFINED)
        , mbMaster(false)
    {
    }

    void PowerPointShapeExport::SetMaster(bool bMaster)
    {
        mbMaster = bMaster;
    }

    void PowerPointShapeExport::SetPageType(PageType ePageType)
    {
        mePageType = ePageType;
    }

    ShapeExport& PowerPointShapeExport::WriteNonVisualProperties(const Reference< XShape >&)
    {
        GetFS()->singleElementNS(XML_p, XML_nvPr, FSEND);

        return *this;
    }

    ShapeExport& PowerPointShapeExport::WriteTextShape(const Reference< XShape >& xShape)
    {
        OUString sShapeType = xShape->getShapeType();

        SAL_INFO("sd.eppt", "shape(text) : " << USS(sShapeType));

        if (sShapeType == "com.sun.star.drawing.TextShape" || sShapeType == "com.sun.star.drawing.GraphicObjectShape")
        {
            ShapeExport::WriteTextShape(xShape);
        }
        else if (sShapeType == "com.sun.star.presentation.DateTimeShape")
        {
            if (!WritePlaceholder(xShape, DateAndTime, mbMaster))
                ShapeExport::WriteTextShape(xShape);
        }
        else if (sShapeType == "com.sun.star.presentation.FooterShape")
        {
            if (!WritePlaceholder(xShape, Footer, mbMaster))
                ShapeExport::WriteTextShape(xShape);
        }
        else if (sShapeType == "com.sun.star.presentation.HeaderShape")
        {
            if (!WritePlaceholder(xShape, Header, mbMaster))
                ShapeExport::WriteTextShape(xShape);
        }
        else if (sShapeType == "com.sun.star.presentation.NotesShape")
        {
            if (mePageType == NOTICE && mrExport.GetPresObj())
                WritePlaceholderShape(xShape, Notes);
            else
                ShapeExport::WriteTextShape(xShape);
        }
        else if (sShapeType == "com.sun.star.presentation.OutlinerShape")
        {
            if (!WritePlaceholder(xShape, Outliner, mbMaster))
                ShapeExport::WriteTextShape(xShape);
        }
        else if (sShapeType == "com.sun.star.presentation.SlideNumberShape")
        {
            if (!WritePlaceholder(xShape, SlideNumber, mbMaster))
                ShapeExport::WriteTextShape(xShape);
        }
        else if (sShapeType == "com.sun.star.presentation.TitleTextShape")
        {
            if (!WritePlaceholder(xShape, Title, mbMaster))
                ShapeExport::WriteTextShape(xShape);
        }
        else
            SAL_WARN("sd.eppt", "PowerPointShapeExport::WriteTextShape: shape of type '" << sShapeType << "' is ignored");

        return *this;
    }

    ShapeExport& PowerPointShapeExport::WriteUnknownShape(const Reference< XShape >& xShape)
    {
        OUString sShapeType = xShape->getShapeType();

        SAL_INFO("sd.eppt", "shape(unknown): " << USS(sShapeType));

        if (sShapeType == "com.sun.star.presentation.PageShape")
        {
            WritePageShape(xShape, mePageType, mrExport.GetPresObj());
        }
        else if (sShapeType == "com.sun.star.presentation.SubtitleShape")
        {
            if(mePageType != MASTER)
            {
                if (!WritePlaceholder(xShape, Subtitle, mbMaster))
                    ShapeExport::WriteTextShape(xShape);
            }
        }
        else
            SAL_WARN("sd.eppt", "unknown shape not handled: " << USS(sShapeType));

        return *this;
    }

    PowerPointExport::PowerPointExport(const Reference< XComponentContext >& rContext, const uno::Sequence<uno::Any>& rArguments)
        : XmlFilterBase(rContext)
        , PPTWriterBase()
        , mnLayoutFileIdMax(1)
        , mnSlideIdMax(1 << 8)
        , mnSlideMasterIdMax(1U << 31)
        , mnAnimationNodeIdMax(1)
        , mbCreateNotes(false)
    {
        comphelper::SequenceAsHashMap aArgumentsMap(rArguments);
        mbPptm = aArgumentsMap.getUnpackedValueOrDefault("IsPPTM", false);
    }

    PowerPointExport::~PowerPointExport()
    {
    }

    void PowerPointExport::writeDocumentProperties()
    {
        uno::Reference<document::XDocumentPropertiesSupplier> xDPS(mXModel, uno::UNO_QUERY);
        uno::Reference<document::XDocumentProperties> xDocProps = xDPS->getDocumentProperties();

        if (xDocProps.is())
        {
            bool bSecurityOptOpenReadOnly = false;
            uno::Reference< lang::XMultiServiceFactory > xFactory(mXModel, uno::UNO_QUERY);
            uno::Reference< beans::XPropertySet > xSettings(xFactory->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY);
            try
            {
                xSettings->getPropertyValue("LoadReadonly") >>= bSecurityOptOpenReadOnly;
            }
            catch( Exception& )
            {
            }
            exportDocumentProperties(xDocProps, bSecurityOptOpenReadOnly);
        }

        exportCustomFragments();
    }

    bool PowerPointExport::importDocument() throw()
    {
        return false;
    }

    bool PowerPointExport::exportDocument()
    {
        DrawingML::ResetCounters();
        maShapeMap.clear();

        mXModel.set(getModel(), UNO_QUERY);

        //write document properties
        writeDocumentProperties();

        addRelation(oox::getRelationship(Relationship::OFFICEDOCUMENT), "ppt/presentation.xml");

        // PPTM needs a different media type for the presentation.xml stream.
        OUString aMediaType("application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml");
        if (mbPptm)
            aMediaType = "application/vnd.ms-powerpoint.presentation.macroEnabled.main+xml";

        mPresentationFS = openFragmentStreamWithSerializer("ppt/presentation.xml", aMediaType);

        addRelation(mPresentationFS->getOutputStream(),
                    oox::getRelationship(Relationship::THEME),
                    "theme/theme1.xml");

        mPresentationFS->startElementNS(XML_p, XML_presentation, PNMSS, FSEND);

        mXStatusIndicator.set(getStatusIndicator(), UNO_QUERY);

        std::vector< PropertyValue > aProperties;
        PropertyValue aProperty;
        aProperty.Name = "BaseURI";
        aProperty.Value <<= getFileUrl();
        aProperties.push_back(aProperty);

        exportPPT(aProperties);

        mPresentationFS->singleElementNS(XML_p, XML_sldSz,
                                         XML_cx, IS(PPTtoEMU(maDestPageSize.Width)),
                                         XML_cy, IS(PPTtoEMU(maDestPageSize.Height)),
                                         FSEND);
        // for some reason if added before slides list it will not load the slides (alas with error reports) in mso
        mPresentationFS->singleElementNS(XML_p, XML_notesSz,
                                         XML_cx, IS(PPTtoEMU(maNotesPageSize.Width)),
                                         XML_cy, IS(PPTtoEMU(maNotesPageSize.Height)),
                                         FSEND);

        WriteAuthors();

        WriteVBA();

        mPresentationFS->endElementNS(XML_p, XML_presentation);
        mPresentationFS.reset();
        // Free all FSHelperPtr, to flush data before committing storage
        mpSlidesFSArray.clear();

        commitStorage();

        maShapeMap.clear();
        maAuthors.clear();

        return true;
    }

    ::oox::ole::VbaProject* PowerPointExport::implCreateVbaProject() const
    {
        return new ::oox::ole::VbaProject(getComponentContext(), getModel(), "Impress");
    }

    void PowerPointExport::ImplWriteBackground(const FSHelperPtr& pFS, const Reference< XPropertySet >& rXPropSet)
    {
        FillStyle aFillStyle(FillStyle_NONE);
        if (ImplGetPropertyValue(rXPropSet, "FillStyle"))
            mAny >>= aFillStyle;

        if (aFillStyle == FillStyle_NONE ||
                aFillStyle == FillStyle_GRADIENT ||
                aFillStyle == FillStyle_HATCH)
            return;

        pFS->startElementNS(XML_p, XML_bg, FSEND);
        pFS->startElementNS(XML_p, XML_bgPr, FSEND);

        PowerPointShapeExport aDML(pFS, &maShapeMap, this);
        aDML.SetBackgroundDark(mbIsBackgroundDark);
        aDML.WriteFill(rXPropSet);

        pFS->endElementNS(XML_p, XML_bgPr);
        pFS->endElementNS(XML_p, XML_bg);
    }

    #define MAIN_GROUP \
         "<p:nvGrpSpPr>\
            <p:cNvPr id=\"1\" name=\"\"/>\
            <p:cNvGrpSpPr/>\
            <p:nvPr/>\
          </p:nvGrpSpPr>\
          <p:grpSpPr>\
            <a:xfrm>\
              <a:off x=\"0\" y=\"0\"/>\
              <a:ext cx=\"0\" cy=\"0\"/>\
              <a:chOff x=\"0\" y=\"0\"/>\
              <a:chExt cx=\"0\" cy=\"0\"/>\
            </a:xfrm>\
          </p:grpSpPr>"

    const char* PowerPointExport::GetSideDirection(sal_uInt8 nDirection)
    {
        const char* pDirection = nullptr;

        switch (nDirection)
        {
        case 0:
            pDirection = "l";
            break;
        case 1:
            pDirection = "u";
            break;
        case 2:
            pDirection = "r";
            break;
        case 3:
            pDirection = "d";
            break;
        }

        return pDirection;
    }

    const char* PowerPointExport::GetCornerDirection(sal_uInt8 nDirection)
    {
        const char* pDirection = nullptr;

        switch (nDirection)
        {
        case 4:
            pDirection = "lu";
            break;
        case 5:
            pDirection = "ru";
            break;
        case 6:
            pDirection = "ld";
            break;
        case 7:
            pDirection = "rd";
            break;
        }

        return pDirection;
    }

    const char* PowerPointExport::Get8Direction(sal_uInt8 nDirection)
    {
        const char* pDirection = GetSideDirection(nDirection);

        if (!pDirection)
            pDirection = GetCornerDirection(nDirection);

        return pDirection;
    }

    void PowerPointExport::WriteTransition(const FSHelperPtr& pFS)
    {
        FadeEffect eFadeEffect = FadeEffect_NONE;
        if (ImplGetPropertyValue(mXPagePropSet, "Effect"))
            mAny >>= eFadeEffect;

        sal_Int16 nTransitionType = 0, nTransitionSubtype = 0;
        sal_Int8 nPPTTransitionType = 0;
        sal_uInt8 nDirection = 0;

        if (ImplGetPropertyValue(mXPagePropSet, "TransitionType") && (mAny >>= nTransitionType) &&
                ImplGetPropertyValue(mXPagePropSet, "TransitionSubtype") && (mAny >>= nTransitionSubtype))
            nPPTTransitionType = GetTransition(nTransitionType, nTransitionSubtype, eFadeEffect, nDirection);

        if (!nPPTTransitionType && eFadeEffect != FadeEffect_NONE)
            nPPTTransitionType = GetTransition(eFadeEffect, nDirection);

        bool bOOXmlSpecificTransition = false;

        sal_Int32 nTransition = 0;
        const char* pDirection = nullptr;
        const char* pOrientation = nullptr;
        const char* pThruBlk = nullptr;
        const char* pSpokes = nullptr;

        char pSpokesTmp[2] = "0";

        // p14
        sal_Int32 nTransition14 = 0;
        const char* pDirection14 = nullptr;
        const char* pInverted = nullptr;
        const char* pPattern = nullptr; // diamond or hexagon

        //p15
        const char* pPresetTransition = nullptr;

        if (!nPPTTransitionType)
        {
            switch (nTransitionType)
            {
            case animations::TransitionType::BARWIPE:
            {
                if (nTransitionSubtype == animations::TransitionSubType::FADEOVERCOLOR)
                {
                    nTransition = XML_cut;
                    pThruBlk = "true";
                    bOOXmlSpecificTransition = true;
                }
                break;
            }
            case animations::TransitionType::MISCSHAPEWIPE:
            {
                switch (nTransitionSubtype)
                {
                case animations::TransitionSubType::TOPTOBOTTOM: // Turn around
                    nTransition = XML_fade;
                    nTransition14 = XML_flip;
                    pDirection14 = "l";
                    bOOXmlSpecificTransition = true;
                    break;
                case animations::TransitionSubType::BOTTOMRIGHT: // Rochade
                    nTransition = XML_fade;
                    nTransition14 = XML_switch;
                    pDirection14 = "r";
                    bOOXmlSpecificTransition = true;
                    break;
                case animations::TransitionSubType::VERTICAL: // Vortex
                    nTransition = XML_fade;
                    nTransition14 = XML_vortex;
                    bOOXmlSpecificTransition = true;
                    break;
                case animations::TransitionSubType::HORIZONTAL: // Ripple
                    nTransition = XML_fade;
                    nTransition14 = XML_ripple;
                    bOOXmlSpecificTransition = true;
                    break;
                case animations::TransitionSubType::LEFTTORIGHT: // Fall
                    nTransition = XML_fade;
                    pPresetTransition = "fallOver";
                    bOOXmlSpecificTransition = true;
                    break;
                case animations::TransitionSubType::CORNERSIN: // Inside turning cube
                    pInverted = "true";
                    SAL_FALLTHROUGH;
                case animations::TransitionSubType::CORNERSOUT: // Outside turning cube
                    nTransition = XML_fade;
                    nTransition14 = XML_prism;
                    bOOXmlSpecificTransition = true;
                    break;
                case animations::TransitionSubType::DIAMOND: // Glitter
                    nTransition = XML_fade;
                    nTransition14 = XML_glitter;
                    pDirection14 = "l";
                    pPattern = "hexagon";
                    bOOXmlSpecificTransition = true;
                    break;
                case animations::TransitionSubType::HEART: // Honeycomb
                    nTransition = XML_fade;
                    nTransition14 = XML_honeycomb;
                    bOOXmlSpecificTransition = true;
                    break;
                }
                break;
            }
            }
        }

        AnimationSpeed animationSpeed = AnimationSpeed_MEDIUM;
        const char* speed = nullptr;
        sal_Int32 advanceTiming = -1;
        sal_Int32 changeType = 0;

        sal_Int32 nTransitionDuration = -1;
        bool isTransitionDurationSet = false;

        // try to use TransitionDuration instead of old Speed property
        if (ImplGetPropertyValue(mXPagePropSet, "TransitionDuration"))
        {
            double fTransitionDuration = -1.0;
            mAny >>= fTransitionDuration;
            if (fTransitionDuration >= 0)
            {
                nTransitionDuration = fTransitionDuration * 1000.0;

                // override values because in MS formats meaning of fast/medium/slow is different
                if (nTransitionDuration <= 500)
                {
                    // fast is default
                    speed = nullptr;
                }
                else if (nTransitionDuration >= 1000)
                {
                    speed = "slow";
                }
                else
                {
                    speed = "med";
                }

                bool isStandardValue = nTransitionDuration == 500
                    || nTransitionDuration == 750
                    || nTransitionDuration == 1000;

                if(!isStandardValue)
                    isTransitionDurationSet = true;
            }
        }
        else if (ImplGetPropertyValue(mXPagePropSet, "Speed"))
        {
            mAny >>= animationSpeed;

            switch (animationSpeed)
            {
            default:
            case AnimationSpeed_MEDIUM:
                speed = "med";
                break;
            case AnimationSpeed_SLOW:
                speed = "slow";
                break;
            case AnimationSpeed_FAST:
                break;
            }
        }

        // check if we resolved what transition to export or time is set
        if (!nPPTTransitionType && !bOOXmlSpecificTransition && !isTransitionDurationSet)
            return;

        if (ImplGetPropertyValue(mXPagePropSet, "Change"))
            mAny >>= changeType;

        // 1 means automatic, 2 half automatic - not sure what it means - at least I don't see it in UI
        if (changeType == 1 && ImplGetPropertyValue(mXPagePropSet, "Duration"))
            mAny >>= advanceTiming;

        if (!bOOXmlSpecificTransition)
        {
            switch (nPPTTransitionType)
            {
            case PPT_TRANSITION_TYPE_BLINDS:
                nTransition = XML_blinds;
                pDirection = (nDirection == 0) ? "vert" : "horz";
                break;
            case PPT_TRANSITION_TYPE_CHECKER:
                nTransition = XML_checker;
                pDirection = (nDirection == 1) ? "vert" : "horz";
                break;
            case PPT_TRANSITION_TYPE_CIRCLE:
                nTransition = XML_circle;
                break;
            case PPT_TRANSITION_TYPE_COMB:
                nTransition = XML_comb;
                pDirection = (nDirection == 1) ? "vert" : "horz";
                break;
            case PPT_TRANSITION_TYPE_COVER:
                nTransition = XML_cover;
                pDirection = Get8Direction(nDirection);
                break;
            case PPT_TRANSITION_TYPE_DIAMOND:
                nTransition = XML_diamond;
                break;
            case PPT_TRANSITION_TYPE_DISSOLVE:
                nTransition = XML_dissolve;
                break;
            case PPT_TRANSITION_TYPE_FADE:
                nTransition = XML_fade;
                pThruBlk = "true";
                break;
            case PPT_TRANSITION_TYPE_SMOOTHFADE:
                nTransition = XML_fade;
                break;
            case PPT_TRANSITION_TYPE_NEWSFLASH:
                nTransition = XML_newsflash;
                break;
            case PPT_TRANSITION_TYPE_PLUS:
                nTransition = XML_plus;
                break;
            case PPT_TRANSITION_TYPE_PULL:
                nTransition = XML_pull;
                pDirection = Get8Direction(nDirection);
                break;
            case PPT_TRANSITION_TYPE_PUSH:
                nTransition = XML_push;
                pDirection = GetSideDirection(nDirection);
                break;
            case PPT_TRANSITION_TYPE_RANDOM:
                nTransition = XML_random;
                break;
            case PPT_TRANSITION_TYPE_RANDOM_BARS:
                nTransition = XML_randomBar;
                pDirection = (nDirection == 1) ? "vert" : "horz";
                break;
            case PPT_TRANSITION_TYPE_SPLIT:
                nTransition = XML_split;
                pDirection = (nDirection & 1) ? "in" : "out";
                pOrientation = (nDirection < 2) ? "horz" : "vert";
                break;
            case PPT_TRANSITION_TYPE_STRIPS:
                nTransition = XML_strips;
                pDirection = GetCornerDirection(nDirection);
                break;
            case PPT_TRANSITION_TYPE_WEDGE:
                nTransition = XML_wedge;
                break;
            case PPT_TRANSITION_TYPE_WHEEL:
                nTransition = XML_wheel;
                if (nDirection != 4 && nDirection <= 9)
                {
                    pSpokesTmp[0] = '0' + nDirection;
                    pSpokes = pSpokesTmp;
                }
                break;
            case PPT_TRANSITION_TYPE_WIPE:
                nTransition = XML_wipe;
                pDirection = GetSideDirection(nDirection);
                break;
            case PPT_TRANSITION_TYPE_ZOOM:
                nTransition = XML_zoom;
                pDirection = (nDirection == 1) ? "in" : "out";
                break;
            // coverity[dead_error_line] - following conditions exist to avoid compiler warning
            case PPT_TRANSITION_TYPE_NONE:
            default:
                nTransition = 0;
                break;
            }
        }

        bool isAdvanceTimingSet = advanceTiming != -1;
        if (nTransition14 || pPresetTransition || isTransitionDurationSet)
        {
            const char* pRequiresNS = (nTransition14 || isTransitionDurationSet) ? "p14" : "p15";

            pFS->startElement(FSNS(XML_mc, XML_AlternateContent), FSEND);
            pFS->startElement(FSNS(XML_mc, XML_Choice), XML_Requires, pRequiresNS, FSEND);

            if(isTransitionDurationSet && isAdvanceTimingSet)
            {
                pFS->startElementNS(XML_p, XML_transition,
                    XML_spd, speed,
                    XML_advTm, I32S(advanceTiming * 1000),
                    FSNS(XML_p14, XML_dur), I32S(nTransitionDuration),
                    FSEND);
            }
            else if(isTransitionDurationSet)
            {
                pFS->startElementNS(XML_p, XML_transition,
                    XML_spd, speed,
                    FSNS(XML_p14, XML_dur), I32S(nTransitionDuration),
                    FSEND);
            }
            else if(isAdvanceTimingSet)
            {
                pFS->startElementNS(XML_p, XML_transition,
                    XML_spd, speed,
                    XML_advTm, I32S(advanceTiming * 1000),
                    FSEND);
            }
            else
            {
                pFS->startElementNS(XML_p, XML_transition,
                    XML_spd, speed,
                    FSEND);
            }

            if (nTransition14)
            {
                pFS->singleElementNS(XML_p14, nTransition14,
                    XML_isInverted, pInverted,
                    XML_dir, pDirection14,
                    XML_pattern, pPattern,
                    FSEND);
            }
            else if (pPresetTransition)
            {
                pFS->singleElementNS(XML_p15, XML_prstTrans,
                    XML_prst, pPresetTransition,
                    FSEND);
            }
            else if (isTransitionDurationSet && nTransition)
            {
                pFS->singleElementNS(XML_p, nTransition,
                    XML_dir, pDirection,
                    XML_orient, pOrientation,
                    XML_spokes, pSpokes,
                    XML_thruBlk, pThruBlk,
                    FSEND);
            }

            pFS->endElement(FSNS(XML_p, XML_transition));

            pFS->endElement(FSNS(XML_mc, XML_Choice));
            pFS->startElement(FSNS(XML_mc, XML_Fallback), FSEND);
        }

        pFS->startElementNS(XML_p, XML_transition,
            XML_spd, speed,
            XML_advTm, isAdvanceTimingSet ? I32S(advanceTiming * 1000) : nullptr,
            FSEND);

        if (nTransition)
        {
            pFS->singleElementNS(XML_p, nTransition,
                                 XML_dir, pDirection,
                                 XML_orient, pOrientation,
                                 XML_spokes, pSpokes,
                                 XML_thruBlk, pThruBlk,
                                 FSEND);
        }

        pFS->endElementNS(XML_p, XML_transition);

        if (nTransition14 || pPresetTransition || isTransitionDurationSet)
        {
            pFS->endElement(FSNS(XML_mc, XML_Fallback));
            pFS->endElement(FSNS(XML_mc, XML_AlternateContent));
        }
    }

    static OUString lcl_GetInitials(const OUString& sName)
    {
        OUStringBuffer sRet;

        if (!sName.isEmpty())
        {
            sRet.append(sName[0]);
            sal_Int32 nStart = 0, nOffset;

            while ((nOffset = sName.indexOf(' ', nStart)) != -1)
            {
                if (nOffset + 1 < sName.getLength())
                    sRet.append(sName[ nOffset + 1 ]);
                nStart = nOffset + 1;
            }
        }

        return sRet.makeStringAndClear();
    }

    void PowerPointExport::WriteAuthors()
    {
        if (maAuthors.empty())
            return;

        FSHelperPtr pFS = openFragmentStreamWithSerializer("ppt/commentAuthors.xml",
                          "application/vnd.openxmlformats-officedocument.presentationml.commentAuthors+xml");
        addRelation(mPresentationFS->getOutputStream(),
                    oox::getRelationship(Relationship::COMMENTAUTHORS),
                    "commentAuthors.xml");

        pFS->startElementNS(XML_p, XML_cmAuthorLst,
                            FSNS(XML_xmlns, XML_p), OUStringToOString(this->getNamespaceURL(OOX_NS(ppt)), RTL_TEXTENCODING_UTF8),
                            FSEND);

        for (const AuthorsMap::value_type& i : maAuthors)
        {
            pFS->singleElementNS(XML_p, XML_cmAuthor,
                                 XML_id, I32S(i.second.nId),
                                 XML_name, USS(i.first),
                                 XML_initials, USS(lcl_GetInitials(i.first)),
                                 XML_lastIdx, I32S(i.second.nLastIndex),
                                 XML_clrIdx, I32S(i.second.nId),
                                 FSEND);
        }

        pFS->endElementNS(XML_p, XML_cmAuthorLst);
    }

    sal_Int32 PowerPointExport::GetAuthorIdAndLastIndex(const OUString& sAuthor, sal_Int32& nLastIndex)
    {
        if (maAuthors.count(sAuthor) <= 0)
        {
            struct AuthorComments aAuthorComments;

            aAuthorComments.nId = maAuthors.size();
            aAuthorComments.nLastIndex = 0;

            maAuthors[ sAuthor ] = aAuthorComments;
        }

        nLastIndex = ++maAuthors[ sAuthor ].nLastIndex;

        return maAuthors[ sAuthor ].nId;
    }

    bool PowerPointExport::WriteComments(sal_uInt32 nPageNum)
    {
        Reference< XAnnotationAccess > xAnnotationAccess(mXDrawPage, uno::UNO_QUERY);
        if (xAnnotationAccess.is())
        {
            Reference< XAnnotationEnumeration > xAnnotationEnumeration(xAnnotationAccess->createAnnotationEnumeration());

            if (xAnnotationEnumeration->hasMoreElements())
            {
                FSHelperPtr pFS = openFragmentStreamWithSerializer(OUStringBuffer()
                                  .append("ppt/comments/comment")
                                  .append(static_cast<sal_Int32>(nPageNum) + 1)
                                  .append(".xml")
                                  .makeStringAndClear(),
                                  "application/vnd.openxmlformats-officedocument.presentationml.comments+xml");

                pFS->startElementNS(XML_p, XML_cmLst,
                                    FSNS(XML_xmlns, XML_p), OUStringToOString(this->getNamespaceURL(OOX_NS(ppt)), RTL_TEXTENCODING_UTF8),
                                    FSEND);

                do
                {
                    Reference< XAnnotation > xAnnotation(xAnnotationEnumeration->nextElement());
                    DateTime aDateTime(xAnnotation->getDateTime());
                    RealPoint2D aRealPoint2D(xAnnotation->getPosition());
                    Reference< XText > xText(xAnnotation->getTextRange());
                    sal_Int32 nLastIndex;
                    sal_Int32 nId = GetAuthorIdAndLastIndex(xAnnotation->getAuthor(), nLastIndex);
                    char cDateTime[32];

                    snprintf(cDateTime, 31, "%02d-%02d-%02dT%02d:%02d:%02d.%09" SAL_PRIuUINT32, aDateTime.Year, aDateTime.Month, aDateTime.Day, aDateTime.Hours, aDateTime.Minutes, aDateTime.Seconds, aDateTime.NanoSeconds);

                    pFS->startElementNS(XML_p, XML_cm,
                                        XML_authorId, I32S(nId),
                                        XML_dt, cDateTime,
                                        XML_idx, I32S(nLastIndex),
                                        FSEND);

                    pFS->singleElementNS(XML_p, XML_pos,
                                         XML_x, I64S(static_cast<sal_Int64>((57600*aRealPoint2D.X + 1270)/2540.0)),
                                         XML_y, I64S(static_cast<sal_Int64>((57600*aRealPoint2D.Y + 1270)/2540.0)),
                                         FSEND);

                    pFS->startElementNS(XML_p, XML_text,
                                        FSEND);
                    pFS->write(xText->getString());
                    pFS->endElementNS(XML_p, XML_text);

                    pFS->endElementNS(XML_p, XML_cm);

                }
                while (xAnnotationEnumeration->hasMoreElements());

                pFS->endElementNS(XML_p, XML_cmLst);

                return true;
            }
        }

        return false;
    }

    void PowerPointExport::WriteVBA()
    {
        if (!mbPptm)
            return;

        uno::Reference<document::XStorageBasedDocument> xStorageBasedDocument(getModel(), uno::UNO_QUERY);
        if (!xStorageBasedDocument.is())
            return;

        uno::Reference<embed::XStorage> xDocumentStorage(xStorageBasedDocument->getDocumentStorage(), uno::UNO_QUERY);
        OUString aMacrosName("_MS_VBA_Macros");
        if (!xDocumentStorage.is() || !xDocumentStorage->hasByName(aMacrosName))
            return;

        const sal_Int32 nOpenMode = embed::ElementModes::READ;
        uno::Reference<io::XInputStream> xMacrosStream(xDocumentStorage->openStreamElement(aMacrosName, nOpenMode), uno::UNO_QUERY);
        if (!xMacrosStream.is())
            return;

        uno::Reference<io::XOutputStream> xOutputStream = openFragmentStream("ppt/vbaProject.bin", "application/vnd.ms-office.vbaProject");
        comphelper::OStorageHelper::CopyInputToOutput(xMacrosStream, xOutputStream);

        // Write the relationship.
        addRelation(mPresentationFS->getOutputStream(), oox::getRelationship(Relationship::VBAPROJECT), "vbaProject.bin");
    }

    void PowerPointExport::ImplWriteSlide(sal_uInt32 nPageNum, sal_uInt32 nMasterNum, sal_uInt16 /* nMode */,
                                          bool bHasBackground, Reference< XPropertySet > const& aXBackgroundPropSet)
    {
        SAL_INFO("sd.eppt", "write slide: " << nPageNum << "\n----------------");

        // slides list
        if (nPageNum == 0)
            mPresentationFS->startElementNS(XML_p, XML_sldIdLst, FSEND);

        // add explicit relation of presentation to this slide
        OUString sRelId = addRelation(mPresentationFS->getOutputStream(),
                                      oox::getRelationship(Relationship::SLIDE),
                                      OUStringBuffer()
                                      .append("slides/slide")
                                      .append(static_cast<sal_Int32>(nPageNum) + 1)
                                      .append(".xml")
                                      .makeStringAndClear());

        mPresentationFS->singleElementNS(XML_p, XML_sldId,
                                         XML_id, I32S(GetNewSlideId()),
                                         FSNS(XML_r, XML_id), USS(sRelId),
                                         FSEND);

        if (nPageNum == mnPages - 1)
            mPresentationFS->endElementNS(XML_p, XML_sldIdLst);

        FSHelperPtr pFS = openFragmentStreamWithSerializer(OUStringBuffer()
                          .append("ppt/slides/slide")
                          .append(static_cast<sal_Int32>(nPageNum) + 1)
                          .append(".xml")
                          .makeStringAndClear(),
                          "application/vnd.openxmlformats-officedocument.presentationml.slide+xml");

        if (mpSlidesFSArray.size() < mnPages)
            mpSlidesFSArray.resize(mnPages);
        mpSlidesFSArray[ nPageNum ] = pFS;

        const char* pShow = nullptr;

        if (ImplGetPropertyValue(mXPagePropSet, "Visible"))
        {
            bool bShow(false);
            if ((mAny >>= bShow) && !bShow)
                pShow = "0";
        }

        pFS->startElementNS(XML_p, XML_sld, PNMSS,
                            XML_show, pShow,
                            FSEND);

        pFS->startElementNS(XML_p, XML_cSld, FSEND);

        // background
        if (bHasBackground)
        {
            ImplWriteBackground(pFS, aXBackgroundPropSet);
        }

        WriteShapeTree(pFS, NORMAL, false);

        pFS->endElementNS(XML_p, XML_cSld);

        WriteTransition(pFS);
        WriteAnimations(pFS, mXDrawPage, *this);

        pFS->endElementNS(XML_p, XML_sld);

        // add implicit relation to slide layout
        addRelation(pFS->getOutputStream(),
                    oox::getRelationship(Relationship::SLIDELAYOUT),
                    OUStringBuffer()
                    .append("../slideLayouts/slideLayout")
                    .append(GetLayoutFileId(GetPPTXLayoutId(GetLayoutOffset(mXPagePropSet)), nMasterNum))
                    .append(".xml")
                    .makeStringAndClear());

        if (WriteComments(nPageNum))
            // add implicit relation to slide comments
            addRelation(pFS->getOutputStream(),
                        oox::getRelationship(Relationship::COMMENTS),
                        OUStringBuffer()
                        .append("../comments/comment")
                        .append(static_cast<sal_Int32>(nPageNum) + 1)
                        .append(".xml")
                        .makeStringAndClear());

        SAL_INFO("sd.eppt", "----------------");
    }

    void PowerPointExport::ImplWriteNotes(sal_uInt32 nPageNum)
    {
        if (!mbCreateNotes || !ContainsOtherShapeThanPlaceholders())
            return;

        SAL_INFO("sd.eppt", "write Notes " << nPageNum << "\n----------------");

        FSHelperPtr pFS = openFragmentStreamWithSerializer(OUStringBuffer()
                          .append("ppt/notesSlides/notesSlide")
                          .append(static_cast<sal_Int32>(nPageNum) + 1)
                          .append(".xml")
                          .makeStringAndClear(),
                          "application/vnd.openxmlformats-officedocument.presentationml.notesSlide+xml");

        pFS->startElementNS(XML_p, XML_notes, PNMSS, FSEND);

        pFS->startElementNS(XML_p, XML_cSld, FSEND);

        WriteShapeTree(pFS, NOTICE, false);

        pFS->endElementNS(XML_p, XML_cSld);

        pFS->endElementNS(XML_p, XML_notes);

        // add implicit relation to slide
        addRelation(pFS->getOutputStream(),
                    oox::getRelationship(Relationship::SLIDE),
                    OUStringBuffer()
                    .append("../slides/slide")
                    .append(static_cast<sal_Int32>(nPageNum) + 1)
                    .append(".xml")
                    .makeStringAndClear());

        // add slide implicit relation to notes
        if (mpSlidesFSArray.size() >= nPageNum)
            addRelation(mpSlidesFSArray[ nPageNum ]->getOutputStream(),
                        oox::getRelationship(Relationship::NOTESSLIDE),
                        OUStringBuffer()
                        .append("../notesSlides/notesSlide")
                        .append(static_cast<sal_Int32>(nPageNum) + 1)
                        .append(".xml")
                        .makeStringAndClear());

        // add implicit relation to notes master
        addRelation(pFS->getOutputStream(),
                    oox::getRelationship(Relationship::NOTESMASTER),
                    "../notesMasters/notesMaster1.xml");

        SAL_INFO("sd.eppt", "-----------------");
    }

    void PowerPointExport::AddLayoutIdAndRelation(const FSHelperPtr& pFS, sal_Int32 nLayoutFileId)
    {
        // add implicit relation of slide master to slide layout
        OUString sRelId = addRelation(pFS->getOutputStream(),
                                      oox::getRelationship(Relationship::SLIDELAYOUT),
                                      OUStringBuffer()
                                      .append("../slideLayouts/slideLayout")
                                      .append(nLayoutFileId)
                                      .append(".xml")
                                      .makeStringAndClear());

        pFS->singleElementNS(XML_p, XML_sldLayoutId,
                             XML_id, I64S(GetNewSlideMasterId()),
                             FSNS(XML_r, XML_id), USS(sRelId),
                             FSEND);
    }

    void PowerPointExport::ImplWriteSlideMaster(sal_uInt32 nPageNum, Reference< XPropertySet > const& aXBackgroundPropSet)
    {
        SAL_INFO("sd.eppt", "write master slide: " << nPageNum << "\n--------------");

        // slides list
        if (nPageNum == 0)
            mPresentationFS->startElementNS(XML_p, XML_sldMasterIdLst, FSEND);

        OUString sRelId = addRelation(mPresentationFS->getOutputStream(),
                                      oox::getRelationship(Relationship::SLIDEMASTER),
                                      OUStringBuffer()
                                      .append("slideMasters/slideMaster")
                                      .append(static_cast<sal_Int32>(nPageNum) + 1)
                                      .append(".xml")
                                      .makeStringAndClear());

        mPresentationFS->singleElementNS(XML_p, XML_sldMasterId,
                                         XML_id, OString::number(GetNewSlideMasterId()).getStr(),
                                         FSNS(XML_r, XML_id), USS(sRelId),
                                         FSEND);

        if (nPageNum == mnMasterPages - 1)
            mPresentationFS->endElementNS(XML_p, XML_sldMasterIdLst);

        FSHelperPtr pFS =
            openFragmentStreamWithSerializer(OUStringBuffer()
                                             .append("ppt/slideMasters/slideMaster")
                                             .append(static_cast<sal_Int32>(nPageNum) + 1)
                                             .append(".xml")
                                             .makeStringAndClear(),
                                             "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml");

        // write theme per master
        WriteTheme(nPageNum);

        // add implicit relation to the presentation theme
        addRelation(pFS->getOutputStream(),
                    oox::getRelationship(Relationship::THEME),
                    OUStringBuffer()
                    .append("../theme/theme")
                    .append(static_cast<sal_Int32>(nPageNum) + 1)
                    .append(".xml")
                    .makeStringAndClear());

        pFS->startElementNS(XML_p, XML_sldMaster, PNMSS, FSEND);

        pFS->startElementNS(XML_p, XML_cSld, FSEND);

        ImplWriteBackground(pFS, aXBackgroundPropSet);
        WriteShapeTree(pFS, MASTER, true);

        pFS->endElementNS(XML_p, XML_cSld);

        // color map - now it uses colors from hardcoded theme, once we eventually generate theme, this might need update
        pFS->singleElementNS(XML_p, XML_clrMap,
                             XML_bg1, "lt1",
                             XML_bg2, "lt2",
                             XML_tx1, "dk1",
                             XML_tx2, "dk2",
                             XML_accent1, "accent1",
                             XML_accent2, "accent2",
                             XML_accent3, "accent3",
                             XML_accent4, "accent4",
                             XML_accent5, "accent5",
                             XML_accent6, "accent6",
                             XML_hlink, "hlink",
                             XML_folHlink, "folHlink",
                             FSEND);

        // use master's id type as they have same range, mso does that as well
        pFS->startElementNS(XML_p, XML_sldLayoutIdLst, FSEND);

        for (int i = 0; i < LAYOUT_SIZE; i++)
        {
            sal_Int32 nLayoutFileId = GetLayoutFileId(i, nPageNum);
            if (nLayoutFileId > 0)
            {
                AddLayoutIdAndRelation(pFS, nLayoutFileId);
            }
            else
            {
                ImplWritePPTXLayout(i, nPageNum);
                AddLayoutIdAndRelation(pFS, GetLayoutFileId(i, nPageNum));
            }
        }

        pFS->endElementNS(XML_p, XML_sldLayoutIdLst);

        pFS->endElementNS(XML_p, XML_sldMaster);

        SAL_INFO("sd.eppt", "----------------");
    }

    sal_Int32 PowerPointExport::GetLayoutFileId(sal_Int32 nOffset, sal_uInt32 nMasterNum)
    {
        SAL_INFO("sd.eppt", "GetLayoutFileId offset: " << nOffset << " master: " << nMasterNum);
        if (mLayoutInfo[ nOffset ].mnFileIdArray.size() <= nMasterNum)
            return 0;

        return mLayoutInfo[ nOffset ].mnFileIdArray[ nMasterNum ];
    }

    void PowerPointExport::ImplWritePPTXLayout(sal_Int32 nOffset, sal_uInt32 nMasterNum)
    {
        SAL_INFO("sd.eppt", "write layout: " << nOffset);

        Reference< drawing::XDrawPagesSupplier > xDPS(getModel(), uno::UNO_QUERY);
        Reference< drawing::XDrawPages > xDrawPages(xDPS->getDrawPages(), uno::UNO_QUERY);
        Reference< drawing::XDrawPage > xSlide;
        Reference< container::XIndexAccess > xIndexAccess(xDrawPages, uno::UNO_QUERY);

        xSlide = xDrawPages->insertNewByIndex(xIndexAccess->getCount());

    #ifdef DEBUG
        if (xSlide.is())
            printf("new page created\n");
    #endif

        Reference< beans::XPropertySet > xPropSet(xSlide, uno::UNO_QUERY);
        xPropSet->setPropertyValue("Layout", makeAny(short(aLayoutInfo[ nOffset ].nType)));
    #if OSL_DEBUG_LEVEL > 1
        dump_pset(xPropSet);
    #endif
        mXPagePropSet.set(xSlide, UNO_QUERY);
        mXShapes.set(xSlide, UNO_QUERY);

        if (mLayoutInfo[ nOffset ].mnFileIdArray.size() < mnMasterPages)
        {
            mLayoutInfo[ nOffset ].mnFileIdArray.resize(mnMasterPages);
        }

        if (mLayoutInfo[ nOffset ].mnFileIdArray[ nMasterNum ] != 0)
            return;

        FSHelperPtr pFS
            = openFragmentStreamWithSerializer(OUStringBuffer()
                                               .append("ppt/slideLayouts/slideLayout")
                                               .append(mnLayoutFileIdMax)
                                               .append(".xml")
                                               .makeStringAndClear(),
                                               "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml");

        // add implicit relation of slide layout to slide master
        addRelation(pFS->getOutputStream(),
                    oox::getRelationship(Relationship::SLIDEMASTER),
                    OUStringBuffer()
                    .append("../slideMasters/slideMaster")
                    .append(static_cast<sal_Int32>(nMasterNum) + 1)
                    .append(".xml")
                    .makeStringAndClear());

        pFS->startElementNS(XML_p, XML_sldLayout,
                            PNMSS,
                            XML_type, aLayoutInfo[ nOffset ].sType,
                            XML_preserve, "1",
                            FSEND);

        pFS->startElementNS(XML_p, XML_cSld,
                            XML_name, aLayoutInfo[ nOffset ].sName,
                            FSEND);
        //pFS->write( MINIMAL_SPTREE ); // TODO: write actual shape tree
        WriteShapeTree(pFS, LAYOUT, true);

        pFS->endElementNS(XML_p, XML_cSld);

        pFS->endElementNS(XML_p, XML_sldLayout);

        mLayoutInfo[ nOffset ].mnFileIdArray[ nMasterNum ] = mnLayoutFileIdMax;

        mnLayoutFileIdMax ++;

        xDrawPages->remove(xSlide);
    }

    void PowerPointExport::WriteShapeTree(const FSHelperPtr& pFS, PageType ePageType, bool bMaster)
    {
        PowerPointShapeExport aDML(pFS, &maShapeMap, this);
        aDML.SetMaster(bMaster);
        aDML.SetPageType(ePageType);
        aDML.SetBackgroundDark(mbIsBackgroundDark);

        pFS->startElementNS(XML_p, XML_spTree, FSEND);
        pFS->write(MAIN_GROUP);

        ResetGroupTable(mXShapes->getCount());

        while (GetNextGroupEntry())
        {

            sal_uInt32 nGroups = GetGroupsClosed();
            for (sal_uInt32 i = 0; i < nGroups; i++)
            {
                SAL_INFO("sd.eppt", "leave group");
            }

            if (GetShapeByIndex(GetCurrentGroupIndex(), true))
            {
                SAL_INFO("sd.eppt", "mType: " << mType);
                aDML.WriteShape(mXShape);
            }
        }

        pFS->endElementNS(XML_p, XML_spTree);
    }

    ShapeExport& PowerPointShapeExport::WritePageShape(const Reference< XShape >& xShape, PageType ePageType, bool bPresObj)
    {
        if ((ePageType == NOTICE && bPresObj) || ePageType == LAYOUT || ePageType == MASTER)
            return WritePlaceholderShape(xShape, SlideImage);

        return WriteTextShape(xShape);
    }

    bool PowerPointShapeExport::WritePlaceholder(const Reference< XShape >& xShape, PlaceholderType ePlaceholder, bool bMaster)
    {
        SAL_INFO("sd.eppt", "WritePlaceholder " << bMaster << " " << ShapeExport::NonEmptyText(xShape));
        if (bMaster && ShapeExport::NonEmptyText(xShape))
        {
            WritePlaceholderShape(xShape, ePlaceholder);

            return true;
        }

        return false;
    }

    ShapeExport& PowerPointShapeExport::WritePlaceholderShape(const Reference< XShape >& xShape, PlaceholderType ePlaceholder)
    {
        mpFS->startElementNS(XML_p, XML_sp, FSEND);

        // non visual shape properties
        mpFS->startElementNS(XML_p, XML_nvSpPr, FSEND);
        const OString aPlaceholderID("PlaceHolder " + OString::number(mnShapeIdMax++));
        WriteNonVisualDrawingProperties(xShape, aPlaceholderID.getStr());
        mpFS->startElementNS(XML_p, XML_cNvSpPr, FSEND);
        mpFS->singleElementNS(XML_a, XML_spLocks, XML_noGrp, "1", FSEND);
        mpFS->endElementNS(XML_p, XML_cNvSpPr);
        mpFS->startElementNS(XML_p, XML_nvPr, FSEND);

        const char* pType = nullptr;
        switch (ePlaceholder)
        {
        case SlideImage:
            pType = "sldImg";
            break;
        case Notes:
            pType = "body";
            break;
        case Header:
            pType = "hdr";
            break;
        case Footer:
            pType = "ftr";
            break;
        case SlideNumber:
            pType = "sldNum";
            break;
        case DateAndTime:
            pType = "dt";
            break;
        case Outliner:
            pType = "body";
            break;
        case Title:
            pType = "title";
            break;
        case Subtitle:
            pType = "subTitle";
            break;
        default:
            SAL_INFO("sd.eppt", "warning: unhandled placeholder type: " << ePlaceholder);
        }
        SAL_INFO("sd.eppt", "write placeholder " << pType);
        mpFS->singleElementNS(XML_p, XML_ph, XML_type, pType, FSEND);
        mpFS->endElementNS(XML_p, XML_nvPr);
        mpFS->endElementNS(XML_p, XML_nvSpPr);

        // visual shape properties
        mpFS->startElementNS(XML_p, XML_spPr, FSEND);
        WriteShapeTransformation(xShape, XML_a);
        WritePresetShape("rect");
        Reference< XPropertySet > xProps(xShape, UNO_QUERY);
        if (xProps.is())
            WriteBlipFill(xProps, "Graphic");
        mpFS->endElementNS(XML_p, XML_spPr);

        WriteTextBox(xShape, XML_p);

        mpFS->endElementNS(XML_p, XML_sp);

        return *this;
    }

    #define SYS_COLOR_SCHEMES "      <a:dk1>\
            <a:sysClr val=\"windowText\" lastClr=\"000000\"/>\
          </a:dk1>\
          <a:lt1>\
            <a:sysClr val=\"window\" lastClr=\"FFFFFF\"/>\
          </a:lt1>"

    #define MINIMAL_THEME "    <a:fontScheme name=\"Office\">\
          <a:majorFont>\
            <a:latin typeface=\"Arial\"/>\
            <a:ea typeface=\"DejaVu Sans\"/>\
            <a:cs typeface=\"DejaVu Sans\"/>\
          </a:majorFont>\
          <a:minorFont>\
            <a:latin typeface=\"Arial\"/>\
            <a:ea typeface=\"DejaVu Sans\"/>\
            <a:cs typeface=\"DejaVu Sans\"/>\
          </a:minorFont>\
        </a:fontScheme>\
        <a:fmtScheme name=\"Office\">\
          <a:fillStyleLst>\
            <a:solidFill>\
              <a:schemeClr val=\"phClr\"/>\
            </a:solidFill>\
            <a:gradFill rotWithShape=\"1\">\
              <a:gsLst>\
                <a:gs pos=\"0\">\
                  <a:schemeClr val=\"phClr\">\
                    <a:tint val=\"50000\"/>\
                    <a:satMod val=\"300000\"/>\
                  </a:schemeClr>\
                </a:gs>\
                <a:gs pos=\"35000\">\
                  <a:schemeClr val=\"phClr\">\
                    <a:tint val=\"37000\"/>\
                    <a:satMod val=\"300000\"/>\
                  </a:schemeClr>\
                </a:gs>\
                <a:gs pos=\"100000\">\
                  <a:schemeClr val=\"phClr\">\
                    <a:tint val=\"15000\"/>\
                    <a:satMod val=\"350000\"/>\
                  </a:schemeClr>\
                </a:gs>\
              </a:gsLst>\
              <a:lin ang=\"16200000\" scaled=\"1\"/>\
            </a:gradFill>\
            <a:gradFill rotWithShape=\"1\">\
              <a:gsLst>\
                <a:gs pos=\"0\">\
                  <a:schemeClr val=\"phClr\">\
                    <a:shade val=\"51000\"/>\
                    <a:satMod val=\"130000\"/>\
                  </a:schemeClr>\
                </a:gs>\
                <a:gs pos=\"80000\">\
                  <a:schemeClr val=\"phClr\">\
                    <a:shade val=\"93000\"/>\
                    <a:satMod val=\"130000\"/>\
                  </a:schemeClr>\
                </a:gs>\
                <a:gs pos=\"100000\">\
                  <a:schemeClr val=\"phClr\">\
                    <a:shade val=\"94000\"/>\
                    <a:satMod val=\"135000\"/>\
                  </a:schemeClr>\
                </a:gs>\
              </a:gsLst>\
              <a:lin ang=\"16200000\" scaled=\"0\"/>\
            </a:gradFill>\
          </a:fillStyleLst>\
          <a:lnStyleLst>\
            <a:ln w=\"9525\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\
              <a:solidFill>\
                <a:schemeClr val=\"phClr\">\
                  <a:shade val=\"95000\"/>\
                  <a:satMod val=\"105000\"/>\
                </a:schemeClr>\
              </a:solidFill>\
              <a:prstDash val=\"solid\"/>\
            </a:ln>\
            <a:ln w=\"25400\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\
              <a:solidFill>\
                <a:schemeClr val=\"phClr\"/>\
              </a:solidFill>\
              <a:prstDash val=\"solid\"/>\
            </a:ln>\
            <a:ln w=\"38100\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">\
              <a:solidFill>\
                <a:schemeClr val=\"phClr\"/>\
              </a:solidFill>\
              <a:prstDash val=\"solid\"/>\
            </a:ln>\
          </a:lnStyleLst>\
          <a:effectStyleLst>\
            <a:effectStyle>\
              <a:effectLst>\
                <a:outerShdw blurRad=\"40000\" dist=\"20000\" dir=\"5400000\" rotWithShape=\"0\">\
                  <a:srgbClr val=\"000000\">\
                    <a:alpha val=\"38000\"/>\
                  </a:srgbClr>\
                </a:outerShdw>\
              </a:effectLst>\
            </a:effectStyle>\
            <a:effectStyle>\
              <a:effectLst>\
                <a:outerShdw blurRad=\"40000\" dist=\"23000\" dir=\"5400000\" rotWithShape=\"0\">\
                  <a:srgbClr val=\"000000\">\
                    <a:alpha val=\"35000\"/>\
                  </a:srgbClr>\
                </a:outerShdw>\
              </a:effectLst>\
            </a:effectStyle>\
            <a:effectStyle>\
              <a:effectLst>\
                <a:outerShdw blurRad=\"40000\" dist=\"23000\" dir=\"5400000\" rotWithShape=\"0\">\
                  <a:srgbClr val=\"000000\">\
                    <a:alpha val=\"35000\"/>\
                  </a:srgbClr>\
                </a:outerShdw>\
              </a:effectLst>\
              <a:scene3d>\
                <a:camera prst=\"orthographicFront\">\
                  <a:rot lat=\"0\" lon=\"0\" rev=\"0\"/>\
                </a:camera>\
                <a:lightRig rig=\"threePt\" dir=\"t\">\
                  <a:rot lat=\"0\" lon=\"0\" rev=\"1200000\"/>\
                </a:lightRig>\
              </a:scene3d>\
              <a:sp3d>\
                <a:bevelT w=\"63500\" h=\"25400\"/>\
              </a:sp3d>\
            </a:effectStyle>\
          </a:effectStyleLst>\
          <a:bgFillStyleLst>\
            <a:solidFill>\
              <a:schemeClr val=\"phClr\"/>\
            </a:solidFill>\
            <a:gradFill rotWithShape=\"1\">\
              <a:gsLst>\
                <a:gs pos=\"0\">\
                  <a:schemeClr val=\"phClr\">\
                    <a:tint val=\"40000\"/>\
                    <a:satMod val=\"350000\"/>\
                  </a:schemeClr>\
                </a:gs>\
                <a:gs pos=\"40000\">\
                  <a:schemeClr val=\"phClr\">\
                    <a:tint val=\"45000\"/>\
                    <a:shade val=\"99000\"/>\
                    <a:satMod val=\"350000\"/>\
                  </a:schemeClr>\
                </a:gs>\
                <a:gs pos=\"100000\">\
                  <a:schemeClr val=\"phClr\">\
                    <a:shade val=\"20000\"/>\
                    <a:satMod val=\"255000\"/>\
                  </a:schemeClr>\
                </a:gs>\
              </a:gsLst>\
              <a:path path=\"circle\">\
                <a:fillToRect l=\"50000\" t=\"-80000\" r=\"50000\" b=\"180000\"/>\
              </a:path>\
            </a:gradFill>\
            <a:gradFill rotWithShape=\"1\">\
              <a:gsLst>\
                <a:gs pos=\"0\">\
                  <a:schemeClr val=\"phClr\">\
                    <a:tint val=\"80000\"/>\
                    <a:satMod val=\"300000\"/>\
                  </a:schemeClr>\
                </a:gs>\
                <a:gs pos=\"100000\">\
                  <a:schemeClr val=\"phClr\">\
                    <a:shade val=\"30000\"/>\
                    <a:satMod val=\"200000\"/>\
                  </a:schemeClr>\
                </a:gs>\
              </a:gsLst>\
              <a:path path=\"circle\">\
                <a:fillToRect l=\"50000\" t=\"50000\" r=\"50000\" b=\"50000\"/>\
              </a:path>\
            </a:gradFill>\
          </a:bgFillStyleLst>\
        </a:fmtScheme>"

    void PowerPointExport::WriteDefaultColorSchemes(const FSHelperPtr& pFS)
    {
        for (int nId = PredefinedClrSchemeId::dk2; nId != PredefinedClrSchemeId::Count; nId++)
        {
            OUString sName = PredefinedClrNames[static_cast<PredefinedClrSchemeId>(nId)];
            sal_Int32 nColor = 0;

            switch (nId)
            {
            case PredefinedClrSchemeId::dk2:
                nColor = 0x1F497D;
                break;
            case PredefinedClrSchemeId::lt2:
                nColor = 0xEEECE1;
                break;
            case PredefinedClrSchemeId::accent1:
                nColor = 0x4F81BD;
                break;
            case PredefinedClrSchemeId::accent2:
                nColor = 0xC0504D;
                break;
            case PredefinedClrSchemeId::accent3:
                nColor = 0x9BBB59;
                break;
            case PredefinedClrSchemeId::accent4:
                nColor = 0x8064A2;
                break;
            case PredefinedClrSchemeId::accent5:
                nColor = 0x4BACC6;
                break;
            case PredefinedClrSchemeId::accent6:
                nColor = 0xF79646;
                break;
            case PredefinedClrSchemeId::hlink:
                nColor = 0x0000FF;
                break;
            case PredefinedClrSchemeId::folHlink:
                nColor = 0x800080;
                break;
            }

            OUString sOpenColorScheme = OUStringBuffer()
                .append("<a:")
                .append(sName)
                .append(">")
                .makeStringAndClear();
            pFS->write(sOpenColorScheme);

            pFS->singleElementNS(XML_a, XML_srgbClr, XML_val, I32SHEX(nColor), FSEND);

            OUString sCloseColorScheme = OUStringBuffer()
                .append("</a:")
                .append(sName)
                .append(">")
                .makeStringAndClear();
            pFS->write(sCloseColorScheme);
        }
    }

    bool PowerPointExport::WriteColorSchemes(const FSHelperPtr& pFS, const OUString& rThemePath)
    {
        try
        {
            uno::Reference<beans::XPropertySet> xDocProps(getModel(), uno::UNO_QUERY);
            if (xDocProps.is())
            {
                uno::Reference<beans::XPropertySetInfo> xPropsInfo = xDocProps->getPropertySetInfo();

                const OUString aGrabBagPropName = "InteropGrabBag";
                if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(aGrabBagPropName))
                {
                    comphelper::SequenceAsHashMap aGrabBag(xDocProps->getPropertyValue(aGrabBagPropName));
                    uno::Sequence<beans::PropertyValue> aCurrentTheme;

                    aGrabBag.getValue(rThemePath) >>= aCurrentTheme;

                    if (!aCurrentTheme.getLength())
                        return false;

                    // Order is important
                    for (int nId = PredefinedClrSchemeId::dk2; nId != PredefinedClrSchemeId::Count; nId++)
                    {
                        OUString sName = PredefinedClrNames[static_cast<PredefinedClrSchemeId>(nId)];
                        sal_Int32 nColor = 0;

                        for (auto aIt = aCurrentTheme.begin(); aIt != aCurrentTheme.end(); aIt++)
                        {
                            if (aIt->Name == sName)
                            {
                                aIt->Value >>= nColor;
                                break;
                            }
                        }

                        OUString sOpenColorScheme = OUStringBuffer()
                            .append("<a:")
                            .append(sName)
                            .append(">")
                            .makeStringAndClear();
                        pFS->write(sOpenColorScheme);

                        pFS->singleElementNS(XML_a, XML_srgbClr, XML_val, I32SHEX(nColor), FSEND);

                        OUString sCloseColorScheme = OUStringBuffer()
                            .append("</a:")
                            .append(sName)
                            .append(">")
                            .makeStringAndClear();
                        pFS->write(sCloseColorScheme);
                    }

                    // TODO: write complete color schemes & only if successful, protection against partial export
                    return true;
                }
            }
        }
        catch (const uno::Exception&)
        {
            SAL_WARN("writerfilter", "Failed to save documents grab bag");
        }

        return false;
    }

    void PowerPointExport::WriteTheme(sal_Int32 nThemeNum)
    {
        OUString sThemePath = OUStringBuffer()
            .append("ppt/theme/theme")
            .append(nThemeNum + 1)
            .append(".xml")
            .makeStringAndClear();

        FSHelperPtr pFS = openFragmentStreamWithSerializer(sThemePath,
                          "application/vnd.openxmlformats-officedocument.theme+xml");

        pFS->startElementNS(XML_a, XML_theme,
                            FSNS(XML_xmlns, XML_a), OUStringToOString(this->getNamespaceURL(OOX_NS(dml)), RTL_TEXTENCODING_UTF8),
                            XML_name, "Office Theme",
                            FSEND);

        pFS->startElementNS(XML_a, XML_themeElements, FSEND);
        pFS->startElementNS(XML_a, XML_clrScheme, XML_name, "Office", FSEND);

        pFS->write(SYS_COLOR_SCHEMES);

        if (!WriteColorSchemes(pFS, sThemePath))
        {
            // if style is not defined, try to use first one
            if (!WriteColorSchemes(pFS, "ppt/theme/theme1.xml"))
            {
                // color schemes are required - use default values
                WriteDefaultColorSchemes(pFS);
            }
        }

        pFS->endElementNS(XML_a, XML_clrScheme);

        // export remaining part
        pFS->write(MINIMAL_THEME);

        pFS->endElementNS(XML_a, XML_themeElements);
        pFS->endElementNS(XML_a, XML_theme);
    }

    bool PowerPointExport::ImplCreateDocument()
    {
        mbCreateNotes = false;

        for (sal_uInt32 i = 0; i < mnPages; i++)
        {
            if (!GetPageByIndex(i, NOTICE))
                return false;

            if (ContainsOtherShapeThanPlaceholders())
            {
                mbCreateNotes = true;
                break;
            }
        }

        return true;
    }

    void PowerPointExport::WriteNotesMaster()
    {
        SAL_INFO("sd.eppt", "write Notes master\n---------------");

        mPresentationFS->startElementNS(XML_p, XML_notesMasterIdLst, FSEND);

        OUString sRelId = addRelation(mPresentationFS->getOutputStream(),
                                      oox::getRelationship(Relationship::NOTESMASTER),
                                      "notesMasters/notesMaster1.xml");

        mPresentationFS->singleElementNS(XML_p, XML_notesMasterId,
                                         FSNS(XML_r, XML_id), USS(sRelId),
                                         FSEND);

        mPresentationFS->endElementNS(XML_p, XML_notesMasterIdLst);

        FSHelperPtr pFS =
            openFragmentStreamWithSerializer("ppt/notesMasters/notesMaster1.xml",
                                             "application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml");
        // write theme per master
        WriteTheme(mnMasterPages);

        // add implicit relation to the presentation theme
        addRelation(pFS->getOutputStream(),
                    oox::getRelationship(Relationship::THEME),
                    OUStringBuffer()
                    .append("../theme/theme")
                    .append(static_cast<sal_Int32>(mnMasterPages) + 1)
                    .append(".xml")
                    .makeStringAndClear());

        pFS->startElementNS(XML_p, XML_notesMaster, PNMSS, FSEND);

        pFS->startElementNS(XML_p, XML_cSld, FSEND);

        Reference< XPropertySet > aXBackgroundPropSet;
        if (ImplGetPropertyValue(mXPagePropSet, "Background") &&
                (mAny >>= aXBackgroundPropSet))
            ImplWriteBackground(pFS, aXBackgroundPropSet);

        WriteShapeTree(pFS, NOTICE, true);

        pFS->endElementNS(XML_p, XML_cSld);

        // color map - now it uses colors from hardcoded theme, once we eventually generate theme, this might need update
        pFS->singleElementNS(XML_p, XML_clrMap,
                             XML_bg1, "lt1",
                             XML_bg2, "lt2",
                             XML_tx1, "dk1",
                             XML_tx2, "dk2",
                             XML_accent1, "accent1",
                             XML_accent2, "accent2",
                             XML_accent3, "accent3",
                             XML_accent4, "accent4",
                             XML_accent5, "accent5",
                             XML_accent6, "accent6",
                             XML_hlink, "hlink",
                             XML_folHlink, "folHlink",
                             FSEND);

        pFS->endElementNS(XML_p, XML_notesMaster);

        SAL_INFO("sd.eppt", "----------------");
    }

    sal_Int32 PowerPointExport::GetShapeID(const Reference<XShape>& rXShape)
    {
        return ShapeExport::GetShapeID(rXShape, &maShapeMap);
    }

    sal_Int32 PowerPointExport::GetNextAnimationNodeID()
    {
        return mnAnimationNodeIdMax++;
    }

    bool PowerPointExport::ImplCreateMainNotes()
    {
        if (mbCreateNotes)
            WriteNotesMaster();

        return true;
    }

    OUString PowerPointExport::getImplementationName()
    {
        return OUString("com.sun.star.comp.Impress.oox.PowerPointExport");
    }

    // UNO component
    extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
    css_comp_Impress_oox_PowerPointExport(uno::XComponentContext* rxCtxt,
                                          uno::Sequence<css::uno::Any> const& rArguments)
    {
        return cppu::acquire(new PowerPointExport(rxCtxt, rArguments));
    }

    #if OSL_DEBUG_LEVEL > 1
    void dump_pset(Reference< XPropertySet > const& rXPropSet)
    {
        Reference< XPropertySetInfo > info = rXPropSet->getPropertySetInfo();
        Sequence< beans::Property > props = info->getProperties();

        for (int i=0; i < props.getLength(); i++)
        {
            OString name = OUStringToOString(props [i].Name, RTL_TEXTENCODING_UTF8);

            Any value = rXPropSet->getPropertyValue(props [i].Name);

            OUString strValue;
            sal_Int32 intValue;
            bool boolValue;
            RectanglePoint pointValue;

            if (value >>= strValue)
                SAL_INFO("sd.eppt", name << " = \"" << strValue << "\"");
            else if (value >>= intValue)
                SAL_INFO("sd.eppt", name << " = " << intValue << "(hex : " << std::hex << intValue << ")");
            else if (value >>= boolValue)
                SAL_INFO("sd.eppt", name << " = " << boolValue << "           (bool)");
            else if (value >>= pointValue)
                SAL_INFO("sd.eppt", name << " = " << pointValue << "    (RectanglePoint)");
            else
                SAL_INFO("sd.eppt", "???          <unhandled type>");
        }
    }
    #endif

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

↑ V557 Array overrun is possible. The 'nPageNum' index is pointing beyond array bound.

↑ V1019 Compound assignment expression 'mAny >>= nTransitionType' is used inside condition.

↑ V1019 Compound assignment expression 'mAny >>= nTransitionSubtype' is used inside condition.

↑ V1019 Compound assignment expression 'mAny >>= aXBackgroundPropSet' is used inside condition.