LibreOffice Module sd (master) 1
EffectMigration.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
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>
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 <o3tl/string_view.hxx>
29#include <tools/debug.hxx>
30#include <svx/unoshape.hxx>
31#include <svx/svdotext.hxx>
32#include <svx/svdopath.hxx>
33#include <svx/svdogrp.hxx>
34#include <svx/svditer.hxx>
35#include <drawdoc.hxx>
36#include <sdpage.hxx>
38#include <TransitionPreset.hxx>
39#include <EffectMigration.hxx>
40#include <anminfo.hxx>
41
42using namespace ::sd;
43using namespace ::com::sun::star::uno;
44using namespace ::com::sun::star::animations;
45using namespace ::com::sun::star::presentation;
46using ::com::sun::star::drawing::XShape;
47using ::com::sun::star::lang::XMultiServiceFactory;
48using ::com::sun::star::drawing::XShape;
49using ::com::sun::star::beans::NamedValue;
50
51namespace {
52
53struct deprecated_FadeEffect_conversion_table_entry
54{
55 FadeEffect meFadeEffect;
56 const char* mpPresetId;
57};
58
59}
60
61deprecated_FadeEffect_conversion_table_entry const deprecated_FadeEffect_conversion_table[] =
62{
63// OOo 1.x transitions
64 { FadeEffect_FADE_FROM_LEFT, "wipe-right" },
65 { FadeEffect_FADE_FROM_TOP, "wipe-down" },
66 { FadeEffect_FADE_FROM_RIGHT, "wipe-left" },
67 { FadeEffect_FADE_FROM_BOTTOM, "wipe-up" },
68
69 { FadeEffect_CLOCKWISE, "wheel-clockwise-1-spoke" },
70
71 { FadeEffect_UNCOVER_TO_LEFT, "uncover-left" },
72 { FadeEffect_UNCOVER_TO_UPPERLEFT, "uncover-left-up" },
73 { FadeEffect_UNCOVER_TO_TOP, "uncover-up" },
74 { FadeEffect_UNCOVER_TO_UPPERRIGHT, "uncover-right-up" },
75 { FadeEffect_UNCOVER_TO_RIGHT, "uncover-right" },
76 { FadeEffect_UNCOVER_TO_LOWERRIGHT, "uncover-right-down" },
77 { FadeEffect_UNCOVER_TO_BOTTOM, "uncover-down" },
78 { FadeEffect_UNCOVER_TO_LOWERLEFT, "uncover-left-down" },
79
80 { FadeEffect_VERTICAL_LINES, "random-bars-vertical" },
81 { FadeEffect_HORIZONTAL_LINES, "random-bars-horizontal" },
82
83 { FadeEffect_VERTICAL_CHECKERBOARD, "checkerboard-down" },
84 { FadeEffect_HORIZONTAL_CHECKERBOARD, "checkerboard-across" },
85
86 { FadeEffect_FADE_TO_CENTER, "box-in" },
87 { FadeEffect_FADE_FROM_CENTER, "box-out" },
88
89 { FadeEffect_VERTICAL_STRIPES, "venetian-blinds-vertical" },
90 { FadeEffect_HORIZONTAL_STRIPES, "venetian-blinds-horizontal" },
91
92 { FadeEffect_MOVE_FROM_LEFT, "cover-right" },
93 { FadeEffect_MOVE_FROM_TOP, "cover-down" },
94 { FadeEffect_MOVE_FROM_RIGHT, "cover-left" },
95 { FadeEffect_MOVE_FROM_BOTTOM, "cover-up" },
96 { FadeEffect_MOVE_FROM_UPPERLEFT, "cover-right-down" },
97 { FadeEffect_MOVE_FROM_UPPERRIGHT, "cover-left-down" },
98 { FadeEffect_MOVE_FROM_LOWERRIGHT, "cover-left-up" },
99 { FadeEffect_MOVE_FROM_LOWERLEFT, "cover-right-up" },
100
101 { FadeEffect_DISSOLVE, "dissolve" },
102
103 { FadeEffect_RANDOM, "random-transition" },
104
105 { FadeEffect_ROLL_FROM_LEFT, "push-right" },
106 { FadeEffect_ROLL_FROM_TOP, "push-down" },
107 { FadeEffect_ROLL_FROM_RIGHT, "push-left" },
108 { FadeEffect_ROLL_FROM_BOTTOM, "push-up" },
109
110 { FadeEffect_CLOSE_VERTICAL, "split-horizontal-in" },
111 { FadeEffect_CLOSE_HORIZONTAL, "split-vertical-in" },
112 { FadeEffect_OPEN_VERTICAL, "split-horizontal-out" },
113 { FadeEffect_OPEN_HORIZONTAL, "split-vertical-out" },
114
115 { FadeEffect_FADE_FROM_UPPERLEFT, "diagonal-squares-right-down" },
116 { FadeEffect_FADE_FROM_UPPERRIGHT, "diagonal-squares-left-down" },
117 { FadeEffect_FADE_FROM_LOWERLEFT, "diagonal-squares-right-up" },
118 { FadeEffect_FADE_FROM_LOWERRIGHT, "diagonal-squares-left-up" },
119
120// OOo 1.x transitions not in OOo 2.x
121 { FadeEffect_CLOCKWISE, "clock-wipe-twelve" },
122 { FadeEffect_COUNTERCLOCKWISE, "reverse-clock-wipe-twelve" },
123 { FadeEffect_SPIRALIN_LEFT, "spiral-wipe-top-left-clockwise" },
124 { FadeEffect_SPIRALIN_RIGHT, "spiral-wipe-top-right-counter-clockwise" },
125 { FadeEffect_SPIRALOUT_LEFT, "spiral-wipe-out-to-bottom-right-clockwise" },
126 { FadeEffect_SPIRALOUT_RIGHT, "spiral-wipe-out-to-bottom-left-counter-clockwise" },
127 { FadeEffect_WAVYLINE_FROM_LEFT, "snake-wipe-top-left-vertical" },
128 { FadeEffect_WAVYLINE_FROM_TOP, "snake-wipe-top-left-horizontal" },
129 { FadeEffect_WAVYLINE_FROM_RIGHT, "snake-wipe-bottom-right-vertical" },
130 { FadeEffect_WAVYLINE_FROM_BOTTOM, "snake-wipe-bottom-right-horizontal" },
131 { FadeEffect_STRETCH_FROM_LEFT, "wipe-right" }, // todo
132 { FadeEffect_STRETCH_FROM_TOP, "wipe-down" }, // todo
133 { FadeEffect_STRETCH_FROM_RIGHT, "wipe-left" }, // todo
134 { FadeEffect_STRETCH_FROM_BOTTOM, "wipe-up" }, // todo
135
136// OOo 1.x not available transitions
137
138 { FadeEffect_CLOCKWISE, "wheel-clockwise-2-spokes" },
139 { FadeEffect_CLOCKWISE, "wheel-clockwise-3-spokes" },
140 { FadeEffect_CLOCKWISE, "wheel-clockwise-4-spokes" },
141 { FadeEffect_CLOCKWISE, "wheel-clockwise-8-spokes" },
142
143 { FadeEffect_FADE_FROM_CENTER, "shape-circle" },
144 { FadeEffect_FADE_FROM_CENTER, "shape-diamond" },
145 { FadeEffect_FADE_FROM_CENTER, "shape-plus" },
146
147 { FadeEffect_CLOCKWISE, "wedge" },
148
149 { FadeEffect_DISSOLVE, "fade-through-black" },
150
151 { FadeEffect_CLOCKWISE, "zoom-rotate-in" },
152
153 { FadeEffect_HORIZONTAL_LINES, "comb-horizontal" },
154 { FadeEffect_VERTICAL_LINES, "comb-vertical" },
155
156 { FadeEffect_DISSOLVE, "fade-smoothly" },
157
158 { FadeEffect_NONE, nullptr }
159};
160
161/* todo
162cut cut (same as NONE?)
163cut-through-black cut toBlack
164wedge wedge
165*/
166
167void EffectMigration::SetFadeEffect( SdPage* pPage, css::presentation::FadeEffect eNewEffect)
168{
169 deprecated_FadeEffect_conversion_table_entry const * pEntry = deprecated_FadeEffect_conversion_table;
170 while( (pEntry->meFadeEffect != FadeEffect_NONE) && (pEntry->meFadeEffect != eNewEffect) )
171 pEntry++;
172
173 if( pEntry->mpPresetId )
174 {
175 const OUString aPresetId( OUString::createFromAscii( pEntry->mpPresetId ) );
176
177 const TransitionPresetList& rPresetList = TransitionPreset::getTransitionPresetList();
178
179 auto aIt = std::find_if(rPresetList.begin(), rPresetList.end(),
180 [&aPresetId](const TransitionPresetPtr& rxPreset) { return rxPreset->getPresetId() == aPresetId; });
181 if (aIt != rPresetList.end())
182 {
183 pPage->setTransitionType( (*aIt)->getTransition() );
184 pPage->setTransitionSubtype( (*aIt)->getSubtype() );
185 pPage->setTransitionDirection( (*aIt)->getDirection() );
186 pPage->setTransitionFadeColor( (*aIt)->getFadeColor() );
187 }
188 }
189 else
190 {
191 pPage->setTransitionType( 0 );
192 pPage->setTransitionSubtype( 0 );
193 pPage->setTransitionDirection( false );
194 pPage->setTransitionFadeColor( 0 );
195 }
196}
197
198FadeEffect EffectMigration::GetFadeEffect( const SdPage* pPage )
199{
200 const TransitionPresetList & rPresetList = TransitionPreset::getTransitionPresetList();
201 auto aIt = std::find_if(rPresetList.begin(), rPresetList.end(),
202 [&pPage](const TransitionPresetPtr& rxPreset) {
203 return (rxPreset->getTransition() == pPage->getTransitionType())
204 && (rxPreset->getSubtype() == pPage->getTransitionSubtype())
205 && (rxPreset->getDirection() == pPage->getTransitionDirection())
206 && (rxPreset->getFadeColor() == pPage->getTransitionFadeColor());
207 });
208 if (aIt != rPresetList.end())
209 {
210 const OUString& aPresetId = (*aIt)->getPresetId();
211
212 deprecated_FadeEffect_conversion_table_entry const * pEntry = deprecated_FadeEffect_conversion_table;
213 while( (pEntry->meFadeEffect != FadeEffect_NONE) && (!aPresetId.equalsAscii( pEntry->mpPresetId ) ) )
214 pEntry++;
215
216 return pEntry->meFadeEffect;
217 }
218 return FadeEffect_NONE;
219}
220
221namespace {
222
223struct deprecated_AnimationEffect_conversion_table_entry
224{
225 AnimationEffect meEffect;
226 const char* mpPresetId;
227 const char* mpPresetSubType;
228};
229
230}
231
232deprecated_AnimationEffect_conversion_table_entry const deprecated_AnimationEffect_conversion_table[] =
233{
234// OOo 1.x entrance effects
235 { AnimationEffect_APPEAR, "ooo-entrance-appear",nullptr },
236
237 { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-box","in" },
238 { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-box","out" },
239
240 { AnimationEffect_VERTICAL_CHECKERBOARD, "ooo-entrance-checkerboard","downward" },
241 { AnimationEffect_HORIZONTAL_CHECKERBOARD, "ooo-entrance-checkerboard","across" },
242
243 { AnimationEffect_FADE_FROM_UPPERLEFT, "ooo-entrance-diagonal-squares","right-to-bottom" },
244 { AnimationEffect_FADE_FROM_UPPERRIGHT, "ooo-entrance-diagonal-squares","left-to-bottom" },
245 { AnimationEffect_FADE_FROM_LOWERLEFT, "ooo-entrance-diagonal-squares","right-to-top" },
246 { AnimationEffect_FADE_FROM_LOWERRIGHT, "ooo-entrance-diagonal-squares","left-to-top" },
247
248 { AnimationEffect_DISSOLVE, "ooo-entrance-dissolve-in",nullptr },
249
250 { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-fly-in","from-left" },
251 { AnimationEffect_MOVE_FROM_TOP, "ooo-entrance-fly-in","from-top" },
252 { AnimationEffect_MOVE_FROM_RIGHT, "ooo-entrance-fly-in","from-right" },
253 { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-fly-in","from-bottom" },
254 { AnimationEffect_MOVE_FROM_UPPERLEFT, "ooo-entrance-fly-in","from-top-left" },
255 { AnimationEffect_MOVE_FROM_UPPERRIGHT, "ooo-entrance-fly-in","from-top-right" },
256 { AnimationEffect_MOVE_FROM_LOWERRIGHT, "ooo-entrance-fly-in","from-bottom-right" },
257 { AnimationEffect_MOVE_FROM_LOWERLEFT, "ooo-entrance-fly-in","from-bottom-left" },
258
259 { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-fly-in-slow", "from-bottom" },
260 { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-fly-in-slow", "from-left" },
261 { AnimationEffect_MOVE_FROM_RIGHT, "ooo-entrance-fly-in-slow", "from-right" },
262 { AnimationEffect_MOVE_FROM_TOP, "ooo-entrance-fly-in-slow", "from-top" },
263
264 { AnimationEffect_MOVE_SHORT_FROM_LEFT, "ooo-entrance-peek-in","from-left" },
265 { AnimationEffect_MOVE_SHORT_FROM_TOP, "ooo-entrance-peek-in","from-top" },
266 { AnimationEffect_MOVE_SHORT_FROM_RIGHT, "ooo-entrance-peek-in","from-right" },
267 { AnimationEffect_MOVE_SHORT_FROM_BOTTOM, "ooo-entrance-peek-in","from-bottom" },
268
269 { AnimationEffect_VERTICAL_LINES, "ooo-entrance-random-bars","horizontal" },
270 { AnimationEffect_HORIZONTAL_LINES, "ooo-entrance-random-bars","vertical" },
271
272 { AnimationEffect_RANDOM, "ooo-entrance-random",nullptr },
273
274 { AnimationEffect_CLOSE_VERTICAL, "ooo-entrance-split","horizontal-in" },
275 { AnimationEffect_CLOSE_HORIZONTAL, "ooo-entrance-split","vertical-in" },
276 { AnimationEffect_OPEN_VERTICAL, "ooo-entrance-split","horizontal-out" },
277 { AnimationEffect_OPEN_HORIZONTAL, "ooo-entrance-split","vertical-out" },
278
279 { AnimationEffect_VERTICAL_STRIPES, "ooo-entrance-venetian-blinds","horizontal" },
280 { AnimationEffect_HORIZONTAL_STRIPES, "ooo-entrance-venetian-blinds","vertical" },
281
282 { AnimationEffect_FADE_FROM_LEFT, "ooo-entrance-wipe","from-left" },
283 { AnimationEffect_FADE_FROM_TOP, "ooo-entrance-wipe","from-bottom" },
284 { AnimationEffect_FADE_FROM_RIGHT, "ooo-entrance-wipe","from-right" },
285 { AnimationEffect_FADE_FROM_BOTTOM, "ooo-entrance-wipe","from-top" },
286
287 { AnimationEffect_HORIZONTAL_ROTATE, "ooo-entrance-swivel","vertical" },
288 { AnimationEffect_VERTICAL_ROTATE, "ooo-entrance-swivel","horizontal" },
289
290 { AnimationEffect_STRETCH_FROM_LEFT, "ooo-entrance-stretchy","from-left" },
291 { AnimationEffect_STRETCH_FROM_UPPERLEFT, "ooo-entrance-stretchy","from-top-left" },
292 { AnimationEffect_STRETCH_FROM_TOP, "ooo-entrance-stretchy","from-top" },
293 { AnimationEffect_STRETCH_FROM_UPPERRIGHT, "ooo-entrance-stretchy","from-top-right" },
294 { AnimationEffect_STRETCH_FROM_RIGHT, "ooo-entrance-stretchy","from-right" },
295 { AnimationEffect_STRETCH_FROM_LOWERRIGHT, "ooo-entrance-stretchy","from-bottom-right" },
296 { AnimationEffect_STRETCH_FROM_BOTTOM, "ooo-entrance-stretchy","from-bottom" },
297 { AnimationEffect_STRETCH_FROM_LOWERLEFT, "ooo-entrance-stretchy","from-bottom-left" },
298
299 { AnimationEffect_HORIZONTAL_STRETCH, "ooo-entrance-expand", nullptr },
300
301 { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel","1" },
302 { AnimationEffect_COUNTERCLOCKWISE, "ooo-entrance-clock-wipe","counter-clockwise" },
303
304 { AnimationEffect_SPIRALIN_LEFT, "ooo-entrance-spiral-wipe", "from-top-left-clockwise" },
305 { AnimationEffect_SPIRALIN_RIGHT, "ooo-entrance-spiral-wipe", "from-top-right-counter-clockwise" },
306 { AnimationEffect_SPIRALOUT_LEFT, "ooo-entrance-spiral-wipe", "from-center-clockwise" },
307 { AnimationEffect_SPIRALOUT_RIGHT, "ooo-entrance-spiral-wipe", "from-center-counter-clockwise" },
308
309 { AnimationEffect_WAVYLINE_FROM_LEFT, "ooo-entrance-snake-wipe","from-top-left-vertical" },
310 { AnimationEffect_WAVYLINE_FROM_TOP, "ooo-entrance-snake-wipe","from-top-left-horizontal" },
311 { AnimationEffect_WAVYLINE_FROM_RIGHT, "ooo-entrance-snake-wipe","from-bottom-right-vertical" },
312 { AnimationEffect_WAVYLINE_FROM_BOTTOM, "ooo-entrance-snake-wipe","from-bottom-right-horizontal" },
313
314// ooo 1.x exit effects
315 { AnimationEffect_HIDE, "ooo-exit-disappear",nullptr },
316 { AnimationEffect_MOVE_TO_LEFT, "ooo-exit-fly-out", "from-right" },
317 { AnimationEffect_MOVE_TO_TOP, "ooo-exit-fly-out", "from-bottom" },
318 { AnimationEffect_MOVE_TO_RIGHT, "ooo-exit-fly-out", "from-left" },
319 { AnimationEffect_MOVE_TO_BOTTOM, "ooo-exit-fly-out", "from-top" },
320 { AnimationEffect_MOVE_TO_UPPERLEFT, "ooo-exit-fly-out", "from-top-right" },
321 { AnimationEffect_MOVE_TO_UPPERRIGHT, "ooo-exit-fly-out", "from-top-left" },
322 { AnimationEffect_MOVE_TO_LOWERRIGHT, "ooo-exit-fly-out", "from-bottom-left" },
323 { AnimationEffect_MOVE_TO_LOWERLEFT, "ooo-exit-fly-out", "from-bottom-right" },
324 { AnimationEffect_MOVE_SHORT_TO_LEFT, "ooo-exit-peek-out", "from-right" },
325 { AnimationEffect_MOVE_SHORT_TO_UPPERLEFT, "ooo-exit-peek-out", "from-right" },
326 { AnimationEffect_MOVE_SHORT_TO_TOP, "ooo-exit-peek-out", "from-bottom" },
327 { AnimationEffect_MOVE_SHORT_TO_UPPERRIGHT, "ooo-exit-peek-out", "from-bottom" },
328 { AnimationEffect_MOVE_SHORT_TO_RIGHT, "ooo-exit-peek-out", "from-left" },
329 { AnimationEffect_MOVE_SHORT_TO_LOWERRIGHT, "ooo-exit-peek-out","from-left" },
330 { AnimationEffect_MOVE_SHORT_TO_BOTTOM, "ooo-exit-peek-out", "from-top" },
331 { AnimationEffect_MOVE_SHORT_TO_LOWERLEFT, "ooo-exit-peek-out", "from-top" },
332
333// no matching in OOo 2.x
334 { AnimationEffect_MOVE_SHORT_FROM_UPPERLEFT, "ooo-entrance-peek-in","from-left" },
335 { AnimationEffect_MOVE_SHORT_FROM_UPPERRIGHT, "ooo-entrance-peek-in","from-top" },
336 { AnimationEffect_MOVE_SHORT_FROM_LOWERRIGHT, "ooo-entrance-peek-in","from-right" },
337 { AnimationEffect_MOVE_SHORT_FROM_LOWERLEFT, "ooo-entrance-peek-in","from-bottom" },
338 { AnimationEffect_LASER_FROM_LEFT, "ooo-entrance-fly-in","from-left" },
339 { AnimationEffect_LASER_FROM_TOP, "ooo-entrance-fly-in","from-top" },
340 { AnimationEffect_LASER_FROM_RIGHT, "ooo-entrance-fly-in","from-right" },
341 { AnimationEffect_LASER_FROM_BOTTOM, "ooo-entrance-fly-in","from-bottom" },
342 { AnimationEffect_LASER_FROM_UPPERLEFT, "ooo-entrance-fly-in","from-top-left" },
343 { AnimationEffect_LASER_FROM_UPPERRIGHT, "ooo-entrance-fly-in","from-top-right" },
344 { AnimationEffect_LASER_FROM_LOWERLEFT, "ooo-entrance-fly-in","from-bottom-left" },
345 { AnimationEffect_LASER_FROM_LOWERRIGHT, "ooo-entrance-fly-in","from-bottom-right" },
346
347// no matching in OOo 1.x
348
349 { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-circle", "in" },
350 { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-circle", "out" },
351 { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-diamond", "in" },
352 { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-diamond", "out" },
353 { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-plus", "in" },
354 { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-plus", "out" },
355 { AnimationEffect_CLOCKWISE, "ooo-entrance-wedge", nullptr },
356 { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "2" },
357 { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "3" },
358 { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "4" },
359 { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "8" },
360
361 { AnimationEffect_MOVE_FROM_RIGHT, "ooo-entrance-boomerang", nullptr },
362 { AnimationEffect_MOVE_FROM_UPPERRIGHT, "ooo-entrance-bounce", nullptr },
363 { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-curve-up", nullptr },
364 { AnimationEffect_MOVE_FROM_TOP, "ooo-entrance-float", nullptr },
365 { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-glide", nullptr },
366 { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-magnify", nullptr },
367 { AnimationEffect_HORIZONTAL_ROTATE, "ooo-entrance-pinwheel", nullptr },
368 { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-breaks", nullptr },
369 { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-sling", nullptr },
370 { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-spiral-in", nullptr },
371 { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-thread", nullptr },
372 { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-ascend", nullptr },
373 { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-center-revolve", nullptr },
374 { AnimationEffect_APPEAR, "ooo-entrance-compress", nullptr },
375 { AnimationEffect_MOVE_SHORT_FROM_TOP, "ooo-entrance-descend", nullptr },
376 { AnimationEffect_MOVE_SHORT_FROM_LEFT, "ooo-entrance-ease-in", nullptr },
377 { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-rise-up", nullptr },
378 { AnimationEffect_HORIZONTAL_ROTATE, "ooo-entrance-spin-in", nullptr },
379 { AnimationEffect_STRETCH_FROM_LEFT, "ooo-entrance-stretchy", "across" },
380 { AnimationEffect_STRETCH_FROM_TOP, "ooo-entrance-stretchy", "downward" },
381
382 { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-zoom","in" },
383 { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-zoom","in-slightly" },
384 { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-zoom","in-from-screen-center" },
385 { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-zoom","out" },
386 { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-zoom","out-slightly" },
387 { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-zoom","out-from-screen-center" },
388
389 { AnimationEffect_DISSOLVE, "ooo-entrance-fade-in", nullptr },
390 { AnimationEffect_DISSOLVE, "ooo-entrance-fade-in-and-zoom", nullptr },
391 { AnimationEffect_DISSOLVE, "ooo-entrance-fade-in-and-swivel", nullptr },
392
393 // still open (no matching effect: AnimationEffect_ZOOM_IN_FROM_*,
394 // AnimationEffect_ZOOM_OUT_FROM_*, AnimationEffect_PATH
395
396 { AnimationEffect_NONE, nullptr, nullptr }
397};
398
399static EffectSequence::iterator ImplFindEffect( MainSequencePtr const & pMainSequence, const Reference< XShape >& rShape, sal_Int16 nSubItem )
400{
401 return std::find_if(pMainSequence->getBegin(), pMainSequence->getEnd(),
402 [&rShape, &nSubItem](const CustomAnimationEffectPtr& pEffect) {
403 return (pEffect->getTargetShape() == rShape)
404 && (pEffect->getTargetSubItem() == nSubItem);
405 });
406}
407
408static bool implIsInsideGroup( SdrObject const * pObj )
409{
410 // TTTT for current state of transition, SdrObject has a parent*
411 // to a SdrObjList. That may be a SdrPage or a SdrObjGroup, both
412 // are already derived from SdrObjList. To finally check, use
413 // the method 'getSdrObjectFromSdrObjList' - if it's not a SdrPage,
414 // it will return SdrObjGroup or E3dScene -> SdrObject.
415 // For future states, test for SdrObject. Trying to get the SdrPage
416 // will in the future depend on the Object(this) to be inserted to a
417 // SdrPage, regardless of e.g. being a group member.
418 if(nullptr == pObj)
419 {
420 return false;
421 }
422
423 SdrObjList* pSdrObjList(pObj->getParentSdrObjListFromSdrObject());
424
425 if(nullptr == pSdrObjList)
426 {
427 return false;
428 }
429
430 return (nullptr != pSdrObjList->getSdrObjectFromSdrObjList());
431}
432
433void EffectMigration::SetAnimationEffect( SvxShape* pShape, AnimationEffect eEffect )
434{
435 DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->getSdrPageFromSdrObject(),
436 "sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
437 if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() )
438 return;
439
440 SdrObject* pObj = pShape->GetSdrObject();
441 if( implIsInsideGroup( pObj ) )
442 return;
443
444 OUString aPresetId;
445 OUString aPresetSubType;
446
447 if( !ConvertAnimationEffect( eEffect, aPresetId, aPresetSubType ) )
448 {
449 OSL_FAIL( "sd::EffectMigration::SetAnimationEffect(), no mapping for given AnimationEffect value" );
450 return;
451 }
452
453 const CustomAnimationPresets& rPresets = CustomAnimationPresets::getCustomAnimationPresets();
454
455 CustomAnimationPresetPtr pPreset( rPresets.getEffectDescriptor( aPresetId ) );
456 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
457
458 if( !(pPreset && pMainSequence) )
459 return;
460
461 const Reference< XShape > xShape( pShape );
462
463 EffectSequence::iterator aIterOnlyBackground( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_BACKGROUND ) );
464 EffectSequence::iterator aIterAsWhole( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::AS_WHOLE ) );
465 const EffectSequence::iterator aEnd( pMainSequence->getEnd() );
466
467 if( (aIterOnlyBackground == aEnd) && (aIterAsWhole == aEnd) )
468 {
469 bool bEffectCreated = false;
470
471 // check if there is already a text effect for this shape
472 EffectSequence::iterator aIterOnlyText( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_TEXT ) );
473 if( aIterOnlyText != aEnd )
474 {
475 // check if this is an animation text group
476 sal_Int32 nGroupId = (*aIterOnlyText)->getGroupId();
477 if( nGroupId >= 0 )
478 {
479 CustomAnimationTextGroupPtr pGroup = pMainSequence->findGroup( nGroupId );
480 if( pGroup )
481 {
482 // add an effect to animate the shape
483 pMainSequence->setAnimateForm( pGroup, true );
484
485 // find this effect
486 EffectSequence::iterator aIter( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_BACKGROUND ) );
487
488 if( aIter != aEnd )
489 {
490 if( ((*aIter)->getPresetId() != aPresetId) ||
491 ((*aIter)->getPresetSubType() != aPresetSubType) )
492 {
493 (*aIter)->replaceNode( pPreset->create( aPresetSubType ) );
494 pMainSequence->rebuild();
495 bEffectCreated = true;
496 }
497 }
498 }
499 }
500 }
501
502 if( !bEffectCreated )
503 {
504 // if there is not yet an effect that target this shape, we generate one
505 // we insert the shape effect before it
506 Reference< XAnimationNode > xNode( pPreset->create( aPresetSubType ) );
507 DBG_ASSERT( xNode.is(), "EffectMigration::SetAnimationEffect(), could not create preset!" );
508 if( xNode.is() )
509 {
510 CustomAnimationEffectPtr pEffect = std::make_shared<CustomAnimationEffect>( xNode );
511 pEffect->setTarget( Any( xShape ) );
512 SdPage* pPage = dynamic_cast< SdPage* >( pObj->getSdrPageFromSdrObject() );
513 const bool bManual = (pPage == nullptr) || (pPage->GetPresChange() == PresChange::Manual);
514 if( !bManual )
515 pEffect->setNodeType( EffectNodeType::AFTER_PREVIOUS );
516
517 pMainSequence->append( pEffect );
518
519 if( ( pObj->GetObjInventor() == SdrInventor::Default ) && ( pObj->GetObjIdentifier() == SdrObjKind::OutlineText ) )
520 {
521 // special case for outline text, effects are always mapped to text group effect
522 pMainSequence->
523 createTextGroup( pEffect, 10, bManual ? -1 : 0.0, false, false );
524 }
525 }
526 }
527 }
528 else
529 {
530 // if there is already an effect targeting this shape
531 // just replace it
533 if( aIterAsWhole != aEnd )
534 {
535 pEffect = *aIterAsWhole;
536 }
537 else
538 {
539 pEffect = *aIterOnlyBackground;
540 }
541
542 if( pEffect )
543 {
544 if( (pEffect->getPresetId() != aPresetId) ||
545 (pEffect->getPresetSubType() != aPresetSubType) )
546 {
547 pMainSequence->replace( pEffect, pPreset, aPresetSubType, -1.0 );
548 }
549 }
550 }
551}
552
553AnimationEffect EffectMigration::GetAnimationEffect( SvxShape* pShape )
554{
555 OUString aPresetId;
556 OUString aPresetSubType;
557
558 SdrObject* pObj = pShape->GetSdrObject();
559 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
560
561 if( pMainSequence )
562 {
563 const Reference< XShape > xShape( pShape );
564
565 EffectSequence::iterator aIter = std::find_if(pMainSequence->getBegin(), pMainSequence->getEnd(),
566 [&xShape](const CustomAnimationEffectPtr& pEffect) {
567 return (pEffect->getTargetShape() == xShape)
568 && ((pEffect->getTargetSubItem() == ShapeAnimationSubType::ONLY_BACKGROUND)
569 || (pEffect->getTargetSubItem() == ShapeAnimationSubType::AS_WHOLE))
570 && (pEffect->getDuration() != 0.1); // ignore appear effects created from old text effect import
571 });
572
573 if (aIter != pMainSequence->getEnd())
574 {
575 aPresetId = (*aIter)->getPresetId();
576 aPresetSubType = (*aIter)->getPresetSubType();
577 }
578 }
579
580 // now find old effect
581 AnimationEffect eEffect = AnimationEffect_NONE;
582
583 if( !ConvertPreset( aPresetId, &aPresetSubType, eEffect ) )
584 ConvertPreset( aPresetId, nullptr, eEffect );
585
586 return eEffect;
587}
588
589void EffectMigration::SetTextAnimationEffect( SvxShape* pShape, AnimationEffect eEffect )
590{
591 DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->getSdrPageFromSdrObject(),
592 "sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
593 if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() )
594 return;
595
596 SdrObject* pObj = pShape->GetSdrObject();
597 if( implIsInsideGroup( pObj ) )
598 return;
599
600 // first map the deprecated AnimationEffect to a preset and subtype
601 OUString aPresetId;
602 OUString aPresetSubType;
603
604 if( !ConvertAnimationEffect( eEffect, aPresetId, aPresetSubType ) )
605 {
606 OSL_FAIL( "sd::EffectMigration::SetAnimationEffect(), no mapping for given AnimationEffect value" );
607 return;
608 }
609
610 SdrTextObj* pTextObj = DynCastSdrTextObj( pObj );
611
612 // ignore old text effects on shape without text
613 if( (pTextObj == nullptr) || (!pTextObj->HasText()) )
614 return;
615
616 const CustomAnimationPresets& rPresets = CustomAnimationPresets::getCustomAnimationPresets();
617
618 // create an effect from this preset
619 CustomAnimationPresetPtr pPreset( rPresets.getEffectDescriptor( aPresetId ) );
620
621 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
622
623 if( !(pPreset && pMainSequence) )
624 return;
625
626 const Reference< XShape > xShape( pShape );
627
628 EffectSequence::iterator aIterOnlyText( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_TEXT ) );
629 const EffectSequence::iterator aEnd( pMainSequence->getEnd() );
630
632
633 // is there already an animation text group for this shape?
634 if( aIterOnlyText != aEnd )
635 {
636 const sal_Int32 nGroupId = (*aIterOnlyText)->getGroupId();
637 if( nGroupId >= 0 )
638 pGroup = pMainSequence->findGroup( nGroupId );
639 }
640
641 // if there is not yet a group, create it
642 if( !pGroup )
643 {
644 CustomAnimationEffectPtr pShapeEffect;
645
646 EffectSequence::iterator aIterOnlyBackground( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_BACKGROUND ) );
647 if( aIterOnlyBackground != aEnd )
648 {
649 pShapeEffect = *aIterOnlyBackground;
650 }
651 else
652 {
653 EffectSequence::iterator aIterAsWhole( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::AS_WHOLE ) );
654 if( aIterAsWhole != aEnd )
655 {
656 pShapeEffect = *aIterAsWhole;
657 }
658 else
659 {
660 Reference< XAnimationNode > xNode( pPreset->create( "" ) );
661 DBG_ASSERT( xNode.is(), "EffectMigration::SetTextAnimationEffect(), could not create preset!" );
662 if( xNode.is() )
663 {
664 pShapeEffect = std::make_shared<CustomAnimationEffect>( xNode );
665 pShapeEffect->setTarget( Any( xShape ) );
666 pShapeEffect->setDuration( 0.1 );
667 pMainSequence->append( pShapeEffect );
668
669 SdPage* pPage = dynamic_cast< SdPage* >( pObj->getSdrPageFromSdrObject() );
670 if( pPage && pPage->GetPresChange() != PresChange::Manual )
671 pShapeEffect->setNodeType( EffectNodeType::AFTER_PREVIOUS );
672 }
673 }
674 }
675
676 if( pShapeEffect )
677 {
678 SdPage* pPage = dynamic_cast< SdPage* >( pObj->getSdrPageFromSdrObject() );
679 const bool bManual = (pPage == nullptr) || (pPage->GetPresChange() == PresChange::Manual);
680
681 // now create effects for each paragraph
682 pGroup =
683 pMainSequence->
684 createTextGroup( pShapeEffect, 10, bManual ? -1 : 0.0, true, false );
685 }
686 }
687
688 if( pGroup )
689 {
690 const bool bLaserEffect = (eEffect >= AnimationEffect_LASER_FROM_LEFT) && (eEffect <= AnimationEffect_LASER_FROM_LOWERRIGHT);
691
692 // now we have a group, so check if all effects are same as we like to have them
693 const EffectSequence& rEffects = pGroup->getEffects();
694
695 for( auto& rxEffect : rEffects )
696 {
697 // only work on paragraph targets
698 if( rxEffect->getTarget().getValueType() == ::cppu::UnoType<ParagraphTarget>::get() )
699 {
700 if( (rxEffect->getPresetId() != aPresetId) ||
701 (rxEffect->getPresetSubType() != aPresetSubType) )
702 {
703 rxEffect->replaceNode( pPreset->create( aPresetSubType ) );
704 }
705
706 if( bLaserEffect )
707 {
708 rxEffect->setIterateType( TextAnimationType::BY_LETTER );
709 rxEffect->setIterateInterval( 0.5 );// TODO:
710 // Determine
711 // interval
712 // according
713 // to
714 // total
715 // effect
716 // duration
717 }
718 }
719 }
720 }
721 pMainSequence->rebuild();
722}
723
724AnimationEffect EffectMigration::GetTextAnimationEffect( SvxShape* pShape )
725{
726 OUString aPresetId;
727 OUString aPresetSubType;
728
729 SdrObject* pObj = pShape->GetSdrObject();
730 if( pObj )
731 {
732 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
733
734 if( pMainSequence )
735 {
736 const Reference< XShape > xShape( pShape );
737 EffectSequence::iterator aIter( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_TEXT ) );
738 if( aIter != pMainSequence->getEnd() )
739 {
740 aPresetId = (*aIter)->getPresetId();
741 aPresetSubType = (*aIter)->getPresetSubType();
742 }
743 }
744 }
745
746 // now find old effect
747 AnimationEffect eEffect = AnimationEffect_NONE;
748
749 if( !ConvertPreset( aPresetId, &aPresetSubType, eEffect ) )
750 ConvertPreset( aPresetId, nullptr, eEffect );
751
752 return eEffect;
753}
754
755bool EffectMigration::ConvertPreset( std::u16string_view rPresetId, const OUString* pPresetSubType, AnimationEffect& rEffect )
756{
757 rEffect = AnimationEffect_NONE;
758 if( !rPresetId.empty() )
759 {
760 // first try a match for preset id and subtype
761 deprecated_AnimationEffect_conversion_table_entry const * p = deprecated_AnimationEffect_conversion_table;
762 while( p->mpPresetId )
763 {
764 if( o3tl::equalsAscii( rPresetId, p->mpPresetId ) &&
765 (( p->mpPresetSubType == nullptr ) ||
766 ( pPresetSubType == nullptr) ||
767 ( pPresetSubType->equalsAscii( p->mpPresetSubType )) ) )
768 {
769 rEffect = p->meEffect;
770 return true;
771 }
772 p++;
773 }
774 return false;
775 }
776 else
777 {
778 // empty preset id means AnimationEffect_NONE
779 return true;
780 }
781}
782
783bool EffectMigration::ConvertAnimationEffect( const AnimationEffect& rEffect, OUString& rPresetId, OUString& rPresetSubType )
784{
785 deprecated_AnimationEffect_conversion_table_entry const * p = deprecated_AnimationEffect_conversion_table;
786 while( p->mpPresetId )
787 {
788 if( p->meEffect == rEffect )
789 {
790 rPresetId = OUString::createFromAscii( p->mpPresetId );
791 rPresetSubType = OUString::createFromAscii( p->mpPresetSubType );
792 return true;
793 }
794 p++;
795 }
796
797 return false;
798}
799
800double EffectMigration::ConvertAnimationSpeed( AnimationSpeed eSpeed )
801{
802 double fDuration;
803 switch( eSpeed )
804 {
805 case AnimationSpeed_SLOW: fDuration = 2.0; break;
806 case AnimationSpeed_FAST: fDuration = 0.5; break;
807 default:
808 fDuration = 1.0; break;
809 }
810 return fDuration;
811}
812
813void EffectMigration::SetAnimationSpeed( SvxShape* pShape, AnimationSpeed eSpeed )
814{
815 DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->getSdrPageFromSdrObject(),
816 "sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
817 if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() )
818 return;
819
820 SdrObject* pObj = pShape->GetSdrObject();
821 if( implIsInsideGroup( pObj ) )
822 return;
823
824 double fDuration = ConvertAnimationSpeed( eSpeed );
825
826 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
827
828 const Reference< XShape > xShape( pShape );
829
830 EffectSequence::iterator aIter;
831 bool bNeedRebuild = false;
832
833 for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter )
834 {
835 CustomAnimationEffectPtr pEffect( *aIter );
836 if( pEffect->getTargetShape() == xShape )
837 {
838 if( pEffect->getDuration() != 0.1 )
839 pEffect->setDuration( fDuration );
840 bNeedRebuild = true;
841 }
842 }
843
844 if( bNeedRebuild )
845 pMainSequence->rebuild();
846}
847
848AnimationSpeed EffectMigration::GetAnimationSpeed( SvxShape* pShape )
849{
850 SdrObject* pObj = pShape->GetSdrObject();
851 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
852
853 const Reference< XShape > xShape( pShape );
854
855 double fDuration = 1.0;
856
857 EffectSequence::iterator aIter = std::find_if(pMainSequence->getBegin(), pMainSequence->getEnd(),
858 [&xShape](const CustomAnimationEffectPtr& pEffect) {
859 return (pEffect->getTargetShape() == xShape)
860 && (pEffect->getDuration() != 0.1);
861 });
862 if (aIter != pMainSequence->getEnd())
863 {
864 CustomAnimationEffectPtr pEffect( *aIter );
865 fDuration = pEffect->getDuration();
866 }
867
868 return ConvertDuration( fDuration );
869}
870
871AnimationSpeed EffectMigration::ConvertDuration( double fDuration )
872{
873 AnimationSpeed eSpeed;
874
875 if( fDuration < 1.0 )
876 eSpeed = AnimationSpeed_FAST;
877 else if( fDuration > 1.5 )
878 eSpeed = AnimationSpeed_SLOW;
879 else
880 eSpeed = AnimationSpeed_MEDIUM;
881
882 return eSpeed;
883}
884
885void EffectMigration::SetDimColor( SvxShape* pShape, sal_Int32 nColor )
886{
887 DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->getSdrPageFromSdrObject(),
888 "sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
889 if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() )
890 return;
891
892 SdrObject* pObj = pShape->GetSdrObject();
893 if( implIsInsideGroup( pObj ) )
894 return;
895
896 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
897
898 const Reference< XShape > xShape( pShape );
899
900 EffectSequence::iterator aIter;
901 bool bNeedRebuild = false;
902
903 for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter )
904 {
905 CustomAnimationEffectPtr pEffect( *aIter );
906 if( pEffect->getTargetShape() == xShape )
907 {
908 pEffect->setHasAfterEffect( true );
909 pEffect->setDimColor( Any( nColor ) );
910 pEffect->setAfterEffectOnNext( true );
911 bNeedRebuild = true;
912 }
913 }
914
915 if( bNeedRebuild )
916 pMainSequence->rebuild();
917}
918
919sal_Int32 EffectMigration::GetDimColor( SvxShape* pShape )
920{
921 sal_Int32 nColor = 0;
922 if( pShape )
923 {
924 SdrObject* pObj = pShape->GetSdrObject();
925 if( pObj && pObj->getSdrPageFromSdrObject() )
926 {
927 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
928
929 const Reference< XShape > xShape( pShape );
930 EffectSequence::iterator aIter = std::find_if(pMainSequence->getBegin(), pMainSequence->getEnd(),
931 [&xShape](const CustomAnimationEffectPtr& pEffect) {
932 return (pEffect->getTargetShape() == xShape)
933 && pEffect->getDimColor().hasValue()
934 && pEffect->hasAfterEffect();
935 });
936 if (aIter != pMainSequence->getEnd())
937 {
938 CustomAnimationEffectPtr pEffect( *aIter );
939 pEffect->getDimColor() >>= nColor;
940 }
941 }
942 }
943
944 return nColor;
945}
946
947void EffectMigration::SetDimHide( SvxShape* pShape, bool bDimHide )
948{
949 DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->getSdrPageFromSdrObject(),
950 "sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
951 if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() )
952 return;
953
954 SdrObject* pObj = pShape->GetSdrObject();
955 if( implIsInsideGroup( pObj ) )
956 return;
957
958 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
959
960 const Reference< XShape > xShape( pShape );
961
962 EffectSequence::iterator aIter;
963 bool bNeedRebuild = false;
964
965 for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter )
966 {
967 CustomAnimationEffectPtr pEffect( *aIter );
968 if( pEffect->getTargetShape() == xShape )
969 {
970 pEffect->setHasAfterEffect( bDimHide );
971 if( bDimHide ) {
972 Any aEmpty;
973 pEffect->setDimColor( aEmpty );
974 }
975 pEffect->setAfterEffectOnNext( false );
976 bNeedRebuild = true;
977 }
978 }
979
980 if( bNeedRebuild )
981 pMainSequence->rebuild();
982}
983
984bool EffectMigration::GetDimHide( SvxShape* pShape )
985{
986 bool bRet = false;
987 if( pShape )
988 {
989 SdrObject* pObj = pShape->GetSdrObject();
990 if( pObj && pObj->getSdrPageFromSdrObject() )
991 {
992 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
993
994 const Reference< XShape > xShape( pShape );
995
996 EffectSequence::iterator aIter = std::find_if(pMainSequence->getBegin(), pMainSequence->getEnd(),
997 [&xShape](const CustomAnimationEffectPtr& pEffect) { return pEffect->getTargetShape() == xShape; });
998 if (aIter != pMainSequence->getEnd())
999 {
1000 CustomAnimationEffectPtr pEffect( *aIter );
1001 bRet = pEffect->hasAfterEffect() &&
1002 !pEffect->getDimColor().hasValue() &&
1003 (!pEffect->IsAfterEffectOnNext());
1004 }
1005 }
1006 }
1007
1008 return bRet;
1009}
1010
1011void EffectMigration::SetDimPrevious( SvxShape* pShape, bool bDimPrevious )
1012{
1013 DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->getSdrPageFromSdrObject(),
1014 "sd::EffectMigration::SetAnimationEffect(), invalid argument!" );
1015 if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() )
1016 return;
1017
1018 SdrObject* pObj = pShape->GetSdrObject();
1019 if( implIsInsideGroup( pObj ) )
1020 return;
1021
1022 Any aColor;
1023
1024 if( bDimPrevious )
1025 aColor <<= COL_LIGHTGRAY;
1026
1027 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
1028
1029 const Reference< XShape > xShape( pShape );
1030
1031 EffectSequence::iterator aIter;
1032 bool bNeedRebuild = false;
1033
1034 for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter )
1035 {
1036 CustomAnimationEffectPtr pEffect( *aIter );
1037 if( pEffect->getTargetShape() == xShape )
1038 {
1039 pEffect->setHasAfterEffect( bDimPrevious );
1040 if( !bDimPrevious || !pEffect->getDimColor().hasValue() )
1041 pEffect->setDimColor( aColor );
1042 pEffect->setAfterEffectOnNext( true );
1043 bNeedRebuild = true;
1044 }
1045 }
1046
1047 if( bNeedRebuild )
1048 pMainSequence->rebuild();
1049}
1050
1051bool EffectMigration::GetDimPrevious( SvxShape* pShape )
1052{
1053 bool bRet = false;
1054 if( pShape )
1055 {
1056 SdrObject* pObj = pShape->GetSdrObject();
1057 if( pObj && pObj->getSdrPageFromSdrObject() )
1058 {
1059 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
1060
1061 const Reference< XShape > xShape( pShape );
1062
1063 EffectSequence::iterator aIter = std::find_if(pMainSequence->getBegin(), pMainSequence->getEnd(),
1064 [&xShape](const CustomAnimationEffectPtr& pEffect) { return pEffect->getTargetShape() == xShape; });
1065 if (aIter != pMainSequence->getEnd())
1066 {
1067 CustomAnimationEffectPtr pEffect( *aIter );
1068 bRet = pEffect->hasAfterEffect() &&
1069 pEffect->getDimColor().hasValue() &&
1070 pEffect->IsAfterEffectOnNext();
1071 }
1072 }
1073 }
1074
1075 return bRet;
1076}
1077
1078void EffectMigration::SetPresentationOrder( SvxShape* pShape, sal_Int32 nNewPos )
1079{
1080 if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->getSdrPageFromSdrObject() )
1081 return;
1082
1083 SdrObject* pObj = pShape->GetSdrObject();
1084 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
1085
1086 EffectSequence& rSequence = pMainSequence->getSequence();
1087 sal_Int32 nPos;
1088 sal_Int32 nCurrentPos = -1;
1089 std::vector< std::vector< EffectSequence::iterator > > aEffectVector(1);
1090
1091 if( !rSequence.empty() )
1092 {
1093 Reference< XShape > xThis( pShape );
1094 Reference< XShape > xCurrent;
1095
1096 EffectSequence::iterator aIter( rSequence.begin() );
1097 EffectSequence::iterator aEnd( rSequence.end() );
1098 for( nPos = 0; aIter != aEnd; ++aIter )
1099 {
1100 CustomAnimationEffectPtr pEffect = *aIter;
1101
1102 if( !xCurrent.is() )
1103 {
1104 xCurrent = pEffect->getTargetShape();
1105 }
1106 else if( pEffect->getTargetShape() != xCurrent )
1107 {
1108 nPos++;
1109 xCurrent = pEffect->getTargetShape();
1110 aEffectVector.resize( nPos+1 );
1111 }
1112
1113 // is this the first effect for xThis shape?
1114 if(( nCurrentPos == -1 ) && ( xCurrent == xThis ) )
1115 {
1116 nCurrentPos = nPos;
1117 }
1118
1119 aEffectVector[nPos].push_back( aIter );
1120 }
1121 }
1122
1123 // check if there is at least one effect for xThis
1124 if( nCurrentPos == -1 )
1125 {
1126 OSL_FAIL("sd::EffectMigration::SetPresentationOrder() failed cause this shape has no effect" );
1127 return;
1128 }
1129
1130 // check trivial case
1131 if( nCurrentPos == nNewPos )
1132 return;
1133
1134 std::vector< CustomAnimationEffectPtr > aEffects;
1135
1136 for( const auto& rIter : aEffectVector[nCurrentPos] )
1137 {
1138 aEffects.push_back( *rIter );
1139 rSequence.erase( rIter );
1140 }
1141
1142 if( nNewPos > nCurrentPos )
1143 nNewPos++;
1144
1145 if( nNewPos == static_cast<sal_Int32>(aEffectVector.size()) )
1146 {
1147 rSequence.insert( rSequence.end(), aEffects.begin(), aEffects.end() );
1148 }
1149 else
1150 {
1151 EffectSequence::iterator aPos( aEffectVector[nNewPos][0] );
1152 for( const auto& rEffect : aEffects )
1153 {
1154 rSequence.insert( aPos, rEffect );
1155 }
1156 }
1157}
1158
1163sal_Int32 EffectMigration::GetPresentationOrder( SvxShape* pShape )
1164{
1165 sal_Int32 nPos = -1, nFound = -1;
1166
1167 SdrObject* pObj = pShape->GetSdrObject();
1168 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
1169
1170 EffectSequence& rSequence = pMainSequence->getSequence();
1171
1172 Reference< XShape > xThis( pShape );
1173 Reference< XShape > xCurrent;
1174
1175 for( const CustomAnimationEffectPtr& pEffect : rSequence )
1176 {
1177 if( !xCurrent.is() || pEffect->getTargetShape() != xCurrent )
1178 {
1179 nPos++;
1180 xCurrent = pEffect->getTargetShape();
1181
1182 // is this the first effect for xThis shape?
1183 if( xCurrent == xThis )
1184 {
1185 nFound = nPos;
1186 break;
1187 }
1188 }
1189 }
1190
1191 return nFound;
1192}
1193
1194void EffectMigration::UpdateSoundEffect( SvxShape* pShape, SdAnimationInfo const * pInfo )
1195{
1196 if( !pInfo )
1197 return;
1198
1199 SdrObject* pObj = pShape->GetSdrObject();
1200 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
1201
1202 const Reference< XShape > xShape( pShape );
1203
1204 EffectSequence::iterator aIter;
1205 bool bNeedRebuild = false;
1206
1207 OUString aSoundFile;
1208 if( pInfo->mbSoundOn )
1209 aSoundFile = pInfo->maSoundFile;
1210
1211 for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter )
1212 {
1213 CustomAnimationEffectPtr pEffect( *aIter );
1214 if( pEffect->getTargetShape() == xShape )
1215 {
1216 if( !aSoundFile.isEmpty() )
1217 {
1218 pEffect->createAudio( Any( aSoundFile ) );
1219 }
1220 else
1221 {
1222 pEffect->removeAudio();
1223 }
1224 bNeedRebuild = true;
1225 }
1226 }
1227
1228 if( bNeedRebuild )
1229 pMainSequence->rebuild();
1230}
1231
1232OUString EffectMigration::GetSoundFile( SvxShape* pShape )
1233{
1234 OUString aSoundFile;
1235
1236 if( pShape )
1237 {
1238 SdrObject* pObj = pShape->GetSdrObject();
1239 if( pObj && pObj->getSdrPageFromSdrObject() )
1240 {
1241 sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->getSdrPageFromSdrObject())->getMainSequence();
1242
1243 const Reference< XShape > xShape( pShape );
1244
1245 EffectSequence::iterator aIter;
1246
1247 for( aIter = pMainSequence->getBegin();
1248 (aSoundFile.isEmpty()) && (aIter != pMainSequence->getEnd());
1249 ++aIter )
1250 {
1251 CustomAnimationEffectPtr pEffect( *aIter );
1252 if( pEffect->getTargetShape() == xShape )
1253 {
1254 if( pEffect->getAudio().is() )
1255 pEffect->getAudio()->getSource() >>= aSoundFile;
1256 }
1257 }
1258 }
1259 }
1260 return aSoundFile;
1261}
1262
1263bool EffectMigration::GetSoundOn( SvxShape* pShape )
1264{
1265 return !GetSoundFile( pShape ).isEmpty();
1266}
1267
1268void EffectMigration::SetAnimationPath( SvxShape* pShape, SdrPathObj const * pPathObj )
1269{
1270 if( !(pShape && pPathObj) )
1271 return;
1272
1273 SdrObject* pObj = pShape->GetSdrObject();
1274
1275 if( pObj )
1276 {
1277 const Reference< XShape > xShape( pShape );
1278 SdPage* pPage = dynamic_cast< SdPage* >(pPathObj->getSdrPageFromSdrObject());
1279 if( pPage )
1280 {
1281 std::shared_ptr< sd::MainSequence > pMainSequence( pPage->getMainSequence() );
1282 if( pMainSequence )
1283 pMainSequence->append( *pPathObj, Any( xShape ), -1.0, "" );
1284 }
1285 }
1286}
1287
1288// #i42894# helper which creates the needed XAnimate for changing visibility and all the (currently) needed embeddings
1289static void createVisibilityOnOffNode(Reference< XTimeContainer > const & rxParentContainer, SdrObject& rCandidate, bool bVisible, bool bOnClick, double fDuration)
1290{
1291 Reference< XMultiServiceFactory > xMsf(::comphelper::getProcessServiceFactory());
1292
1293 // create par container node
1294 Reference< XAnimationNode > xOuterSeqTimeContainer(xMsf->createInstance("com.sun.star.animations.ParallelTimeContainer"), UNO_QUERY_THROW);
1295
1296 // set begin
1297 xOuterSeqTimeContainer->setBegin(Any(0.0));
1298
1299 // set fill
1300 xOuterSeqTimeContainer->setFill(AnimationFill::HOLD);
1301
1302 // set named values
1303 Sequence< NamedValue > aUserDataSequence{
1304 { /* Name */ "node-type",
1305 /* Value */ Any(bOnClick ? EffectNodeType::ON_CLICK : EffectNodeType::AFTER_PREVIOUS) }
1306 };
1307
1308 xOuterSeqTimeContainer->setUserData(aUserDataSequence);
1309
1310 // create animate set to change visibility for rCandidate
1311 Reference< XAnimationNode > xAnimateSetForLast(xMsf->createInstance("com.sun.star.animations.AnimateSet"), UNO_QUERY_THROW);
1312
1313 // set begin
1314 xAnimateSetForLast->setBegin(Any(0.0));
1315
1316 // set duration
1317 xAnimateSetForLast->setDuration(Any(fDuration));
1318
1319 // set fill
1320 xAnimateSetForLast->setFill(AnimationFill::HOLD);
1321
1322 // set target
1323 Reference< XAnimate > xAnimate(xAnimateSetForLast, UNO_QUERY);
1324 Reference< XShape > xTargetShape(rCandidate.getUnoShape(), UNO_QUERY);
1325 xAnimate->setTarget(Any(xTargetShape));
1326
1327 // set AttributeName
1328 xAnimate->setAttributeName("Visibility");
1329
1330 // set attribute value
1331 xAnimate->setTo(Any(bVisible));
1332
1333 // ad set node to par node
1334 Reference< XTimeContainer > xParentContainer(xOuterSeqTimeContainer, UNO_QUERY_THROW);
1335 xParentContainer->appendChild(xAnimateSetForLast);
1336
1337 // add node
1338 rxParentContainer->appendChild(xOuterSeqTimeContainer);
1339}
1340
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
1346void EffectMigration::CreateAnimatedGroup(SdrObjGroup const & rGroupObj, SdPage& rPage)
1347{
1348 // aw080 will give a vector immediately
1349 SdrObjListIter aIter(rGroupObj);
1350
1351 if(!aIter.Count())
1352 return;
1353
1354 std::shared_ptr< sd::MainSequence > pMainSequence(rPage.getMainSequence());
1355
1356 if(!pMainSequence)
1357 return;
1358
1359 std::vector< SdrObject* > aObjects;
1360 aObjects.reserve(aIter.Count());
1361
1362 while(aIter.IsMore())
1363 {
1364 // do move to page rough with old/current stuff, will be different in aw080 anyways
1365 rtl::Reference<SdrObject> pCandidate = aIter.Next();
1366 rGroupObj.GetSubList()->NbcRemoveObject(pCandidate->GetOrdNum());
1367 rPage.NbcInsertObject(pCandidate.get());
1368 aObjects.push_back(pCandidate.get());
1369 }
1370
1371 // create main node
1372 Reference< XMultiServiceFactory > xMsf(::comphelper::getProcessServiceFactory());
1373 Reference< XAnimationNode > xOuterSeqTimeContainer(xMsf->createInstance("com.sun.star.animations.ParallelTimeContainer"), UNO_QUERY_THROW);
1374
1375 // set begin
1376 xOuterSeqTimeContainer->setBegin(Any(0.0));
1377
1378 // prepare parent container
1379 Reference< XTimeContainer > xParentContainer(xOuterSeqTimeContainer, UNO_QUERY_THROW);
1380
1381 // prepare loop over objects
1382 SdrObject* pNext = nullptr;
1383 const double fDurationShow(0.2);
1384 const double fDurationHide(0.001);
1385
1386 for(size_t a(0); a < aObjects.size(); a++)
1387 {
1388 SdrObject* pLast = pNext;
1389 pNext = aObjects[a];
1390
1391 // create node
1392 if(pLast)
1393 {
1394 createVisibilityOnOffNode(xParentContainer, *pLast, false, false, fDurationHide);
1395 }
1396
1397 if(pNext)
1398 {
1399 createVisibilityOnOffNode(xParentContainer, *pNext, true, !a, fDurationShow);
1400 }
1401 }
1402
1403 // create end node
1404 if(pNext)
1405 {
1406 createVisibilityOnOffNode(xParentContainer, *pNext, false, false, fDurationHide);
1407 }
1408
1409 // add to main sequence and rebuild
1410 pMainSequence->createEffects(xOuterSeqTimeContainer);
1411 pMainSequence->rebuild();
1412}
1413
1414void EffectMigration::DocumentLoaded(SdDrawDocument & rDoc)
1415{
1416 if (DocumentType::Draw == rDoc.GetDocumentType())
1417 return; // no animations in Draw
1418 for (sal_uInt16 n = 0; n < rDoc.GetSdPageCount(PageKind::Standard); ++n)
1419 {
1420 SdPage *const pPage = rDoc.GetSdPage(n, PageKind::Standard);
1421 if (pPage->hasAnimationNode())
1422 {
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();
1427 }
1428 }
1429 for (sal_uInt16 n = 0; n < rDoc.GetMasterSdPageCount(PageKind::Standard); ++n)
1430 {
1431 SdPage *const pPage = rDoc.GetMasterSdPage(n, PageKind::Standard);
1432 if (pPage->hasAnimationNode())
1433 {
1434 pPage->getMainSequence()->getRootNode();
1435 }
1436 }
1437}
1438
1439/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static EffectSequence::iterator ImplFindEffect(MainSequencePtr const &pMainSequence, const Reference< XShape > &rShape, sal_Int16 nSubItem)
static void createVisibilityOnOffNode(Reference< XTimeContainer > const &rxParentContainer, SdrObject &rCandidate, bool bVisible, bool bOnClick, double fDuration)
deprecated_AnimationEffect_conversion_table_entry const deprecated_AnimationEffect_conversion_table[]
deprecated_FadeEffect_conversion_table_entry const deprecated_FadeEffect_conversion_table[]
static bool implIsInsideGroup(SdrObject const *pObj)
OUString maSoundFile
Path to the sound file in MS DOS notation.
Definition: anminfo.hxx:45
bool mbSoundOn
Sound on / off.
Definition: anminfo.hxx:46
sal_uInt16 GetMasterSdPageCount(PageKind ePgKind) const
Definition: drawdoc2.cxx:222
SdPage * GetSdPage(sal_uInt16 nPgNum, PageKind ePgKind) const
Definition: drawdoc2.cxx:207
SdPage * GetMasterSdPage(sal_uInt16 nPgNum, PageKind ePgKind)
Definition: drawdoc2.cxx:217
SAL_DLLPRIVATE DocumentType GetDocumentType() const
Definition: drawdoc.hxx:251
sal_uInt16 GetSdPageCount(PageKind ePgKind) const
Definition: drawdoc2.cxx:212
void setTransitionFadeColor(sal_Int32 nTransitionFadeColor)
Definition: sdpage2.cxx:516
PresChange GetPresChange() const
Definition: sdpage.hxx:214
void setTransitionDirection(bool bTransitionbDirection)
Definition: sdpage2.cxx:510
std::shared_ptr< sd::MainSequence > const & getMainSequence()
returns a helper class to manipulate effects inside the main sequence
void setTransitionSubtype(sal_Int16 nTransitionSubtype)
Definition: sdpage2.cxx:504
bool hasAnimationNode() const
quick check if this slide has an animation node.
virtual void NbcInsertObject(SdrObject *pObj, size_t nPos=SAL_MAX_SIZE) override
Definition: sdpage.cxx:1681
void setTransitionType(sal_Int16 nTransitionType)
Definition: sdpage2.cxx:498
virtual SdrObjList * GetSubList() const override
size_t Count() const
SdrObject * Next()
bool IsMore() const
virtual rtl::Reference< SdrObject > NbcRemoveObject(size_t nObjNum)
virtual SdrObject * getSdrObjectFromSdrObjList() const
virtual SdrInventor GetObjInventor() const
virtual css::uno::Reference< css::drawing::XShape > getUnoShape()
SdrObjList * getParentSdrObjListFromSdrObject() const
virtual SdrObjKind GetObjIdentifier() const
SdrPage * getSdrPageFromSdrObject() const
virtual bool HasText() const override
SdrObject * GetSdrObject() const
css::uno::Type const & get()
CustomAnimationPresetPtr getEffectDescriptor(const OUString &rPresetId) const
constexpr ::Color COL_LIGHTGRAY(0xC0, 0xC0, 0xC0)
#define DBG_ASSERT(sCon, aError)
void * p
sal_Int64 n
uno_Any a
sal_uInt16 nPos
bool equalsAscii(std::u16string_view s1, std::string_view s2)
std::list< CustomAnimationEffectPtr > EffectSequence
std::shared_ptr< MainSequence > MainSequencePtr
std::shared_ptr< CustomAnimationTextGroup > CustomAnimationTextGroupPtr
std::shared_ptr< CustomAnimationPreset > CustomAnimationPresetPtr
std::vector< TransitionPresetPtr > TransitionPresetList
std::shared_ptr< CustomAnimationEffect > CustomAnimationEffectPtr
std::shared_ptr< TransitionPreset > TransitionPresetPtr
SVXCORE_DLLPUBLIC SdrTextObj * DynCastSdrTextObj(SdrObject *)
bool bVisible