[Libreoffice-commits] core.git: sd/Library_sdfilt.mk sd/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Thu Aug 30 17:19:30 UTC 2018


 sd/Library_sdfilt.mk                      |    1 
 sd/source/filter/eppt/pptx-animations.cxx | 1076 ++++++++++++++++++++++++++++++
 sd/source/filter/eppt/pptx-epptooxml.cxx  | 1025 ----------------------------
 3 files changed, 1077 insertions(+), 1025 deletions(-)

New commits:
commit f4a9ce33415a85d0b86ced3a0bf780f4ec61e25f
Author:     Mark Hung <marklh9 at gmail.com>
AuthorDate: Mon Aug 27 22:38:30 2018 +0800
Commit:     Mark Hung <marklh9 at gmail.com>
CommitDate: Thu Aug 30 19:19:03 2018 +0200

    sd/pptx export: move animation export code to a single file.
    
    Move animation export functions in PowerPointExport to
    a single file for further refactor work.
    
    Change-Id: I957599bb293fcdda3d51db48334ef5825b1cba64
    Reviewed-on: https://gerrit.libreoffice.org/59731
    Tested-by: Jenkins
    Reviewed-by: Mark Hung <marklh9 at gmail.com>

diff --git a/sd/Library_sdfilt.mk b/sd/Library_sdfilt.mk
index f371c274edda..8428a4a82df5 100644
--- a/sd/Library_sdfilt.mk
+++ b/sd/Library_sdfilt.mk
@@ -63,6 +63,7 @@ $(eval $(call gb_Library_add_exception_objects,sdfilt,\
     sd/source/filter/eppt/pptexsoundcollection \
     sd/source/filter/eppt/pptx-epptbase \
     sd/source/filter/eppt/pptx-epptooxml \
+    sd/source/filter/eppt/pptx-animations \
     sd/source/filter/eppt/pptx-grouptable \
     sd/source/filter/eppt/pptx-stylesheet \
     sd/source/filter/eppt/pptx-text \
diff --git a/sd/source/filter/eppt/pptx-animations.cxx b/sd/source/filter/eppt/pptx-animations.cxx
new file mode 100644
index 000000000000..82dbb8eb59ab
--- /dev/null
+++ b/sd/source/filter/eppt/pptx-animations.cxx
@@ -0,0 +1,1076 @@
+/* -*- 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 <o3tl/any.hxx>
+#include <oox/token/namespaces.hxx>
+#include <oox/token/tokens.hxx>
+#include "epptooxml.hxx"
+#include <sax/fshelper.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+
+#include <com/sun/star/animations/AnimationAdditiveMode.hpp>
+#include <com/sun/star/animations/AnimationCalcMode.hpp>
+#include <com/sun/star/animations/AnimationFill.hpp>
+#include <com/sun/star/animations/AnimationNodeType.hpp>
+#include <com/sun/star/animations/AnimationRestart.hpp>
+#include <com/sun/star/animations/AnimationTransformType.hpp>
+#include <com/sun/star/animations/AnimationValueType.hpp>
+#include <com/sun/star/animations/AnimationColorSpace.hpp>
+#include <com/sun/star/animations/Event.hpp>
+#include <com/sun/star/animations/EventTrigger.hpp>
+#include <com/sun/star/animations/Timing.hpp>
+#include <com/sun/star/animations/ValuePair.hpp>
+#include <com/sun/star/animations/XAnimateMotion.hpp>
+#include <com/sun/star/animations/XAnimateTransform.hpp>
+#include <com/sun/star/animations/XAnimationNode.hpp>
+#include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
+#include <com/sun/star/animations/XAnimateColor.hpp>
+#include <com/sun/star/animations/XCommand.hpp>
+#include <com/sun/star/animations/XTransitionFilter.hpp>
+#include <com/sun/star/animations/XIterateContainer.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/presentation/AnimationSpeed.hpp>
+#include <com/sun/star/presentation/EffectCommands.hpp>
+#include <com/sun/star/presentation/EffectNodeType.hpp>
+#include <com/sun/star/presentation/EffectPresetClass.hpp>
+#include <com/sun/star/presentation/ParagraphTarget.hpp>
+#include <com/sun/star/presentation/TextAnimationType.hpp>
+#include <com/sun/star/text/XSimpleText.hpp>
+
+#include <oox/export/utils.hxx>
+#include <oox/ppt/pptfilterhelpers.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+
+#include "pptexanimations.hxx"
+#include "../ppt/pptanimations.hxx"
+
+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::presentation;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::uno;
+using namespace ::ppt;
+using ::sax_fastparser::FSHelperPtr;
+using namespace oox::drawingml;
+using namespace oox::core;
+
+void PowerPointExport::WriteAnimationProperty(const FSHelperPtr& pFS, const Any& rAny,
+                                              sal_Int32 nToken)
+{
+    if (!rAny.hasValue())
+        return;
+
+    ValuePair aPair;
+
+    if (rAny >>= aPair)
+    {
+        double x, y;
+        if ((aPair.First >>= x) && (aPair.Second >>= y))
+        {
+            if (nToken == XML_by)
+            {
+                // MS needs ending values but we have offset values.
+                x += 1.0;
+                y += 1.0;
+            }
+            pFS->singleElementNS(XML_p, nToken, XML_x, OString::number(x * 100000).getStr(), XML_y,
+                                 OString::number(y * 100000).getStr(), FSEND);
+        }
+        return;
+    }
+
+    sal_uInt32 nRgb;
+    double fDouble;
+
+    uno::TypeClass aClass = rAny.getValueType().getTypeClass();
+    bool bWriteToken
+        = nToken
+          && (aClass == TypeClass_LONG || aClass == TypeClass_DOUBLE || aClass == TypeClass_STRING);
+
+    if (bWriteToken)
+        pFS->startElementNS(XML_p, nToken, FSEND);
+
+    switch (rAny.getValueType().getTypeClass())
+    {
+        case TypeClass_LONG:
+            rAny >>= nRgb;
+            pFS->singleElementNS(XML_a, XML_srgbClr, XML_val, I32SHEX(nRgb), FSEND);
+            break;
+        case TypeClass_DOUBLE:
+            rAny >>= fDouble;
+            pFS->singleElementNS(XML_p, XML_fltVal, XML_val, DS(fDouble), FSEND);
+            break;
+        case TypeClass_STRING:
+            pFS->singleElementNS(XML_p, XML_strVal, XML_val, USS(*o3tl::doAccess<OUString>(rAny)),
+                                 FSEND);
+            break;
+        default:
+            break;
+    }
+
+    if (bWriteToken)
+        pFS->endElementNS(XML_p, nToken);
+}
+
+void PowerPointExport::WriteAnimateValues(const FSHelperPtr& pFS,
+                                          const Reference<XAnimate>& rXAnimate)
+{
+    const Sequence<double> aKeyTimes = rXAnimate->getKeyTimes();
+    if (aKeyTimes.getLength() <= 0)
+        return;
+    const Sequence<Any> aValues = rXAnimate->getValues();
+    const OUString& sFormula = rXAnimate->getFormula();
+    const OUString& rAttributeName = rXAnimate->getAttributeName();
+
+    SAL_INFO("sd.eppt", "animate values, formula: " << USS(sFormula));
+
+    pFS->startElementNS(XML_p, XML_tavLst, FSEND);
+
+    for (int i = 0; i < aKeyTimes.getLength(); i++)
+    {
+        SAL_INFO("sd.eppt", "animate value " << i << ": " << aKeyTimes[i]);
+        if (aValues[i].hasValue())
+        {
+            pFS->startElementNS(XML_p, XML_tav, XML_fmla,
+                                sFormula.isEmpty() ? nullptr : USS(sFormula), XML_tm,
+                                I32S(static_cast<sal_Int32>(aKeyTimes[i] * 100000.0)), FSEND);
+            pFS->startElementNS(XML_p, XML_val, FSEND);
+            ValuePair aPair;
+            if (aValues[i] >>= aPair)
+            {
+                WriteAnimationProperty(
+                    pFS, AnimationExporter::convertAnimateValue(aPair.First, rAttributeName));
+                WriteAnimationProperty(
+                    pFS, AnimationExporter::convertAnimateValue(aPair.Second, rAttributeName));
+            }
+            else
+                WriteAnimationProperty(
+                    pFS, AnimationExporter::convertAnimateValue(aValues[i], rAttributeName));
+
+            pFS->endElementNS(XML_p, XML_val);
+            pFS->endElementNS(XML_p, XML_tav);
+        }
+    }
+
+    pFS->endElementNS(XML_p, XML_tavLst);
+}
+
+void PowerPointExport::WriteAnimateTo(const FSHelperPtr& pFS, const Any& rValue,
+                                      const OUString& rAttributeName)
+{
+    if (!rValue.hasValue())
+        return;
+
+    SAL_INFO("sd.eppt", "to attribute name: " << USS(rAttributeName));
+
+    WriteAnimationProperty(pFS, AnimationExporter::convertAnimateValue(rValue, rAttributeName),
+                           XML_to);
+}
+
+void PowerPointExport::WriteAnimationAttributeName(const FSHelperPtr& pFS,
+                                                   const OUString& rAttributeName)
+{
+    if (rAttributeName.isEmpty())
+        return;
+
+    pFS->startElementNS(XML_p, XML_attrNameLst, FSEND);
+
+    SAL_INFO("sd.eppt", "write attribute name: " << USS(rAttributeName));
+
+    if (rAttributeName == "X;Y")
+    {
+        pFS->startElementNS(XML_p, XML_attrName, FSEND);
+        pFS->writeEscaped("ppt_x");
+        pFS->endElementNS(XML_p, XML_attrName);
+
+        pFS->startElementNS(XML_p, XML_attrName, FSEND);
+        pFS->writeEscaped("ppt_y");
+        pFS->endElementNS(XML_p, XML_attrName);
+    }
+    else
+    {
+        const oox::ppt::ImplAttributeNameConversion* attrConv
+            = oox::ppt::getAttributeConversionList();
+        const char* pAttribute = nullptr;
+
+        while (attrConv->mpAPIName != nullptr)
+        {
+            if (rAttributeName.equalsAscii(attrConv->mpAPIName))
+            {
+                pAttribute = attrConv->mpMSName;
+                break;
+            }
+            attrConv++;
+        }
+
+        if (pAttribute)
+        {
+            pFS->startElementNS(XML_p, XML_attrName, FSEND);
+            pFS->writeEscaped(pAttribute);
+            pFS->endElementNS(XML_p, XML_attrName);
+        }
+        else
+        {
+            SAL_WARN("sd.eppt", "unhandled animation attribute name: " << rAttributeName);
+        }
+    }
+
+    pFS->endElementNS(XML_p, XML_attrNameLst);
+}
+
+void PowerPointExport::WriteAnimationTarget(const FSHelperPtr& pFS, const Any& rTarget)
+{
+    sal_Int32 nParagraph = -1;
+    bool bParagraphTarget = false;
+
+    Reference<XShape> rXShape;
+    rTarget >>= rXShape;
+
+    if (!rXShape.is())
+    {
+        ParagraphTarget aParagraphTarget;
+        if (rTarget >>= aParagraphTarget)
+            rXShape = aParagraphTarget.Shape;
+        if (rXShape.is())
+        {
+            nParagraph = static_cast<sal_Int32>(aParagraphTarget.Paragraph);
+            Reference<XSimpleText> xText(rXShape, UNO_QUERY);
+            if (xText.is())
+            {
+                bParagraphTarget = true;
+            }
+        }
+    }
+
+    if (rXShape.is())
+    {
+        pFS->startElementNS(XML_p, XML_tgtEl, FSEND);
+        pFS->startElementNS(XML_p, XML_spTgt, XML_spid,
+                            I32S(ShapeExport::GetShapeID(rXShape, &maShapeMap)), FSEND);
+        if (bParagraphTarget)
+        {
+            pFS->startElementNS(XML_p, XML_txEl, FSEND);
+            pFS->singleElementNS(XML_p, XML_pRg, XML_st, I32S(nParagraph), XML_end,
+                                 I32S(nParagraph), FSEND);
+            pFS->endElementNS(XML_p, XML_txEl);
+        }
+        pFS->endElementNS(XML_p, XML_spTgt);
+        pFS->endElementNS(XML_p, XML_tgtEl);
+    }
+}
+
+void PowerPointExport::WriteAnimationNodeAnimate(const FSHelperPtr& pFS,
+                                                 const Reference<XAnimationNode>& rXNode,
+                                                 sal_Int32 nXmlNodeType, bool bMainSeqChild)
+{
+    Reference<XAnimate> rXAnimate(rXNode, UNO_QUERY);
+    if (!rXAnimate.is())
+        return;
+
+    const char* pCalcMode = nullptr;
+    const char* pValueType = nullptr;
+    bool bSimple = (nXmlNodeType != XML_anim);
+    bool bTo = true;
+
+    if (!bSimple)
+    {
+        switch (rXAnimate->getCalcMode())
+        {
+            case AnimationCalcMode::DISCRETE:
+                pCalcMode = "discrete";
+                break;
+            case AnimationCalcMode::LINEAR:
+                pCalcMode = "lin";
+                break;
+        }
+
+        switch (AnimationExporter::GetValueTypeForAttributeName(rXAnimate->getAttributeName()))
+        {
+            case AnimationValueType::STRING:
+                pValueType = "str";
+                break;
+            case AnimationValueType::NUMBER:
+                pValueType = "num";
+                break;
+            case AnimationValueType::COLOR:
+                pValueType = "clr";
+                break;
+        }
+    }
+
+    if (nXmlNodeType == XML_animMotion)
+    {
+        OUString aPath;
+        Reference<XAnimateMotion> xMotion(rXNode, UNO_QUERY);
+        if (xMotion.is())
+        {
+            xMotion->getPath() >>= aPath;
+            ::basegfx::B2DPolyPolygon aPolyPoly;
+            if (::basegfx::utils::importFromSvgD(aPolyPoly, aPath, true, nullptr))
+                aPath = ::basegfx::utils::exportToSvgD(aPolyPoly, false, false, true, true);
+        }
+
+        pFS->startElementNS(XML_p, nXmlNodeType, XML_origin, "layout", XML_path,
+                            OUStringToOString(aPath, RTL_TEXTENCODING_UTF8), FSEND);
+    }
+    else if (nXmlNodeType == XML_animRot)
+    {
+        // when const char* is nullptr, the attribute is completely omitted in the output
+        const char* pBy = nullptr;
+        const char* pFrom = nullptr;
+        const char* pTo = nullptr;
+        OString aBy, aFrom, aTo;
+
+        Reference<XAnimateTransform> xTransform(rXNode, UNO_QUERY);
+        if (xTransform.is())
+        {
+            double value;
+            if (xTransform->getBy() >>= value)
+            {
+                aBy = OString::number(static_cast<int>(value * PER_DEGREE));
+                pBy = aBy.getStr();
+            }
+
+            if (xTransform->getFrom() >>= value)
+            {
+                aFrom = OString::number(static_cast<int>(value * PER_DEGREE));
+                pFrom = aFrom.getStr();
+            }
+
+            if (xTransform->getTo() >>= value)
+            {
+                aTo = OString::number(static_cast<int>(value * PER_DEGREE));
+                pTo = aTo.getStr();
+            }
+        }
+
+        pFS->startElementNS(XML_p, nXmlNodeType, XML_by, pBy, XML_from, pFrom, XML_to, pTo, FSEND);
+    }
+    else if (nXmlNodeType == XML_animClr)
+    {
+        Reference<XAnimateColor> xColor(rXNode, UNO_QUERY);
+        const char* pColorSpace = "rgb";
+        const char* pDirection = nullptr;
+        if (xColor.is() && xColor->getColorInterpolation() == AnimationColorSpace::HSL)
+        {
+            // Note: from, to, by can still be specified in any supported format.
+            pColorSpace = "hsl";
+            pDirection = xColor->getDirection() ? "cw" : "ccw";
+        }
+        pFS->startElementNS(XML_p, nXmlNodeType, XML_clrSpc, pColorSpace, XML_dir, pDirection,
+                            XML_calcmode, pCalcMode, XML_valueType, pValueType, FSEND);
+    }
+    else
+    {
+        OUString sFrom, sTo, sBy;
+        if (rXAnimate.is() && nXmlNodeType == XML_anim)
+        {
+            OUString sAttributeName = rXAnimate->getAttributeName();
+            Any aFrom
+                = AnimationExporter::convertAnimateValue(rXAnimate->getFrom(), sAttributeName);
+            aFrom >>= sFrom;
+            Any aTo = AnimationExporter::convertAnimateValue(rXAnimate->getTo(), sAttributeName);
+            aTo >>= sTo;
+            Any aBy = AnimationExporter::convertAnimateValue(rXAnimate->getBy(), sAttributeName);
+            aBy >>= sBy;
+        }
+
+        pFS->startElementNS(XML_p, nXmlNodeType, XML_calcmode, pCalcMode, XML_valueType, pValueType,
+                            XML_from, sFrom.getLength() ? USS(sFrom) : nullptr, XML_to,
+                            sTo.getLength() ? USS(sTo) : nullptr, XML_by,
+                            sBy.getLength() ? USS(sBy) : nullptr, FSEND);
+        bTo = sTo.isEmpty() && sFrom.isEmpty() && sBy.isEmpty();
+    }
+
+    WriteAnimationNodeAnimateInside(pFS, rXNode, bMainSeqChild, bSimple, bTo);
+    pFS->endElementNS(XML_p, nXmlNodeType);
+}
+
+void PowerPointExport::WriteAnimateColorColor(const FSHelperPtr& pFS, const Any& rAny,
+                                              sal_Int32 nToken)
+{
+    if (!rAny.hasValue())
+        return;
+
+    sal_Int32 nColor = 0;
+    if (rAny >>= nColor)
+    {
+        pFS->startElementNS(XML_p, nToken, FSEND);
+
+        if (nToken == XML_by)
+        {
+            // CT_TLByRgbColorTransform
+            SAL_WARN("sd.eppt", "Export p:rgb in p:by of animClr isn't implemented yet.");
+        }
+        else
+        {
+            // CT_Color
+            pFS->singleElementNS(XML_a, XML_srgbClr, XML_val, I32SHEX(nColor), FSEND);
+        }
+
+        pFS->endElementNS(XML_p, nToken);
+    }
+
+    Sequence<double> aHSL(3);
+    if (rAny >>= aHSL)
+    {
+        pFS->startElementNS(XML_p, nToken, FSEND);
+
+        if (nToken == XML_by)
+        {
+            // CT_TLByHslColorTransform
+            pFS->singleElementNS(XML_p, XML_hsl, XML_h, I32S(aHSL[0] * 60000), // ST_Angel
+                                 XML_s, I32S(aHSL[1] * 100000), XML_l, I32S(aHSL[2] * 100000),
+                                 FSEND);
+        }
+        else
+        {
+            // CT_Color
+            SAL_WARN("sd.eppt", "Export p:hsl in p:from or p:to of animClr isn't implemented yet.");
+        }
+
+        pFS->endElementNS(XML_p, nToken);
+    }
+}
+
+void PowerPointExport::WriteAnimationNodeAnimateInside(const FSHelperPtr& pFS,
+                                                       const Reference<XAnimationNode>& rXNode,
+                                                       bool bMainSeqChild, bool bSimple,
+                                                       bool bWriteTo)
+{
+    Reference<XAnimate> rXAnimate(rXNode, UNO_QUERY);
+    if (!rXAnimate.is())
+        return;
+
+    const char* pAdditive = nullptr;
+
+    if (!bSimple)
+    {
+        switch (rXAnimate->getAdditive())
+        {
+            case AnimationAdditiveMode::BASE:
+                pAdditive = "base";
+                break;
+            case AnimationAdditiveMode::SUM:
+                pAdditive = "sum";
+                break;
+            case AnimationAdditiveMode::REPLACE:
+                pAdditive = "repl";
+                break;
+            case AnimationAdditiveMode::MULTIPLY:
+                pAdditive = "mult";
+                break;
+            case AnimationAdditiveMode::NONE:
+                pAdditive = "none";
+                break;
+        }
+    }
+
+    pFS->startElementNS(XML_p, XML_cBhvr, XML_additive, pAdditive, FSEND);
+    WriteAnimationNodeCommonPropsStart(pFS, rXNode, true, bMainSeqChild);
+
+    Reference<XIterateContainer> xIterate(rXNode->getParent(), UNO_QUERY);
+    WriteAnimationTarget(pFS, xIterate.is() ? xIterate->getTarget() : rXAnimate->getTarget());
+
+    Reference<XAnimateTransform> xTransform(rXNode, UNO_QUERY);
+
+    // The attribute name of AnimateTransform is "Transform", we have to fix it.
+    OUString sNewAttr;
+    if (xTransform.is() && xTransform->getTransformType() == AnimationTransformType::ROTATE)
+        sNewAttr = "Rotate";
+
+    WriteAnimationAttributeName(pFS, xTransform.is() ? sNewAttr : rXAnimate->getAttributeName());
+
+    pFS->endElementNS(XML_p, XML_cBhvr);
+    WriteAnimateValues(pFS, rXAnimate);
+
+    Reference<XAnimateColor> xColor(rXNode, UNO_QUERY);
+
+    if (xColor.is())
+    {
+        WriteAnimateColorColor(pFS, xColor->getBy(), XML_by);
+        WriteAnimateColorColor(pFS, xColor->getFrom(), XML_from);
+        WriteAnimateColorColor(pFS, xColor->getTo(), XML_to);
+    }
+    else if (xTransform.is() && xTransform->getTransformType() == AnimationTransformType::SCALE)
+    {
+        WriteAnimationProperty(pFS, rXAnimate->getBy(), XML_by);
+        WriteAnimationProperty(pFS, rXAnimate->getFrom(), XML_from);
+        WriteAnimationProperty(pFS, rXAnimate->getTo(), XML_to);
+    }
+    else if (bWriteTo)
+        WriteAnimateTo(pFS, rXAnimate->getTo(), rXAnimate->getAttributeName());
+}
+
+void PowerPointExport::WriteAnimationCondition(const FSHelperPtr& pFS, const char* pDelay,
+                                               const char* pEvent, double fDelay, bool bHasFDelay,
+                                               sal_Int32 nToken)
+{
+    if (bHasFDelay || pDelay || pEvent)
+    {
+        pFS->startElementNS(XML_p, nToken, FSEND);
+
+        if (!pEvent)
+            pFS->singleElementNS(
+                XML_p, XML_cond, XML_delay,
+                bHasFDelay ? I64S(static_cast<sal_uInt32>(fDelay * 1000.0)) : pDelay, FSEND);
+        else
+        {
+            pFS->startElementNS(XML_p, XML_cond, XML_delay,
+                                bHasFDelay ? I64S(static_cast<sal_uInt32>(fDelay * 1000.0))
+                                           : pDelay,
+                                XML_evt, pEvent, FSEND);
+
+            pFS->startElementNS(XML_p, XML_tgtEl, FSEND);
+            pFS->singleElementNS(XML_p, XML_sldTgt, FSEND);
+            pFS->endElementNS(XML_p, XML_tgtEl);
+
+            pFS->endElementNS(XML_p, XML_cond);
+        }
+
+        pFS->endElementNS(XML_p, nToken);
+    }
+}
+
+void PowerPointExport::WriteAnimationCondition(const FSHelperPtr& pFS, Any const& rAny,
+                                               bool bWriteEvent, bool bMainSeqChild,
+                                               sal_Int32 nToken)
+{
+    bool bHasFDelay = false;
+    double fDelay = 0;
+    Timing eTiming;
+    Event aEvent;
+    Reference<XShape> xShape;
+    const char* pDelay = nullptr;
+    const char* pEvent = nullptr;
+
+    if (rAny >>= fDelay)
+        bHasFDelay = true;
+    else if (rAny >>= eTiming)
+    {
+        if (eTiming == Timing_INDEFINITE)
+            pDelay = "indefinite";
+    }
+    else if (rAny >>= aEvent)
+    {
+        // TODO
+
+        SAL_INFO("sd.eppt", "animation condition event: TODO");
+        SAL_INFO("sd.eppt", "event offset has value: "
+                                << aEvent.Offset.hasValue() << " trigger: " << aEvent.Trigger
+                                << " source has value: " << aEvent.Source.hasValue());
+        if (!bWriteEvent && aEvent.Trigger == EventTrigger::ON_NEXT && bMainSeqChild)
+            pDelay = "indefinite";
+        else if (bWriteEvent)
+        {
+            switch (aEvent.Trigger)
+            {
+                case EventTrigger::ON_NEXT:
+                    pEvent = "onNext";
+                    break;
+                case EventTrigger::ON_PREV:
+                    pEvent = "onPrev";
+                    break;
+                case EventTrigger::BEGIN_EVENT:
+                    pEvent = "begin";
+                    break;
+                case EventTrigger::END_EVENT:
+                    pEvent = "end";
+                    break;
+                case EventTrigger::ON_BEGIN:
+                    pEvent = "onBegin";
+                    break;
+                case EventTrigger::ON_END:
+                    pEvent = "onEnd";
+                    break;
+                case EventTrigger::ON_CLICK:
+                    pEvent = "onClick";
+                    break;
+                case EventTrigger::ON_DBL_CLICK:
+                    pEvent = "onDblClick";
+                    break;
+                case EventTrigger::ON_STOP_AUDIO:
+                    pEvent = "onStopAudio";
+                    break;
+                case EventTrigger::ON_MOUSE_ENTER:
+                    pEvent = "onMouseOver"; // not exact?
+                    break;
+                case EventTrigger::ON_MOUSE_LEAVE:
+                    pEvent = "onMouseOut";
+                    break;
+            }
+        }
+
+        if (aEvent.Offset >>= fDelay)
+        {
+            bHasFDelay = true;
+            SAL_INFO("sd.eppt", "event offset: " << fDelay);
+        }
+        else if (aEvent.Offset >>= eTiming)
+        {
+            if (eTiming == Timing_INDEFINITE)
+                pDelay = "indefinite";
+            SAL_INFO("sd.eppt", "event offset timing: " << static_cast<int>(eTiming));
+        }
+    }
+    else if (rAny >>= xShape)
+    {
+        SAL_INFO("sd.eppt", "Got the xShape: " << xShape->getShapeType());
+        if (xShape->getShapeType() == "com.sun.star.drawing.MediaShape"
+            || xShape->getShapeType() == "com.sun.star.presentation.MediaShape")
+        {
+            // write the default
+            bHasFDelay = true;
+        }
+    }
+
+    WriteAnimationCondition(pFS, pDelay, pEvent, fDelay, bHasFDelay, nToken);
+}
+
+void PowerPointExport::WriteAnimationNodeCommonPropsStart(const FSHelperPtr& pFS,
+                                                          const Reference<XAnimationNode>& rXNode,
+                                                          bool bSingle, bool bMainSeqChild)
+{
+    const char* pDuration = nullptr;
+    const char* pRestart = nullptr;
+    const char* pNodeType = nullptr;
+    const char* pPresetClass = nullptr;
+    const char* pFill = nullptr;
+    double fDuration = 0;
+    Any aAny;
+
+    aAny = rXNode->getDuration();
+    if (aAny.hasValue())
+    {
+        Timing eTiming;
+
+        if (aAny >>= eTiming)
+        {
+            if (eTiming == Timing_INDEFINITE)
+                pDuration = "indefinite";
+        }
+        else
+            aAny >>= fDuration;
+    }
+
+    switch (rXNode->getRestart())
+    {
+        case AnimationRestart::ALWAYS:
+            pRestart = "always";
+            break;
+        case AnimationRestart::WHEN_NOT_ACTIVE:
+            pRestart = "whenNotActive";
+            break;
+        case AnimationRestart::NEVER:
+            pRestart = "never";
+            break;
+    }
+
+    const Sequence<NamedValue> aUserData = rXNode->getUserData();
+    const Any* pAny[DFF_ANIM_PROPERTY_ID_COUNT];
+    AnimationExporter::GetUserData(aUserData, pAny, sizeof(pAny));
+
+    sal_Int16 nType = 0;
+    if (pAny[DFF_ANIM_NODE_TYPE] && (*pAny[DFF_ANIM_NODE_TYPE] >>= nType))
+    {
+        switch (nType)
+        {
+            case EffectNodeType::TIMING_ROOT:
+                pNodeType = "tmRoot";
+                if (!pDuration)
+                    pDuration = "indefinite";
+                if (!pRestart)
+                    pRestart = "never";
+                break;
+            case EffectNodeType::MAIN_SEQUENCE:
+                pNodeType = "mainSeq";
+                pDuration = "indefinite";
+                break;
+            case EffectNodeType::ON_CLICK:
+                pNodeType = "clickEffect";
+                break;
+            case EffectNodeType::AFTER_PREVIOUS:
+                pNodeType = "afterEffect";
+                break;
+            case EffectNodeType::WITH_PREVIOUS:
+                pNodeType = "withEffect";
+                break;
+            case EffectNodeType::INTERACTIVE_SEQUENCE:
+                pNodeType = "interactiveSeq";
+                break;
+        }
+    }
+
+    sal_uInt32 nPresetClass = DFF_ANIM_PRESS_CLASS_USER_DEFINED;
+    if (pAny[DFF_ANIM_PRESET_CLASS])
+    {
+        if (*pAny[DFF_ANIM_PRESET_CLASS] >>= nPresetClass)
+        {
+            switch (nPresetClass)
+            {
+                case EffectPresetClass::ENTRANCE:
+                    pPresetClass = "entr";
+                    break;
+                case EffectPresetClass::EXIT:
+                    pPresetClass = "exit";
+                    break;
+                case EffectPresetClass::EMPHASIS:
+                    pPresetClass = "emph";
+                    break;
+                case EffectPresetClass::MOTIONPATH:
+                    pPresetClass = "path";
+                    break;
+                case EffectPresetClass::OLEACTION:
+                    pPresetClass = "verb"; // ?
+                    break;
+                case EffectPresetClass::MEDIACALL:
+                    pPresetClass = "mediacall";
+                    break;
+            }
+        }
+    }
+
+    sal_uInt32 nPresetId = 0;
+    bool bPresetId = false;
+    if (pAny[DFF_ANIM_PRESET_ID])
+    {
+        OUString sPreset;
+        if (*pAny[DFF_ANIM_PRESET_ID] >>= sPreset)
+            nPresetId = AnimationExporter::GetPresetID(sPreset, nPresetClass, bPresetId);
+    }
+
+    sal_uInt32 nPresetSubType = 0;
+    bool bPresetSubType = false;
+    if (pAny[DFF_ANIM_PRESET_SUB_TYPE])
+    {
+        OUString sPresetSubType;
+        if (*pAny[DFF_ANIM_PRESET_SUB_TYPE] >>= sPresetSubType)
+        {
+            nPresetSubType = AnimationExporter::TranslatePresetSubType(nPresetClass, nPresetId,
+                                                                       sPresetSubType);
+            bPresetSubType = true;
+        }
+    }
+
+    if (nType != EffectNodeType::TIMING_ROOT && nType != EffectNodeType::MAIN_SEQUENCE)
+    {
+        // it doesn't seem to work right on root and mainseq nodes
+        sal_Int16 nFill = AnimationExporter::GetFillMode(rXNode, AnimationFill::AUTO);
+        switch (nFill)
+        {
+            case AnimationFill::FREEZE:
+                pFill = "hold";
+                break;
+            case AnimationFill::HOLD:
+                pFill = "hold";
+                break;
+            case AnimationFill::REMOVE:
+                pFill = "remove";
+                break;
+            case AnimationFill::TRANSITION:
+                pFill = "transition";
+                break;
+        }
+    }
+
+    bool bAutoReverse = rXNode->getAutoReverse();
+
+    pFS->startElementNS(
+        XML_p, XML_cTn, XML_id, I64S(mnAnimationNodeIdMax++), XML_dur,
+        fDuration != 0 ? I32S(static_cast<sal_Int32>(fDuration * 1000.0)) : pDuration, XML_autoRev,
+        bAutoReverse ? "1" : nullptr, XML_restart, pRestart, XML_nodeType, pNodeType, XML_fill,
+        pFill, XML_presetClass, pPresetClass, XML_presetID, bPresetId ? I64S(nPresetId) : nullptr,
+        XML_presetSubtype, bPresetSubType ? I64S(nPresetSubType) : nullptr, FSEND);
+
+    aAny = rXNode->getBegin();
+    if (aAny.hasValue())
+    {
+        Sequence<Any> aCondSeq;
+
+        if (aAny >>= aCondSeq)
+        {
+            for (int i = 0; i < aCondSeq.getLength(); i++)
+                WriteAnimationCondition(pFS, aCondSeq[i], false, bMainSeqChild, XML_stCondLst);
+        }
+        else
+            WriteAnimationCondition(pFS, aAny, false, bMainSeqChild, XML_stCondLst);
+    }
+
+    aAny = rXNode->getEnd();
+    if (aAny.hasValue())
+    {
+        Sequence<Any> aCondSeq;
+
+        if (aAny >>= aCondSeq)
+        {
+            for (int i = 0; i < aCondSeq.getLength(); i++)
+                WriteAnimationCondition(pFS, aCondSeq[i], false, bMainSeqChild, XML_endCondLst);
+        }
+        else
+            WriteAnimationCondition(pFS, aAny, false, bMainSeqChild, XML_endCondLst);
+    }
+
+    if (rXNode->getType() == AnimationNodeType::ITERATE)
+    {
+        Reference<XIterateContainer> xIterate(rXNode, UNO_QUERY);
+        if (xIterate.is())
+        {
+            const char* sType = nullptr;
+            switch (xIterate->getIterateType())
+            {
+                case TextAnimationType::BY_PARAGRAPH:
+                    sType = "el";
+                    break;
+                case TextAnimationType::BY_LETTER:
+                    sType = "lt";
+                    break;
+                case TextAnimationType::BY_WORD:
+                default:
+                    sType = "wd";
+                    break;
+            }
+            pFS->startElementNS(XML_p, XML_iterate, XML_type, sType, FSEND);
+            pFS->singleElementNS(XML_p, XML_tmAbs, XML_val,
+                                 I32S(xIterate->getIterateInterval() * 1000), FSEND);
+            pFS->endElementNS(XML_p, XML_iterate);
+        }
+    }
+
+    Reference<XEnumerationAccess> xEnumerationAccess(rXNode, UNO_QUERY);
+    if (xEnumerationAccess.is())
+    {
+        Reference<XEnumeration> xEnumeration(xEnumerationAccess->createEnumeration(), UNO_QUERY);
+        if (xEnumeration.is())
+        {
+            SAL_INFO("sd.eppt", "-----");
+
+            if (xEnumeration->hasMoreElements())
+            {
+                pFS->startElementNS(XML_p, XML_childTnLst, FSEND);
+
+                do
+                {
+                    Reference<XAnimationNode> xChildNode(xEnumeration->nextElement(), UNO_QUERY);
+                    if (xChildNode.is())
+                        WriteAnimationNode(pFS, xChildNode, nType == EffectNodeType::MAIN_SEQUENCE);
+                } while (xEnumeration->hasMoreElements());
+
+                pFS->endElementNS(XML_p, XML_childTnLst);
+            }
+            SAL_INFO("sd.eppt", "-----");
+        }
+    }
+
+    if (bSingle)
+        pFS->endElementNS(XML_p, XML_cTn);
+}
+
+void PowerPointExport::WriteAnimationNodeSeq(const FSHelperPtr& pFS,
+                                             const Reference<XAnimationNode>& rXNode, sal_Int32,
+                                             bool bMainSeqChild)
+{
+    SAL_INFO("sd.eppt", "write animation node SEQ");
+
+    pFS->startElementNS(XML_p, XML_seq, FSEND);
+
+    WriteAnimationNodeCommonPropsStart(pFS, rXNode, true, bMainSeqChild);
+
+    WriteAnimationCondition(pFS, nullptr, "onPrev", 0, true, XML_prevCondLst);
+    WriteAnimationCondition(pFS, nullptr, "onNext", 0, true, XML_nextCondLst);
+
+    pFS->endElementNS(XML_p, XML_seq);
+}
+
+void PowerPointExport::WriteAnimationNodeEffect(const FSHelperPtr& pFS,
+                                                const Reference<XAnimationNode>& rXNode, sal_Int32,
+                                                bool bMainSeqChild)
+{
+    SAL_INFO("sd.eppt", "write animation node FILTER");
+    Reference<XTransitionFilter> xFilter(rXNode, UNO_QUERY);
+    if (xFilter.is())
+    {
+        const char* pFilter = ::ppt::AnimationExporter::FindTransitionName(
+            xFilter->getTransition(), xFilter->getSubtype(), xFilter->getDirection());
+        const char* pMode = xFilter->getMode() ? "in" : "out";
+        pFS->startElementNS(XML_p, XML_animEffect, XML_filter, pFilter, XML_transition, pMode,
+                            FSEND);
+
+        WriteAnimationNodeAnimateInside(pFS, rXNode, bMainSeqChild, false);
+
+        pFS->endElementNS(XML_p, XML_animEffect);
+    }
+}
+
+void PowerPointExport::WriteAnimationNodeCommand(const FSHelperPtr& pFS,
+                                                 const Reference<XAnimationNode>& rXNode, sal_Int32,
+                                                 bool bMainSeqChild)
+{
+    SAL_INFO("sd.eppt", "write animation node COMMAND");
+    Reference<XCommand> xCommand(rXNode, UNO_QUERY);
+    if (xCommand.is())
+    {
+        const char* pType = "call";
+        const char* pCommand = nullptr;
+        switch (xCommand->getCommand())
+        {
+            case EffectCommands::VERB:
+                pType = "verb";
+                pCommand = "1"; /* FIXME hardcoded viewing */
+                break;
+            case EffectCommands::PLAY:
+                pCommand = "play";
+                break;
+            case EffectCommands::TOGGLEPAUSE:
+                pCommand = "togglePause";
+                break;
+            case EffectCommands::STOP:
+                pCommand = "stop";
+                break;
+            default:
+                SAL_WARN("sd.eppt", "unknown command: " << xCommand->getCommand());
+                break;
+        }
+
+        pFS->startElementNS(XML_p, XML_cmd, XML_type, pType, XML_cmd, pCommand, FSEND);
+
+        WriteAnimationNodeAnimateInside(pFS, rXNode, bMainSeqChild, false);
+        pFS->startElementNS(XML_p, XML_cBhvr, FSEND);
+        WriteAnimationNodeCommonPropsStart(pFS, rXNode, true, bMainSeqChild);
+        WriteAnimationTarget(pFS, xCommand->getTarget());
+        pFS->endElementNS(XML_p, XML_cBhvr);
+
+        pFS->endElementNS(XML_p, XML_cmd);
+    }
+}
+
+void PowerPointExport::WriteAnimationNode(const FSHelperPtr& pFS,
+                                          const Reference<XAnimationNode>& rXNode,
+                                          bool bMainSeqChild)
+{
+    SAL_INFO("sd.eppt", "export node type: " << rXNode->getType());
+    sal_Int32 xmlNodeType = -1;
+    typedef void (PowerPointExport::*AnimationNodeWriteMethod)(
+        const FSHelperPtr&, const Reference<XAnimationNode>&, sal_Int32, bool);
+    AnimationNodeWriteMethod pMethod = nullptr;
+
+    switch (rXNode->getType())
+    {
+        case AnimationNodeType::ITERATE:
+        case AnimationNodeType::PAR:
+            xmlNodeType = XML_par;
+            break;
+        case AnimationNodeType::SEQ:
+            pMethod = &PowerPointExport::WriteAnimationNodeSeq;
+            break;
+        case AnimationNodeType::ANIMATE:
+            xmlNodeType = XML_anim;
+            pMethod = &PowerPointExport::WriteAnimationNodeAnimate;
+            break;
+        case AnimationNodeType::ANIMATEMOTION:
+            xmlNodeType = XML_animMotion;
+            pMethod = &PowerPointExport::WriteAnimationNodeAnimate;
+            break;
+        case AnimationNodeType::ANIMATETRANSFORM:
+        {
+            Reference<XAnimateTransform> xTransform(rXNode, UNO_QUERY);
+            if (xTransform.is())
+            {
+                if (xTransform->getTransformType() == AnimationTransformType::SCALE)
+                {
+                    xmlNodeType = XML_animScale;
+                    pMethod = &PowerPointExport::WriteAnimationNodeAnimate;
+                }
+                else if (xTransform->getTransformType() == AnimationTransformType::ROTATE)
+                {
+                    xmlNodeType = XML_animRot;
+                    pMethod = &PowerPointExport::WriteAnimationNodeAnimate;
+                }
+            }
+        }
+        break;
+        case AnimationNodeType::ANIMATECOLOR:
+            xmlNodeType = XML_animClr;
+            pMethod = &PowerPointExport::WriteAnimationNodeAnimate;
+            break;
+        case AnimationNodeType::SET:
+            xmlNodeType = XML_set;
+            pMethod = &PowerPointExport::WriteAnimationNodeAnimate;
+            break;
+        case AnimationNodeType::TRANSITIONFILTER:
+            xmlNodeType = XML_animEffect;
+            pMethod = &PowerPointExport::WriteAnimationNodeEffect;
+            break;
+        case AnimationNodeType::COMMAND:
+            xmlNodeType = XML_cmd;
+            pMethod = &PowerPointExport::WriteAnimationNodeCommand;
+            break;
+        default:
+            SAL_WARN("sd.eppt", "unhandled animation node: " << rXNode->getType());
+            break;
+    }
+
+    if (pMethod)
+    {
+        (this->*pMethod)(pFS, rXNode, xmlNodeType, bMainSeqChild);
+        return;
+    }
+
+    if (xmlNodeType == -1)
+        return;
+
+    pFS->startElementNS(XML_p, xmlNodeType, FSEND);
+
+    WriteAnimationNodeCommonPropsStart(pFS, rXNode, true, bMainSeqChild);
+
+    pFS->endElementNS(XML_p, xmlNodeType);
+}
+
+void PowerPointExport::WriteAnimations(const FSHelperPtr& pFS)
+{
+    Reference<XAnimationNodeSupplier> xNodeSupplier(mXDrawPage, UNO_QUERY);
+    if (xNodeSupplier.is())
+    {
+        const Reference<XAnimationNode> xNode(xNodeSupplier->getAnimationNode());
+        if (xNode.is())
+        {
+            Reference<XEnumerationAccess> xEnumerationAccess(xNode, UNO_QUERY);
+            if (xEnumerationAccess.is())
+            {
+                Reference<XEnumeration> xEnumeration(xEnumerationAccess->createEnumeration(),
+                                                     UNO_QUERY);
+                if (xEnumeration.is() && xEnumeration->hasMoreElements())
+                {
+                    pFS->startElementNS(XML_p, XML_timing, FSEND);
+                    pFS->startElementNS(XML_p, XML_tnLst, FSEND);
+
+                    WriteAnimationNode(pFS, xNode, false);
+
+                    pFS->endElementNS(XML_p, XML_tnLst);
+                    pFS->endElementNS(XML_p, XML_timing);
+                }
+            }
+        }
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx
index d5b654e72b39..6142e15a66cb 100644
--- a/sd/source/filter/eppt/pptx-epptooxml.cxx
+++ b/sd/source/filter/eppt/pptx-epptooxml.cxx
@@ -38,29 +38,8 @@
 #include <sal/log.hxx>
 #include <filter/msfilter/escherex.hxx>
 #include <tools/poly.hxx>
-
-#include <com/sun/star/animations/AnimationAdditiveMode.hpp>
-#include <com/sun/star/animations/AnimationCalcMode.hpp>
-#include <com/sun/star/animations/AnimationFill.hpp>
-#include <com/sun/star/animations/AnimationNodeType.hpp>
-#include <com/sun/star/animations/AnimationRestart.hpp>
-#include <com/sun/star/animations/AnimationTransformType.hpp>
-#include <com/sun/star/animations/AnimationValueType.hpp>
-#include <com/sun/star/animations/AnimationColorSpace.hpp>
-#include <com/sun/star/animations/Event.hpp>
-#include <com/sun/star/animations/EventTrigger.hpp>
-#include <com/sun/star/animations/Timing.hpp>
 #include <com/sun/star/animations/TransitionType.hpp>
 #include <com/sun/star/animations/TransitionSubType.hpp>
-#include <com/sun/star/animations/ValuePair.hpp>
-#include <com/sun/star/animations/XAnimateMotion.hpp>
-#include <com/sun/star/animations/XAnimateTransform.hpp>
-#include <com/sun/star/animations/XAnimationNode.hpp>
-#include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
-#include <com/sun/star/animations/XAnimateColor.hpp>
-#include <com/sun/star/animations/XCommand.hpp>
-#include <com/sun/star/animations/XTransitionFilter.hpp>
-#include <com/sun/star/animations/XIterateContainer.hpp>
 #include <com/sun/star/beans/Property.hpp>
 #include <com/sun/star/beans/XPropertySetInfo.hpp>
 #include <com/sun/star/container/XEnumerationAccess.hpp>
@@ -73,11 +52,6 @@
 #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/presentation/EffectCommands.hpp>
-#include <com/sun/star/presentation/EffectNodeType.hpp>
-#include <com/sun/star/presentation/EffectPresetClass.hpp>
-#include <com/sun/star/presentation/ParagraphTarget.hpp>
-#include <com/sun/star/presentation/TextAnimationType.hpp>
 #include <com/sun/star/util/DateTime.hpp>
 #include <com/sun/star/task/XStatusIndicator.hpp>
 #include <com/sun/star/frame/XModel.hpp>
@@ -917,1005 +891,6 @@ void PowerPointExport::WriteTransition(const FSHelperPtr& pFS)
     }
 }
 
