diff options
Diffstat (limited to 'sd/source/core/EffectMigration.cxx')
-rw-r--r-- | sd/source/core/EffectMigration.cxx | 1439 |
1 files changed, 1439 insertions, 0 deletions
diff --git a/sd/source/core/EffectMigration.cxx b/sd/source/core/EffectMigration.cxx new file mode 100644 index 000000000..8dd9d0905 --- /dev/null +++ b/sd/source/core/EffectMigration.cxx @@ -0,0 +1,1439 @@ +/* -*- 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 <com/sun/star/presentation/EffectNodeType.hpp> +#include <com/sun/star/presentation/ShapeAnimationSubType.hpp> +#include <com/sun/star/presentation/TextAnimationType.hpp> +#include <com/sun/star/presentation/ParagraphTarget.hpp> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/animations/AnimationFill.hpp> +#include <com/sun/star/animations/XAnimate.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <o3tl/string_view.hxx> +#include <tools/debug.hxx> +#include <svx/unoshape.hxx> +#include <svx/svdotext.hxx> +#include <svx/svdopath.hxx> +#include <svx/svdogrp.hxx> +#include <svx/svditer.hxx> +#include <drawdoc.hxx> +#include <sdpage.hxx> +#include <CustomAnimationPreset.hxx> +#include <TransitionPreset.hxx> +#include <EffectMigration.hxx> +#include <anminfo.hxx> + +using namespace ::sd; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::presentation; +using ::com::sun::star::drawing::XShape; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::drawing::XShape; +using ::com::sun::star::beans::NamedValue; + +namespace { + +struct deprecated_FadeEffect_conversion_table_entry +{ + FadeEffect meFadeEffect; + const char* mpPresetId; +}; + +} + +deprecated_FadeEffect_conversion_table_entry const deprecated_FadeEffect_conversion_table[] = +{ +// OOo 1.x transitions + { FadeEffect_FADE_FROM_LEFT, "wipe-right" }, + { FadeEffect_FADE_FROM_TOP, "wipe-down" }, + { FadeEffect_FADE_FROM_RIGHT, "wipe-left" }, + { FadeEffect_FADE_FROM_BOTTOM, "wipe-up" }, + + { FadeEffect_CLOCKWISE, "wheel-clockwise-1-spoke" }, + + { FadeEffect_UNCOVER_TO_LEFT, "uncover-left" }, + { FadeEffect_UNCOVER_TO_UPPERLEFT, "uncover-left-up" }, + { FadeEffect_UNCOVER_TO_TOP, "uncover-up" }, + { FadeEffect_UNCOVER_TO_UPPERRIGHT, "uncover-right-up" }, + { FadeEffect_UNCOVER_TO_RIGHT, "uncover-right" }, + { FadeEffect_UNCOVER_TO_LOWERRIGHT, "uncover-right-down" }, + { FadeEffect_UNCOVER_TO_BOTTOM, "uncover-down" }, + { FadeEffect_UNCOVER_TO_LOWERLEFT, "uncover-left-down" }, + + { FadeEffect_VERTICAL_LINES, "random-bars-vertical" }, + { FadeEffect_HORIZONTAL_LINES, "random-bars-horizontal" }, + + { FadeEffect_VERTICAL_CHECKERBOARD, "checkerboard-down" }, + { FadeEffect_HORIZONTAL_CHECKERBOARD, "checkerboard-across" }, + + { FadeEffect_FADE_TO_CENTER, "box-in" }, + { FadeEffect_FADE_FROM_CENTER, "box-out" }, + + { FadeEffect_VERTICAL_STRIPES, "venetian-blinds-vertical" }, + { FadeEffect_HORIZONTAL_STRIPES, "venetian-blinds-horizontal" }, + + { FadeEffect_MOVE_FROM_LEFT, "cover-right" }, + { FadeEffect_MOVE_FROM_TOP, "cover-down" }, + { FadeEffect_MOVE_FROM_RIGHT, "cover-left" }, + { FadeEffect_MOVE_FROM_BOTTOM, "cover-up" }, + { FadeEffect_MOVE_FROM_UPPERLEFT, "cover-right-down" }, + { FadeEffect_MOVE_FROM_UPPERRIGHT, "cover-left-down" }, + { FadeEffect_MOVE_FROM_LOWERRIGHT, "cover-left-up" }, + { FadeEffect_MOVE_FROM_LOWERLEFT, "cover-right-up" }, + + { FadeEffect_DISSOLVE, "dissolve" }, + + { FadeEffect_RANDOM, "random-transition" }, + + { FadeEffect_ROLL_FROM_LEFT, "push-right" }, + { FadeEffect_ROLL_FROM_TOP, "push-down" }, + { FadeEffect_ROLL_FROM_RIGHT, "push-left" }, + { FadeEffect_ROLL_FROM_BOTTOM, "push-up" }, + + { FadeEffect_CLOSE_VERTICAL, "split-horizontal-in" }, + { FadeEffect_CLOSE_HORIZONTAL, "split-vertical-in" }, + { FadeEffect_OPEN_VERTICAL, "split-horizontal-out" }, + { FadeEffect_OPEN_HORIZONTAL, "split-vertical-out" }, + + { FadeEffect_FADE_FROM_UPPERLEFT, "diagonal-squares-right-down" }, + { FadeEffect_FADE_FROM_UPPERRIGHT, "diagonal-squares-left-down" }, + { FadeEffect_FADE_FROM_LOWERLEFT, "diagonal-squares-right-up" }, + { FadeEffect_FADE_FROM_LOWERRIGHT, "diagonal-squares-left-up" }, + +// OOo 1.x transitions not in OOo 2.x + { FadeEffect_CLOCKWISE, "clock-wipe-twelve" }, + { FadeEffect_COUNTERCLOCKWISE, "reverse-clock-wipe-twelve" }, + { FadeEffect_SPIRALIN_LEFT, "spiral-wipe-top-left-clockwise" }, + { FadeEffect_SPIRALIN_RIGHT, "spiral-wipe-top-right-counter-clockwise" }, + { FadeEffect_SPIRALOUT_LEFT, "spiral-wipe-out-to-bottom-right-clockwise" }, + { FadeEffect_SPIRALOUT_RIGHT, "spiral-wipe-out-to-bottom-left-counter-clockwise" }, + { FadeEffect_WAVYLINE_FROM_LEFT, "snake-wipe-top-left-vertical" }, + { FadeEffect_WAVYLINE_FROM_TOP, "snake-wipe-top-left-horizontal" }, + { FadeEffect_WAVYLINE_FROM_RIGHT, "snake-wipe-bottom-right-vertical" }, + { FadeEffect_WAVYLINE_FROM_BOTTOM, "snake-wipe-bottom-right-horizontal" }, + { FadeEffect_STRETCH_FROM_LEFT, "wipe-right" }, // todo + { FadeEffect_STRETCH_FROM_TOP, "wipe-down" }, // todo + { FadeEffect_STRETCH_FROM_RIGHT, "wipe-left" }, // todo + { FadeEffect_STRETCH_FROM_BOTTOM, "wipe-up" }, // todo + +// OOo 1.x not available transitions + + { FadeEffect_CLOCKWISE, "wheel-clockwise-2-spokes" }, + { FadeEffect_CLOCKWISE, "wheel-clockwise-3-spokes" }, + { FadeEffect_CLOCKWISE, "wheel-clockwise-4-spokes" }, + { FadeEffect_CLOCKWISE, "wheel-clockwise-8-spokes" }, + + { FadeEffect_FADE_FROM_CENTER, "shape-circle" }, + { FadeEffect_FADE_FROM_CENTER, "shape-diamond" }, + { FadeEffect_FADE_FROM_CENTER, "shape-plus" }, + + { FadeEffect_CLOCKWISE, "wedge" }, + + { FadeEffect_DISSOLVE, "fade-through-black" }, + + { FadeEffect_CLOCKWISE, "zoom-rotate-in" }, + + { FadeEffect_HORIZONTAL_LINES, "comb-horizontal" }, + { FadeEffect_VERTICAL_LINES, "comb-vertical" }, + + { FadeEffect_DISSOLVE, "fade-smoothly" }, + + { FadeEffect_NONE, nullptr } +}; + +/* todo +cut cut (same as NONE?) +cut-through-black cut toBlack +wedge wedge +*/ + +void EffectMigration::SetFadeEffect( SdPage* pPage, css::presentation::FadeEffect eNewEffect) +{ + deprecated_FadeEffect_conversion_table_entry const * pEntry = deprecated_FadeEffect_conversion_table; + while( (pEntry->meFadeEffect != FadeEffect_NONE) && (pEntry->meFadeEffect != eNewEffect) ) + pEntry++; + + if( pEntry->mpPresetId ) + { + const OUString aPresetId( OUString::createFromAscii( pEntry->mpPresetId ) ); + + const TransitionPresetList& rPresetList = TransitionPreset::getTransitionPresetList(); + + auto aIt = std::find_if(rPresetList.begin(), rPresetList.end(), + [&aPresetId](const TransitionPresetPtr& rxPreset) { return rxPreset->getPresetId() == aPresetId; }); + if (aIt != rPresetList.end()) + { + pPage->setTransitionType( (*aIt)->getTransition() ); + pPage->setTransitionSubtype( (*aIt)->getSubtype() ); + pPage->setTransitionDirection( (*aIt)->getDirection() ); + pPage->setTransitionFadeColor( (*aIt)->getFadeColor() ); + } + } + else + { + pPage->setTransitionType( 0 ); + pPage->setTransitionSubtype( 0 ); + pPage->setTransitionDirection( false ); + pPage->setTransitionFadeColor( 0 ); + } +} + +FadeEffect EffectMigration::GetFadeEffect( const SdPage* pPage ) +{ + const TransitionPresetList & rPresetList = TransitionPreset::getTransitionPresetList(); + auto aIt = std::find_if(rPresetList.begin(), rPresetList.end(), + [&pPage](const TransitionPresetPtr& rxPreset) { + return (rxPreset->getTransition() == pPage->getTransitionType()) + && (rxPreset->getSubtype() == pPage->getTransitionSubtype()) + && (rxPreset->getDirection() == pPage->getTransitionDirection()) + && (rxPreset->getFadeColor() == pPage->getTransitionFadeColor()); + }); + if (aIt != rPresetList.end()) + { + const OUString& aPresetId = (*aIt)->getPresetId(); + + deprecated_FadeEffect_conversion_table_entry const * pEntry = deprecated_FadeEffect_conversion_table; + while( (pEntry->meFadeEffect != FadeEffect_NONE) && (!aPresetId.equalsAscii( pEntry->mpPresetId ) ) ) + pEntry++; + + return pEntry->meFadeEffect; + } + return FadeEffect_NONE; +} + +namespace { + +struct deprecated_AnimationEffect_conversion_table_entry +{ + AnimationEffect meEffect; + const char* mpPresetId; + const char* mpPresetSubType; +}; + +} + +deprecated_AnimationEffect_conversion_table_entry const deprecated_AnimationEffect_conversion_table[] = +{ +// OOo 1.x entrance effects + { AnimationEffect_APPEAR, "ooo-entrance-appear",nullptr }, + + { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-box","in" }, + { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-box","out" }, + + { AnimationEffect_VERTICAL_CHECKERBOARD, "ooo-entrance-checkerboard","downward" }, + { AnimationEffect_HORIZONTAL_CHECKERBOARD, "ooo-entrance-checkerboard","across" }, + + { AnimationEffect_FADE_FROM_UPPERLEFT, "ooo-entrance-diagonal-squares","right-to-bottom" }, + { AnimationEffect_FADE_FROM_UPPERRIGHT, "ooo-entrance-diagonal-squares","left-to-bottom" }, + { AnimationEffect_FADE_FROM_LOWERLEFT, "ooo-entrance-diagonal-squares","right-to-top" }, + { AnimationEffect_FADE_FROM_LOWERRIGHT, "ooo-entrance-diagonal-squares","left-to-top" }, + + { AnimationEffect_DISSOLVE, "ooo-entrance-dissolve-in",nullptr }, + + { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-fly-in","from-left" }, + { AnimationEffect_MOVE_FROM_TOP, "ooo-entrance-fly-in","from-top" }, + { AnimationEffect_MOVE_FROM_RIGHT, "ooo-entrance-fly-in","from-right" }, + { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-fly-in","from-bottom" }, + { AnimationEffect_MOVE_FROM_UPPERLEFT, "ooo-entrance-fly-in","from-top-left" }, + { AnimationEffect_MOVE_FROM_UPPERRIGHT, "ooo-entrance-fly-in","from-top-right" }, + { AnimationEffect_MOVE_FROM_LOWERRIGHT, "ooo-entrance-fly-in","from-bottom-right" }, + { AnimationEffect_MOVE_FROM_LOWERLEFT, "ooo-entrance-fly-in","from-bottom-left" }, + + { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-fly-in-slow", "from-bottom" }, + { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-fly-in-slow", "from-left" }, + { AnimationEffect_MOVE_FROM_RIGHT, "ooo-entrance-fly-in-slow", "from-right" }, + { AnimationEffect_MOVE_FROM_TOP, "ooo-entrance-fly-in-slow", "from-top" }, + + { AnimationEffect_MOVE_SHORT_FROM_LEFT, "ooo-entrance-peek-in","from-left" }, + { AnimationEffect_MOVE_SHORT_FROM_TOP, "ooo-entrance-peek-in","from-top" }, + { AnimationEffect_MOVE_SHORT_FROM_RIGHT, "ooo-entrance-peek-in","from-right" }, + { AnimationEffect_MOVE_SHORT_FROM_BOTTOM, "ooo-entrance-peek-in","from-bottom" }, + + { AnimationEffect_VERTICAL_LINES, "ooo-entrance-random-bars","horizontal" }, + { AnimationEffect_HORIZONTAL_LINES, "ooo-entrance-random-bars","vertical" }, + + { AnimationEffect_RANDOM, "ooo-entrance-random",nullptr }, + + { AnimationEffect_CLOSE_VERTICAL, "ooo-entrance-split","horizontal-in" }, + { AnimationEffect_CLOSE_HORIZONTAL, "ooo-entrance-split","vertical-in" }, + { AnimationEffect_OPEN_VERTICAL, "ooo-entrance-split","horizontal-out" }, + { AnimationEffect_OPEN_HORIZONTAL, "ooo-entrance-split","vertical-out" }, + + { AnimationEffect_VERTICAL_STRIPES, "ooo-entrance-venetian-blinds","horizontal" }, + { AnimationEffect_HORIZONTAL_STRIPES, "ooo-entrance-venetian-blinds","vertical" }, + + { AnimationEffect_FADE_FROM_LEFT, "ooo-entrance-wipe","from-left" }, + { AnimationEffect_FADE_FROM_TOP, "ooo-entrance-wipe","from-bottom" }, + { AnimationEffect_FADE_FROM_RIGHT, "ooo-entrance-wipe","from-right" }, + { AnimationEffect_FADE_FROM_BOTTOM, "ooo-entrance-wipe","from-top" }, + + { AnimationEffect_HORIZONTAL_ROTATE, "ooo-entrance-swivel","vertical" }, + { AnimationEffect_VERTICAL_ROTATE, "ooo-entrance-swivel","horizontal" }, + + { AnimationEffect_STRETCH_FROM_LEFT, "ooo-entrance-stretchy","from-left" }, + { AnimationEffect_STRETCH_FROM_UPPERLEFT, "ooo-entrance-stretchy","from-top-left" }, + { AnimationEffect_STRETCH_FROM_TOP, "ooo-entrance-stretchy","from-top" }, + { AnimationEffect_STRETCH_FROM_UPPERRIGHT, "ooo-entrance-stretchy","from-top-right" }, + { AnimationEffect_STRETCH_FROM_RIGHT, "ooo-entrance-stretchy","from-right" }, + { AnimationEffect_STRETCH_FROM_LOWERRIGHT, "ooo-entrance-stretchy","from-bottom-right" }, + { AnimationEffect_STRETCH_FROM_BOTTOM, "ooo-entrance-stretchy","from-bottom" }, + { AnimationEffect_STRETCH_FROM_LOWERLEFT, "ooo-entrance-stretchy","from-bottom-left" }, + + { AnimationEffect_HORIZONTAL_STRETCH, "ooo-entrance-expand", nullptr }, + + { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel","1" }, + { AnimationEffect_COUNTERCLOCKWISE, "ooo-entrance-clock-wipe","counter-clockwise" }, + + { AnimationEffect_SPIRALIN_LEFT, "ooo-entrance-spiral-wipe", "from-top-left-clockwise" }, + { AnimationEffect_SPIRALIN_RIGHT, "ooo-entrance-spiral-wipe", "from-top-right-counter-clockwise" }, + { AnimationEffect_SPIRALOUT_LEFT, "ooo-entrance-spiral-wipe", "from-center-clockwise" }, + { AnimationEffect_SPIRALOUT_RIGHT, "ooo-entrance-spiral-wipe", "from-center-counter-clockwise" }, + + { AnimationEffect_WAVYLINE_FROM_LEFT, "ooo-entrance-snake-wipe","from-top-left-vertical" }, + { AnimationEffect_WAVYLINE_FROM_TOP, "ooo-entrance-snake-wipe","from-top-left-horizontal" }, + { AnimationEffect_WAVYLINE_FROM_RIGHT, "ooo-entrance-snake-wipe","from-bottom-right-vertical" }, + { AnimationEffect_WAVYLINE_FROM_BOTTOM, "ooo-entrance-snake-wipe","from-bottom-right-horizontal" }, + +// ooo 1.x exit effects + { AnimationEffect_HIDE, "ooo-exit-disappear",nullptr }, + { AnimationEffect_MOVE_TO_LEFT, "ooo-exit-fly-out", "from-right" }, + { AnimationEffect_MOVE_TO_TOP, "ooo-exit-fly-out", "from-bottom" }, + { AnimationEffect_MOVE_TO_RIGHT, "ooo-exit-fly-out", "from-left" }, + { AnimationEffect_MOVE_TO_BOTTOM, "ooo-exit-fly-out", "from-top" }, + { AnimationEffect_MOVE_TO_UPPERLEFT, "ooo-exit-fly-out", "from-top-right" }, + { AnimationEffect_MOVE_TO_UPPERRIGHT, "ooo-exit-fly-out", "from-top-left" }, + { AnimationEffect_MOVE_TO_LOWERRIGHT, "ooo-exit-fly-out", "from-bottom-left" }, + { AnimationEffect_MOVE_TO_LOWERLEFT, "ooo-exit-fly-out", "from-bottom-right" }, + { AnimationEffect_MOVE_SHORT_TO_LEFT, "ooo-exit-peek-out", "from-right" }, + { AnimationEffect_MOVE_SHORT_TO_UPPERLEFT, "ooo-exit-peek-out", "from-right" }, + { AnimationEffect_MOVE_SHORT_TO_TOP, "ooo-exit-peek-out", "from-bottom" }, + { AnimationEffect_MOVE_SHORT_TO_UPPERRIGHT, "ooo-exit-peek-out", "from-bottom" }, + { AnimationEffect_MOVE_SHORT_TO_RIGHT, "ooo-exit-peek-out", "from-left" }, + { AnimationEffect_MOVE_SHORT_TO_LOWERRIGHT, "ooo-exit-peek-out","from-left" }, + { AnimationEffect_MOVE_SHORT_TO_BOTTOM, "ooo-exit-peek-out", "from-top" }, + { AnimationEffect_MOVE_SHORT_TO_LOWERLEFT, "ooo-exit-peek-out", "from-top" }, + +// no matching in OOo 2.x + { AnimationEffect_MOVE_SHORT_FROM_UPPERLEFT, "ooo-entrance-peek-in","from-left" }, + { AnimationEffect_MOVE_SHORT_FROM_UPPERRIGHT, "ooo-entrance-peek-in","from-top" }, + { AnimationEffect_MOVE_SHORT_FROM_LOWERRIGHT, "ooo-entrance-peek-in","from-right" }, + { AnimationEffect_MOVE_SHORT_FROM_LOWERLEFT, "ooo-entrance-peek-in","from-bottom" }, + { AnimationEffect_LASER_FROM_LEFT, "ooo-entrance-fly-in","from-left" }, + { AnimationEffect_LASER_FROM_TOP, "ooo-entrance-fly-in","from-top" }, + { AnimationEffect_LASER_FROM_RIGHT, "ooo-entrance-fly-in","from-right" }, + { AnimationEffect_LASER_FROM_BOTTOM, "ooo-entrance-fly-in","from-bottom" }, + { AnimationEffect_LASER_FROM_UPPERLEFT, "ooo-entrance-fly-in","from-top-left" }, + { AnimationEffect_LASER_FROM_UPPERRIGHT, "ooo-entrance-fly-in","from-top-right" }, + { AnimationEffect_LASER_FROM_LOWERLEFT, "ooo-entrance-fly-in","from-bottom-left" }, + { AnimationEffect_LASER_FROM_LOWERRIGHT, "ooo-entrance-fly-in","from-bottom-right" }, + +// no matching in OOo 1.x + + { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-circle", "in" }, + { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-circle", "out" }, + { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-diamond", "in" }, + { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-diamond", "out" }, + { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-plus", "in" }, + { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-plus", "out" }, + { AnimationEffect_CLOCKWISE, "ooo-entrance-wedge", nullptr }, + { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "2" }, + { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "3" }, + { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "4" }, + { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "8" }, + + { AnimationEffect_MOVE_FROM_RIGHT, "ooo-entrance-boomerang", nullptr }, + { AnimationEffect_MOVE_FROM_UPPERRIGHT, "ooo-entrance-bounce", nullptr }, + { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-curve-up", nullptr }, + { AnimationEffect_MOVE_FROM_TOP, "ooo-entrance-float", nullptr }, + { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-glide", nullptr }, + { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-magnify", nullptr }, + { AnimationEffect_HORIZONTAL_ROTATE, "ooo-entrance-pinwheel", nullptr }, + { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-breaks", nullptr }, + { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-sling", nullptr }, + { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-spiral-in", nullptr }, + { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-thread", nullptr }, + { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-ascend", nullptr }, + { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-center-revolve", nullptr }, + { AnimationEffect_APPEAR, "ooo-entrance-compress", nullptr }, + { AnimationEffect_MOVE_SHORT_FROM_TOP, "ooo-entrance-descend", nullptr }, + { AnimationEffect_MOVE_SHORT_FROM_LEFT, "ooo-entrance-ease-in", nullptr }, + { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-rise-up", nullptr }, + { AnimationEffect_HORIZONTAL_ROTATE, "ooo-entrance-spin-in", nullptr }, + { AnimationEffect_STRETCH_FROM_LEFT, "ooo-entrance-stretchy", "across" }, + { AnimationEffect_STRETCH_FROM_TOP, "ooo-entrance-stretchy", "downward" }, + + { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-zoom","in" }, + { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-zoom","in-slightly" }, + { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-zoom","in-from-screen-center" }, + { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-zoom","out" }, + { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-zoom","out-slightly" }, + { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-zoom","out-from-screen-center" }, + + { AnimationEffect_DISSOLVE, "ooo-entrance-fade-in", nullptr }, + { AnimationEffect_DISSOLVE, "ooo-entrance-fade-in-and-zoom", nullptr }, + { AnimationEffect_DISSOLVE, "ooo-entrance-fade-in-and-swivel", nullptr }, + + // still open (no matching effect: AnimationEffect_ZOOM_IN_FROM_*, + // AnimationEffect_ZOOM_OUT_FROM_*, AnimationEffect_PATH + + { AnimationEffect_NONE, nullptr, nullptr } +}; + +static EffectSequence::iterator ImplFindEffect( MainSequencePtr const & pMainSequence, const Reference< XShape >& rShape, sal_Int16 nSubItem ) +{ + return std::find_if(pMainSequence->getBegin(), pMainSequence->getEnd(), + [&rShape, &nSubItem](const CustomAnimationEffectPtr& pEffect) { + return (pEffect->getTargetShape() == rShape) + && (pEffect->getTargetSubItem() == nSubItem); + }); +} + +static bool implIsInsideGroup( SdrObject const * pObj ) +{ + // TTTT for current state of transition, SdrObject has a parent* + // to a SdrObjList. That may be a SdrPage or a SdrObjGroup, both + // are already derived from SdrObjList. To finally check, use + // the method 'getSdrObjectFromSdrObjList' - if it's not a SdrPage, + // it will return SdrObjGroup or E3dScene -> SdrObject. + // For future states, test for SdrObject. Trying to get the SdrPage + // will in the future depend on the Object(this) to be inserted to a + // SdrPage, regardless of e.g. being a group member. + if(nullptr == pObj) + { + return false; + } + + SdrObjList* pSdrObjList(pObj->getParentSdrObjListFromSdrObject()); + + if(nullptr == pSdrObjList) + { + return false; + } + + return (nullptr != pSdrObjList->getSdrObjectFromSdrObjList()); +} + +void EffectMigration::SetAnimationEffect( SvxShape* pShape, AnimationEffect eEffect ) +{ + DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->getSdrPageFromSdrObject(), + "sd::EffectMigration::SetAnimationEffect(), invalid argument!" ); + if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() ) + return; + + SdrObject* pObj = pShape->GetSdrObject(); + if( implIsInsideGroup( pObj ) ) + return; + + OUString aPresetId; + OUString aPresetSubType; + + if( !ConvertAnimationEffect( eEffect, aPresetId, aPresetSubType ) ) + { + OSL_FAIL( "sd::EffectMigration::SetAnimationEffect(), no mapping for given AnimationEffect value" ); + return; + } + + const CustomAnimationPresets& rPresets = CustomAnimationPresets::getCustomAnimationPresets(); + + CustomAnimationPresetPtr pPreset( rPresets.getEffectDescriptor( aPresetId ) ); + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence(); + + if( !(pPreset && pMainSequence) ) + return; + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIterOnlyBackground( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_BACKGROUND ) ); + EffectSequence::iterator aIterAsWhole( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::AS_WHOLE ) ); + const EffectSequence::iterator aEnd( pMainSequence->getEnd() ); + + if( (aIterOnlyBackground == aEnd) && (aIterAsWhole == aEnd) ) + { + bool bEffectCreated = false; + + // check if there is already a text effect for this shape + EffectSequence::iterator aIterOnlyText( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_TEXT ) ); + if( aIterOnlyText != aEnd ) + { + // check if this is an animation text group + sal_Int32 nGroupId = (*aIterOnlyText)->getGroupId(); + if( nGroupId >= 0 ) + { + CustomAnimationTextGroupPtr pGroup = pMainSequence->findGroup( nGroupId ); + if( pGroup ) + { + // add an effect to animate the shape + pMainSequence->setAnimateForm( pGroup, true ); + + // find this effect + EffectSequence::iterator aIter( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_BACKGROUND ) ); + + if( aIter != aEnd ) + { + if( ((*aIter)->getPresetId() != aPresetId) || + ((*aIter)->getPresetSubType() != aPresetSubType) ) + { + (*aIter)->replaceNode( pPreset->create( aPresetSubType ) ); + pMainSequence->rebuild(); + bEffectCreated = true; + } + } + } + } + } + + if( !bEffectCreated ) + { + // if there is not yet an effect that target this shape, we generate one + // we insert the shape effect before it + Reference< XAnimationNode > xNode( pPreset->create( aPresetSubType ) ); + DBG_ASSERT( xNode.is(), "EffectMigration::SetAnimationEffect(), could not create preset!" ); + if( xNode.is() ) + { + CustomAnimationEffectPtr pEffect = std::make_shared<CustomAnimationEffect>( xNode ); + pEffect->setTarget( Any( xShape ) ); + SdPage* pPage = dynamic_cast< SdPage* >( pObj->getSdrPageFromSdrObject() ); + const bool bManual = (pPage == nullptr) || (pPage->GetPresChange() == PresChange::Manual); + if( !bManual ) + pEffect->setNodeType( EffectNodeType::AFTER_PREVIOUS ); + + pMainSequence->append( pEffect ); + + if( ( pObj->GetObjInventor() == SdrInventor::Default ) && ( pObj->GetObjIdentifier() == SdrObjKind::OutlineText ) ) + { + // special case for outline text, effects are always mapped to text group effect + pMainSequence-> + createTextGroup( pEffect, 10, bManual ? -1 : 0.0, false, false ); + } + } + } + } + else + { + // if there is already an effect targeting this shape + // just replace it + CustomAnimationEffectPtr pEffect; + if( aIterAsWhole != aEnd ) + { + pEffect = *aIterAsWhole; + } + else + { + pEffect = *aIterOnlyBackground; + } + + if( pEffect ) + { + if( (pEffect->getPresetId() != aPresetId) || + (pEffect->getPresetSubType() != aPresetSubType) ) + { + pMainSequence->replace( pEffect, pPreset, aPresetSubType, -1.0 ); + } + } + } +} + +AnimationEffect EffectMigration::GetAnimationEffect( SvxShape* pShape ) +{ + OUString aPresetId; + OUString aPresetSubType; + + SdrObject* pObj = pShape->GetSdrObject(); + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence(); + + if( pMainSequence ) + { + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter = std::find_if(pMainSequence->getBegin(), pMainSequence->getEnd(), + [&xShape](const CustomAnimationEffectPtr& pEffect) { + return (pEffect->getTargetShape() == xShape) + && ((pEffect->getTargetSubItem() == ShapeAnimationSubType::ONLY_BACKGROUND) + || (pEffect->getTargetSubItem() == ShapeAnimationSubType::AS_WHOLE)) + && (pEffect->getDuration() != 0.1); // ignore appear effects created from old text effect import + }); + + if (aIter != pMainSequence->getEnd()) + { + aPresetId = (*aIter)->getPresetId(); + aPresetSubType = (*aIter)->getPresetSubType(); + } + } + + // now find old effect + AnimationEffect eEffect = AnimationEffect_NONE; + + if( !ConvertPreset( aPresetId, &aPresetSubType, eEffect ) ) + ConvertPreset( aPresetId, nullptr, eEffect ); + + return eEffect; +} + +void EffectMigration::SetTextAnimationEffect( SvxShape* pShape, AnimationEffect eEffect ) +{ + DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->getSdrPageFromSdrObject(), + "sd::EffectMigration::SetAnimationEffect(), invalid argument!" ); + if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() ) + return; + + SdrObject* pObj = pShape->GetSdrObject(); + if( implIsInsideGroup( pObj ) ) + return; + + // first map the deprecated AnimationEffect to a preset and subtype + OUString aPresetId; + OUString aPresetSubType; + + if( !ConvertAnimationEffect( eEffect, aPresetId, aPresetSubType ) ) + { + OSL_FAIL( "sd::EffectMigration::SetAnimationEffect(), no mapping for given AnimationEffect value" ); + return; + } + + SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( pObj ); + + // ignore old text effects on shape without text + if( (pTextObj == nullptr) || (!pTextObj->HasText()) ) + return; + + const CustomAnimationPresets& rPresets = CustomAnimationPresets::getCustomAnimationPresets(); + + // create an effect from this preset + CustomAnimationPresetPtr pPreset( rPresets.getEffectDescriptor( aPresetId ) ); + + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence(); + + if( !(pPreset && pMainSequence) ) + return; + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIterOnlyText( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_TEXT ) ); + const EffectSequence::iterator aEnd( pMainSequence->getEnd() ); + + CustomAnimationTextGroupPtr pGroup; + + // is there already an animation text group for this shape? + if( aIterOnlyText != aEnd ) + { + const sal_Int32 nGroupId = (*aIterOnlyText)->getGroupId(); + if( nGroupId >= 0 ) + pGroup = pMainSequence->findGroup( nGroupId ); + } + + // if there is not yet a group, create it + if( !pGroup ) + { + CustomAnimationEffectPtr pShapeEffect; + + EffectSequence::iterator aIterOnlyBackground( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_BACKGROUND ) ); + if( aIterOnlyBackground != aEnd ) + { + pShapeEffect = *aIterOnlyBackground; + } + else + { + EffectSequence::iterator aIterAsWhole( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::AS_WHOLE ) ); + if( aIterAsWhole != aEnd ) + { + pShapeEffect = *aIterAsWhole; + } + else + { + Reference< XAnimationNode > xNode( pPreset->create( "" ) ); + DBG_ASSERT( xNode.is(), "EffectMigration::SetTextAnimationEffect(), could not create preset!" ); + if( xNode.is() ) + { + pShapeEffect = std::make_shared<CustomAnimationEffect>( xNode ); + pShapeEffect->setTarget( Any( xShape ) ); + pShapeEffect->setDuration( 0.1 ); + pMainSequence->append( pShapeEffect ); + + SdPage* pPage = dynamic_cast< SdPage* >( pObj->getSdrPageFromSdrObject() ); + if( pPage && pPage->GetPresChange() != PresChange::Manual ) + pShapeEffect->setNodeType( EffectNodeType::AFTER_PREVIOUS ); + } + } + } + + if( pShapeEffect ) + { + SdPage* pPage = dynamic_cast< SdPage* >( pObj->getSdrPageFromSdrObject() ); + const bool bManual = (pPage == nullptr) || (pPage->GetPresChange() == PresChange::Manual); + + // now create effects for each paragraph + pGroup = + pMainSequence-> + createTextGroup( pShapeEffect, 10, bManual ? -1 : 0.0, true, false ); + } + } + + if( pGroup ) + { + const bool bLaserEffect = (eEffect >= AnimationEffect_LASER_FROM_LEFT) && (eEffect <= AnimationEffect_LASER_FROM_LOWERRIGHT); + + // now we have a group, so check if all effects are same as we like to have them + const EffectSequence& rEffects = pGroup->getEffects(); + + for( auto& rxEffect : rEffects ) + { + // only work on paragraph targets + if( rxEffect->getTarget().getValueType() == ::cppu::UnoType<ParagraphTarget>::get() ) + { + if( (rxEffect->getPresetId() != aPresetId) || + (rxEffect->getPresetSubType() != aPresetSubType) ) + { + rxEffect->replaceNode( pPreset->create( aPresetSubType ) ); + } + + if( bLaserEffect ) + { + rxEffect->setIterateType( TextAnimationType::BY_LETTER ); + rxEffect->setIterateInterval( 0.5 );// TODO: + // Determine + // interval + // according + // to + // total + // effect + // duration + } + } + } + } + pMainSequence->rebuild(); +} + +AnimationEffect EffectMigration::GetTextAnimationEffect( SvxShape* pShape ) +{ + OUString aPresetId; + OUString aPresetSubType; + + SdrObject* pObj = pShape->GetSdrObject(); + if( pObj ) + { + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence(); + + if( pMainSequence ) + { + const Reference< XShape > xShape( pShape ); + EffectSequence::iterator aIter( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_TEXT ) ); + if( aIter != pMainSequence->getEnd() ) + { + aPresetId = (*aIter)->getPresetId(); + aPresetSubType = (*aIter)->getPresetSubType(); + } + } + } + + // now find old effect + AnimationEffect eEffect = AnimationEffect_NONE; + + if( !ConvertPreset( aPresetId, &aPresetSubType, eEffect ) ) + ConvertPreset( aPresetId, nullptr, eEffect ); + + return eEffect; +} + +bool EffectMigration::ConvertPreset( std::u16string_view rPresetId, const OUString* pPresetSubType, AnimationEffect& rEffect ) +{ + rEffect = AnimationEffect_NONE; + if( !rPresetId.empty() ) + { + // first try a match for preset id and subtype + deprecated_AnimationEffect_conversion_table_entry const * p = deprecated_AnimationEffect_conversion_table; + while( p->mpPresetId ) + { + if( o3tl::equalsAscii( rPresetId, p->mpPresetId ) && + (( p->mpPresetSubType == nullptr ) || + ( pPresetSubType == nullptr) || + ( pPresetSubType->equalsAscii( p->mpPresetSubType )) ) ) + { + rEffect = p->meEffect; + return true; + } + p++; + } + return false; + } + else + { + // empty preset id means AnimationEffect_NONE + return true; + } +} + +bool EffectMigration::ConvertAnimationEffect( const AnimationEffect& rEffect, OUString& rPresetId, OUString& rPresetSubType ) +{ + deprecated_AnimationEffect_conversion_table_entry const * p = deprecated_AnimationEffect_conversion_table; + while( p->mpPresetId ) + { + if( p->meEffect == rEffect ) + { + rPresetId = OUString::createFromAscii( p->mpPresetId ); + rPresetSubType = OUString::createFromAscii( p->mpPresetSubType ); + return true; + } + p++; + } + + return false; +} + +double EffectMigration::ConvertAnimationSpeed( AnimationSpeed eSpeed ) +{ + double fDuration; + switch( eSpeed ) + { + case AnimationSpeed_SLOW: fDuration = 2.0; break; + case AnimationSpeed_FAST: fDuration = 0.5; break; + default: + fDuration = 1.0; break; + } + return fDuration; +} + +void EffectMigration::SetAnimationSpeed( SvxShape* pShape, AnimationSpeed eSpeed ) +{ + DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->getSdrPageFromSdrObject(), + "sd::EffectMigration::SetAnimationEffect(), invalid argument!" ); + if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() ) + return; + + SdrObject* pObj = pShape->GetSdrObject(); + if( implIsInsideGroup( pObj ) ) + return; + + double fDuration = ConvertAnimationSpeed( eSpeed ); + + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter; + bool bNeedRebuild = false; + + for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter ) + { + CustomAnimationEffectPtr pEffect( *aIter ); + if( pEffect->getTargetShape() == xShape ) + { + if( pEffect->getDuration() != 0.1 ) + pEffect->setDuration( fDuration ); + bNeedRebuild = true; + } + } + + if( bNeedRebuild ) + pMainSequence->rebuild(); +} + +AnimationSpeed EffectMigration::GetAnimationSpeed( SvxShape* pShape ) +{ + SdrObject* pObj = pShape->GetSdrObject(); + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + + double fDuration = 1.0; + + EffectSequence::iterator aIter = std::find_if(pMainSequence->getBegin(), pMainSequence->getEnd(), + [&xShape](const CustomAnimationEffectPtr& pEffect) { + return (pEffect->getTargetShape() == xShape) + && (pEffect->getDuration() != 0.1); + }); + if (aIter != pMainSequence->getEnd()) + { + CustomAnimationEffectPtr pEffect( *aIter ); + fDuration = pEffect->getDuration(); + } + + return ConvertDuration( fDuration ); +} + +AnimationSpeed EffectMigration::ConvertDuration( double fDuration ) +{ + AnimationSpeed eSpeed; + + if( fDuration < 1.0 ) + eSpeed = AnimationSpeed_FAST; + else if( fDuration > 1.5 ) + eSpeed = AnimationSpeed_SLOW; + else + eSpeed = AnimationSpeed_MEDIUM; + + return eSpeed; +} + +void EffectMigration::SetDimColor( SvxShape* pShape, sal_Int32 nColor ) +{ + DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->getSdrPageFromSdrObject(), + "sd::EffectMigration::SetAnimationEffect(), invalid argument!" ); + if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() ) + return; + + SdrObject* pObj = pShape->GetSdrObject(); + if( implIsInsideGroup( pObj ) ) + return; + + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter; + bool bNeedRebuild = false; + + for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter ) + { + CustomAnimationEffectPtr pEffect( *aIter ); + if( pEffect->getTargetShape() == xShape ) + { + pEffect->setHasAfterEffect( true ); + pEffect->setDimColor( Any( nColor ) ); + pEffect->setAfterEffectOnNext( true ); + bNeedRebuild = true; + } + } + + if( bNeedRebuild ) + pMainSequence->rebuild(); +} + +sal_Int32 EffectMigration::GetDimColor( SvxShape* pShape ) +{ + sal_Int32 nColor = 0; + if( pShape ) + { + SdrObject* pObj = pShape->GetSdrObject(); + if( pObj && pObj->getSdrPageFromSdrObject() ) + { + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + EffectSequence::iterator aIter = std::find_if(pMainSequence->getBegin(), pMainSequence->getEnd(), + [&xShape](const CustomAnimationEffectPtr& pEffect) { + return (pEffect->getTargetShape() == xShape) + && pEffect->getDimColor().hasValue() + && pEffect->hasAfterEffect(); + }); + if (aIter != pMainSequence->getEnd()) + { + CustomAnimationEffectPtr pEffect( *aIter ); + pEffect->getDimColor() >>= nColor; + } + } + } + + return nColor; +} + +void EffectMigration::SetDimHide( SvxShape* pShape, bool bDimHide ) +{ + DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->getSdrPageFromSdrObject(), + "sd::EffectMigration::SetAnimationEffect(), invalid argument!" ); + if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() ) + return; + + SdrObject* pObj = pShape->GetSdrObject(); + if( implIsInsideGroup( pObj ) ) + return; + + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter; + bool bNeedRebuild = false; + + for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter ) + { + CustomAnimationEffectPtr pEffect( *aIter ); + if( pEffect->getTargetShape() == xShape ) + { + pEffect->setHasAfterEffect( bDimHide ); + if( bDimHide ) { + Any aEmpty; + pEffect->setDimColor( aEmpty ); + } + pEffect->setAfterEffectOnNext( false ); + bNeedRebuild = true; + } + } + + if( bNeedRebuild ) + pMainSequence->rebuild(); +} + +bool EffectMigration::GetDimHide( SvxShape* pShape ) +{ + bool bRet = false; + if( pShape ) + { + SdrObject* pObj = pShape->GetSdrObject(); + if( pObj && pObj->getSdrPageFromSdrObject() ) + { + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter = std::find_if(pMainSequence->getBegin(), pMainSequence->getEnd(), + [&xShape](const CustomAnimationEffectPtr& pEffect) { return pEffect->getTargetShape() == xShape; }); + if (aIter != pMainSequence->getEnd()) + { + CustomAnimationEffectPtr pEffect( *aIter ); + bRet = pEffect->hasAfterEffect() && + !pEffect->getDimColor().hasValue() && + (!pEffect->IsAfterEffectOnNext()); + } + } + } + + return bRet; +} + +void EffectMigration::SetDimPrevious( SvxShape* pShape, bool bDimPrevious ) +{ + DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->getSdrPageFromSdrObject(), + "sd::EffectMigration::SetAnimationEffect(), invalid argument!" ); + if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() ) + return; + + SdrObject* pObj = pShape->GetSdrObject(); + if( implIsInsideGroup( pObj ) ) + return; + + Any aColor; + + if( bDimPrevious ) + aColor <<= COL_LIGHTGRAY; + + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter; + bool bNeedRebuild = false; + + for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter ) + { + CustomAnimationEffectPtr pEffect( *aIter ); + if( pEffect->getTargetShape() == xShape ) + { + pEffect->setHasAfterEffect( bDimPrevious ); + if( !bDimPrevious || !pEffect->getDimColor().hasValue() ) + pEffect->setDimColor( aColor ); + pEffect->setAfterEffectOnNext( true ); + bNeedRebuild = true; + } + } + + if( bNeedRebuild ) + pMainSequence->rebuild(); +} + +bool EffectMigration::GetDimPrevious( SvxShape* pShape ) +{ + bool bRet = false; + if( pShape ) + { + SdrObject* pObj = pShape->GetSdrObject(); + if( pObj && pObj->getSdrPageFromSdrObject() ) + { + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter = std::find_if(pMainSequence->getBegin(), pMainSequence->getEnd(), + [&xShape](const CustomAnimationEffectPtr& pEffect) { return pEffect->getTargetShape() == xShape; }); + if (aIter != pMainSequence->getEnd()) + { + CustomAnimationEffectPtr pEffect( *aIter ); + bRet = pEffect->hasAfterEffect() && + pEffect->getDimColor().hasValue() && + pEffect->IsAfterEffectOnNext(); + } + } + } + + return bRet; +} + +void EffectMigration::SetPresentationOrder( SvxShape* pShape, sal_Int32 nNewPos ) +{ + if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() ) + return; + + SdrObject* pObj = pShape->GetSdrObject(); + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence(); + + EffectSequence& rSequence = pMainSequence->getSequence(); + sal_Int32 nPos; + sal_Int32 nCurrentPos = -1; + std::vector< std::vector< EffectSequence::iterator > > aEffectVector(1); + + if( !rSequence.empty() ) + { + Reference< XShape > xThis( pShape ); + Reference< XShape > xCurrent; + + EffectSequence::iterator aIter( rSequence.begin() ); + EffectSequence::iterator aEnd( rSequence.end() ); + for( nPos = 0; aIter != aEnd; ++aIter ) + { + CustomAnimationEffectPtr pEffect = *aIter; + + if( !xCurrent.is() ) + { + xCurrent = pEffect->getTargetShape(); + } + else if( pEffect->getTargetShape() != xCurrent ) + { + nPos++; + xCurrent = pEffect->getTargetShape(); + aEffectVector.resize( nPos+1 ); + } + + // is this the first effect for xThis shape? + if(( nCurrentPos == -1 ) && ( xCurrent == xThis ) ) + { + nCurrentPos = nPos; + } + + aEffectVector[nPos].push_back( aIter ); + } + } + + // check if there is at least one effect for xThis + if( nCurrentPos == -1 ) + { + OSL_FAIL("sd::EffectMigration::SetPresentationOrder() failed cause this shape has no effect" ); + return; + } + + // check trivial case + if( nCurrentPos == nNewPos ) + return; + + std::vector< CustomAnimationEffectPtr > aEffects; + + for( const auto& rIter : aEffectVector[nCurrentPos] ) + { + aEffects.push_back( *rIter ); + rSequence.erase( rIter ); + } + + if( nNewPos > nCurrentPos ) + nNewPos++; + + if( nNewPos == static_cast<sal_Int32>(aEffectVector.size()) ) + { + rSequence.insert( rSequence.end(), aEffects.begin(), aEffects.end() ); + } + else + { + EffectSequence::iterator aPos( aEffectVector[nNewPos][0] ); + for( const auto& rEffect : aEffects ) + { + rSequence.insert( aPos, rEffect ); + } + } +} + +/** Returns the position of the given SdrObject in the Presentation order. + * This function returns -1 if the SdrObject is not in the Presentation order + * or if it's the path-object. + */ +sal_Int32 EffectMigration::GetPresentationOrder( SvxShape* pShape ) +{ + sal_Int32 nPos = -1, nFound = -1; + + SdrObject* pObj = pShape->GetSdrObject(); + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence(); + + EffectSequence& rSequence = pMainSequence->getSequence(); + + Reference< XShape > xThis( pShape ); + Reference< XShape > xCurrent; + + for( const CustomAnimationEffectPtr& pEffect : rSequence ) + { + if( !xCurrent.is() || pEffect->getTargetShape() != xCurrent ) + { + nPos++; + xCurrent = pEffect->getTargetShape(); + + // is this the first effect for xThis shape? + if( xCurrent == xThis ) + { + nFound = nPos; + break; + } + } + } + + return nFound; +} + +void EffectMigration::UpdateSoundEffect( SvxShape* pShape, SdAnimationInfo const * pInfo ) +{ + if( !pInfo ) + return; + + SdrObject* pObj = pShape->GetSdrObject(); + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter; + bool bNeedRebuild = false; + + OUString aSoundFile; + if( pInfo->mbSoundOn ) + aSoundFile = pInfo->maSoundFile; + + for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter ) + { + CustomAnimationEffectPtr pEffect( *aIter ); + if( pEffect->getTargetShape() == xShape ) + { + if( !aSoundFile.isEmpty() ) + { + pEffect->createAudio( Any( aSoundFile ) ); + } + else + { + pEffect->removeAudio(); + } + bNeedRebuild = true; + } + } + + if( bNeedRebuild ) + pMainSequence->rebuild(); +} + +OUString EffectMigration::GetSoundFile( SvxShape* pShape ) +{ + OUString aSoundFile; + + if( pShape ) + { + SdrObject* pObj = pShape->GetSdrObject(); + if( pObj && pObj->getSdrPageFromSdrObject() ) + { + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter; + + for( aIter = pMainSequence->getBegin(); + (aSoundFile.isEmpty()) && (aIter != pMainSequence->getEnd()); + ++aIter ) + { + CustomAnimationEffectPtr pEffect( *aIter ); + if( pEffect->getTargetShape() == xShape ) + { + if( pEffect->getAudio().is() ) + pEffect->getAudio()->getSource() >>= aSoundFile; + } + } + } + } + return aSoundFile; +} + +bool EffectMigration::GetSoundOn( SvxShape* pShape ) +{ + return !GetSoundFile( pShape ).isEmpty(); +} + +void EffectMigration::SetAnimationPath( SvxShape* pShape, SdrPathObj const * pPathObj ) +{ + if( !(pShape && pPathObj) ) + return; + + SdrObject* pObj = pShape->GetSdrObject(); + + if( pObj ) + { + const Reference< XShape > xShape( pShape ); + SdPage* pPage = dynamic_cast< SdPage* >(pPathObj->getSdrPageFromSdrObject()); + if( pPage ) + { + std::shared_ptr< sd::MainSequence > pMainSequence( pPage->getMainSequence() ); + if( pMainSequence ) + pMainSequence->append( *pPathObj, Any( xShape ), -1.0, "" ); + } + } +} + +// #i42894# helper which creates the needed XAnimate for changing visibility and all the (currently) needed embeddings +static void createVisibilityOnOffNode(Reference< XTimeContainer > const & rxParentContainer, SdrObject& rCandidate, bool bVisible, bool bOnClick, double fDuration) +{ + Reference< XMultiServiceFactory > xMsf(::comphelper::getProcessServiceFactory()); + + // create par container node + Reference< XAnimationNode > xOuterSeqTimeContainer(xMsf->createInstance("com.sun.star.animations.ParallelTimeContainer"), UNO_QUERY_THROW); + + // set begin + xOuterSeqTimeContainer->setBegin(Any(0.0)); + + // set fill + xOuterSeqTimeContainer->setFill(AnimationFill::HOLD); + + // set named values + Sequence< NamedValue > aUserDataSequence{ + { /* Name */ "node-type", + /* Value */ Any(bOnClick ? EffectNodeType::ON_CLICK : EffectNodeType::AFTER_PREVIOUS) } + }; + + xOuterSeqTimeContainer->setUserData(aUserDataSequence); + + // create animate set to change visibility for rCandidate + Reference< XAnimationNode > xAnimateSetForLast(xMsf->createInstance("com.sun.star.animations.AnimateSet"), UNO_QUERY_THROW); + + // set begin + xAnimateSetForLast->setBegin(Any(0.0)); + + // set duration + xAnimateSetForLast->setDuration(Any(fDuration)); + + // set fill + xAnimateSetForLast->setFill(AnimationFill::HOLD); + + // set target + Reference< XAnimate > xAnimate(xAnimateSetForLast, UNO_QUERY); + Reference< XShape > xTargetShape(rCandidate.getUnoShape(), UNO_QUERY); + xAnimate->setTarget(Any(xTargetShape)); + + // set AttributeName + xAnimate->setAttributeName("Visibility"); + + // set attribute value + xAnimate->setTo(Any(bVisible)); + + // ad set node to par node + Reference< XTimeContainer > xParentContainer(xOuterSeqTimeContainer, UNO_QUERY_THROW); + xParentContainer->appendChild(xAnimateSetForLast); + + // add node + rxParentContainer->appendChild(xOuterSeqTimeContainer); +} + +// #i42894# older native formats supported animated group objects, that means all members of the group +// were shown animated by showing one after the other. This is no longer supported, but the following +// fallback will create the needed SMIL animation stuff. Unfortunately the members of the group +// have to be moved directly to the page, else the (explained to be generic, thus I expected this to +// work) animations will not work in slideshow +void EffectMigration::CreateAnimatedGroup(SdrObjGroup const & rGroupObj, SdPage& rPage) +{ + // aw080 will give a vector immediately + SdrObjListIter aIter(rGroupObj); + + if(!aIter.Count()) + return; + + std::shared_ptr< sd::MainSequence > pMainSequence(rPage.getMainSequence()); + + if(!pMainSequence) + return; + + std::vector< SdrObject* > aObjects; + aObjects.reserve(aIter.Count()); + + while(aIter.IsMore()) + { + // do move to page rough with old/current stuff, will be different in aw080 anyways + SdrObject* pCandidate = aIter.Next(); + rGroupObj.GetSubList()->NbcRemoveObject(pCandidate->GetOrdNum()); + rPage.NbcInsertObject(pCandidate); + aObjects.push_back(pCandidate); + } + + // create main node + Reference< XMultiServiceFactory > xMsf(::comphelper::getProcessServiceFactory()); + Reference< XAnimationNode > xOuterSeqTimeContainer(xMsf->createInstance("com.sun.star.animations.ParallelTimeContainer"), UNO_QUERY_THROW); + + // set begin + xOuterSeqTimeContainer->setBegin(Any(0.0)); + + // prepare parent container + Reference< XTimeContainer > xParentContainer(xOuterSeqTimeContainer, UNO_QUERY_THROW); + + // prepare loop over objects + SdrObject* pNext = nullptr; + const double fDurationShow(0.2); + const double fDurationHide(0.001); + + for(size_t a(0); a < aObjects.size(); a++) + { + SdrObject* pLast = pNext; + pNext = aObjects[a]; + + // create node + if(pLast) + { + createVisibilityOnOffNode(xParentContainer, *pLast, false, false, fDurationHide); + } + + if(pNext) + { + createVisibilityOnOffNode(xParentContainer, *pNext, true, !a, fDurationShow); + } + } + + // create end node + if(pNext) + { + createVisibilityOnOffNode(xParentContainer, *pNext, false, false, fDurationHide); + } + + // add to main sequence and rebuild + pMainSequence->createEffects(xOuterSeqTimeContainer); + pMainSequence->rebuild(); +} + +void EffectMigration::DocumentLoaded(SdDrawDocument & rDoc) +{ + if (DocumentType::Draw == rDoc.GetDocumentType()) + return; // no animations in Draw + for (sal_uInt16 n = 0; n < rDoc.GetSdPageCount(PageKind::Standard); ++n) + { + SdPage *const pPage = rDoc.GetSdPage(n, PageKind::Standard); + if (pPage->hasAnimationNode()) + { + // this will force the equivalent of the MainSequence::onTimerHdl + // so that the animations are present in export-able representation + // *before* the import is finished + pPage->getMainSequence()->getRootNode(); + } + } + for (sal_uInt16 n = 0; n < rDoc.GetMasterSdPageCount(PageKind::Standard); ++n) + { + SdPage *const pPage = rDoc.GetMasterSdPage(n, PageKind::Standard); + if (pPage->hasAnimationNode()) + { + pPage->getMainSequence()->getRootNode(); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |