sd/Library_sd.mk | 1 sd/source/ui/unoidl/unomodel.cxx | 768 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 716 insertions(+), 53 deletions(-)
New commits: commit 2ffea94540f6ba6702ad2a07926bfd24a56afa20 Author: Marco Cecchetti <marco.cecche...@collabora.com> AuthorDate: Fri Jul 19 23:24:53 2024 +0200 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Mon Jul 22 16:20:59 2024 +0200 lok: sd: slideshow: provide animations info This patch is an initial effort for collecting animations information and make them available in json format. Change-Id: I00470ea3b56c215c591f7e1e56227b63cf3be014 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170785 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> diff --git a/sd/Library_sd.mk b/sd/Library_sd.mk index e6eb7c82540c..7f526c33a061 100644 --- a/sd/Library_sd.mk +++ b/sd/Library_sd.mk @@ -86,6 +86,7 @@ $(eval $(call gb_Library_use_libraries,sd,\ sal \ salhelper \ sax \ + xo \ sb \ sfx \ sot \ diff --git a/sd/source/ui/unoidl/unomodel.cxx b/sd/source/ui/unoidl/unomodel.cxx index 47b5f6a97cb4..234aabd72cde 100644 --- a/sd/source/ui/unoidl/unomodel.cxx +++ b/sd/source/ui/unoidl/unomodel.cxx @@ -30,8 +30,22 @@ #include <com/sun/star/document/IndexedPropertyValues.hpp> #include <com/sun/star/beans/PropertyAttribute.hpp> #include <com/sun/star/util/XTheme.hpp> +#include <com/sun/star/animations/AnimationNodeType.hpp> +#include <com/sun/star/animations/AnimationTransformType.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/XAnimate.hpp> +#include <com/sun/star/animations/XAnimateMotion.hpp> +#include <com/sun/star/animations/XAnimateTransform.hpp> +#include <com/sun/star/animations/XTimeContainer.hpp> +#include <com/sun/star/animations/XTransitionFilter.hpp> +#include <com/sun/star/presentation/EffectNodeType.hpp> +#include <com/sun/star/presentation/ParagraphTarget.hpp> + #include <com/sun/star/embed/Aspects.hpp> @@ -60,6 +74,7 @@ #include <editeng/UnoForbiddenCharsTable.hxx> #include <svx/svdoutl.hxx> +#include <o3tl/any.hxx> #include <o3tl/safeint.hxx> #include <o3tl/string_view.hxx> #include <o3tl/unit_conversion.hxx> @@ -82,7 +97,10 @@ #include <editeng/unonrule.hxx> #include <editeng/eeitem.hxx> #include <unotools/datetime.hxx> +#include <sax/tools/converter.hxx> #include <xmloff/autolayout.hxx> +#include <xmloff/xmltoken.hxx> +#include <rtl/math.hxx> #include <tools/helpers.hxx> #include <tools/json_writer.hxx> #include <tools/helpers.hxx> @@ -313,6 +331,696 @@ bool SlideBackgroundInfo::getFillStyleImpl(const uno::Reference<drawing::XDrawPa return false; } +using namespace ::css::animations; +using namespace ::css::beans; +using namespace ::css::container; +using namespace ::css::uno; +using namespace ::xmloff::token; +using namespace ::css::presentation; + +template <typename T, std::size_t N> +constexpr auto mapEnumToString(std::pair<T, std::string_view> const (&items)[N]) +{ + return frozen::make_unordered_map<T, std::string_view, N>(items); +} + +constexpr auto constTransitionTypeToString = mapEnumToString<sal_Int16>({ + { animations::TransitionType::BARWIPE, "BarWipe" }, // Wipe + { animations::TransitionType::PINWHEELWIPE, "PineWheelWipe" }, // Wheel + { animations::TransitionType::SLIDEWIPE, "SlideWipe" }, // Cover, Uncover + { animations::TransitionType::RANDOMBARWIPE, "RandomBarWipe" }, // Bars + { animations::TransitionType::CHECKERBOARDWIPE, "CheckerBoardWipe" }, // Checkers + { animations::TransitionType::FOURBOXWIPE, "FourBoxWipe" }, // Shape + { animations::TransitionType::IRISWIPE, "IrisWipe" }, // Box + { animations::TransitionType::FANWIPE, "FanWipe" }, // Wedge + { animations::TransitionType::BLINDSWIPE, "BlindWipe"}, // Venetian + { animations::TransitionType::FADE, "Fade"}, + { animations::TransitionType::DISSOLVE, "Dissolve"}, + { animations::TransitionType::PUSHWIPE, "PushWipe"}, // Comb + { animations::TransitionType::ELLIPSEWIPE, "EllipseWipe"}, // Shape + { animations::TransitionType::BARNDOORWIPE, "BarnDoorWipe"}, // Split + { animations::TransitionType::WATERFALLWIPE, "WaterfallWipe"}, // Diagonal +}); + +constexpr auto constTransitionSubTypeToString = mapEnumToString<sal_Int16>({ + { animations::TransitionSubType::LEFTTORIGHT, "LeftToRight" }, + { animations::TransitionSubType::TOPTOBOTTOM, "TopToBottom" }, + { animations::TransitionSubType::EIGHTBLADE, "8Blade" }, + { animations::TransitionSubType::FOURBLADE, "4Blade" }, + { animations::TransitionSubType::THREEBLADE, "3Blade" }, + { animations::TransitionSubType::TWOBLADEVERTICAL, "2BladeVertical" }, + { animations::TransitionSubType::ONEBLADE, "1Blade" }, + { animations::TransitionSubType::FROMTOPLEFT, "FromTopLeft" }, + { animations::TransitionSubType::FROMTOPRIGHT, "FromTopRight"}, + { animations::TransitionSubType::FROMBOTTOMLEFT, "FromBottomLeft"}, + { animations::TransitionSubType::FROMBOTTOMRIGHT, "FromBottomRight"}, + { animations::TransitionSubType::VERTICAL, "Vertical"}, + { animations::TransitionSubType::HORIZONTAL, "Horizontal"}, + { animations::TransitionSubType::DOWN, "Down"}, + { animations::TransitionSubType::ACROSS, "Across"}, + { animations::TransitionSubType::CORNERSOUT, "CornersOut"}, + { animations::TransitionSubType::DIAMOND, "Diamond"}, + { animations::TransitionSubType::CIRCLE, "Circle"}, + { animations::TransitionSubType::RECTANGLE, "Rectangle"}, + { animations::TransitionSubType::CENTERTOP, "CenterTop"}, + { animations::TransitionSubType::CROSSFADE, "CrossFade"}, + { animations::TransitionSubType::FADEOVERCOLOR, "FadeOverColor"}, + { animations::TransitionSubType::FROMLEFT, "FromLeft"}, + { animations::TransitionSubType::FROMRIGHT, "FromRight"}, + { animations::TransitionSubType::FROMTOP, "FromTop"}, + { animations::TransitionSubType::HORIZONTALLEFT, "HorizontalLeft"}, + { animations::TransitionSubType::HORIZONTALRIGHT, "HorizontalRight"}, +}); + +constexpr auto constAnimationNodeTypeToString = mapEnumToString<sal_Int16>({ + { AnimationNodeType::ANIMATE, "Animate" }, + { AnimationNodeType::ANIMATECOLOR, "AnimateColor" }, + { AnimationNodeType::ANIMATEMOTION, "Animate" }, + { AnimationNodeType::ANIMATEPHYSICS, "Animate" }, + { AnimationNodeType::ANIMATETRANSFORM, "Animate" }, + { AnimationNodeType::AUDIO, "Audio" }, + { AnimationNodeType::COMMAND, "Command" }, + { AnimationNodeType::CUSTOM, "Custom" }, + { AnimationNodeType::ITERATE, "Iterate" }, + { AnimationNodeType::PAR, "Par" }, + { AnimationNodeType::SEQ, "Seq" }, + { AnimationNodeType::SET, "Set" }, + { AnimationNodeType::TRANSITIONFILTER, "TransitionFilter" }, +}); + +constexpr auto constEffectNodeTypeToString = mapEnumToString<sal_Int16>({ + { EffectNodeType::DEFAULT, "Default" }, + { EffectNodeType::ON_CLICK, "OnClick" }, + { EffectNodeType::WITH_PREVIOUS, "WithPrevious" }, + { EffectNodeType::AFTER_PREVIOUS, "AfterPrevious" }, + { EffectNodeType::MAIN_SEQUENCE, "MainSequence" }, + { EffectNodeType::TIMING_ROOT, "TimingRoot" }, + { EffectNodeType::INTERACTIVE_SEQUENCE, "InteractiveSequence" }, +}); + +constexpr auto constEventTriggerToString = mapEnumToString<sal_Int16>({ + { EventTrigger::BEGIN_EVENT, "BeginEvent" }, + { EventTrigger::END_EVENT, "EndEvent" }, + { EventTrigger::NONE, "None" }, + { EventTrigger::ON_BEGIN, "OnBegin" }, + { EventTrigger::ON_CLICK, "OnClick" }, + { EventTrigger::ON_DBL_CLICK, "OnDblClick" }, + { EventTrigger::ON_END, "OnEnd" }, + { EventTrigger::ON_MOUSE_ENTER, "OnMouseEnter" }, + { EventTrigger::ON_MOUSE_LEAVE, "OnMouseLeave" }, + { EventTrigger::ON_NEXT, "OnNext" }, + { EventTrigger::ON_PREV, "OnPrev" }, + { EventTrigger::ON_STOP_AUDIO, "OnStopAudio" }, + { EventTrigger::REPEAT, "Repeat" }, +}); + +constexpr auto constTimingToString = mapEnumToString<Timing>({ + { Timing_INDEFINITE, "Indefinite" }, + { Timing_MEDIA, "Media" }, +}); + +constexpr auto constTransformTypeToString = mapEnumToString<sal_Int16>({ + { AnimationTransformType::TRANSLATE, "Translate" }, + { AnimationTransformType::SCALE, "Scale" }, + { AnimationTransformType::ROTATE, "Rotate" }, + { AnimationTransformType::SKEWX, "SkewX" }, + { AnimationTransformType::SKEWY, "SkewY" }, +}); + +constexpr auto constAttributeNameToXMLEnum + = frozen::make_unordered_map<std::string_view, XMLTokenEnum>({ + { "X", XML_X }, + { "Y", XML_Y }, + { "Width", XML_WIDTH }, + { "Height", XML_HEIGHT }, + { "Rotate", XML_ROTATE }, + { "SkewX", XML_SKEWX }, + { "Visibility", XML_VISIBILITY }, + { "Opacity", XML_OPACITY }, + }); + +inline OString convertXMLEnumToString(XMLTokenEnum eToken) +{ + if (eToken == XML_NODE_TYPE) + return "nodeType"_ostr; + + const OUString& rAttrName = GetXMLToken(eToken); + return rAttrName.toUtf8(); +} + +class AnimationsExporter +{ +public: + AnimationsExporter(::tools::JsonWriter& rWriter, + const Reference<drawing::XDrawPage>& xDrawPage); + void exportAnimations(); + [[nodiscard]] bool hasEffects() const { return mbHasEffects; } + +private: + void exportNode(const Reference<XAnimationNode>& xNode); + void exportContainer(const Reference<XTimeContainer>& xContainer); + + void exportAnimate(const Reference<XAnimate>& xAnimate); + + void convertValue(XMLTokenEnum eAttributeName, OStringBuffer& sTmp, const Any& rValue) const; + static void convertTarget(OStringBuffer& sTmp, const Any& rTarget); + void convertTiming(OStringBuffer& sTmp, const Any& rValue) const; + +private: + ::tools::JsonWriter& mrWriter; + Reference<drawing::XDrawPage> mxDrawPage; + Reference<XPropertySet> mxPageProps; + Reference<XAnimationNode> mxRootNode; + bool mbHasEffects; +}; + +AnimationsExporter::AnimationsExporter(::tools::JsonWriter& rWriter, + const Reference<drawing::XDrawPage>& xDrawPage) + : mrWriter(rWriter) + , mxDrawPage(xDrawPage) + , mbHasEffects(false) +{ + if (!mxDrawPage.is()) + return; + + try + { + mxPageProps = Reference<XPropertySet>(xDrawPage, UNO_QUERY); + if (!mxPageProps.is()) + return; + + Reference<XAnimationNodeSupplier> xAnimNodeSupplier(mxDrawPage, UNO_QUERY); + if (!xAnimNodeSupplier.is()) + return; + + Reference<XAnimationNode> xRootNode = xAnimNodeSupplier->getAnimationNode(); + if (xRootNode.is()) + { + // first check if there are no animations + Reference<XEnumerationAccess> xEnumerationAccess(xRootNode, UNO_QUERY_THROW); + Reference<XEnumeration> xEnumeration(xEnumerationAccess->createEnumeration(), + css::uno::UNO_SET_THROW); + if (xEnumeration->hasMoreElements()) + { + // first child node may be an empty main sequence, check this + Reference<XAnimationNode> xMainNode(xEnumeration->nextElement(), UNO_QUERY_THROW); + Reference<XEnumerationAccess> xMainEnumerationAccess(xMainNode, UNO_QUERY_THROW); + Reference<XEnumeration> xMainEnumeration( + xMainEnumerationAccess->createEnumeration(), css::uno::UNO_SET_THROW); + + // only export if the main sequence is not empty or if there are additional + // trigger sequences + mbHasEffects + = xMainEnumeration->hasMoreElements() || xEnumeration->hasMoreElements(); + } + } + if (mbHasEffects) + mxRootNode = xRootNode; + } + catch (const RuntimeException&) + { + TOOLS_WARN_EXCEPTION("sd", "unomodel: AnimationsExporter"); + } +} + +template <typename EnumT, size_t N> +constexpr bool convertEnum(OStringBuffer& rBuffer, EnumT nValue, + const frozen::unordered_map<EnumT, std::string_view, N>& rMap) +{ + auto iterator = rMap.find(nValue); + if (iterator == constAnimationNodeTypeToString.end()) + return false; + rBuffer.append(iterator->second); + return true; +} + +void convertDouble(OStringBuffer& rBuffer, const Any& rValue) +{ + double fValue = 0; + if (rValue >>= fValue) + { + ::rtl::math::doubleToStringBuffer(rBuffer, fValue, rtl_math_StringFormat_Automatic, + rtl_math_DecimalPlaces_Max, '.', true); + } +} +void convertPath(OStringBuffer& sTmp, const Any& rPath) +{ + OUString aStr; + rPath >>= aStr; + sTmp = aStr.toUtf8(); +} + +void convertColor(OStringBuffer& rBuffer, sal_Int32 nColor) +{ + OUStringBuffer aUBuffer; + ::sax::Converter::convertColor(aUBuffer, nColor); + rBuffer.append(aUBuffer.makeStringAndClear().toUtf8()); +} + +void AnimationsExporter::exportAnimations() +{ + if (!mxDrawPage.is() || !mxPageProps.is() || !mxRootNode.is() || !hasEffects()) + return; + + exportNode(mxRootNode); +} + +void AnimationsExporter::exportNode(const Reference<XAnimationNode>& xNode) +{ + try + { + sal_Int16 nNodeType = xNode->getType(); + auto iterator = constAnimationNodeTypeToString.find(nNodeType); + if (iterator == constAnimationNodeTypeToString.end()) + return; + + ::tools::ScopedJsonWriterNode aNode = mrWriter.startNode(iterator->second); + + // common properties + OStringBuffer sTmp; + Any aTemp; + double fTemp = 0; + + aTemp = xNode->getBegin(); + if (aTemp.hasValue()) + { + convertTiming(sTmp, aTemp); + mrWriter.put(convertXMLEnumToString(XML_BEGIN), sTmp.makeStringAndClear()); + } + aTemp = xNode->getDuration(); + if (aTemp.hasValue()) + { + if (aTemp >>= fTemp) + { + convertDouble(sTmp, aTemp); + sTmp.append('s'); + mrWriter.put(convertXMLEnumToString(XML_DUR), sTmp.makeStringAndClear()); + } + else + { + Timing eTiming; + if (aTemp >>= eTiming) + { + mrWriter.put(convertXMLEnumToString(XML_DUR), + convertXMLEnumToString( + eTiming == Timing_INDEFINITE ? XML_INDEFINITE : XML_MEDIA)); + } + } + } + aTemp = xNode->getEnd(); + if (aTemp.hasValue()) + { + convertTiming(sTmp, aTemp); + mrWriter.put(convertXMLEnumToString(XML_END), sTmp.makeStringAndClear()); + } + + sal_Int16 nContainerNodeType = EffectNodeType::DEFAULT; + const Sequence<NamedValue> aUserData(xNode->getUserData()); + for (const auto& rValue : aUserData) + { + if (IsXMLToken(rValue.Name, XML_NODE_TYPE)) + { + if ((rValue.Value >>= nContainerNodeType) + && (nContainerNodeType != EffectNodeType::DEFAULT)) + { + convertEnum(sTmp, nContainerNodeType, constEffectNodeTypeToString); + mrWriter.put(convertXMLEnumToString(XML_NODE_TYPE), sTmp.makeStringAndClear()); + } + } + } + + switch (nNodeType) + { + case AnimationNodeType::PAR: + case AnimationNodeType::SEQ: + case AnimationNodeType::ITERATE: + { + Reference<XTimeContainer> xContainer(xNode, UNO_QUERY_THROW); + exportContainer(xContainer); + } + break; + + case AnimationNodeType::ANIMATE: + case AnimationNodeType::SET: + case AnimationNodeType::ANIMATEMOTION: + case AnimationNodeType::ANIMATEPHYSICS: + case AnimationNodeType::ANIMATECOLOR: + case AnimationNodeType::ANIMATETRANSFORM: + case AnimationNodeType::TRANSITIONFILTER: + { + Reference<XAnimate> xAnimate(xNode, UNO_QUERY_THROW); + exportAnimate(xAnimate); + } + break; + default: + { + OSL_FAIL( + "sd unomodel: AnimationsExporter::exportNode(), invalid AnimationNodeType!"); + } + } + } + catch (const RuntimeException&) + { + TOOLS_WARN_EXCEPTION("sd", "unomodel: AnimationsExporter"); + } +} + +void AnimationsExporter::convertTarget(OStringBuffer& sTmp, const Any& rTarget) +{ + if (!rTarget.hasValue()) + return; + + Reference<XInterface> xRef; + rTarget >>= xRef; + + SAL_WARN_IF(!xRef.is(), "sd", "AnimationsExporter::convertTarget(), invalid target type!"); + if (xRef.is()) + { + const std::string& rIdentifier(GetInterfaceHash(xRef)); + if (!rIdentifier.empty()) + sTmp.append(rIdentifier); + } +} + +void AnimationsExporter::convertTiming(OStringBuffer& sTmp, const Any& rValue) const +{ + if (!rValue.hasValue()) + return; + + if (auto pSequence = o3tl::tryAccess<Sequence<Any>>(rValue)) + { + const sal_Int32 nLength = pSequence->getLength(); + sal_Int32 nElement; + const Any* pAny = pSequence->getConstArray(); + + OStringBuffer sTmp2; + + for (nElement = 0; nElement < nLength; nElement++, pAny++) + { + if (!sTmp.isEmpty()) + sTmp.append(';'); + convertTiming(sTmp2, *pAny); + sTmp.append(sTmp2); + sTmp2.setLength(0); + } + } + else if (auto x = o3tl::tryAccess<double>(rValue)) + { + sTmp.append(*x); + sTmp.append('s'); + } + else if (auto pTiming = o3tl::tryAccess<Timing>(rValue)) + { + const auto svTiming = (*pTiming == Timing_MEDIA) + ? constTimingToString.at(Timing_MEDIA) + : constTimingToString.at(Timing_INDEFINITE); + sTmp.append(svTiming); + } + else if (auto pEvent = o3tl::tryAccess<Event>(rValue)) + { + OStringBuffer sTmp2; + + if (pEvent->Trigger != EventTrigger::NONE) + { + if (pEvent->Source.hasValue()) + { + convertTarget(sTmp, pEvent->Source); + sTmp.append('.'); + } + + convertEnum(sTmp2, pEvent->Trigger, constEventTriggerToString); + + sTmp.append(sTmp2); + sTmp2.setLength(0); + } + + if (pEvent->Offset.hasValue()) + { + convertTiming(sTmp2, pEvent->Offset); + + if (!sTmp.isEmpty()) + sTmp.append('+'); + + sTmp.append(sTmp2); + sTmp2.setLength(0); + } + } + else + { + OSL_FAIL("sd.unomodel: AnimationsExporter::convertTiming, invalid value type!"); + } +} + +void AnimationsExporter::convertValue(XMLTokenEnum eAttributeName, OStringBuffer& sTmp, + const Any& rValue) const +{ + if (!rValue.hasValue()) + return; + + if (auto pValuePair = o3tl::tryAccess<ValuePair>(rValue)) + { + OStringBuffer sTmp2; + convertValue(eAttributeName, sTmp, pValuePair->First); + sTmp.append(','); + convertValue(eAttributeName, sTmp2, pValuePair->Second); + sTmp.append(sTmp2); + } + else if (auto pSequence = o3tl::tryAccess<Sequence<Any>>(rValue)) + { + const sal_Int32 nLength = pSequence->getLength(); + sal_Int32 nElement; + const Any* pAny = pSequence->getConstArray(); + + OStringBuffer sTmp2; + + for (nElement = 0; nElement < nLength; nElement++, pAny++) + { + if (!sTmp.isEmpty()) + sTmp.append(';'); + convertValue(eAttributeName, sTmp2, *pAny); + sTmp.append(sTmp2); + sTmp2.setLength(0); + } + } + else + { + switch (eAttributeName) + { + case XML_X: + case XML_Y: + case XML_WIDTH: + case XML_HEIGHT: + case XML_ANIMATETRANSFORM: + case XML_ANIMATEMOTION: + case XML_ANIMATEPHYSICS: + { + if (auto sValue = o3tl::tryAccess<OUString>(rValue)) + { + sTmp.append(sValue->toUtf8()); + } + else if (auto aValue = o3tl::tryAccess<double>(rValue)) + { + sTmp.append(*aValue); + } + else + { + OSL_FAIL("sd::AnimationsExporter::convertValue(), invalid value type!"); + } + return; + } + case XML_SKEWX: + case XML_ROTATE: + case XML_OPACITY: + case XML_TRANSITIONFILTER: + if (auto aValue = o3tl::tryAccess<double>(rValue)) + { + sTmp.append(*aValue); + } + break; + case XML_VISIBILITY: + if (auto aValue = o3tl::tryAccess<bool>(rValue)) + { + OUString sValue = *aValue ? GetXMLToken(XML_VISIBLE) : GetXMLToken(XML_HIDDEN); + sTmp.append(sValue.toUtf8()); + } + break; + default: + OSL_FAIL("xmloff::AnimationsExporterImpl::convertValue(), invalid AttributeName!"); + } + } +} + +void AnimationsExporter::exportContainer(const Reference<XTimeContainer>& xContainer) +{ + try + { + Reference<XEnumerationAccess> xEnumerationAccess(xContainer, UNO_QUERY_THROW); + Reference<XEnumeration> xEnumeration(xEnumerationAccess->createEnumeration(), + css::uno::UNO_SET_THROW); + while (xEnumeration->hasMoreElements()) + { + Reference<XAnimationNode> xChildNode(xEnumeration->nextElement(), UNO_QUERY_THROW); + exportNode(xChildNode); + } + } + catch (const RuntimeException&) + { + TOOLS_WARN_EXCEPTION("sd", "unomodel: AnimationsExporter"); + } +} + +void AnimationsExporter::exportAnimate(const Reference<XAnimate>& xAnimate) +{ + try + { + const sal_Int16 nNodeType = xAnimate->getType(); + + OStringBuffer sTmp; + sal_Int16 nTemp; + bool bTemp; + + Any aTemp(xAnimate->getTarget()); + if (aTemp.hasValue()) + { + convertTarget(sTmp, aTemp); + mrWriter.put(convertXMLEnumToString(XML_TARGETELEMENT), sTmp.makeStringAndClear()); + } + + XMLTokenEnum eAttributeName = XML_TOKEN_INVALID; + if (nNodeType == AnimationNodeType::TRANSITIONFILTER) + { + eAttributeName = XML_TRANSITIONFILTER; + } + else if (nNodeType == AnimationNodeType::ANIMATETRANSFORM) + { + eAttributeName = XML_ANIMATETRANSFORM; + } + else if (nNodeType == AnimationNodeType::ANIMATEMOTION) + { + eAttributeName = XML_ANIMATEMOTION; + } + else if (nNodeType == AnimationNodeType::ANIMATEPHYSICS) + { + eAttributeName = XML_ANIMATEPHYSICS; + } + else + { + OString sTemp(xAnimate->getAttributeName().toUtf8()); + if (!sTemp.isEmpty()) + { + auto iterator = constAttributeNameToXMLEnum.find(sTemp); + if (iterator != constAttributeNameToXMLEnum.end()) + { + eAttributeName = iterator->second; + mrWriter.put(convertXMLEnumToString(XML_ATTRIBUTENAME), sTemp); + } + } + } + + Sequence<Any> aValues(xAnimate->getValues()); + if (aValues.hasElements()) + { + aTemp <<= aValues; + convertValue(eAttributeName, sTmp, aTemp); + mrWriter.put(convertXMLEnumToString(XML_VALUES), sTmp.makeStringAndClear()); + } + else + { + aTemp = xAnimate->getFrom(); + if (aTemp.hasValue()) + { + convertValue(eAttributeName, sTmp, aTemp); + mrWriter.put(convertXMLEnumToString(XML_FROM), sTmp.makeStringAndClear()); + } + + aTemp = xAnimate->getBy(); + if (aTemp.hasValue()) + { + convertValue(eAttributeName, sTmp, aTemp); + mrWriter.put(convertXMLEnumToString(XML_BY), sTmp.makeStringAndClear()); + } + + aTemp = xAnimate->getTo(); + if (aTemp.hasValue()) + { + convertValue(eAttributeName, sTmp, aTemp); + mrWriter.put(convertXMLEnumToString(XML_TO), sTmp.makeStringAndClear()); + } + } + + switch (nNodeType) + { + case AnimationNodeType::ANIMATEMOTION: + { + Reference<XAnimateMotion> xAnimateMotion(xAnimate, UNO_QUERY_THROW); + + aTemp = xAnimateMotion->getPath(); + if (aTemp.hasValue()) + { + convertPath(sTmp, aTemp); + mrWriter.put(convertXMLEnumToString(XML_PATH), sTmp.makeStringAndClear()); + } + } + break; + case AnimationNodeType::ANIMATETRANSFORM: + { + mrWriter.put(convertXMLEnumToString(XML_ATTRIBUTENAME), + convertXMLEnumToString(XML_TRANSFORM)); + + Reference<XAnimateTransform> xTransform(xAnimate, UNO_QUERY_THROW); + nTemp = xTransform->getTransformType(); + convertEnum(sTmp, nTemp, constTransformTypeToString); + mrWriter.put(convertXMLEnumToString(XML_TYPE), sTmp.makeStringAndClear()); + } + break; + case AnimationNodeType::TRANSITIONFILTER: + { + Reference<XTransitionFilter> xTransitionFilter(xAnimate, UNO_QUERY); + + sal_Int16 nTransition = xTransitionFilter->getTransition(); + convertEnum(sTmp, nTransition, constTransitionTypeToString); + mrWriter.put(convertXMLEnumToString(XML_TYPE), sTmp.makeStringAndClear()); + + sal_Int16 nSubtype = xTransitionFilter->getSubtype(); + if (nSubtype != TransitionSubType::DEFAULT) + { + convertEnum(sTmp, nSubtype, constTransitionSubTypeToString); + mrWriter.put(convertXMLEnumToString(XML_SUBTYPE), sTmp.makeStringAndClear()); + } + + bTemp = xTransitionFilter->getMode(); + if (!bTemp) + mrWriter.put(convertXMLEnumToString(XML_MODE), convertXMLEnumToString(XML_OUT)); + + bTemp = xTransitionFilter->getDirection(); + if (!bTemp) + mrWriter.put(convertXMLEnumToString(XML_DIRECTION), + convertXMLEnumToString(XML_REVERSE)); + + if ((nTransition == TransitionType::FADE) + && ((nSubtype == TransitionSubType::FADETOCOLOR) + || (nSubtype == TransitionSubType::FADEFROMCOLOR))) + { + nTemp = xTransitionFilter->getFadeColor(); + convertColor(sTmp, nTemp); + mrWriter.put(convertXMLEnumToString(XML_FADECOLOR), sTmp.makeStringAndClear()); + } + } + break; + + default: + { + SAL_WARN("sd", + "unomodel: AnimationsExporter::exportAnimate: node type: " << nNodeType); + } + } + } + catch (const Exception&) + { + TOOLS_WARN_EXCEPTION("sd", "unomodel: AnimationsExporter"); + } +} + } // end anonymous namespace SdUnoForbiddenCharsTable::SdUnoForbiddenCharsTable( SdrModel* pModel ) @@ -3004,59 +3712,6 @@ void SdXImpressDocument::initializeDocument() } } -namespace -{ - -constexpr auto constTransitionTypeToString = frozen::make_unordered_map<sal_Int16, std::string_view>({ - { animations::TransitionType::BARWIPE, "BarWipe" }, // Wipe - { animations::TransitionType::PINWHEELWIPE, "PineWheelWipe" }, // Wheel - { animations::TransitionType::SLIDEWIPE, "SlideWipe" }, // Cover, Uncover - { animations::TransitionType::RANDOMBARWIPE, "RandomBarWipe" }, // Bars - { animations::TransitionType::CHECKERBOARDWIPE, "CheckerBoardWipe" }, // Checkers - { animations::TransitionType::FOURBOXWIPE, "FourBoxWipe" }, // Shape - { animations::TransitionType::IRISWIPE, "IrisWipe" }, // Box - { animations::TransitionType::FANWIPE, "FanWipe" }, // Wedge - { animations::TransitionType::BLINDSWIPE, "BlindWipe"}, // Venetian - { animations::TransitionType::FADE, "Fade"}, - { animations::TransitionType::DISSOLVE, "Dissolve"}, - { animations::TransitionType::PUSHWIPE, "PushWipe"}, // Comb - { animations::TransitionType::ELLIPSEWIPE, "EllipseWipe"}, // Shape - { animations::TransitionType::BARNDOORWIPE, "BarnDoorWipe"}, // Split - { animations::TransitionType::WATERFALLWIPE, "WaterfallWipe"}, // Diagonal -}); - -constexpr auto constTransitionSubTypeToString = frozen::make_unordered_map<sal_Int16, std::string_view>({ - { animations::TransitionSubType::LEFTTORIGHT, "LeftToRight" }, - { animations::TransitionSubType::TOPTOBOTTOM, "TopToBottom" }, - { animations::TransitionSubType::EIGHTBLADE, "8Blade" }, - { animations::TransitionSubType::FOURBLADE, "4Blade" }, - { animations::TransitionSubType::THREEBLADE, "3Blade" }, - { animations::TransitionSubType::TWOBLADEVERTICAL, "2BladeVertical" }, - { animations::TransitionSubType::ONEBLADE, "1Blade" }, - { animations::TransitionSubType::FROMTOPLEFT, "FromTopLeft" }, - { animations::TransitionSubType::FROMTOPRIGHT, "FromTopRight"}, - { animations::TransitionSubType::FROMBOTTOMLEFT, "FromBottomLeft"}, - { animations::TransitionSubType::FROMBOTTOMRIGHT, "FromBottomRight"}, - { animations::TransitionSubType::VERTICAL, "Vertical"}, - { animations::TransitionSubType::HORIZONTAL, "Horizontal"}, - { animations::TransitionSubType::DOWN, "Down"}, - { animations::TransitionSubType::ACROSS, "Across"}, - { animations::TransitionSubType::CORNERSOUT, "CornersOut"}, - { animations::TransitionSubType::DIAMOND, "Diamond"}, - { animations::TransitionSubType::CIRCLE, "Circle"}, - { animations::TransitionSubType::RECTANGLE, "Rectangle"}, - { animations::TransitionSubType::CENTERTOP, "CenterTop"}, - { animations::TransitionSubType::CROSSFADE, "CrossFade"}, - { animations::TransitionSubType::FADEOVERCOLOR, "FadeOverColor"}, - { animations::TransitionSubType::FROMLEFT, "FromLeft"}, - { animations::TransitionSubType::FROMRIGHT, "FromRight"}, - { animations::TransitionSubType::FROMTOP, "FromTop"}, - { animations::TransitionSubType::HORIZONTALLEFT, "HorizontalLeft"}, - { animations::TransitionSubType::HORIZONTALRIGHT, "HorizontalRight"}, -}); - -} - OString SdXImpressDocument::getPresentationInfo() const { ::tools::JsonWriter aJsonWriter; @@ -3204,6 +3859,13 @@ OString SdXImpressDocument::getPresentationInfo() const } } } + + AnimationsExporter aAnimationExporter(aJsonWriter, xSlide); + if (aAnimationExporter.hasEffects()) + { + ::tools::ScopedJsonWriterNode aAnimationsNode = aJsonWriter.startNode("animations"); + aAnimationExporter.exportAnimations(); + } } } }