-void PowerPointExport::WriteAnimationProperty(const FSHelperPtr& pFS, const Any& rAny, sal_Int32 nToken)
-{
-    if (!rAny.hasValue())
-        return;
-
-    ValuePair aPair;
-
-    if (rAny >>= aPair)
-    {
-        double x, y;
-        if ((aPair.First >>= x) && (aPair.Second >>= y))
-        {
-            if (nToken == XML_by)
-            {
-                // MS needs ending values but we have offset values.
-                x += 1.0;
-                y += 1.0;
-            }
-            pFS->singleElementNS(XML_p, nToken,
-                XML_x, OString::number(x*100000).getStr(),
-                XML_y, OString::number(y*100000).getStr(),
-                FSEND);
-        }
-        return;
-    }
-
-    sal_uInt32 nRgb;
-    double fDouble;
-
-    uno::TypeClass aClass = rAny.getValueType().getTypeClass();
-    bool bWriteToken = nToken &&
-        (  aClass == TypeClass_LONG
-        || aClass == TypeClass_DOUBLE
-        || aClass == TypeClass_STRING );
-
-    if (bWriteToken)
-        pFS->startElementNS(XML_p, nToken, FSEND);
-
-    switch (rAny.getValueType().getTypeClass())
-    {
-    case TypeClass_LONG:
-        rAny >>= nRgb;
-        pFS->singleElementNS(XML_a, XML_srgbClr,
-                             XML_val, I32SHEX(nRgb),
-                             FSEND);
-        break;
-    case TypeClass_DOUBLE:
-        rAny >>= fDouble;
-        pFS->singleElementNS(XML_p, XML_fltVal,
-            XML_val, DS(fDouble),
-            FSEND);
-        break;
-    case TypeClass_STRING:
-        pFS->singleElementNS(XML_p, XML_strVal,
-                             XML_val, USS(*o3tl::doAccess<OUString>(rAny)),
-                             FSEND);
-        break;
-    default:
-        break;
-    }
-
-    if (bWriteToken)
-        pFS->endElementNS(XML_p, nToken);
-}
-
-void PowerPointExport::WriteAnimateValues(const FSHelperPtr& pFS, const Reference< XAnimate >& rXAnimate)
-{
-    const Sequence< double > aKeyTimes = rXAnimate->getKeyTimes();
-    if (aKeyTimes.getLength() <= 0)
-        return;
-    const Sequence< Any > aValues = rXAnimate->getValues();
-    const OUString& sFormula = rXAnimate->getFormula();
-    const OUString& rAttributeName = rXAnimate->getAttributeName();
-
-    SAL_INFO("sd.eppt", "animate values, formula: " << USS(sFormula));
-
-    pFS->startElementNS(XML_p, XML_tavLst, FSEND);
-
-    for (int i = 0; i < aKeyTimes.getLength(); i++)
-    {
-        SAL_INFO("sd.eppt", "animate value " << i << ": " << aKeyTimes[i]);
-        if (aValues[ i ].hasValue())
-        {
-            pFS->startElementNS(XML_p, XML_tav,
-                                XML_fmla, sFormula.isEmpty() ? nullptr : USS(sFormula),
-                                XML_tm, I32S(static_cast<sal_Int32>(aKeyTimes[ i ]*100000.0)),
-                                FSEND);
-            pFS->startElementNS(XML_p, XML_val, FSEND);
-            ValuePair aPair;
-            if (aValues[ i ] >>= aPair)
-            {
-                WriteAnimationProperty(pFS, AnimationExporter::convertAnimateValue(aPair.First, rAttributeName));
-                WriteAnimationProperty(pFS, AnimationExporter::convertAnimateValue(aPair.Second, rAttributeName));
-            }
-            else
-                WriteAnimationProperty(pFS, AnimationExporter::convertAnimateValue(aValues[ i ], rAttributeName));
-
-            pFS->endElementNS(XML_p, XML_val);
-            pFS->endElementNS(XML_p, XML_tav);
-        }
-    }
-
-    pFS->endElementNS(XML_p, XML_tavLst);
-}
-
-void PowerPointExport::WriteAnimateTo(const FSHelperPtr& pFS, const Any& rValue, const OUString& rAttributeName)
-{
-    if (!rValue.hasValue())
-        return;
-
-    SAL_INFO("sd.eppt", "to attribute name: " << USS(rAttributeName));
-
-    WriteAnimationProperty(pFS, AnimationExporter::convertAnimateValue(rValue, rAttributeName), XML_to);
-}
-
-void PowerPointExport::WriteAnimationAttributeName(const FSHelperPtr& pFS, const OUString& rAttributeName)
-{
-    if (rAttributeName.isEmpty())
-        return;
-
-    pFS->startElementNS(XML_p, XML_attrNameLst, FSEND);
-
-    SAL_INFO("sd.eppt", "write attribute name: " << USS(rAttributeName));
-
-    if (rAttributeName == "X;Y")
-    {
-        pFS->startElementNS(XML_p, XML_attrName, FSEND);
-        pFS->writeEscaped("ppt_x");
-        pFS->endElementNS(XML_p, XML_attrName);
-
-        pFS->startElementNS(XML_p, XML_attrName, FSEND);
-        pFS->writeEscaped("ppt_y");
-        pFS->endElementNS(XML_p, XML_attrName);
-    }
-    else
-    {
-        const oox::ppt::ImplAttributeNameConversion *attrConv = oox::ppt::getAttributeConversionList();
-        const char* pAttribute = nullptr;
-
-        while(attrConv->mpAPIName != nullptr)
-        {
-            if(rAttributeName.equalsAscii(attrConv->mpAPIName))
-            {
-                pAttribute = attrConv->mpMSName;
-                break;
-            }
-            attrConv++;
-        }
-
-        if (pAttribute)
-        {
-            pFS->startElementNS(XML_p, XML_attrName, FSEND);
-            pFS->writeEscaped(pAttribute);
-            pFS->endElementNS(XML_p, XML_attrName);
-        }
-        else
-        {
-            SAL_WARN("sd.eppt", "unhandled animation attribute name: " << rAttributeName);
-        }
-    }
-
-    pFS->endElementNS(XML_p, XML_attrNameLst);
-}
-
-void PowerPointExport::WriteAnimationTarget(const FSHelperPtr& pFS, const Any& rTarget)
-{
-    sal_Int32 nParagraph = -1;
-    bool bParagraphTarget = false;
-
-    Reference< XShape > rXShape;
-    rTarget >>= rXShape;
-
-    if (!rXShape.is())
-    {
-        ParagraphTarget aParagraphTarget;
-        if (rTarget >>= aParagraphTarget)
-            rXShape = aParagraphTarget.Shape;
-        if (rXShape.is())
-        {
-            nParagraph = static_cast< sal_Int32 >(aParagraphTarget.Paragraph);
-            Reference< XSimpleText > xText(rXShape, UNO_QUERY);
-            if (xText.is())
-            {
-                bParagraphTarget = true;
-            }
-        }
-    }
-
-    if (rXShape.is())
-    {
-        pFS->startElementNS(XML_p, XML_tgtEl, FSEND);
-        pFS->startElementNS(XML_p, XML_spTgt,
-                            XML_spid, I32S(ShapeExport::GetShapeID(rXShape, &maShapeMap)),
-                            FSEND);
-        if (bParagraphTarget)
-        {
-            pFS->startElementNS(XML_p, XML_txEl, FSEND);
-            pFS->singleElementNS(XML_p, XML_pRg,
-                                 XML_st, I32S(nParagraph),
-                                 XML_end, I32S(nParagraph),
-                                 FSEND);
-            pFS->endElementNS(XML_p, XML_txEl);
-        }
-        pFS->endElementNS(XML_p, XML_spTgt);
-        pFS->endElementNS(XML_p, XML_tgtEl);
-    }
-}
-
-void PowerPointExport::WriteAnimationNodeAnimate(const FSHelperPtr& pFS, const Reference< XAnimationNode >& rXNode, sal_Int32 nXmlNodeType, bool bMainSeqChild)
-{
-    Reference< XAnimate > rXAnimate(rXNode, UNO_QUERY);
-    if (!rXAnimate.is())
-        return;
-
-    const char* pCalcMode = nullptr;
-    const char* pValueType = nullptr;
-    bool bSimple = (nXmlNodeType != XML_anim);
-    bool bTo = true;
-
-    if (!bSimple)
-    {
-        switch (rXAnimate->getCalcMode())
-        {
-        case AnimationCalcMode::DISCRETE:
-            pCalcMode = "discrete";
-            break;
-        case AnimationCalcMode::LINEAR:
-            pCalcMode = "lin";
-            break;
-        }
-
-        switch (AnimationExporter::GetValueTypeForAttributeName(rXAnimate->getAttributeName()))
-        {
-        case AnimationValueType::STRING:
-            pValueType = "str";
-            break;
-        case AnimationValueType::NUMBER:
-            pValueType = "num";
-            break;
-        case AnimationValueType::COLOR:
-            pValueType = "clr";
-            break;
-        }
-
-
-    }
-
-    if (nXmlNodeType == XML_animMotion)
-    {
-        OUString aPath;
-        Reference<XAnimateMotion> xMotion(rXNode, UNO_QUERY);
-        if (xMotion.is())
-        {
-            xMotion->getPath() >>= aPath;
-            ::basegfx::B2DPolyPolygon aPolyPoly;
-            if (::basegfx::utils::importFromSvgD(aPolyPoly, aPath, true, nullptr))
-                aPath = ::basegfx::utils::exportToSvgD(aPolyPoly, false, false, true, true);
-        }
-
-        pFS->startElementNS(XML_p, nXmlNodeType,
-                            XML_origin, "layout",
-                            XML_path, OUStringToOString(aPath, RTL_TEXTENCODING_UTF8),
-                            FSEND);
-    }
-    else if (nXmlNodeType == XML_animRot)
-    {
-        // when const char* is nullptr, the attribute is completely omitted in the output
-        const char* pBy = nullptr;
-        const char* pFrom = nullptr;
-        const char* pTo = nullptr;
-        OString aBy, aFrom, aTo;
-
-        Reference<XAnimateTransform> xTransform(rXNode, UNO_QUERY);
-        if (xTransform.is())
-        {
-            double value;
-            if (xTransform->getBy() >>= value)
-            {
-                aBy = OString::number(static_cast<int>(value * PER_DEGREE));
-                pBy = aBy.getStr();
-            }
-
-            if (xTransform->getFrom() >>= value)
-            {
-                aFrom = OString::number(static_cast<int>(value * PER_DEGREE));
-                pFrom = aFrom.getStr();
-            }
-
-            if (xTransform->getTo() >>= value)
-            {
-                aTo = OString::number(static_cast<int>(value * PER_DEGREE));
-                pTo = aTo.getStr();
-            }
-        }
-
-        pFS->startElementNS(XML_p, nXmlNodeType,
-                            XML_by, pBy,
-                            XML_from, pFrom,
-                            XML_to, pTo,
-                            FSEND);
-    }
-    else if (nXmlNodeType == XML_animClr)
-    {
-        Reference<XAnimateColor> xColor(rXNode, UNO_QUERY);
-        const char *pColorSpace = "rgb";
-        const char *pDirection = nullptr;
-        if (xColor.is() && xColor->getColorInterpolation() == AnimationColorSpace::HSL)
-        {
-            // Note: from, to, by can still be specified in any supported format.
-            pColorSpace = "hsl";
-            pDirection = xColor->getDirection() ? "cw" : "ccw";
-        }
-        pFS->startElementNS(XML_p, nXmlNodeType,
-            XML_clrSpc, pColorSpace,
-            XML_dir, pDirection,
-            XML_calcmode, pCalcMode,
-            XML_valueType, pValueType,
-            FSEND);
-    }
-    else
-    {
-        OUString sFrom, sTo, sBy;
-        if (rXAnimate.is() && nXmlNodeType == XML_anim)
-        {
-            OUString sAttributeName = rXAnimate->getAttributeName();
-            Any aFrom = AnimationExporter::convertAnimateValue(rXAnimate->getFrom(), sAttributeName);
-            aFrom >>= sFrom;
-            Any aTo = AnimationExporter::convertAnimateValue(rXAnimate->getTo(), sAttributeName);
-            aTo >>= sTo;
-            Any aBy = AnimationExporter::convertAnimateValue(rXAnimate->getBy(), sAttributeName);
-            aBy >>= sBy;
-        }
-
-        pFS->startElementNS(XML_p, nXmlNodeType,
-            XML_calcmode, pCalcMode,
-            XML_valueType, pValueType,
-            XML_from, sFrom.getLength() ? USS(sFrom) : nullptr,
-            XML_to, sTo.getLength() ? USS(sTo) : nullptr,
-            XML_by, sBy.getLength() ? USS(sBy) : nullptr,
-            FSEND);
-        bTo = sTo.isEmpty() && sFrom.isEmpty() && sBy.isEmpty();
-    }
-
-    WriteAnimationNodeAnimateInside(pFS, rXNode, bMainSeqChild, bSimple, bTo);
-    pFS->endElementNS(XML_p, nXmlNodeType);
-}
-
-void PowerPointExport::WriteAnimateColorColor(const FSHelperPtr& pFS, const Any& rAny, sal_Int32 nToken)
-{
-    if (!rAny.hasValue())
-        return;
-
-    sal_Int32 nColor = 0;
-    if (rAny >>= nColor)
-    {
-        pFS->startElementNS(XML_p, nToken, FSEND);
-
-        if (nToken == XML_by)
-        {
-            // CT_TLByRgbColorTransform
-            SAL_WARN("sd.eppt", "Export p:rgb in p:by of animClr isn't implemented yet.");
-        }
-        else
-        {
-            // CT_Color
-            pFS->singleElementNS(XML_a, XML_srgbClr, XML_val, I32SHEX(nColor), FSEND);
-        }
-
-        pFS->endElementNS(XML_p, nToken);
-    }
-
-    Sequence< double > aHSL(3);
-    if (rAny >>= aHSL)
-    {
-        pFS->startElementNS(XML_p, nToken, FSEND);
-
-        if (nToken == XML_by)
-        {
-            // CT_TLByHslColorTransform
-            pFS->singleElementNS(XML_p, XML_hsl,
-                             XML_h, I32S(aHSL[0] * 60000),  // ST_Angel
-                             XML_s, I32S(aHSL[1] * 100000),
-                             XML_l, I32S(aHSL[2] * 100000),
-                             FSEND);
-        }
-        else
-        {
-            // CT_Color
-            SAL_WARN("sd.eppt", "Export p:hsl in p:from or p:to of animClr isn't implemented yet.");
-        }
-
-        pFS->endElementNS(XML_p, nToken);
-    }
-}
-
-void PowerPointExport::WriteAnimationNodeAnimateInside(const FSHelperPtr& pFS, const Reference< XAnimationNode >& rXNode, bool bMainSeqChild, bool bSimple, bool bWriteTo)
-{
-    Reference< XAnimate > rXAnimate(rXNode, UNO_QUERY);
-    if (!rXAnimate.is())
-        return;
-
-    const char* pAdditive = nullptr;
-
-    if (!bSimple)
-    {
-        switch (rXAnimate->getAdditive())
-        {
-        case AnimationAdditiveMode::BASE:
-            pAdditive = "base";
-            break;
-        case AnimationAdditiveMode::SUM:
-            pAdditive = "sum";
-            break;
-        case AnimationAdditiveMode::REPLACE:
-            pAdditive = "repl";
-            break;
-        case AnimationAdditiveMode::MULTIPLY:
-            pAdditive = "mult";
-            break;
-        case AnimationAdditiveMode::NONE:
-            pAdditive = "none";
-            break;
-        }
-    }
-
-    pFS->startElementNS(XML_p, XML_cBhvr,
-                        XML_additive, pAdditive,
-                        FSEND);
-    WriteAnimationNodeCommonPropsStart(pFS, rXNode, true, bMainSeqChild);
-
-    Reference<XIterateContainer> xIterate(rXNode->getParent(), UNO_QUERY);
-    WriteAnimationTarget(pFS, xIterate.is() ?
-            xIterate->getTarget() : rXAnimate->getTarget());
-
-    Reference<XAnimateTransform> xTransform(rXNode, UNO_QUERY);
-
-    // The attribute name of AnimateTransform is "Transform", we have to fix it.
-    OUString sNewAttr;
-    if (xTransform.is() && xTransform->getTransformType() == AnimationTransformType::ROTATE)
-            sNewAttr = "Rotate";
-
-    WriteAnimationAttributeName(pFS, xTransform.is() ? sNewAttr : rXAnimate->getAttributeName());
-
-    pFS->endElementNS(XML_p, XML_cBhvr);
-    WriteAnimateValues(pFS, rXAnimate);
-
-    Reference<XAnimateColor> xColor(rXNode, UNO_QUERY);
-
-    if (xColor.is())
-    {
-        WriteAnimateColorColor(pFS, xColor->getBy(), XML_by);
-        WriteAnimateColorColor(pFS, xColor->getFrom(), XML_from);
-        WriteAnimateColorColor(pFS, xColor->getTo(), XML_to);
-    }
-    else if (xTransform.is() && xTransform->getTransformType() == AnimationTransformType::SCALE)
-    {
-        WriteAnimationProperty(pFS, rXAnimate->getBy(), XML_by);
-        WriteAnimationProperty(pFS, rXAnimate->getFrom(), XML_from);
-        WriteAnimationProperty(pFS, rXAnimate->getTo(), XML_to);
-    }
-    else if (bWriteTo)
-        WriteAnimateTo(pFS, rXAnimate->getTo(), rXAnimate->getAttributeName());
-}
-
-void PowerPointExport::WriteAnimationCondition(const FSHelperPtr& pFS, const char* pDelay, const char* pEvent, double fDelay, bool bHasFDelay, sal_Int32 nToken)
-{
-    if (bHasFDelay || pDelay || pEvent)
-    {
-        pFS->startElementNS(XML_p, nToken, FSEND);
-
-        if (!pEvent)
-            pFS->singleElementNS(XML_p, XML_cond,
-                                 XML_delay, bHasFDelay ? I64S(static_cast<sal_uInt32>(fDelay*1000.0)) : pDelay,
-                                 FSEND);
-        else
-        {
-            pFS->startElementNS(XML_p, XML_cond,
-                                XML_delay, bHasFDelay ? I64S(static_cast<sal_uInt32>(fDelay*1000.0)) : pDelay,
-                                XML_evt, pEvent,
-                                FSEND);
-
-            pFS->startElementNS(XML_p, XML_tgtEl, FSEND);
-            pFS->singleElementNS(XML_p, XML_sldTgt, FSEND);
-            pFS->endElementNS(XML_p, XML_tgtEl);
-
-            pFS->endElementNS(XML_p, XML_cond);
-        }
-
-        pFS->endElementNS(XML_p, nToken);
-    }
-}
-
-void PowerPointExport::WriteAnimationCondition(const FSHelperPtr& pFS, Any const& rAny, bool bWriteEvent, bool bMainSeqChild, sal_Int32 nToken)
-{
-    bool bHasFDelay = false;
-    double fDelay = 0;
-    Timing eTiming;
-    Event aEvent;
-    Reference<XShape> xShape;
-    const char* pDelay = nullptr;
-    const char* pEvent = nullptr;
-
-    if (rAny >>= fDelay)
-        bHasFDelay = true;
-    else if (rAny >>= eTiming)
-    {
-        if (eTiming == Timing_INDEFINITE)
-            pDelay = "indefinite";
-    }
-    else if (rAny >>= aEvent)
-    {
-        // TODO
-
-        SAL_INFO("sd.eppt", "animation condition event: TODO");
-        SAL_INFO("sd.eppt", "event offset has value: " << aEvent.Offset.hasValue() << " trigger: " <<  aEvent.Trigger
-                 << " source has value: " <<  aEvent.Source.hasValue());
-        if (!bWriteEvent && aEvent.Trigger == EventTrigger::ON_NEXT && bMainSeqChild)
-            pDelay = "indefinite";
-        else if (bWriteEvent)
-        {
-            switch (aEvent.Trigger)
-            {
-            case EventTrigger::ON_NEXT:
-                pEvent = "onNext";
-                break;
-            case EventTrigger::ON_PREV:
-                pEvent = "onPrev";
-                break;
-            case EventTrigger::BEGIN_EVENT:
-                pEvent = "begin";
-                break;
-            case EventTrigger::END_EVENT:
-                pEvent = "end";
-                break;
-            case EventTrigger::ON_BEGIN:
-                pEvent = "onBegin";
-                break;
-            case EventTrigger::ON_END:
-                pEvent = "onEnd";
-                break;
-            case EventTrigger::ON_CLICK:
-                pEvent = "onClick";
-                break;
-            case EventTrigger::ON_DBL_CLICK:
-                pEvent = "onDblClick";
-                break;
-            case EventTrigger::ON_STOP_AUDIO:
-                pEvent = "onStopAudio";
-                break;
-            case EventTrigger::ON_MOUSE_ENTER:
-                pEvent = "onMouseOver";   // not exact?
-                break;
-            case EventTrigger::ON_MOUSE_LEAVE:
-                pEvent = "onMouseOut";
-                break;
-            }
-        }
-
-        if (aEvent.Offset >>= fDelay)
-        {
-            bHasFDelay = true;
-            SAL_INFO("sd.eppt", "event offset: " << fDelay);
-        }
-        else if (aEvent.Offset >>= eTiming)
-        {
-            if (eTiming == Timing_INDEFINITE)
-                pDelay = "indefinite";
-            SAL_INFO("sd.eppt", "event offset timing: " << static_cast<int>(eTiming));
-        }
-    }
-    else if (rAny >>= xShape)
-    {
-        SAL_INFO("sd.eppt", "Got the xShape: " << xShape->getShapeType());
-        if (xShape->getShapeType() == "com.sun.star.drawing.MediaShape" || xShape->getShapeType() == "com.sun.star.presentation.MediaShape")
-        {
-            // write the default
-            bHasFDelay = true;
-        }
-    }
-
-    WriteAnimationCondition(pFS, pDelay, pEvent, fDelay, bHasFDelay, nToken);
-}
-
-void PowerPointExport::WriteAnimationNodeCommonPropsStart(const FSHelperPtr& pFS, const Reference< XAnimationNode >& rXNode, bool bSingle, bool bMainSeqChild)
-{
-    const char* pDuration = nullptr;
-    const char* pRestart = nullptr;
-    const char* pNodeType = nullptr;
-    const char* pPresetClass = nullptr;
-    const char* pFill = nullptr;
-    double fDuration = 0;
-    Any aAny;
-
-    aAny = rXNode->getDuration();
-    if (aAny.hasValue())
-    {
-        Timing eTiming;
-
-        if (aAny >>= eTiming)
-        {
-            if (eTiming == Timing_INDEFINITE)
-                pDuration = "indefinite";
-        }
-        else
-            aAny >>= fDuration;
-    }
-
-    switch (rXNode->getRestart())
-    {
-    case AnimationRestart::ALWAYS:
-        pRestart = "always";
-        break;
-    case AnimationRestart::WHEN_NOT_ACTIVE:
-        pRestart = "whenNotActive";
-        break;
-    case AnimationRestart::NEVER:
-        pRestart = "never";
-        break;
-    }
-
-    const Sequence< NamedValue > aUserData = rXNode->getUserData();
-    const Any* pAny[ DFF_ANIM_PROPERTY_ID_COUNT ];
-    AnimationExporter::GetUserData(aUserData, pAny, sizeof(pAny));
-
-    sal_Int16 nType = 0;
-    if (pAny[ DFF_ANIM_NODE_TYPE ] && (*pAny[ DFF_ANIM_NODE_TYPE ] >>= nType))
-    {
-        switch (nType)
-        {
-        case EffectNodeType::TIMING_ROOT:
-            pNodeType = "tmRoot";
-            if (!pDuration)
-                pDuration = "indefinite";
-            if (!pRestart)
-                pRestart = "never";
-            break;
-        case EffectNodeType::MAIN_SEQUENCE:
-            pNodeType = "mainSeq";
-            pDuration = "indefinite";
-            break;
-        case EffectNodeType::ON_CLICK:
-            pNodeType = "clickEffect";
-            break;
-        case EffectNodeType::AFTER_PREVIOUS:
-            pNodeType = "afterEffect";
-            break;
-        case EffectNodeType::WITH_PREVIOUS:
-            pNodeType = "withEffect";
-            break;
-        case EffectNodeType::INTERACTIVE_SEQUENCE:
-            pNodeType = "interactiveSeq";
-            break;
-        }
-    }
-
-    sal_uInt32 nPresetClass = DFF_ANIM_PRESS_CLASS_USER_DEFINED;
-    if (pAny[ DFF_ANIM_PRESET_CLASS ])
-    {
-        if (*pAny[ DFF_ANIM_PRESET_CLASS ] >>= nPresetClass)
-        {
-            switch (nPresetClass)
-            {
-            case EffectPresetClass::ENTRANCE:
-                pPresetClass = "entr";
-                break;
-            case EffectPresetClass::EXIT:
-                pPresetClass = "exit";
-                break;
-            case EffectPresetClass::EMPHASIS:
-                pPresetClass = "emph";
-                break;
-            case EffectPresetClass::MOTIONPATH:
-                pPresetClass = "path";
-                break;
-            case EffectPresetClass::OLEACTION:
-                pPresetClass = "verb";  // ?
-                break;
-            case EffectPresetClass::MEDIACALL:
-                pPresetClass = "mediacall";
-                break;
-            }
-        }
-    }
-
-    sal_uInt32 nPresetId = 0;
-    bool bPresetId = false;
-    if (pAny[ DFF_ANIM_PRESET_ID ])
-    {
-        OUString sPreset;
-        if (*pAny[ DFF_ANIM_PRESET_ID ] >>= sPreset)
-            nPresetId = AnimationExporter::GetPresetID(sPreset, nPresetClass, bPresetId);
-    }
-
-    sal_uInt32 nPresetSubType = 0;
-    bool bPresetSubType = false;
-    if (pAny[ DFF_ANIM_PRESET_SUB_TYPE ])
-    {
-        OUString sPresetSubType;
-        if (*pAny[ DFF_ANIM_PRESET_SUB_TYPE ] >>= sPresetSubType)
-        {
-            nPresetSubType = AnimationExporter::TranslatePresetSubType(nPresetClass, nPresetId, sPresetSubType);
-            bPresetSubType = true;
-        }
-    }
-
-    if (nType != EffectNodeType::TIMING_ROOT && nType != EffectNodeType::MAIN_SEQUENCE)
-    {
-        // it doesn't seem to work right on root and mainseq nodes
-        sal_Int16 nFill = AnimationExporter::GetFillMode(rXNode, AnimationFill::AUTO);
-        switch (nFill)
-        {
-        case AnimationFill::FREEZE:
-            pFill = "hold";
-            break;
-        case AnimationFill::HOLD:
-            pFill = "hold";
-            break;
-        case AnimationFill::REMOVE:
-            pFill = "remove";
-            break;
-        case AnimationFill::TRANSITION:
-            pFill = "transition";
-            break;
-        }
-    }
-
-    bool bAutoReverse = rXNode->getAutoReverse();
-
-    pFS->startElementNS(XML_p, XML_cTn,
-                        XML_id, I64S(mnAnimationNodeIdMax ++),
-                        XML_dur, fDuration != 0 ? I32S(static_cast<sal_Int32>(fDuration * 1000.0)) : pDuration,
-                        XML_autoRev, bAutoReverse ? "1" : nullptr,
-                        XML_restart, pRestart,
-                        XML_nodeType, pNodeType,
-                        XML_fill, pFill,
-                        XML_presetClass, pPresetClass,
-                        XML_presetID, bPresetId ? I64S(nPresetId) : nullptr,
-                        XML_presetSubtype, bPresetSubType ? I64S(nPresetSubType) : nullptr,
-                        FSEND);
-
-    aAny = rXNode->getBegin();
-    if (aAny.hasValue())
-    {
-        Sequence< Any > aCondSeq;
-
-        if (aAny >>= aCondSeq)
-        {
-            for (int i = 0; i < aCondSeq.getLength(); i ++)
-                WriteAnimationCondition(pFS, aCondSeq[ i ], false, bMainSeqChild, XML_stCondLst);
-        }
-        else
-            WriteAnimationCondition(pFS, aAny, false, bMainSeqChild, XML_stCondLst);
-    }
-
-    aAny = rXNode->getEnd();
-    if (aAny.hasValue())
-    {
-        Sequence< Any > aCondSeq;
-
-        if (aAny >>= aCondSeq)
-        {
-            for (int i = 0; i < aCondSeq.getLength(); i ++)
-                WriteAnimationCondition(pFS, aCondSeq[ i ], false, bMainSeqChild, XML_endCondLst);
-        }
-        else
-            WriteAnimationCondition(pFS, aAny, false, bMainSeqChild, XML_endCondLst);
-    }
-
-    if (rXNode->getType() == AnimationNodeType::ITERATE)
-    {
-        Reference<XIterateContainer> xIterate(rXNode, UNO_QUERY);
-        if (xIterate.is())
-        {
-            const char *sType = nullptr;
-            switch(xIterate->getIterateType())
-            {
-                case TextAnimationType::BY_PARAGRAPH:
-                    sType = "el";
-                break;
-                case TextAnimationType::BY_LETTER:
-                    sType = "lt";
-                break;
-                case TextAnimationType::BY_WORD:
-                default:
-                    sType = "wd";
-                break;
-
-            }
-            pFS->startElementNS(XML_p, XML_iterate, XML_type, sType, FSEND);
-            pFS->singleElementNS(XML_p, XML_tmAbs, XML_val, I32S(xIterate->getIterateInterval() * 1000), FSEND);
-            pFS->endElementNS(XML_p, XML_iterate);
-        }
-    }
-
-    Reference< XEnumerationAccess > xEnumerationAccess(rXNode, UNO_QUERY);
-    if (xEnumerationAccess.is())
-    {
-        Reference< XEnumeration > xEnumeration(xEnumerationAccess->createEnumeration(), UNO_QUERY);
-        if (xEnumeration.is())
-        {
-            SAL_INFO("sd.eppt", "-----");
-
-            if (xEnumeration->hasMoreElements())
-            {
-                pFS->startElementNS(XML_p, XML_childTnLst, FSEND);
-
-                do
-                {
-                    Reference< XAnimationNode > xChildNode(xEnumeration->nextElement(), UNO_QUERY);
-                    if (xChildNode.is())
-                        WriteAnimationNode(pFS, xChildNode, nType == EffectNodeType::MAIN_SEQUENCE);
-                }
-                while (xEnumeration->hasMoreElements());
-
-                pFS->endElementNS(XML_p, XML_childTnLst);
-            }
-            SAL_INFO("sd.eppt", "-----");
-        }
-    }
-
-    if (bSingle)
-        pFS->endElementNS(XML_p, XML_cTn);
-}
-
-void PowerPointExport::WriteAnimationNodeSeq(const FSHelperPtr& pFS, const Reference< XAnimationNode >& rXNode, sal_Int32, bool bMainSeqChild)
-{
-    SAL_INFO("sd.eppt", "write animation node SEQ");
-
-    pFS->startElementNS(XML_p, XML_seq, FSEND);
-
-    WriteAnimationNodeCommonPropsStart(pFS, rXNode, true, bMainSeqChild);
-
-    WriteAnimationCondition(pFS, nullptr, "onPrev", 0, true, XML_prevCondLst);
-    WriteAnimationCondition(pFS, nullptr, "onNext", 0, true, XML_nextCondLst);
-
-    pFS->endElementNS(XML_p, XML_seq);
-}
-
-void PowerPointExport::WriteAnimationNodeEffect(const FSHelperPtr& pFS, const Reference< XAnimationNode >& rXNode, sal_Int32, bool bMainSeqChild)
-{
-    SAL_INFO("sd.eppt", "write animation node FILTER");
-    Reference< XTransitionFilter > xFilter(rXNode, UNO_QUERY);
-    if (xFilter.is())
-    {
-        const char* pFilter = ::ppt::AnimationExporter::FindTransitionName(xFilter->getTransition(), xFilter->getSubtype(), xFilter->getDirection());
-        const char* pMode = xFilter->getMode() ? "in" : "out";
-        pFS->startElementNS(XML_p, XML_animEffect,
-                            XML_filter, pFilter,
-                            XML_transition, pMode,
-                            FSEND);
-
-        WriteAnimationNodeAnimateInside(pFS, rXNode, bMainSeqChild, false);
-
-        pFS->endElementNS(XML_p, XML_animEffect);
-    }
-}
-
-void PowerPointExport::WriteAnimationNodeCommand(const FSHelperPtr& pFS, const Reference< XAnimationNode >& rXNode, sal_Int32, bool bMainSeqChild)
-{
-    SAL_INFO("sd.eppt", "write animation node COMMAND");
-    Reference<XCommand> xCommand(rXNode, UNO_QUERY);
-    if (xCommand.is())
-    {
-        const char* pType = "call";
-        const char* pCommand = nullptr;
-        switch (xCommand->getCommand())
-        {
-        case EffectCommands::VERB:        pType = "verb"; pCommand = "1"; /* FIXME hardcoded viewing */ break;
-        case EffectCommands::PLAY:        pCommand = "play"; break;
-        case EffectCommands::TOGGLEPAUSE: pCommand = "togglePause"; break;
-        case EffectCommands::STOP:        pCommand = "stop"; break;
-        default:
-            SAL_WARN("sd.eppt", "unknown command: " << xCommand->getCommand());
-            break;
-        }
-
-        pFS->startElementNS(XML_p, XML_cmd,
-                            XML_type, pType,
-                            XML_cmd, pCommand,
-                            FSEND);
-
-        WriteAnimationNodeAnimateInside(pFS, rXNode, bMainSeqChild, false);
-        pFS->startElementNS(XML_p, XML_cBhvr,
-                            FSEND);
-        WriteAnimationNodeCommonPropsStart(pFS, rXNode, true, bMainSeqChild);
-        WriteAnimationTarget(pFS, xCommand->getTarget());
-        pFS->endElementNS(XML_p, XML_cBhvr);
-
-        pFS->endElementNS(XML_p, XML_cmd);
-    }
-}
-
-void PowerPointExport::WriteAnimationNode(const FSHelperPtr& pFS, const Reference< XAnimationNode >& rXNode, bool bMainSeqChild)
-{
-    SAL_INFO("sd.eppt", "export node type: " << rXNode->getType());
-    sal_Int32 xmlNodeType = -1;
-    typedef void (PowerPointExport::*AnimationNodeWriteMethod)(const FSHelperPtr&, const Reference< XAnimationNode >&, sal_Int32, bool);
-    AnimationNodeWriteMethod pMethod = nullptr;
-
-    switch (rXNode->getType())
-    {
-    case AnimationNodeType::ITERATE:
-    case AnimationNodeType::PAR:
-        xmlNodeType = XML_par;
-        break;
-    case AnimationNodeType::SEQ:
-        pMethod = &PowerPointExport::WriteAnimationNodeSeq;
-        break;
-    case AnimationNodeType::ANIMATE:
-        xmlNodeType = XML_anim;
-        pMethod = &PowerPointExport::WriteAnimationNodeAnimate;
-        break;
-    case AnimationNodeType::ANIMATEMOTION:
-        xmlNodeType = XML_animMotion;
-        pMethod = &PowerPointExport::WriteAnimationNodeAnimate;
-        break;
-    case AnimationNodeType::ANIMATETRANSFORM:
-        {
-            Reference<XAnimateTransform> xTransform(rXNode, UNO_QUERY);
-            if (xTransform.is())
-            {
-                if (xTransform->getTransformType() == AnimationTransformType::SCALE)
-                {
-                    xmlNodeType = XML_animScale;
-                    pMethod = &PowerPointExport::WriteAnimationNodeAnimate;
-                }
-                else if (xTransform->getTransformType() == AnimationTransformType::ROTATE)
-                {
-                    xmlNodeType = XML_animRot;
-                    pMethod = &PowerPointExport::WriteAnimationNodeAnimate;
-                }
-            }
-        }
-        break;
-    case AnimationNodeType::ANIMATECOLOR:
-        xmlNodeType = XML_animClr;
-        pMethod = &PowerPointExport::WriteAnimationNodeAnimate;
-        break;
-    case AnimationNodeType::SET:
-        xmlNodeType = XML_set;
-        pMethod = &PowerPointExport::WriteAnimationNodeAnimate;
-        break;
-    case AnimationNodeType::TRANSITIONFILTER:
-        xmlNodeType = XML_animEffect;
-        pMethod = &PowerPointExport::WriteAnimationNodeEffect;
-        break;
-    case AnimationNodeType::COMMAND:
-        xmlNodeType = XML_cmd;
-        pMethod = &PowerPointExport::WriteAnimationNodeCommand;
-        break;
-    default:
-        SAL_WARN("sd.eppt", "unhandled animation node: " << rXNode->getType());
-        break;
-    }
-
-    if (pMethod)
-    {
-        (this->*pMethod)(pFS, rXNode, xmlNodeType, bMainSeqChild);
-        return;
-    }
-
-    if (xmlNodeType == -1)
-        return;
-
-    pFS->startElementNS(XML_p, xmlNodeType, FSEND);
-
-    WriteAnimationNodeCommonPropsStart(pFS, rXNode, true, bMainSeqChild);
-
-    pFS->endElementNS(XML_p, xmlNodeType);
-}
-
-void PowerPointExport::WriteAnimations(const FSHelperPtr& pFS)
-{
-    Reference< XAnimationNodeSupplier > xNodeSupplier(mXDrawPage, UNO_QUERY);
-    if (xNodeSupplier.is())
-    {
-        const Reference< XAnimationNode > xNode(xNodeSupplier->getAnimationNode());
-        if (xNode.is())
-        {
-            Reference< XEnumerationAccess > xEnumerationAccess(xNode, UNO_QUERY);
-            if (xEnumerationAccess.is())
-            {
-                Reference< XEnumeration > xEnumeration(xEnumerationAccess->createEnumeration(), UNO_QUERY);
-                if (xEnumeration.is() && xEnumeration->hasMoreElements())
-                {
-
-                    pFS->startElementNS(XML_p, XML_timing, FSEND);
-                    pFS->startElementNS(XML_p, XML_tnLst, FSEND);
-
-                    WriteAnimationNode(pFS, xNode, false);
-
-                    pFS->endElementNS(XML_p, XML_tnLst);
-                    pFS->endElementNS(XML_p, XML_timing);
-                }
-            }
-        }
-    }
-}
-
 static OUString lcl_GetInitials(const OUString& sName)
 {
     OUStringBuffer sRet;


More information about the Libreoffice-commits mailing list