1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/presentation/EffectNodeType.hpp>
21 #include <com/sun/star/presentation/ShapeAnimationSubType.hpp>
22 #include <com/sun/star/presentation/TextAnimationType.hpp>
23 #include <com/sun/star/presentation/ParagraphTarget.hpp>
24 #include <comphelper/processfactory.hxx>
25 #include <com/sun/star/animations/AnimationFill.hpp>
26 #include <com/sun/star/animations/XAnimate.hpp>
27 #include <com/sun/star/beans/NamedValue.hpp>
28 #include <tools/debug.hxx>
29 #include <svx/unoshape.hxx>
30 #include <svx/svdotext.hxx>
31 #include <svx/svdopath.hxx>
32 #include <svx/svdogrp.hxx>
33 #include <svx/svditer.hxx>
34 #include <drawdoc.hxx>
36 #include <CustomAnimationPreset.hxx>
37 #include <TransitionPreset.hxx>
38 #include <EffectMigration.hxx>
39 #include <anminfo.hxx>
42 using namespace ::com::sun::star::uno
;
43 using namespace ::com::sun::star::animations
;
44 using namespace ::com::sun::star::presentation
;
45 using ::com::sun::star::drawing::XShape
;
46 using ::com::sun::star::lang::XMultiServiceFactory
;
47 using ::com::sun::star::drawing::XShape
;
48 using ::com::sun::star::beans::NamedValue
;
52 struct deprecated_FadeEffect_conversion_table_entry
54 FadeEffect meFadeEffect
;
55 const char* mpPresetId
;
60 deprecated_FadeEffect_conversion_table_entry
const deprecated_FadeEffect_conversion_table
[] =
62 // OOo 1.x transitions
63 { FadeEffect_FADE_FROM_LEFT
, "wipe-right" },
64 { FadeEffect_FADE_FROM_TOP
, "wipe-down" },
65 { FadeEffect_FADE_FROM_RIGHT
, "wipe-left" },
66 { FadeEffect_FADE_FROM_BOTTOM
, "wipe-up" },
68 { FadeEffect_CLOCKWISE
, "wheel-clockwise-1-spoke" },
70 { FadeEffect_UNCOVER_TO_LEFT
, "uncover-left" },
71 { FadeEffect_UNCOVER_TO_UPPERLEFT
, "uncover-left-up" },
72 { FadeEffect_UNCOVER_TO_TOP
, "uncover-up" },
73 { FadeEffect_UNCOVER_TO_UPPERRIGHT
, "uncover-right-up" },
74 { FadeEffect_UNCOVER_TO_RIGHT
, "uncover-right" },
75 { FadeEffect_UNCOVER_TO_LOWERRIGHT
, "uncover-right-down" },
76 { FadeEffect_UNCOVER_TO_BOTTOM
, "uncover-down" },
77 { FadeEffect_UNCOVER_TO_LOWERLEFT
, "uncover-left-down" },
79 { FadeEffect_VERTICAL_LINES
, "random-bars-vertical" },
80 { FadeEffect_HORIZONTAL_LINES
, "random-bars-horizontal" },
82 { FadeEffect_VERTICAL_CHECKERBOARD
, "checkerboard-down" },
83 { FadeEffect_HORIZONTAL_CHECKERBOARD
, "checkerboard-across" },
85 { FadeEffect_FADE_TO_CENTER
, "box-in" },
86 { FadeEffect_FADE_FROM_CENTER
, "box-out" },
88 { FadeEffect_VERTICAL_STRIPES
, "venetian-blinds-vertical" },
89 { FadeEffect_HORIZONTAL_STRIPES
, "venetian-blinds-horizontal" },
91 { FadeEffect_MOVE_FROM_LEFT
, "cover-right" },
92 { FadeEffect_MOVE_FROM_TOP
, "cover-down" },
93 { FadeEffect_MOVE_FROM_RIGHT
, "cover-left" },
94 { FadeEffect_MOVE_FROM_BOTTOM
, "cover-up" },
95 { FadeEffect_MOVE_FROM_UPPERLEFT
, "cover-right-down" },
96 { FadeEffect_MOVE_FROM_UPPERRIGHT
, "cover-left-down" },
97 { FadeEffect_MOVE_FROM_LOWERRIGHT
, "cover-left-up" },
98 { FadeEffect_MOVE_FROM_LOWERLEFT
, "cover-right-up" },
100 { FadeEffect_DISSOLVE
, "dissolve" },
102 { FadeEffect_RANDOM
, "random-transition" },
104 { FadeEffect_ROLL_FROM_LEFT
, "push-right" },
105 { FadeEffect_ROLL_FROM_TOP
, "push-down" },
106 { FadeEffect_ROLL_FROM_RIGHT
, "push-left" },
107 { FadeEffect_ROLL_FROM_BOTTOM
, "push-up" },
109 { FadeEffect_CLOSE_VERTICAL
, "split-horizontal-in" },
110 { FadeEffect_CLOSE_HORIZONTAL
, "split-vertical-in" },
111 { FadeEffect_OPEN_VERTICAL
, "split-horizontal-out" },
112 { FadeEffect_OPEN_HORIZONTAL
, "split-vertical-out" },
114 { FadeEffect_FADE_FROM_UPPERLEFT
, "diagonal-squares-right-down" },
115 { FadeEffect_FADE_FROM_UPPERRIGHT
, "diagonal-squares-left-down" },
116 { FadeEffect_FADE_FROM_LOWERLEFT
, "diagonal-squares-right-up" },
117 { FadeEffect_FADE_FROM_LOWERRIGHT
, "diagonal-squares-left-up" },
119 // OOo 1.x transitions not in OOo 2.x
120 { FadeEffect_CLOCKWISE
, "clock-wipe-twelve" },
121 { FadeEffect_COUNTERCLOCKWISE
, "reverse-clock-wipe-twelve" },
122 { FadeEffect_SPIRALIN_LEFT
, "spiral-wipe-top-left-clockwise" },
123 { FadeEffect_SPIRALIN_RIGHT
, "spiral-wipe-top-right-counter-clockwise" },
124 { FadeEffect_SPIRALOUT_LEFT
, "spiral-wipe-out-to-bottom-right-clockwise" },
125 { FadeEffect_SPIRALOUT_RIGHT
, "spiral-wipe-out-to-bottom-left-counter-clockwise" },
126 { FadeEffect_WAVYLINE_FROM_LEFT
, "snake-wipe-top-left-vertical" },
127 { FadeEffect_WAVYLINE_FROM_TOP
, "snake-wipe-top-left-horizontal" },
128 { FadeEffect_WAVYLINE_FROM_RIGHT
, "snake-wipe-bottom-right-vertical" },
129 { FadeEffect_WAVYLINE_FROM_BOTTOM
, "snake-wipe-bottom-right-horizontal" },
130 { FadeEffect_STRETCH_FROM_LEFT
, "wipe-right" }, // todo
131 { FadeEffect_STRETCH_FROM_TOP
, "wipe-down" }, // todo
132 { FadeEffect_STRETCH_FROM_RIGHT
, "wipe-left" }, // todo
133 { FadeEffect_STRETCH_FROM_BOTTOM
, "wipe-up" }, // todo
135 // OOo 1.x not available transitions
137 { FadeEffect_CLOCKWISE
, "wheel-clockwise-2-spokes" },
138 { FadeEffect_CLOCKWISE
, "wheel-clockwise-3-spokes" },
139 { FadeEffect_CLOCKWISE
, "wheel-clockwise-4-spokes" },
140 { FadeEffect_CLOCKWISE
, "wheel-clockwise-8-spokes" },
142 { FadeEffect_FADE_FROM_CENTER
, "shape-circle" },
143 { FadeEffect_FADE_FROM_CENTER
, "shape-diamond" },
144 { FadeEffect_FADE_FROM_CENTER
, "shape-plus" },
146 { FadeEffect_CLOCKWISE
, "wedge" },
148 { FadeEffect_DISSOLVE
, "fade-through-black" },
150 { FadeEffect_CLOCKWISE
, "zoom-rotate-in" },
152 { FadeEffect_HORIZONTAL_LINES
, "comb-horizontal" },
153 { FadeEffect_VERTICAL_LINES
, "comb-vertical" },
155 { FadeEffect_DISSOLVE
, "fade-smoothly" },
157 { FadeEffect_NONE
, nullptr }
161 cut cut (same as NONE?)
162 cut-through-black cut toBlack
166 void EffectMigration::SetFadeEffect( SdPage
* pPage
, css::presentation::FadeEffect eNewEffect
)
168 deprecated_FadeEffect_conversion_table_entry
const * pEntry
= deprecated_FadeEffect_conversion_table
;
169 while( (pEntry
->meFadeEffect
!= FadeEffect_NONE
) && (pEntry
->meFadeEffect
!= eNewEffect
) )
172 if( pEntry
->mpPresetId
)
174 const OUString
aPresetId( OUString::createFromAscii( pEntry
->mpPresetId
) );
176 const TransitionPresetList
& rPresetList
= TransitionPreset::getTransitionPresetList();
178 auto aIt
= std::find_if(rPresetList
.begin(), rPresetList
.end(),
179 [&aPresetId
](const TransitionPresetPtr
& rxPreset
) { return rxPreset
->getPresetId() == aPresetId
; });
180 if (aIt
!= rPresetList
.end())
182 pPage
->setTransitionType( (*aIt
)->getTransition() );
183 pPage
->setTransitionSubtype( (*aIt
)->getSubtype() );
184 pPage
->setTransitionDirection( (*aIt
)->getDirection() );
185 pPage
->setTransitionFadeColor( (*aIt
)->getFadeColor() );
190 pPage
->setTransitionType( 0 );
191 pPage
->setTransitionSubtype( 0 );
192 pPage
->setTransitionDirection( false );
193 pPage
->setTransitionFadeColor( 0 );
197 FadeEffect
EffectMigration::GetFadeEffect( const SdPage
* pPage
)
199 const TransitionPresetList
& rPresetList
= TransitionPreset::getTransitionPresetList();
200 auto aIt
= std::find_if(rPresetList
.begin(), rPresetList
.end(),
201 [&pPage
](const TransitionPresetPtr
& rxPreset
) {
202 return (rxPreset
->getTransition() == pPage
->getTransitionType())
203 && (rxPreset
->getSubtype() == pPage
->getTransitionSubtype())
204 && (rxPreset
->getDirection() == pPage
->getTransitionDirection())
205 && (rxPreset
->getFadeColor() == pPage
->getTransitionFadeColor());
207 if (aIt
!= rPresetList
.end())
209 const OUString
& aPresetId
= (*aIt
)->getPresetId();
211 deprecated_FadeEffect_conversion_table_entry
const * pEntry
= deprecated_FadeEffect_conversion_table
;
212 while( (pEntry
->meFadeEffect
!= FadeEffect_NONE
) && (!aPresetId
.equalsAscii( pEntry
->mpPresetId
) ) )
215 return pEntry
->meFadeEffect
;
217 return FadeEffect_NONE
;
222 struct deprecated_AnimationEffect_conversion_table_entry
224 AnimationEffect meEffect
;
225 const char* mpPresetId
;
226 const char* mpPresetSubType
;
231 deprecated_AnimationEffect_conversion_table_entry
const deprecated_AnimationEffect_conversion_table
[] =
233 // OOo 1.x entrance effects
234 { AnimationEffect_APPEAR
, "ooo-entrance-appear",nullptr },
236 { AnimationEffect_FADE_TO_CENTER
, "ooo-entrance-box","in" },
237 { AnimationEffect_FADE_FROM_CENTER
, "ooo-entrance-box","out" },
239 { AnimationEffect_VERTICAL_CHECKERBOARD
, "ooo-entrance-checkerboard","downward" },
240 { AnimationEffect_HORIZONTAL_CHECKERBOARD
, "ooo-entrance-checkerboard","across" },
242 { AnimationEffect_FADE_FROM_UPPERLEFT
, "ooo-entrance-diagonal-squares","right-to-bottom" },
243 { AnimationEffect_FADE_FROM_UPPERRIGHT
, "ooo-entrance-diagonal-squares","left-to-bottom" },
244 { AnimationEffect_FADE_FROM_LOWERLEFT
, "ooo-entrance-diagonal-squares","right-to-top" },
245 { AnimationEffect_FADE_FROM_LOWERRIGHT
, "ooo-entrance-diagonal-squares","left-to-top" },
247 { AnimationEffect_DISSOLVE
, "ooo-entrance-dissolve-in",nullptr },
249 { AnimationEffect_MOVE_FROM_LEFT
, "ooo-entrance-fly-in","from-left" },
250 { AnimationEffect_MOVE_FROM_TOP
, "ooo-entrance-fly-in","from-top" },
251 { AnimationEffect_MOVE_FROM_RIGHT
, "ooo-entrance-fly-in","from-right" },
252 { AnimationEffect_MOVE_FROM_BOTTOM
, "ooo-entrance-fly-in","from-bottom" },
253 { AnimationEffect_MOVE_FROM_UPPERLEFT
, "ooo-entrance-fly-in","from-top-left" },
254 { AnimationEffect_MOVE_FROM_UPPERRIGHT
, "ooo-entrance-fly-in","from-top-right" },
255 { AnimationEffect_MOVE_FROM_LOWERRIGHT
, "ooo-entrance-fly-in","from-bottom-right" },
256 { AnimationEffect_MOVE_FROM_LOWERLEFT
, "ooo-entrance-fly-in","from-bottom-left" },
258 { AnimationEffect_MOVE_FROM_BOTTOM
, "ooo-entrance-fly-in-slow", "from-bottom" },
259 { AnimationEffect_MOVE_FROM_LEFT
, "ooo-entrance-fly-in-slow", "from-left" },
260 { AnimationEffect_MOVE_FROM_RIGHT
, "ooo-entrance-fly-in-slow", "from-right" },
261 { AnimationEffect_MOVE_FROM_TOP
, "ooo-entrance-fly-in-slow", "from-top" },
263 { AnimationEffect_MOVE_SHORT_FROM_LEFT
, "ooo-entrance-peek-in","from-left" },
264 { AnimationEffect_MOVE_SHORT_FROM_TOP
, "ooo-entrance-peek-in","from-top" },
265 { AnimationEffect_MOVE_SHORT_FROM_RIGHT
, "ooo-entrance-peek-in","from-right" },
266 { AnimationEffect_MOVE_SHORT_FROM_BOTTOM
, "ooo-entrance-peek-in","from-bottom" },
268 { AnimationEffect_VERTICAL_LINES
, "ooo-entrance-random-bars","horizontal" },
269 { AnimationEffect_HORIZONTAL_LINES
, "ooo-entrance-random-bars","vertical" },
271 { AnimationEffect_RANDOM
, "ooo-entrance-random",nullptr },
273 { AnimationEffect_CLOSE_VERTICAL
, "ooo-entrance-split","horizontal-in" },
274 { AnimationEffect_CLOSE_HORIZONTAL
, "ooo-entrance-split","vertical-in" },
275 { AnimationEffect_OPEN_VERTICAL
, "ooo-entrance-split","horizontal-out" },
276 { AnimationEffect_OPEN_HORIZONTAL
, "ooo-entrance-split","vertical-out" },
278 { AnimationEffect_VERTICAL_STRIPES
, "ooo-entrance-venetian-blinds","horizontal" },
279 { AnimationEffect_HORIZONTAL_STRIPES
, "ooo-entrance-venetian-blinds","vertical" },
281 { AnimationEffect_FADE_FROM_LEFT
, "ooo-entrance-wipe","from-left" },
282 { AnimationEffect_FADE_FROM_TOP
, "ooo-entrance-wipe","from-bottom" },
283 { AnimationEffect_FADE_FROM_RIGHT
, "ooo-entrance-wipe","from-right" },
284 { AnimationEffect_FADE_FROM_BOTTOM
, "ooo-entrance-wipe","from-top" },
286 { AnimationEffect_HORIZONTAL_ROTATE
, "ooo-entrance-swivel","vertical" },
287 { AnimationEffect_VERTICAL_ROTATE
, "ooo-entrance-swivel","horizontal" },
289 { AnimationEffect_STRETCH_FROM_LEFT
, "ooo-entrance-stretchy","from-left" },
290 { AnimationEffect_STRETCH_FROM_UPPERLEFT
, "ooo-entrance-stretchy","from-top-left" },
291 { AnimationEffect_STRETCH_FROM_TOP
, "ooo-entrance-stretchy","from-top" },
292 { AnimationEffect_STRETCH_FROM_UPPERRIGHT
, "ooo-entrance-stretchy","from-top-right" },
293 { AnimationEffect_STRETCH_FROM_RIGHT
, "ooo-entrance-stretchy","from-right" },
294 { AnimationEffect_STRETCH_FROM_LOWERRIGHT
, "ooo-entrance-stretchy","from-bottom-right" },
295 { AnimationEffect_STRETCH_FROM_BOTTOM
, "ooo-entrance-stretchy","from-bottom" },
296 { AnimationEffect_STRETCH_FROM_LOWERLEFT
, "ooo-entrance-stretchy","from-bottom-left" },
298 { AnimationEffect_HORIZONTAL_STRETCH
, "ooo-entrance-expand", nullptr },
300 { AnimationEffect_CLOCKWISE
, "ooo-entrance-wheel","1" },
301 { AnimationEffect_COUNTERCLOCKWISE
, "ooo-entrance-clock-wipe","counter-clockwise" },
303 { AnimationEffect_SPIRALIN_LEFT
, "ooo-entrance-spiral-wipe", "from-top-left-clockwise" },
304 { AnimationEffect_SPIRALIN_RIGHT
, "ooo-entrance-spiral-wipe", "from-top-right-counter-clockwise" },
305 { AnimationEffect_SPIRALOUT_LEFT
, "ooo-entrance-spiral-wipe", "from-center-clockwise" },
306 { AnimationEffect_SPIRALOUT_RIGHT
, "ooo-entrance-spiral-wipe", "from-center-counter-clockwise" },
308 { AnimationEffect_WAVYLINE_FROM_LEFT
, "ooo-entrance-snake-wipe","from-top-left-vertical" },
309 { AnimationEffect_WAVYLINE_FROM_TOP
, "ooo-entrance-snake-wipe","from-top-left-horizontal" },
310 { AnimationEffect_WAVYLINE_FROM_RIGHT
, "ooo-entrance-snake-wipe","from-bottom-right-vertical" },
311 { AnimationEffect_WAVYLINE_FROM_BOTTOM
, "ooo-entrance-snake-wipe","from-bottom-right-horizontal" },
313 // ooo 1.x exit effects
314 { AnimationEffect_HIDE
, "ooo-exit-disappear",nullptr },
315 { AnimationEffect_MOVE_TO_LEFT
, "ooo-exit-fly-out", "from-right" },
316 { AnimationEffect_MOVE_TO_TOP
, "ooo-exit-fly-out", "from-bottom" },
317 { AnimationEffect_MOVE_TO_RIGHT
, "ooo-exit-fly-out", "from-left" },
318 { AnimationEffect_MOVE_TO_BOTTOM
, "ooo-exit-fly-out", "from-top" },
319 { AnimationEffect_MOVE_TO_UPPERLEFT
, "ooo-exit-fly-out", "from-top-right" },
320 { AnimationEffect_MOVE_TO_UPPERRIGHT
, "ooo-exit-fly-out", "from-top-left" },
321 { AnimationEffect_MOVE_TO_LOWERRIGHT
, "ooo-exit-fly-out", "from-bottom-left" },
322 { AnimationEffect_MOVE_TO_LOWERLEFT
, "ooo-exit-fly-out", "from-bottom-right" },
323 { AnimationEffect_MOVE_SHORT_TO_LEFT
, "ooo-exit-peek-out", "from-right" },
324 { AnimationEffect_MOVE_SHORT_TO_UPPERLEFT
, "ooo-exit-peek-out", "from-right" },
325 { AnimationEffect_MOVE_SHORT_TO_TOP
, "ooo-exit-peek-out", "from-bottom" },
326 { AnimationEffect_MOVE_SHORT_TO_UPPERRIGHT
, "ooo-exit-peek-out", "from-bottom" },
327 { AnimationEffect_MOVE_SHORT_TO_RIGHT
, "ooo-exit-peek-out", "from-left" },
328 { AnimationEffect_MOVE_SHORT_TO_LOWERRIGHT
, "ooo-exit-peek-out","from-left" },
329 { AnimationEffect_MOVE_SHORT_TO_BOTTOM
, "ooo-exit-peek-out", "from-top" },
330 { AnimationEffect_MOVE_SHORT_TO_LOWERLEFT
, "ooo-exit-peek-out", "from-top" },
332 // no matching in OOo 2.x
333 { AnimationEffect_MOVE_SHORT_FROM_UPPERLEFT
, "ooo-entrance-peek-in","from-left" },
334 { AnimationEffect_MOVE_SHORT_FROM_UPPERRIGHT
, "ooo-entrance-peek-in","from-top" },
335 { AnimationEffect_MOVE_SHORT_FROM_LOWERRIGHT
, "ooo-entrance-peek-in","from-right" },
336 { AnimationEffect_MOVE_SHORT_FROM_LOWERLEFT
, "ooo-entrance-peek-in","from-bottom" },
337 { AnimationEffect_LASER_FROM_LEFT
, "ooo-entrance-fly-in","from-left" },
338 { AnimationEffect_LASER_FROM_TOP
, "ooo-entrance-fly-in","from-top" },
339 { AnimationEffect_LASER_FROM_RIGHT
, "ooo-entrance-fly-in","from-right" },
340 { AnimationEffect_LASER_FROM_BOTTOM
, "ooo-entrance-fly-in","from-bottom" },
341 { AnimationEffect_LASER_FROM_UPPERLEFT
, "ooo-entrance-fly-in","from-top-left" },
342 { AnimationEffect_LASER_FROM_UPPERRIGHT
, "ooo-entrance-fly-in","from-top-right" },
343 { AnimationEffect_LASER_FROM_LOWERLEFT
, "ooo-entrance-fly-in","from-bottom-left" },
344 { AnimationEffect_LASER_FROM_LOWERRIGHT
, "ooo-entrance-fly-in","from-bottom-right" },
346 // no matching in OOo 1.x
348 { AnimationEffect_FADE_TO_CENTER
, "ooo-entrance-circle", "in" },
349 { AnimationEffect_FADE_FROM_CENTER
, "ooo-entrance-circle", "out" },
350 { AnimationEffect_FADE_TO_CENTER
, "ooo-entrance-diamond", "in" },
351 { AnimationEffect_FADE_FROM_CENTER
, "ooo-entrance-diamond", "out" },
352 { AnimationEffect_FADE_TO_CENTER
, "ooo-entrance-plus", "in" },
353 { AnimationEffect_FADE_FROM_CENTER
, "ooo-entrance-plus", "out" },
354 { AnimationEffect_CLOCKWISE
, "ooo-entrance-wedge", nullptr },
355 { AnimationEffect_CLOCKWISE
, "ooo-entrance-wheel", "2" },
356 { AnimationEffect_CLOCKWISE
, "ooo-entrance-wheel", "3" },
357 { AnimationEffect_CLOCKWISE
, "ooo-entrance-wheel", "4" },
358 { AnimationEffect_CLOCKWISE
, "ooo-entrance-wheel", "8" },
360 { AnimationEffect_MOVE_FROM_RIGHT
, "ooo-entrance-boomerang", nullptr },
361 { AnimationEffect_MOVE_FROM_UPPERRIGHT
, "ooo-entrance-bounce", nullptr },
362 { AnimationEffect_MOVE_FROM_BOTTOM
, "ooo-entrance-curve-up", nullptr },
363 { AnimationEffect_MOVE_FROM_TOP
, "ooo-entrance-float", nullptr },
364 { AnimationEffect_MOVE_FROM_LEFT
, "ooo-entrance-glide", nullptr },
365 { AnimationEffect_MOVE_FROM_BOTTOM
, "ooo-entrance-magnify", nullptr },
366 { AnimationEffect_HORIZONTAL_ROTATE
, "ooo-entrance-pinwheel", nullptr },
367 { AnimationEffect_MOVE_FROM_LEFT
, "ooo-entrance-breaks", nullptr },
368 { AnimationEffect_MOVE_FROM_LEFT
, "ooo-entrance-sling", nullptr },
369 { AnimationEffect_MOVE_FROM_LEFT
, "ooo-entrance-spiral-in", nullptr },
370 { AnimationEffect_MOVE_FROM_LEFT
, "ooo-entrance-thread", nullptr },
371 { AnimationEffect_MOVE_FROM_BOTTOM
, "ooo-entrance-ascend", nullptr },
372 { AnimationEffect_MOVE_FROM_BOTTOM
, "ooo-entrance-center-revolve", nullptr },
373 { AnimationEffect_APPEAR
, "ooo-entrance-compress", nullptr },
374 { AnimationEffect_MOVE_SHORT_FROM_TOP
, "ooo-entrance-descend", nullptr },
375 { AnimationEffect_MOVE_SHORT_FROM_LEFT
, "ooo-entrance-ease-in", nullptr },
376 { AnimationEffect_MOVE_FROM_BOTTOM
, "ooo-entrance-rise-up", nullptr },
377 { AnimationEffect_HORIZONTAL_ROTATE
, "ooo-entrance-spin-in", nullptr },
378 { AnimationEffect_STRETCH_FROM_LEFT
, "ooo-entrance-stretchy", "across" },
379 { AnimationEffect_STRETCH_FROM_TOP
, "ooo-entrance-stretchy", "downward" },
381 { AnimationEffect_FADE_FROM_CENTER
, "ooo-entrance-zoom","in" },
382 { AnimationEffect_FADE_FROM_CENTER
, "ooo-entrance-zoom","in-slightly" },
383 { AnimationEffect_FADE_FROM_CENTER
, "ooo-entrance-zoom","in-from-screen-center" },
384 { AnimationEffect_FADE_TO_CENTER
, "ooo-entrance-zoom","out" },
385 { AnimationEffect_FADE_TO_CENTER
, "ooo-entrance-zoom","out-slightly" },
386 { AnimationEffect_FADE_TO_CENTER
, "ooo-entrance-zoom","out-from-screen-center" },
388 { AnimationEffect_DISSOLVE
, "ooo-entrance-fade-in", nullptr },
389 { AnimationEffect_DISSOLVE
, "ooo-entrance-fade-in-and-zoom", nullptr },
390 { AnimationEffect_DISSOLVE
, "ooo-entrance-fade-in-and-swivel", nullptr },
392 // still open (no matching effect: AnimationEffect_ZOOM_IN_FROM_*,
393 // AnimationEffect_ZOOM_OUT_FROM_*, AnimationEffect_PATH
395 { AnimationEffect_NONE
, nullptr, nullptr }
398 static EffectSequence::iterator
ImplFindEffect( MainSequencePtr
const & pMainSequence
, const Reference
< XShape
>& rShape
, sal_Int16 nSubItem
)
400 return std::find_if(pMainSequence
->getBegin(), pMainSequence
->getEnd(),
401 [&rShape
, &nSubItem
](const CustomAnimationEffectPtr
& pEffect
) {
402 return (pEffect
->getTargetShape() == rShape
)
403 && (pEffect
->getTargetSubItem() == nSubItem
);
407 static bool implIsInsideGroup( SdrObject
const * pObj
)
409 // TTTT for current state of transition, SdrObject has a parent*
410 // to a SdrObjList. That may be a SdrPage or a SdrObjGroup, both
411 // are already derived from SdrObjList. To finally check, use
412 // the method 'getSdrObjectFromSdrObjList' - if it's not a SdrPage,
413 // it will return SdrObjGroup or E3dScene -> SdrObject.
414 // For future states, test for SdrObject. Trying to get the SdrPage
415 // will in the future depend on the Object(this) to be inserted to a
416 // SdrPage, regardless of e.g. being a group member.
422 SdrObjList
* pSdrObjList(pObj
->getParentSdrObjListFromSdrObject());
424 if(nullptr == pSdrObjList
)
429 return (nullptr != pSdrObjList
->getSdrObjectFromSdrObjList());
432 void EffectMigration::SetAnimationEffect( SvxShape
* pShape
, AnimationEffect eEffect
)
434 DBG_ASSERT( pShape
&& pShape
->GetSdrObject() && pShape
->GetSdrObject()->getSdrPageFromSdrObject(),
435 "sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
436 if( !pShape
|| !pShape
->GetSdrObject() || !pShape
->GetSdrObject()->getSdrPageFromSdrObject() )
439 SdrObject
* pObj
= pShape
->GetSdrObject();
440 if( implIsInsideGroup( pObj
) )
444 OUString aPresetSubType
;
446 if( !ConvertAnimationEffect( eEffect
, aPresetId
, aPresetSubType
) )
448 OSL_FAIL( "sd::EffectMigration::SetAnimationEffect(), no mapping for given AnimationEffect value" );
452 const CustomAnimationPresets
& rPresets
= CustomAnimationPresets::getCustomAnimationPresets();
454 CustomAnimationPresetPtr
pPreset( rPresets
.getEffectDescriptor( aPresetId
) );
455 sd::MainSequencePtr pMainSequence
= static_cast<SdPage
*>(pObj
->getSdrPageFromSdrObject())->getMainSequence();
457 if( !(pPreset
&& pMainSequence
) )
460 const Reference
< XShape
> xShape( pShape
);
462 EffectSequence::iterator
aIterOnlyBackground( ImplFindEffect( pMainSequence
, xShape
, ShapeAnimationSubType::ONLY_BACKGROUND
) );
463 EffectSequence::iterator
aIterAsWhole( ImplFindEffect( pMainSequence
, xShape
, ShapeAnimationSubType::AS_WHOLE
) );
464 const EffectSequence::iterator
aEnd( pMainSequence
->getEnd() );
466 if( (aIterOnlyBackground
== aEnd
) && (aIterAsWhole
== aEnd
) )
468 bool bEffectCreated
= false;
470 // check if there is already a text effect for this shape
471 EffectSequence::iterator
aIterOnlyText( ImplFindEffect( pMainSequence
, xShape
, ShapeAnimationSubType::ONLY_TEXT
) );
472 if( aIterOnlyText
!= aEnd
)
474 // check if this is an animation text group
475 sal_Int32 nGroupId
= (*aIterOnlyText
)->getGroupId();
478 CustomAnimationTextGroupPtr pGroup
= pMainSequence
->findGroup( nGroupId
);
481 // add an effect to animate the shape
482 pMainSequence
->setAnimateForm( pGroup
, true );
485 EffectSequence::iterator
aIter( ImplFindEffect( pMainSequence
, xShape
, ShapeAnimationSubType::ONLY_BACKGROUND
) );
489 if( ((*aIter
)->getPresetId() != aPresetId
) ||
490 ((*aIter
)->getPresetSubType() != aPresetSubType
) )
492 (*aIter
)->replaceNode( pPreset
->create( aPresetSubType
) );
493 pMainSequence
->rebuild();
494 bEffectCreated
= true;
501 if( !bEffectCreated
)
503 // if there is not yet an effect that target this shape, we generate one
504 // we insert the shape effect before it
505 Reference
< XAnimationNode
> xNode( pPreset
->create( aPresetSubType
) );
506 DBG_ASSERT( xNode
.is(), "EffectMigration::SetAnimationEffect(), could not create preset!" );
509 CustomAnimationEffectPtr pEffect
= std::make_shared
<CustomAnimationEffect
>( xNode
);
510 pEffect
->setTarget( makeAny( xShape
) );
511 SdPage
* pPage
= dynamic_cast< SdPage
* >( pObj
->getSdrPageFromSdrObject() );
512 const bool bManual
= (pPage
== nullptr) || (pPage
->GetPresChange() == PresChange::Manual
);
514 pEffect
->setNodeType( EffectNodeType::AFTER_PREVIOUS
);
516 pMainSequence
->append( pEffect
);
518 if( ( pObj
->GetObjInventor() == SdrInventor::Default
) && ( pObj
->GetObjIdentifier() == OBJ_OUTLINETEXT
) )
520 // special case for outline text, effects are always mapped to text group effect
522 createTextGroup( pEffect
, 10, bManual
? -1 : 0.0, false, false );
529 // if there is already an effect targeting this shape
531 CustomAnimationEffectPtr pEffect
;
532 if( aIterAsWhole
!= aEnd
)
534 pEffect
= *aIterAsWhole
;
538 pEffect
= *aIterOnlyBackground
;
543 if( (pEffect
->getPresetId() != aPresetId
) ||
544 (pEffect
->getPresetSubType() != aPresetSubType
) )
546 pMainSequence
->replace( pEffect
, pPreset
, aPresetSubType
, -1.0 );
552 AnimationEffect
EffectMigration::GetAnimationEffect( SvxShape
* pShape
)
555 OUString aPresetSubType
;
557 SdrObject
* pObj
= pShape
->GetSdrObject();
558 sd::MainSequencePtr pMainSequence
= static_cast<SdPage
*>(pObj
->getSdrPageFromSdrObject())->getMainSequence();
562 const Reference
< XShape
> xShape( pShape
);
564 EffectSequence::iterator aIter
= std::find_if(pMainSequence
->getBegin(), pMainSequence
->getEnd(),
565 [&xShape
](const CustomAnimationEffectPtr
& pEffect
) {
566 return (pEffect
->getTargetShape() == xShape
)
567 && ((pEffect
->getTargetSubItem() == ShapeAnimationSubType::ONLY_BACKGROUND
)
568 || (pEffect
->getTargetSubItem() == ShapeAnimationSubType::AS_WHOLE
))
569 && (pEffect
->getDuration() != 0.1); // ignore appear effects created from old text effect import
572 if (aIter
!= pMainSequence
->getEnd())
574 aPresetId
= (*aIter
)->getPresetId();
575 aPresetSubType
= (*aIter
)->getPresetSubType();
579 // now find old effect
580 AnimationEffect eEffect
= AnimationEffect_NONE
;
582 if( !ConvertPreset( aPresetId
, &aPresetSubType
, eEffect
) )
583 ConvertPreset( aPresetId
, nullptr, eEffect
);
588 void EffectMigration::SetTextAnimationEffect( SvxShape
* pShape
, AnimationEffect eEffect
)
590 DBG_ASSERT( pShape
&& pShape
->GetSdrObject() && pShape
->GetSdrObject()->getSdrPageFromSdrObject(),
591 "sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
592 if( !pShape
|| !pShape
->GetSdrObject() || !pShape
->GetSdrObject()->getSdrPageFromSdrObject() )
595 SdrObject
* pObj
= pShape
->GetSdrObject();
596 if( implIsInsideGroup( pObj
) )
599 // first map the deprecated AnimationEffect to a preset and subtype
601 OUString aPresetSubType
;
603 if( !ConvertAnimationEffect( eEffect
, aPresetId
, aPresetSubType
) )
605 OSL_FAIL( "sd::EffectMigration::SetAnimationEffect(), no mapping for given AnimationEffect value" );
609 SdrTextObj
* pTextObj
= dynamic_cast< SdrTextObj
* >( pObj
);
611 // ignore old text effects on shape without text
612 if( (pTextObj
== nullptr) || (!pTextObj
->HasText()) )
615 const CustomAnimationPresets
& rPresets
= CustomAnimationPresets::getCustomAnimationPresets();
617 // create an effect from this preset
618 CustomAnimationPresetPtr
pPreset( rPresets
.getEffectDescriptor( aPresetId
) );
620 sd::MainSequencePtr pMainSequence
= static_cast<SdPage
*>(pObj
->getSdrPageFromSdrObject())->getMainSequence();
622 if( !(pPreset
&& pMainSequence
) )
625 const Reference
< XShape
> xShape( pShape
);
627 EffectSequence::iterator
aIterOnlyText( ImplFindEffect( pMainSequence
, xShape
, ShapeAnimationSubType::ONLY_TEXT
) );
628 const EffectSequence::iterator
aEnd( pMainSequence
->getEnd() );
630 CustomAnimationTextGroupPtr pGroup
;
632 // is there already an animation text group for this shape?
633 if( aIterOnlyText
!= aEnd
)
635 const sal_Int32 nGroupId
= (*aIterOnlyText
)->getGroupId();
637 pGroup
= pMainSequence
->findGroup( nGroupId
);
640 // if there is not yet a group, create it
643 CustomAnimationEffectPtr pShapeEffect
;
645 EffectSequence::iterator
aIterOnlyBackground( ImplFindEffect( pMainSequence
, xShape
, ShapeAnimationSubType::ONLY_BACKGROUND
) );
646 if( aIterOnlyBackground
!= aEnd
)
648 pShapeEffect
= *aIterOnlyBackground
;
652 EffectSequence::iterator
aIterAsWhole( ImplFindEffect( pMainSequence
, xShape
, ShapeAnimationSubType::AS_WHOLE
) );
653 if( aIterAsWhole
!= aEnd
)
655 pShapeEffect
= *aIterAsWhole
;
659 Reference
< XAnimationNode
> xNode( pPreset
->create( "" ) );
660 DBG_ASSERT( xNode
.is(), "EffectMigration::SetTextAnimationEffect(), could not create preset!" );
663 pShapeEffect
= std::make_shared
<CustomAnimationEffect
>( xNode
);
664 pShapeEffect
->setTarget( makeAny( xShape
) );
665 pShapeEffect
->setDuration( 0.1 );
666 pMainSequence
->append( pShapeEffect
);
668 SdPage
* pPage
= dynamic_cast< SdPage
* >( pObj
->getSdrPageFromSdrObject() );
669 if( pPage
&& pPage
->GetPresChange() != PresChange::Manual
)
670 pShapeEffect
->setNodeType( EffectNodeType::AFTER_PREVIOUS
);
677 SdPage
* pPage
= dynamic_cast< SdPage
* >( pObj
->getSdrPageFromSdrObject() );
678 const bool bManual
= (pPage
== nullptr) || (pPage
->GetPresChange() == PresChange::Manual
);
680 // now create effects for each paragraph
683 createTextGroup( pShapeEffect
, 10, bManual
? -1 : 0.0, true, false );
689 const bool bLaserEffect
= (eEffect
>= AnimationEffect_LASER_FROM_LEFT
) && (eEffect
<= AnimationEffect_LASER_FROM_LOWERRIGHT
);
691 // now we have a group, so check if all effects are same as we like to have them
692 const EffectSequence
& rEffects
= pGroup
->getEffects();
694 for( auto& rxEffect
: rEffects
)
696 // only work on paragraph targets
697 if( rxEffect
->getTarget().getValueType() == ::cppu::UnoType
<ParagraphTarget
>::get() )
699 if( (rxEffect
->getPresetId() != aPresetId
) ||
700 (rxEffect
->getPresetSubType() != aPresetSubType
) )
702 rxEffect
->replaceNode( pPreset
->create( aPresetSubType
) );
707 rxEffect
->setIterateType( TextAnimationType::BY_LETTER
);
708 rxEffect
->setIterateInterval( 0.5 );// TODO:
720 pMainSequence
->rebuild();
723 AnimationEffect
EffectMigration::GetTextAnimationEffect( SvxShape
* pShape
)
726 OUString aPresetSubType
;
728 SdrObject
* pObj
= pShape
->GetSdrObject();
731 sd::MainSequencePtr pMainSequence
= static_cast<SdPage
*>(pObj
->getSdrPageFromSdrObject())->getMainSequence();
735 const Reference
< XShape
> xShape( pShape
);
736 EffectSequence::iterator
aIter( ImplFindEffect( pMainSequence
, xShape
, ShapeAnimationSubType::ONLY_TEXT
) );
737 if( aIter
!= pMainSequence
->getEnd() )
739 aPresetId
= (*aIter
)->getPresetId();
740 aPresetSubType
= (*aIter
)->getPresetSubType();
745 // now find old effect
746 AnimationEffect eEffect
= AnimationEffect_NONE
;
748 if( !ConvertPreset( aPresetId
, &aPresetSubType
, eEffect
) )
749 ConvertPreset( aPresetId
, nullptr, eEffect
);
754 bool EffectMigration::ConvertPreset( const OUString
& rPresetId
, const OUString
* pPresetSubType
, AnimationEffect
& rEffect
)
756 rEffect
= AnimationEffect_NONE
;
757 if( !rPresetId
.isEmpty() )
759 // first try a match for preset id and subtype
760 deprecated_AnimationEffect_conversion_table_entry
const * p
= deprecated_AnimationEffect_conversion_table
;
761 while( p
->mpPresetId
)
763 if( rPresetId
.equalsAscii( p
->mpPresetId
) &&
764 (( p
->mpPresetSubType
== nullptr ) ||
765 ( pPresetSubType
== nullptr) ||
766 ( pPresetSubType
->equalsAscii( p
->mpPresetSubType
)) ) )
768 rEffect
= p
->meEffect
;
777 // empty preset id means AnimationEffect_NONE
782 bool EffectMigration::ConvertAnimationEffect( const AnimationEffect
& rEffect
, OUString
& rPresetId
, OUString
& rPresetSubType
)
784 deprecated_AnimationEffect_conversion_table_entry
const * p
= deprecated_AnimationEffect_conversion_table
;
785 while( p
->mpPresetId
)
787 if( p
->meEffect
== rEffect
)
789 rPresetId
= OUString::createFromAscii( p
->mpPresetId
);
790 rPresetSubType
= OUString::createFromAscii( p
->mpPresetSubType
);
799 double EffectMigration::ConvertAnimationSpeed( AnimationSpeed eSpeed
)
804 case AnimationSpeed_SLOW
: fDuration
= 2.0; break;
805 case AnimationSpeed_FAST
: fDuration
= 0.5; break;
807 fDuration
= 1.0; break;
812 void EffectMigration::SetAnimationSpeed( SvxShape
* pShape
, AnimationSpeed eSpeed
)
814 DBG_ASSERT( pShape
&& pShape
->GetSdrObject() && pShape
->GetSdrObject()->getSdrPageFromSdrObject(),
815 "sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
816 if( !pShape
|| !pShape
->GetSdrObject() || !pShape
->GetSdrObject()->getSdrPageFromSdrObject() )
819 SdrObject
* pObj
= pShape
->GetSdrObject();
820 if( implIsInsideGroup( pObj
) )
823 double fDuration
= ConvertAnimationSpeed( eSpeed
);
825 sd::MainSequencePtr pMainSequence
= static_cast<SdPage
*>(pObj
->getSdrPageFromSdrObject())->getMainSequence();
827 const Reference
< XShape
> xShape( pShape
);
829 EffectSequence::iterator aIter
;
830 bool bNeedRebuild
= false;
832 for( aIter
= pMainSequence
->getBegin(); aIter
!= pMainSequence
->getEnd(); ++aIter
)
834 CustomAnimationEffectPtr
pEffect( *aIter
);
835 if( pEffect
->getTargetShape() == xShape
)
837 if( pEffect
->getDuration() != 0.1 )
838 pEffect
->setDuration( fDuration
);
844 pMainSequence
->rebuild();
847 AnimationSpeed
EffectMigration::GetAnimationSpeed( SvxShape
* pShape
)
849 SdrObject
* pObj
= pShape
->GetSdrObject();
850 sd::MainSequencePtr pMainSequence
= static_cast<SdPage
*>(pObj
->getSdrPageFromSdrObject())->getMainSequence();
852 const Reference
< XShape
> xShape( pShape
);
854 double fDuration
= 1.0;
856 EffectSequence::iterator aIter
= std::find_if(pMainSequence
->getBegin(), pMainSequence
->getEnd(),
857 [&xShape
](const CustomAnimationEffectPtr
& pEffect
) {
858 return (pEffect
->getTargetShape() == xShape
)
859 && (pEffect
->getDuration() != 0.1);
861 if (aIter
!= pMainSequence
->getEnd())
863 CustomAnimationEffectPtr
pEffect( *aIter
);
864 fDuration
= pEffect
->getDuration();
867 return ConvertDuration( fDuration
);
870 AnimationSpeed
EffectMigration::ConvertDuration( double fDuration
)
872 AnimationSpeed eSpeed
;
874 if( fDuration
< 1.0 )
875 eSpeed
= AnimationSpeed_FAST
;
876 else if( fDuration
> 1.5 )
877 eSpeed
= AnimationSpeed_SLOW
;
879 eSpeed
= AnimationSpeed_MEDIUM
;
884 void EffectMigration::SetDimColor( SvxShape
* pShape
, sal_Int32 nColor
)
886 DBG_ASSERT( pShape
&& pShape
->GetSdrObject() && pShape
->GetSdrObject()->getSdrPageFromSdrObject(),
887 "sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
888 if( !pShape
|| !pShape
->GetSdrObject() || !pShape
->GetSdrObject()->getSdrPageFromSdrObject() )
891 SdrObject
* pObj
= pShape
->GetSdrObject();
892 if( implIsInsideGroup( pObj
) )
895 sd::MainSequencePtr pMainSequence
= static_cast<SdPage
*>(pObj
->getSdrPageFromSdrObject())->getMainSequence();
897 const Reference
< XShape
> xShape( pShape
);
899 EffectSequence::iterator aIter
;
900 bool bNeedRebuild
= false;
902 for( aIter
= pMainSequence
->getBegin(); aIter
!= pMainSequence
->getEnd(); ++aIter
)
904 CustomAnimationEffectPtr
pEffect( *aIter
);
905 if( pEffect
->getTargetShape() == xShape
)
907 pEffect
->setHasAfterEffect( true );
908 pEffect
->setDimColor( makeAny( nColor
) );
909 pEffect
->setAfterEffectOnNext( true );
915 pMainSequence
->rebuild();
918 sal_Int32
EffectMigration::GetDimColor( SvxShape
* pShape
)
920 sal_Int32 nColor
= 0;
923 SdrObject
* pObj
= pShape
->GetSdrObject();
924 if( pObj
&& pObj
->getSdrPageFromSdrObject() )
926 sd::MainSequencePtr pMainSequence
= static_cast<SdPage
*>(pObj
->getSdrPageFromSdrObject())->getMainSequence();
928 const Reference
< XShape
> xShape( pShape
);
929 EffectSequence::iterator aIter
= std::find_if(pMainSequence
->getBegin(), pMainSequence
->getEnd(),
930 [&xShape
](const CustomAnimationEffectPtr
& pEffect
) {
931 return (pEffect
->getTargetShape() == xShape
)
932 && pEffect
->getDimColor().hasValue()
933 && pEffect
->hasAfterEffect();
935 if (aIter
!= pMainSequence
->getEnd())
937 CustomAnimationEffectPtr
pEffect( *aIter
);
938 pEffect
->getDimColor() >>= nColor
;
946 void EffectMigration::SetDimHide( SvxShape
* pShape
, bool bDimHide
)
948 DBG_ASSERT( pShape
&& pShape
->GetSdrObject() && pShape
->GetSdrObject()->getSdrPageFromSdrObject(),
949 "sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
950 if( !pShape
|| !pShape
->GetSdrObject() || !pShape
->GetSdrObject()->getSdrPageFromSdrObject() )
953 SdrObject
* pObj
= pShape
->GetSdrObject();
954 if( implIsInsideGroup( pObj
) )
957 sd::MainSequencePtr pMainSequence
= static_cast<SdPage
*>(pObj
->getSdrPageFromSdrObject())->getMainSequence();
959 const Reference
< XShape
> xShape( pShape
);
961 EffectSequence::iterator aIter
;
962 bool bNeedRebuild
= false;
964 for( aIter
= pMainSequence
->getBegin(); aIter
!= pMainSequence
->getEnd(); ++aIter
)
966 CustomAnimationEffectPtr
pEffect( *aIter
);
967 if( pEffect
->getTargetShape() == xShape
)
969 pEffect
->setHasAfterEffect( bDimHide
);
972 pEffect
->setDimColor( aEmpty
);
974 pEffect
->setAfterEffectOnNext( false );
980 pMainSequence
->rebuild();
983 bool EffectMigration::GetDimHide( SvxShape
* pShape
)
988 SdrObject
* pObj
= pShape
->GetSdrObject();
989 if( pObj
&& pObj
->getSdrPageFromSdrObject() )
991 sd::MainSequencePtr pMainSequence
= static_cast<SdPage
*>(pObj
->getSdrPageFromSdrObject())->getMainSequence();
993 const Reference
< XShape
> xShape( pShape
);
995 EffectSequence::iterator aIter
= std::find_if(pMainSequence
->getBegin(), pMainSequence
->getEnd(),
996 [&xShape
](const CustomAnimationEffectPtr
& pEffect
) { return pEffect
->getTargetShape() == xShape
; });
997 if (aIter
!= pMainSequence
->getEnd())
999 CustomAnimationEffectPtr
pEffect( *aIter
);
1000 bRet
= pEffect
->hasAfterEffect() &&
1001 !pEffect
->getDimColor().hasValue() &&
1002 (!pEffect
->IsAfterEffectOnNext());
1010 void EffectMigration::SetDimPrevious( SvxShape
* pShape
, bool bDimPrevious
)
1012 DBG_ASSERT( pShape
&& pShape
->GetSdrObject() && pShape
->GetSdrObject()->getSdrPageFromSdrObject(),
1013 "sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
1014 if( !pShape
|| !pShape
->GetSdrObject() || !pShape
->GetSdrObject()->getSdrPageFromSdrObject() )
1017 SdrObject
* pObj
= pShape
->GetSdrObject();
1018 if( implIsInsideGroup( pObj
) )
1024 aColor
<<= COL_LIGHTGRAY
;
1026 sd::MainSequencePtr pMainSequence
= static_cast<SdPage
*>(pObj
->getSdrPageFromSdrObject())->getMainSequence();
1028 const Reference
< XShape
> xShape( pShape
);
1030 EffectSequence::iterator aIter
;
1031 bool bNeedRebuild
= false;
1033 for( aIter
= pMainSequence
->getBegin(); aIter
!= pMainSequence
->getEnd(); ++aIter
)
1035 CustomAnimationEffectPtr
pEffect( *aIter
);
1036 if( pEffect
->getTargetShape() == xShape
)
1038 pEffect
->setHasAfterEffect( bDimPrevious
);
1039 if( !bDimPrevious
|| !pEffect
->getDimColor().hasValue() )
1040 pEffect
->setDimColor( aColor
);
1041 pEffect
->setAfterEffectOnNext( true );
1042 bNeedRebuild
= true;
1047 pMainSequence
->rebuild();
1050 bool EffectMigration::GetDimPrevious( SvxShape
* pShape
)
1055 SdrObject
* pObj
= pShape
->GetSdrObject();
1056 if( pObj
&& pObj
->getSdrPageFromSdrObject() )
1058 sd::MainSequencePtr pMainSequence
= static_cast<SdPage
*>(pObj
->getSdrPageFromSdrObject())->getMainSequence();
1060 const Reference
< XShape
> xShape( pShape
);
1062 EffectSequence::iterator aIter
= std::find_if(pMainSequence
->getBegin(), pMainSequence
->getEnd(),
1063 [&xShape
](const CustomAnimationEffectPtr
& pEffect
) { return pEffect
->getTargetShape() == xShape
; });
1064 if (aIter
!= pMainSequence
->getEnd())
1066 CustomAnimationEffectPtr
pEffect( *aIter
);
1067 bRet
= pEffect
->hasAfterEffect() &&
1068 pEffect
->getDimColor().hasValue() &&
1069 pEffect
->IsAfterEffectOnNext();
1077 void EffectMigration::SetPresentationOrder( SvxShape
* pShape
, sal_Int32 nNewPos
)
1079 if( !pShape
|| !pShape
->GetSdrObject() || !pShape
->GetSdrObject()->getSdrPageFromSdrObject() )
1082 SdrObject
* pObj
= pShape
->GetSdrObject();
1083 sd::MainSequencePtr pMainSequence
= static_cast<SdPage
*>(pObj
->getSdrPageFromSdrObject())->getMainSequence();
1085 EffectSequence
& rSequence
= pMainSequence
->getSequence();
1087 sal_Int32 nCurrentPos
= -1;
1088 std::vector
< std::vector
< EffectSequence::iterator
> > aEffectVector(1);
1090 if( !rSequence
.empty() )
1092 Reference
< XShape
> xThis( pShape
);
1093 Reference
< XShape
> xCurrent
;
1095 EffectSequence::iterator
aIter( rSequence
.begin() );
1096 EffectSequence::iterator
aEnd( rSequence
.end() );
1097 for( nPos
= 0; aIter
!= aEnd
; ++aIter
)
1099 CustomAnimationEffectPtr pEffect
= *aIter
;
1101 if( !xCurrent
.is() )
1103 xCurrent
= pEffect
->getTargetShape();
1105 else if( pEffect
->getTargetShape() != xCurrent
)
1108 xCurrent
= pEffect
->getTargetShape();
1109 aEffectVector
.resize( nPos
+1 );
1112 // is this the first effect for xThis shape?
1113 if(( nCurrentPos
== -1 ) && ( xCurrent
== xThis
) )
1118 aEffectVector
[nPos
].push_back( aIter
);
1122 // check if there is at least one effect for xThis
1123 if( nCurrentPos
== -1 )
1125 OSL_FAIL("sd::EffectMigration::SetPresentationOrder() failed cause this shape has no effect" );
1129 // check trivial case
1130 if( nCurrentPos
== nNewPos
)
1133 std::vector
< CustomAnimationEffectPtr
> aEffects
;
1135 for( const auto& rIter
: aEffectVector
[nCurrentPos
] )
1137 aEffects
.push_back( *rIter
);
1138 rSequence
.erase( rIter
);
1141 if( nNewPos
> nCurrentPos
)
1144 if( nNewPos
== static_cast<sal_Int32
>(aEffectVector
.size()) )
1146 rSequence
.insert( rSequence
.end(), aEffects
.begin(), aEffects
.end() );
1150 EffectSequence::iterator
aPos( aEffectVector
[nNewPos
][0] );
1151 for( const auto& rEffect
: aEffects
)
1153 rSequence
.insert( aPos
, rEffect
);
1158 /** Returns the position of the given SdrObject in the Presentation order.
1159 * This function returns -1 if the SdrObject is not in the Presentation order
1160 * or if it's the path-object.
1162 sal_Int32
EffectMigration::GetPresentationOrder( SvxShape
* pShape
)
1164 sal_Int32 nPos
= -1, nFound
= -1;
1166 SdrObject
* pObj
= pShape
->GetSdrObject();
1167 sd::MainSequencePtr pMainSequence
= static_cast<SdPage
*>(pObj
->getSdrPageFromSdrObject())->getMainSequence();
1169 EffectSequence
& rSequence
= pMainSequence
->getSequence();
1171 Reference
< XShape
> xThis( pShape
);
1172 Reference
< XShape
> xCurrent
;
1174 for( const CustomAnimationEffectPtr
& pEffect
: rSequence
)
1176 if( !xCurrent
.is() || pEffect
->getTargetShape() != xCurrent
)
1179 xCurrent
= pEffect
->getTargetShape();
1181 // is this the first effect for xThis shape?
1182 if( xCurrent
== xThis
)
1193 void EffectMigration::UpdateSoundEffect( SvxShape
* pShape
, SdAnimationInfo
const * pInfo
)
1198 SdrObject
* pObj
= pShape
->GetSdrObject();
1199 sd::MainSequencePtr pMainSequence
= static_cast<SdPage
*>(pObj
->getSdrPageFromSdrObject())->getMainSequence();
1201 const Reference
< XShape
> xShape( pShape
);
1203 EffectSequence::iterator aIter
;
1204 bool bNeedRebuild
= false;
1206 OUString aSoundFile
;
1207 if( pInfo
->mbSoundOn
)
1208 aSoundFile
= pInfo
->maSoundFile
;
1210 for( aIter
= pMainSequence
->getBegin(); aIter
!= pMainSequence
->getEnd(); ++aIter
)
1212 CustomAnimationEffectPtr
pEffect( *aIter
);
1213 if( pEffect
->getTargetShape() == xShape
)
1215 if( !aSoundFile
.isEmpty() )
1217 pEffect
->createAudio( makeAny( aSoundFile
) );
1221 pEffect
->removeAudio();
1223 bNeedRebuild
= true;
1228 pMainSequence
->rebuild();
1231 OUString
EffectMigration::GetSoundFile( SvxShape
* pShape
)
1233 OUString aSoundFile
;
1237 SdrObject
* pObj
= pShape
->GetSdrObject();
1238 if( pObj
&& pObj
->getSdrPageFromSdrObject() )
1240 sd::MainSequencePtr pMainSequence
= static_cast<SdPage
*>(pObj
->getSdrPageFromSdrObject())->getMainSequence();
1242 const Reference
< XShape
> xShape( pShape
);
1244 EffectSequence::iterator aIter
;
1246 for( aIter
= pMainSequence
->getBegin();
1247 (aSoundFile
.isEmpty()) && (aIter
!= pMainSequence
->getEnd());
1250 CustomAnimationEffectPtr
pEffect( *aIter
);
1251 if( pEffect
->getTargetShape() == xShape
)
1253 if( pEffect
->getAudio().is() )
1254 pEffect
->getAudio()->getSource() >>= aSoundFile
;
1262 bool EffectMigration::GetSoundOn( SvxShape
* pShape
)
1264 return !GetSoundFile( pShape
).isEmpty();
1267 void EffectMigration::SetAnimationPath( SvxShape
* pShape
, SdrPathObj
const * pPathObj
)
1269 if( !(pShape
&& pPathObj
) )
1272 SdrObject
* pObj
= pShape
->GetSdrObject();
1276 const Reference
< XShape
> xShape( pShape
);
1277 SdPage
* pPage
= dynamic_cast< SdPage
* >(pPathObj
->getSdrPageFromSdrObject());
1280 std::shared_ptr
< sd::MainSequence
> pMainSequence( pPage
->getMainSequence() );
1282 pMainSequence
->append( *pPathObj
, makeAny( xShape
), -1.0, "" );
1287 // #i42894# helper which creates the needed XAnimate for changing visibility and all the (currently) needed embeddings
1288 static void createVisibilityOnOffNode(Reference
< XTimeContainer
> const & rxParentContainer
, SdrObject
& rCandidate
, bool bVisible
, bool bOnClick
, double fDuration
)
1290 Reference
< XMultiServiceFactory
> xMsf(::comphelper::getProcessServiceFactory());
1292 // create par container node
1293 Reference
< XAnimationNode
> xOuterSeqTimeContainer(xMsf
->createInstance("com.sun.star.animations.ParallelTimeContainer"), UNO_QUERY_THROW
);
1296 xOuterSeqTimeContainer
->setBegin(Any(0.0));
1299 xOuterSeqTimeContainer
->setFill(AnimationFill::HOLD
);
1302 Sequence
< NamedValue
> aUserDataSequence
;
1303 aUserDataSequence
.realloc(1);
1305 aUserDataSequence
[0].Name
= "node-type";
1306 aUserDataSequence
[0].Value
<<= bOnClick
? EffectNodeType::ON_CLICK
: EffectNodeType::AFTER_PREVIOUS
;
1308 xOuterSeqTimeContainer
->setUserData(aUserDataSequence
);
1310 // create animate set to change visibility for rCandidate
1311 Reference
< XAnimationNode
> xAnimateSetForLast(xMsf
->createInstance("com.sun.star.animations.AnimateSet"), UNO_QUERY_THROW
);
1314 xAnimateSetForLast
->setBegin(Any(0.0));
1317 xAnimateSetForLast
->setDuration(Any(fDuration
));
1320 xAnimateSetForLast
->setFill(AnimationFill::HOLD
);
1323 Reference
< XAnimate
> xAnimate(xAnimateSetForLast
, UNO_QUERY
);
1324 Reference
< XShape
> xTargetShape(rCandidate
.getUnoShape(), UNO_QUERY
);
1325 xAnimate
->setTarget(Any(xTargetShape
));
1327 // set AttributeName
1328 xAnimate
->setAttributeName("Visibility");
1330 // set attribute value
1331 xAnimate
->setTo(Any(bVisible
));
1333 // ad set node to par node
1334 Reference
< XTimeContainer
> xParentContainer(xOuterSeqTimeContainer
, UNO_QUERY_THROW
);
1335 xParentContainer
->appendChild(xAnimateSetForLast
);
1338 rxParentContainer
->appendChild(xOuterSeqTimeContainer
);
1341 // #i42894# older native formats supported animated group objects, that means all members of the group
1342 // were shown animated by showing one after the other. This is no longer supported, but the following
1343 // fallback will create the needed SMIL animation stuff. Unfortunately the members of the group
1344 // have to be moved directly to the page, else the (explained to be generic, thus I expected this to
1345 // work) animations will not work in slideshow
1346 void EffectMigration::CreateAnimatedGroup(SdrObjGroup
const & rGroupObj
, SdPage
& rPage
)
1348 // aw080 will give a vector immediately
1349 SdrObjListIter
aIter(rGroupObj
);
1354 std::shared_ptr
< sd::MainSequence
> pMainSequence(rPage
.getMainSequence());
1359 std::vector
< SdrObject
* > aObjects
;
1360 aObjects
.reserve(aIter
.Count());
1362 while(aIter
.IsMore())
1364 // do move to page rough with old/current stuff, will be different in aw080 anyways
1365 SdrObject
* pCandidate
= aIter
.Next();
1366 rGroupObj
.GetSubList()->NbcRemoveObject(pCandidate
->GetOrdNum());
1367 rPage
.NbcInsertObject(pCandidate
);
1368 aObjects
.push_back(pCandidate
);
1372 Reference
< XMultiServiceFactory
> xMsf(::comphelper::getProcessServiceFactory());
1373 Reference
< XAnimationNode
> xOuterSeqTimeContainer(xMsf
->createInstance("com.sun.star.animations.ParallelTimeContainer"), UNO_QUERY_THROW
);
1376 xOuterSeqTimeContainer
->setBegin(Any(0.0));
1378 // prepare parent container
1379 Reference
< XTimeContainer
> xParentContainer(xOuterSeqTimeContainer
, UNO_QUERY_THROW
);
1381 // prepare loop over objects
1382 SdrObject
* pNext
= nullptr;
1383 const double fDurationShow(0.2);
1384 const double fDurationHide(0.001);
1386 for(size_t a(0); a
< aObjects
.size(); a
++)
1388 SdrObject
* pLast
= pNext
;
1389 pNext
= aObjects
[a
];
1394 createVisibilityOnOffNode(xParentContainer
, *pLast
, false, false, fDurationHide
);
1399 createVisibilityOnOffNode(xParentContainer
, *pNext
, true, !a
, fDurationShow
);
1406 createVisibilityOnOffNode(xParentContainer
, *pNext
, false, false, fDurationHide
);
1409 // add to main sequence and rebuild
1410 pMainSequence
->createEffects(xOuterSeqTimeContainer
);
1411 pMainSequence
->rebuild();
1414 void EffectMigration::DocumentLoaded(SdDrawDocument
& rDoc
)
1416 if (DocumentType::Draw
== rDoc
.GetDocumentType())
1417 return; // no animations in Draw
1418 for (sal_uInt16 n
= 0; n
< rDoc
.GetSdPageCount(PageKind::Standard
); ++n
)
1420 SdPage
*const pPage
= rDoc
.GetSdPage(n
, PageKind::Standard
);
1421 if (pPage
->hasAnimationNode())
1423 // this will force the equivalent of the MainSequence::onTimerHdl
1424 // so that the animations are present in export-able representation
1425 // *before* the import is finished
1426 pPage
->getMainSequence()->getRootNode();
1429 for (sal_uInt16 n
= 0; n
< rDoc
.GetMasterSdPageCount(PageKind::Standard
); ++n
)
1431 SdPage
*const pPage
= rDoc
.GetMasterSdPage(n
, PageKind::Standard
);
1432 if (pPage
->hasAnimationNode())
1434 pPage
->getMainSequence()->getRootNode();
1439 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */