Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sd/source/core/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 55 kB image not shown  

Quelle  EffectMigration.cxx   Sprache: C

 
/* -*- 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, falsefalse );
                }
            }
        }
    }
    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 = DynCastSdrTextObj( 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( u""_ustr ) );
                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, truefalse );
        }
    }

    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();

        forauto& 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 )
    {
        const 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())
    {
        const 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 )
    {
        const 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())
            {
                const 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 )
    {
        const 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())
            {
                const 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 )
    {
        const 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())
            {
                const 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 )
        {
            const 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;

    forconst 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] );
        forconst 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;

    forconst 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 )
    {
        const 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 )
            {
                const 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, u""_ustr );
        }
    }
}

// #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(u"com.sun.star.animations.ParallelTimeContainer"_ustr), UNO_QUERY_THROW);

    // set begin
    xOuterSeqTimeContainer->setBegin(Any(0.0));

    // set fill
    xOuterSeqTimeContainer->setFill(AnimationFill::HOLD);

    // set named values
    Sequence< NamedValue > aUserDataSequence{
        { /* Name  */ u"node-type"_ustr,
          /* 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(u"com.sun.star.animations.AnimateSet"_ustr), 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(u"Visibility"_ustr);

    // 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&&nbsp;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
        rtl::Reference<SdrObject> pCandidate = aIter.Next();
        rGroupObj.GetSubList()->NbcRemoveObject(pCandidate->GetOrdNum());
        rPage.NbcInsertObject(pCandidate.get());
        aObjects.push_back(pCandidate.get());
    }

    // create main node
    Reference< XMultiServiceFactory > xMsf(::comphelper::getProcessServiceFactory());
    Reference< XAnimationNode > xOuterSeqTimeContainer(xMsf->createInstance(u"com.sun.star.animations.ParallelTimeContainer"_ustr), 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, falsefalse, fDurationHide);
        }

        if(pNext)
        {
            createVisibilityOnOffNode(xParentContainer, *pNext, true, !a, fDurationShow);
        }
    }

    // create end node
    if(pNext)
    {
        createVisibilityOnOffNode(xParentContainer, *pNext, falsefalse, 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: */

Messung V0.5
C=94 H=92 G=92

¤ Dauer der Verarbeitung: 0.23 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.