1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_slideshow.hxx"
26
27 #include <canvas/debug.hxx>
28 #include <tools/diagnose_ex.h>
29
30 #include <basegfx/matrix/b2dhommatrix.hxx>
31 #include <basegfx/tools/canvastools.hxx>
32 #include <basegfx/polygon/b2dpolygontools.hxx>
33 #include <basegfx/polygon/b2dpolypolygontools.hxx>
34
35 #include <cppcanvas/basegfxfactory.hxx>
36
37 #include <comphelper/optional.hxx>
38 #include <comphelper/make_shared_from_uno.hxx>
39
40 #include <com/sun/star/rendering/XIntegerBitmap.hpp>
41 #include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
42 #include <com/sun/star/animations/TransitionType.hpp>
43 #include <com/sun/star/animations/TransitionSubType.hpp>
44 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
45
46 #include "slidechangebase.hxx"
47 #include "transitionfactory.hxx"
48 #include "transitiontools.hxx"
49 #include "parametricpolypolygonfactory.hxx"
50 #include "animationfactory.hxx"
51 #include "clippingfunctor.hxx"
52 #include "combtransition.hxx"
53 #include "tools.hxx"
54
55 #include <boost/bind.hpp>
56
57
58 /***************************************************
59 *** ***
60 *** Slide Transition Effects ***
61 *** ***
62 ***************************************************/
63
64 using namespace com::sun::star;
65
66 namespace slideshow {
67 namespace internal {
68
69 namespace {
70
71 // helper methods
72 // =============================================
73
fillPage(const::cppcanvas::CanvasSharedPtr & rDestinationCanvas,const::basegfx::B2DSize & rPageSizePixel,const RGBColor & rFillColor)74 void fillPage( const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
75 const ::basegfx::B2DSize& rPageSizePixel,
76 const RGBColor& rFillColor )
77 {
78 // need to render without any transformation (we
79 // assume rPageSizePixel to represent device units)
80 const ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas(
81 rDestinationCanvas->clone() );
82 pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
83
84 // TODO(F2): Properly respect clip here.
85 // Might have to be transformed, too.
86 const ::basegfx::B2DHomMatrix aViewTransform(
87 rDestinationCanvas->getTransformation() );
88 const ::basegfx::B2DPoint aOutputPosPixel(
89 aViewTransform * ::basegfx::B2DPoint() );
90
91 fillRect( pDevicePixelCanvas,
92 ::basegfx::B2DRectangle(
93 aOutputPosPixel.getX(),
94 aOutputPosPixel.getY(),
95 aOutputPosPixel.getX() + rPageSizePixel.getX(),
96 aOutputPosPixel.getY() + rPageSizePixel.getY() ),
97 rFillColor.getIntegerColor() );
98 }
99
100 class PluginSlideChange: public SlideChangeBase
101 {
102 struct TransitionViewPair {
103 uno::Reference<presentation::XTransition> mxTransition;
104 UnoViewSharedPtr mpView;
105
TransitionViewPairslideshow::internal::__anon0db743360111::PluginSlideChange::TransitionViewPair106 TransitionViewPair( uno::Reference<presentation::XTransition> xTransition, const UnoViewSharedPtr pView )
107 {
108 mxTransition = xTransition;
109 mpView = pView;
110 }
111
~TransitionViewPairslideshow::internal::__anon0db743360111::PluginSlideChange::TransitionViewPair112 ~TransitionViewPair()
113 {
114 mxTransition.clear();
115 mpView.reset();;
116 }
117
updateslideshow::internal::__anon0db743360111::PluginSlideChange::TransitionViewPair118 void update( double t )
119 {
120 mxTransition->update( t );
121 }
122 };
123
124 public:
125 /** Create a new SlideChanger, for the given leaving and
126 entering slide bitmaps, which uses super secret OpenGL
127 stuff.
128 */
PluginSlideChange(sal_Int16 nTransitionType,sal_Int16 nTransitionSubType,boost::optional<SlideSharedPtr> const & leavingSlide_,const SlideSharedPtr & pEnteringSlide,const UnoViewContainer & rViewContainer,ScreenUpdater & rScreenUpdater,const uno::Reference<presentation::XTransitionFactory> & xFactory,const SoundPlayerSharedPtr & pSoundPlayer,EventMultiplexer & rEventMultiplexer)129 PluginSlideChange( sal_Int16 nTransitionType,
130 sal_Int16 nTransitionSubType,
131 boost::optional<SlideSharedPtr> const& leavingSlide_,
132 const SlideSharedPtr& pEnteringSlide,
133 const UnoViewContainer& rViewContainer,
134 ScreenUpdater& rScreenUpdater,
135 const uno::Reference<
136 presentation::XTransitionFactory>& xFactory,
137 const SoundPlayerSharedPtr& pSoundPlayer,
138 EventMultiplexer& rEventMultiplexer) :
139 SlideChangeBase( leavingSlide_,
140 pEnteringSlide,
141 pSoundPlayer,
142 rViewContainer,
143 rScreenUpdater,
144 rEventMultiplexer ),
145 maTransitions(),
146 mbSuccess( false ),
147 mnTransitionType( nTransitionType ),
148 mnTransitionSubType( nTransitionSubType ),
149 mxFactory( xFactory )
150 {
151 // create one transition per view
152 UnoViewVector::const_iterator aCurrView (rViewContainer.begin());
153 const UnoViewVector::const_iterator aEnd(rViewContainer.end());
154 while( aCurrView != aEnd )
155 {
156 if(! addTransition( *aCurrView ) )
157 return;
158
159 ENSURE_OR_THROW(maTransitions.back() && maTransitions.back()->mxTransition.is(),
160 "Failed to create plugin transition");
161 ++aCurrView;
162 }
163 mbSuccess = true;
164 }
165
~PluginSlideChange()166 ~PluginSlideChange()
167 {
168 mxFactory.clear();
169
170 ::std::vector< TransitionViewPair* >::const_iterator aCurrView (maTransitions.begin());
171 ::std::vector< TransitionViewPair* >::const_iterator aEnd(maTransitions.end());
172 while( aCurrView != aEnd )
173 {
174 delete (*aCurrView);
175 ++aCurrView;
176 }
177 maTransitions.clear();
178 }
179
addTransition(const UnoViewSharedPtr & rView)180 bool addTransition( const UnoViewSharedPtr& rView )
181 {
182 uno::Reference<presentation::XTransition> rTransition = mxFactory->createTransition(
183 mnTransitionType,
184 mnTransitionSubType,
185 rView->getUnoView(),
186 getLeavingBitmap(ViewEntry(rView))->getXBitmap(),
187 getEnteringBitmap(ViewEntry(rView))->getXBitmap() );
188
189 if( rTransition.is() )
190 maTransitions.push_back( new TransitionViewPair( rTransition, rView ) );
191 else
192 return false;
193
194 return true;
195 }
196
operator ()(double t)197 virtual bool operator()( double t )
198 {
199 std::for_each(maTransitions.begin(),
200 maTransitions.end(),
201 boost::bind( &TransitionViewPair::update,
202 _1, t) );
203 return true;
204 }
205
Success()206 bool Success()
207 {
208 return mbSuccess;
209 }
210
211 // ViewEventHandler
viewAdded(const UnoViewSharedPtr & rView)212 virtual void viewAdded( const UnoViewSharedPtr& rView )
213 {
214 OSL_TRACE("PluginSlideChange viewAdded");
215 SlideChangeBase::viewAdded( rView );
216
217 ::std::vector< TransitionViewPair* >::const_iterator aCurrView (maTransitions.begin());
218 ::std::vector< TransitionViewPair* >::const_iterator aEnd(maTransitions.end());
219 bool bKnown = false;
220 while( aCurrView != aEnd )
221 {
222 if( (*aCurrView)->mpView == rView ) {
223 bKnown = true;
224 break;
225 }
226 ++aCurrView;
227 }
228
229 if( !bKnown ) {
230 OSL_TRACE("need to be added");
231
232 addTransition( rView );
233 }
234 }
235
viewRemoved(const UnoViewSharedPtr & rView)236 virtual void viewRemoved( const UnoViewSharedPtr& rView )
237 {
238 OSL_TRACE("PluginSlideChange viewRemoved");
239 SlideChangeBase::viewRemoved( rView );
240
241 ::std::vector< TransitionViewPair* >::iterator aCurrView (maTransitions.begin());
242 ::std::vector< TransitionViewPair* >::const_iterator aEnd(maTransitions.end());
243 while( aCurrView != aEnd )
244 {
245 if( (*aCurrView)->mpView == rView ) {
246 OSL_TRACE( "view removed" );
247 delete (*aCurrView);
248 maTransitions.erase( aCurrView );
249 break;
250 }
251 ++aCurrView;
252 }
253 }
254
viewChanged(const UnoViewSharedPtr & rView)255 virtual void viewChanged( const UnoViewSharedPtr& rView )
256 {
257 OSL_TRACE("PluginSlideChange viewChanged");
258 SlideChangeBase::viewChanged( rView );
259
260 ::std::vector< TransitionViewPair* >::const_iterator aCurrView (maTransitions.begin());
261 ::std::vector< TransitionViewPair* >::const_iterator aEnd(maTransitions.end());
262 while( aCurrView != aEnd )
263 {
264 if( (*aCurrView)->mpView == rView ) {
265 OSL_TRACE( "view changed" );
266 (*aCurrView)->mxTransition->viewChanged( rView->getUnoView(),
267 getLeavingBitmap(ViewEntry(rView))->getXBitmap(),
268 getEnteringBitmap(ViewEntry(rView))->getXBitmap() );
269 } else
270 OSL_TRACE( "view did not changed" );
271
272 ++aCurrView;
273 }
274 }
275
viewsChanged()276 virtual void viewsChanged()
277 {
278 OSL_TRACE("PluginSlideChange viewsChanged");
279 SlideChangeBase::viewsChanged();
280
281 ::std::vector< TransitionViewPair* >::const_iterator aCurrView (maTransitions.begin());
282 ::std::vector< TransitionViewPair* >::const_iterator aEnd(maTransitions.end());
283 while( aCurrView != aEnd )
284 {
285 OSL_TRACE( "view changed" );
286 (*aCurrView)->mxTransition->viewChanged( (*aCurrView)->mpView->getUnoView(),
287 getLeavingBitmap(ViewEntry((*aCurrView)->mpView))->getXBitmap(),
288 getEnteringBitmap(ViewEntry((*aCurrView)->mpView))->getXBitmap() );
289 ++aCurrView;
290 }
291 }
292
293 private:
294 // One transition object per view
295 std::vector< TransitionViewPair* > maTransitions;
296
297 // bool
298 bool mbSuccess;
299
300 sal_Int16 mnTransitionType;
301 sal_Int16 mnTransitionSubType;
302
303 uno::Reference<presentation::XTransitionFactory> mxFactory;
304 };
305
306 class ClippedSlideChange : public SlideChangeBase
307 {
308 public:
309 /** Create a new SlideChanger, for the given leaving and
310 entering slide bitmaps, which applies the given clip
311 polygon.
312 */
ClippedSlideChange(const SlideSharedPtr & pEnteringSlide,const ParametricPolyPolygonSharedPtr & rPolygon,const TransitionInfo & rTransitionInfo,const UnoViewContainer & rViewContainer,ScreenUpdater & rScreenUpdater,EventMultiplexer & rEventMultiplexer,bool bDirectionForward,const SoundPlayerSharedPtr & pSoundPlayer)313 ClippedSlideChange(
314 const SlideSharedPtr& pEnteringSlide,
315 const ParametricPolyPolygonSharedPtr& rPolygon,
316 const TransitionInfo& rTransitionInfo,
317 const UnoViewContainer& rViewContainer,
318 ScreenUpdater& rScreenUpdater,
319 EventMultiplexer& rEventMultiplexer,
320 bool bDirectionForward,
321 const SoundPlayerSharedPtr& pSoundPlayer ) :
322 SlideChangeBase(
323 // leaving bitmap is empty, we're leveraging the fact that the
324 // old slide is still displayed in the background:
325 boost::optional<SlideSharedPtr>(),
326 pEnteringSlide,
327 pSoundPlayer,
328 rViewContainer,
329 rScreenUpdater,
330 rEventMultiplexer ),
331 maClippingFunctor( rPolygon,
332 rTransitionInfo,
333 bDirectionForward,
334 true )
335 {}
336
337 virtual void performIn(
338 const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
339 const ViewEntry& rViewEntry,
340 const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
341 double t );
342
343 virtual void performOut(
344 const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
345 const ViewEntry& rViewEntry,
346 const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
347 double t );
348
349 private:
350 ClippingFunctor maClippingFunctor;
351 };
352
performIn(const::cppcanvas::CustomSpriteSharedPtr & rSprite,const ViewEntry & rViewEntry,const::cppcanvas::CanvasSharedPtr &,double t)353 void ClippedSlideChange::performIn(
354 const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
355 const ViewEntry& rViewEntry,
356 const ::cppcanvas::CanvasSharedPtr& /*rDestinationCanvas*/,
357 double t )
358 {
359 // #i46602# Better work in device coordinate space here,
360 // otherwise, we too easily suffer from roundoffs. Apart from
361 // that, getEnteringSizePixel() _guarantees_ to cover the whole
362 // slide bitmap. There's a catch, though: this removes any effect
363 // of the view transformation (e.g. rotation) from the transition.
364 rSprite->setClipPixel(
365 maClippingFunctor( t,
366 getEnteringSlideSizePixel(rViewEntry.mpView) ) );
367 }
368
performOut(const::cppcanvas::CustomSpriteSharedPtr &,const ViewEntry &,const::cppcanvas::CanvasSharedPtr &,double)369 void ClippedSlideChange::performOut(
370 const ::cppcanvas::CustomSpriteSharedPtr& /*rSprite*/,
371 const ViewEntry& /*rViewEntry*/,
372 const ::cppcanvas::CanvasSharedPtr& /*rDestinationCanvas*/,
373 double /*t*/ )
374 {
375 // not needed here
376 }
377
378
379 class FadingSlideChange : public SlideChangeBase
380 {
381 public:
382 /** Create a new SlideChanger, for the given leaving and
383 entering slides, which applies a fade effect.
384 */
FadingSlideChange(boost::optional<SlideSharedPtr> const & leavingSlide,const SlideSharedPtr & pEnteringSlide,boost::optional<RGBColor> const & rFadeColor,const SoundPlayerSharedPtr & pSoundPlayer,const UnoViewContainer & rViewContainer,ScreenUpdater & rScreenUpdater,EventMultiplexer & rEventMultiplexer)385 FadingSlideChange(
386 boost::optional<SlideSharedPtr> const & leavingSlide,
387 const SlideSharedPtr& pEnteringSlide,
388 boost::optional<RGBColor> const& rFadeColor,
389 const SoundPlayerSharedPtr& pSoundPlayer,
390 const UnoViewContainer& rViewContainer,
391 ScreenUpdater& rScreenUpdater,
392 EventMultiplexer& rEventMultiplexer )
393 : SlideChangeBase( leavingSlide,
394 pEnteringSlide,
395 pSoundPlayer,
396 rViewContainer,
397 rScreenUpdater,
398 rEventMultiplexer ),
399 maFadeColor( rFadeColor ),
400 mbFirstTurn( true )
401 {}
402
403 virtual void performIn(
404 const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
405 const ViewEntry& rViewEntry,
406 const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
407 double t );
408
409 virtual void performOut(
410 const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
411 const ViewEntry& rViewEntry,
412 const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
413 double t );
414
415 private:
416 const boost::optional< RGBColor > maFadeColor;
417 bool mbFirstTurn;
418 };
419
performIn(const::cppcanvas::CustomSpriteSharedPtr & rSprite,const ViewEntry &,const::cppcanvas::CanvasSharedPtr &,double t)420 void FadingSlideChange::performIn(
421 const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
422 const ViewEntry& /*rViewEntry*/,
423 const ::cppcanvas::CanvasSharedPtr& /*rDestinationCanvas*/,
424 double t )
425 {
426 ENSURE_OR_THROW(
427 rSprite,
428 "FadingSlideChange::performIn(): Invalid sprite" );
429
430 if( maFadeColor )
431 // After half of the active time, fade in new slide
432 rSprite->setAlpha( t > 0.5 ? 2.0*(t-0.5) : 0.0 );
433 else
434 // Fade in new slide over full active time
435 rSprite->setAlpha( t );
436 }
437
performOut(const::cppcanvas::CustomSpriteSharedPtr & rSprite,const ViewEntry & rViewEntry,const::cppcanvas::CanvasSharedPtr & rDestinationCanvas,double t)438 void FadingSlideChange::performOut(
439 const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
440 const ViewEntry& rViewEntry,
441 const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
442 double t )
443 {
444 ENSURE_OR_THROW(
445 rSprite,
446 "FadingSlideChange::performOut(): Invalid sprite" );
447 ENSURE_OR_THROW(
448 rDestinationCanvas,
449 "FadingSlideChange::performOut(): Invalid dest canvas" );
450
451 // only needed for color fades
452 if( maFadeColor )
453 {
454 if( mbFirstTurn )
455 {
456 mbFirstTurn = false;
457
458 // clear page to given fade color. 'Leaving' slide is
459 // painted atop of that, but slowly fading out.
460 fillPage( rDestinationCanvas,
461 getEnteringSlideSizePixel( rViewEntry.mpView ),
462 *maFadeColor );
463 }
464
465 // Until half of the active time, fade out old
466 // slide. After half of the active time, old slide
467 // will be invisible.
468 rSprite->setAlpha( t > 0.5 ? 0.0 : 2.0*(0.5-t) );
469 }
470 }
471
472 class MovingSlideChange : public SlideChangeBase
473 {
474 /// Direction vector for leaving slide,
475 const ::basegfx::B2DVector maLeavingDirection;
476
477 /// Direction vector for entering slide,
478 const ::basegfx::B2DVector maEnteringDirection;
479
480 bool mbFirstPerformCall;
481
482 public:
483 /** Create a new SlideChanger, for the given entering slide
484 bitmaps, which performs a moving slide change effect
485
486 @param rLeavingDirection
487 Direction vector. The move is performed along this
488 direction vector, starting at a position where the leaving
489 slide is fully visible, and ending at a position where the
490 leaving slide is just not visible. The vector must have
491 unit length.
492
493 @param rEnteringDirection
494 Direction vector. The move is performed along this
495 direction vector, starting at a position where the
496 entering slide is just not visible, and ending at the
497 final slide position. The vector must have unit length.
498 */
MovingSlideChange(const boost::optional<SlideSharedPtr> & leavingSlide,const SlideSharedPtr & pEnteringSlide,const SoundPlayerSharedPtr & pSoundPlayer,const UnoViewContainer & rViewContainer,ScreenUpdater & rScreenUpdater,EventMultiplexer & rEventMultiplexer,const::basegfx::B2DVector & rLeavingDirection,const::basegfx::B2DVector & rEnteringDirection)499 MovingSlideChange(
500 const boost::optional<SlideSharedPtr>& leavingSlide,
501 const SlideSharedPtr& pEnteringSlide,
502 const SoundPlayerSharedPtr& pSoundPlayer,
503 const UnoViewContainer& rViewContainer,
504 ScreenUpdater& rScreenUpdater,
505 EventMultiplexer& rEventMultiplexer,
506 const ::basegfx::B2DVector& rLeavingDirection,
507 const ::basegfx::B2DVector& rEnteringDirection )
508 : SlideChangeBase(
509 leavingSlide, pEnteringSlide, pSoundPlayer,
510 rViewContainer, rScreenUpdater, rEventMultiplexer,
511 // Optimization: when leaving bitmap is given,
512 // but it does not move, don't create sprites for it,
513 // we simply paint it once at startup:
514 !rLeavingDirection.equalZero() /* bCreateLeavingSprites */,
515 !rEnteringDirection.equalZero() /* bCreateEnteringSprites */ ),
516 // TODO(F1): calc correct length of direction
517 // vector. Directions not strictly horizontal or vertical
518 // must travel a longer distance.
519 maLeavingDirection( rLeavingDirection ),
520 // TODO(F1): calc correct length of direction
521 // vector. Directions not strictly horizontal or vertical
522 // must travel a longer distance.
523 maEnteringDirection( rEnteringDirection ),
524 mbFirstPerformCall( true )
525 {}
526
527 virtual void performIn(
528 const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
529 const ViewEntry& rViewEntry,
530 const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
531 double t );
532
533 virtual void performOut(
534 const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
535 const ViewEntry& rViewEntry,
536 const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
537 double t );
538 };
539
performIn(const::cppcanvas::CustomSpriteSharedPtr & rSprite,const ViewEntry & rViewEntry,const::cppcanvas::CanvasSharedPtr & rDestinationCanvas,double t)540 void MovingSlideChange::performIn(
541 const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
542 const ViewEntry& rViewEntry,
543 const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
544 double t )
545 {
546 // intro sprite moves:
547
548 ENSURE_OR_THROW(
549 rSprite,
550 "MovingSlideChange::performIn(): Invalid sprite" );
551 ENSURE_OR_THROW(
552 rDestinationCanvas,
553 "MovingSlideChange::performIn(): Invalid dest canvas" );
554
555 if (mbFirstPerformCall && maLeavingDirection.equalZero())
556 {
557 mbFirstPerformCall = false;
558 renderBitmap( getLeavingBitmap(rViewEntry), rDestinationCanvas );
559 }
560
561 // TODO(F1): This does not account for non-translational
562 // transformations! If the canvas is rotated, we still
563 // move the sprite unrotated (which might or might not
564 // produce the intended effect).
565 const basegfx::B2DHomMatrix aViewTransform(
566 rDestinationCanvas->getTransformation() );
567 const basegfx::B2DPoint aPageOrigin(
568 aViewTransform * basegfx::B2DPoint() );
569
570 // move sprite
571 rSprite->movePixel(
572 aPageOrigin +
573 ((t - 1.0) *
574 ::basegfx::B2DSize( getEnteringSlideSizePixel(rViewEntry.mpView) ) *
575 maEnteringDirection) );
576 }
577
performOut(const::cppcanvas::CustomSpriteSharedPtr & rSprite,const ViewEntry & rViewEntry,const::cppcanvas::CanvasSharedPtr & rDestinationCanvas,double t)578 void MovingSlideChange::performOut(
579 const ::cppcanvas::CustomSpriteSharedPtr& rSprite,
580 const ViewEntry& rViewEntry,
581 const ::cppcanvas::CanvasSharedPtr& rDestinationCanvas,
582 double t )
583 {
584 // outro sprite moves:
585
586 ENSURE_OR_THROW(
587 rSprite,
588 "MovingSlideChange::performOut(): Invalid sprite" );
589 ENSURE_OR_THROW(
590 rDestinationCanvas,
591 "MovingSlideChange::performOut(): Invalid dest canvas" );
592
593 if (mbFirstPerformCall && maEnteringDirection.equalZero())
594 {
595 mbFirstPerformCall = false;
596 renderBitmap( getEnteringBitmap(rViewEntry), rDestinationCanvas );
597 }
598
599 // TODO(F1): This does not account for non-translational
600 // transformations! If the canvas is rotated, we still
601 // move the sprite unrotated (which might or might not
602 // produce the intended effect).
603 const basegfx::B2DHomMatrix aViewTransform(
604 rDestinationCanvas->getTransformation() );
605 const basegfx::B2DPoint aPageOrigin(
606 aViewTransform * basegfx::B2DPoint() );
607
608 // move sprite
609 rSprite->movePixel(
610 aPageOrigin + (t *
611 ::basegfx::B2DSize( getEnteringSlideSizePixel(rViewEntry.mpView) ) *
612 maLeavingDirection) );
613 }
614
615
createPushWipeTransition(boost::optional<SlideSharedPtr> const & leavingSlide_,const SlideSharedPtr & pEnteringSlide,const UnoViewContainer & rViewContainer,ScreenUpdater & rScreenUpdater,EventMultiplexer & rEventMultiplexer,sal_Int16,sal_Int16 nTransitionSubType,bool,const SoundPlayerSharedPtr & pSoundPlayer)616 NumberAnimationSharedPtr createPushWipeTransition(
617 boost::optional<SlideSharedPtr> const & leavingSlide_,
618 const SlideSharedPtr& pEnteringSlide,
619 const UnoViewContainer& rViewContainer,
620 ScreenUpdater& rScreenUpdater,
621 EventMultiplexer& rEventMultiplexer,
622 sal_Int16 /*nTransitionType*/,
623 sal_Int16 nTransitionSubType,
624 bool /*bTransitionDirection*/,
625 const SoundPlayerSharedPtr& pSoundPlayer )
626 {
627 boost::optional<SlideSharedPtr> leavingSlide; // no bitmap
628 if (leavingSlide_ && (*leavingSlide_).get() != 0)
629 {
630 // opt: only page, if we've an
631 // actual slide to move out here. We
632 // _don't_ need a fake black background
633 // bitmap, neither for push nor for comb
634 // wipes.
635 leavingSlide = leavingSlide_;
636 }
637
638 // setup direction vector
639 bool bComb( false );
640 ::basegfx::B2DVector aDirection;
641 switch( nTransitionSubType )
642 {
643 default:
644 OSL_ENSURE(
645 false,
646 "createPushWipeTransition(): Unexpected transition "
647 "subtype for animations::TransitionType::PUSHWIPE "
648 "transitions" );
649 return NumberAnimationSharedPtr();
650
651 case animations::TransitionSubType::FROMTOP:
652 aDirection = ::basegfx::B2DVector( 0.0, 1.0 );
653 break;
654
655 case animations::TransitionSubType::FROMBOTTOM:
656 aDirection = ::basegfx::B2DVector( 0.0, -1.0 );
657 break;
658
659 case animations::TransitionSubType::FROMLEFT:
660 aDirection = ::basegfx::B2DVector( 1.0, 0.0 );
661 break;
662
663 case animations::TransitionSubType::FROMRIGHT:
664 aDirection = ::basegfx::B2DVector( -1.0, 0.0 );
665 break;
666
667 case animations::TransitionSubType::FROMBOTTOMRIGHT:
668 aDirection = ::basegfx::B2DVector( -1.0, -1.0 );
669 break;
670
671 case animations::TransitionSubType::FROMBOTTOMLEFT:
672 aDirection = ::basegfx::B2DVector( 1.0, -1.0 );
673 break;
674
675 case animations::TransitionSubType::FROMTOPRIGHT:
676 aDirection = ::basegfx::B2DVector( -1.0, 1.0 );
677 break;
678
679 case animations::TransitionSubType::FROMTOPLEFT:
680 aDirection = ::basegfx::B2DVector( 1.0, 1.0 );
681 break;
682
683 case animations::TransitionSubType::COMBHORIZONTAL:
684 aDirection = ::basegfx::B2DVector( 1.0, 0.0 );
685 bComb = true;
686 break;
687
688 case animations::TransitionSubType::COMBVERTICAL:
689 aDirection = ::basegfx::B2DVector( 0.0, 1.0 );
690 bComb = true;
691 break;
692 }
693
694 if( bComb )
695 {
696 return NumberAnimationSharedPtr(
697 new CombTransition( leavingSlide,
698 pEnteringSlide,
699 pSoundPlayer,
700 rViewContainer,
701 rScreenUpdater,
702 rEventMultiplexer,
703 aDirection,
704 24 /* comb with 12 stripes */ ));
705 }
706 else
707 {
708 return NumberAnimationSharedPtr(
709 new MovingSlideChange( leavingSlide,
710 pEnteringSlide,
711 pSoundPlayer,
712 rViewContainer,
713 rScreenUpdater,
714 rEventMultiplexer,
715 aDirection,
716 aDirection ));
717 }
718 }
719
createSlideWipeTransition(boost::optional<SlideSharedPtr> const & leavingSlide,const SlideSharedPtr & pEnteringSlide,const UnoViewContainer & rViewContainer,ScreenUpdater & rScreenUpdater,EventMultiplexer & rEventMultiplexer,sal_Int16,sal_Int16 nTransitionSubType,bool bTransitionDirection,const SoundPlayerSharedPtr & pSoundPlayer)720 NumberAnimationSharedPtr createSlideWipeTransition(
721 boost::optional<SlideSharedPtr> const & leavingSlide,
722 const SlideSharedPtr& pEnteringSlide,
723 const UnoViewContainer& rViewContainer,
724 ScreenUpdater& rScreenUpdater,
725 EventMultiplexer& rEventMultiplexer,
726 sal_Int16 /*nTransitionType*/,
727 sal_Int16 nTransitionSubType,
728 bool bTransitionDirection,
729 const SoundPlayerSharedPtr& pSoundPlayer )
730 {
731 // setup 'in' direction vector
732 ::basegfx::B2DVector aInDirection;
733 switch( nTransitionSubType )
734 {
735 default:
736 OSL_ENSURE(
737 false,
738 "createSlideWipeTransition(): Unexpected transition "
739 "subtype for animations::TransitionType::SLIDEWIPE "
740 "transitions" );
741 return NumberAnimationSharedPtr();
742
743 case animations::TransitionSubType::FROMTOP:
744 aInDirection = ::basegfx::B2DVector( 0.0, 1.0 );
745 break;
746
747 case animations::TransitionSubType::FROMRIGHT:
748 aInDirection = ::basegfx::B2DVector( -1.0, 0.0 );
749 break;
750
751 case animations::TransitionSubType::FROMLEFT:
752 aInDirection = ::basegfx::B2DVector( 1.0, 0.0 );
753 break;
754
755 case animations::TransitionSubType::FROMBOTTOM:
756 aInDirection = ::basegfx::B2DVector( 0.0, -1.0 );
757 break;
758
759 case animations::TransitionSubType::FROMBOTTOMRIGHT:
760 aInDirection = ::basegfx::B2DVector( -1.0, -1.0 );
761 break;
762
763 case animations::TransitionSubType::FROMBOTTOMLEFT:
764 aInDirection = ::basegfx::B2DVector( 1.0, -1.0 );
765 break;
766
767 case animations::TransitionSubType::FROMTOPRIGHT:
768 aInDirection = ::basegfx::B2DVector( -1.0, 1.0 );
769 break;
770
771 case animations::TransitionSubType::FROMTOPLEFT:
772 aInDirection = ::basegfx::B2DVector( 1.0, 1.0 );
773 break;
774 }
775
776 if( bTransitionDirection )
777 {
778 // normal, 'forward' slide wipe effect. Since the old
779 // content is still on screen (and does not move), we omit
780 // the 'leaving' slide.
781 // =======================================================
782
783 return NumberAnimationSharedPtr(
784 new MovingSlideChange(
785 boost::optional<SlideSharedPtr>() /* no slide */,
786 pEnteringSlide,
787 pSoundPlayer,
788 rViewContainer,
789 rScreenUpdater,
790 rEventMultiplexer,
791 basegfx::B2DVector(),
792 aInDirection ));
793 }
794 else
795 {
796 // 'reversed' slide wipe effect. Reverse for slide wipes
797 // means, that the new slide is in the back, statically,
798 // and the old one is moving off in the foreground.
799 // =======================================================
800
801 return NumberAnimationSharedPtr(
802 new MovingSlideChange( leavingSlide,
803 pEnteringSlide,
804 pSoundPlayer,
805 rViewContainer,
806 rScreenUpdater,
807 rEventMultiplexer,
808 aInDirection,
809 basegfx::B2DVector() ));
810 }
811 }
812
createPluginTransition(sal_Int16 nTransitionType,sal_Int16 nTransitionSubType,boost::optional<SlideSharedPtr> const & pLeavingSlide,const SlideSharedPtr & pEnteringSlide,const UnoViewContainer & rViewContainer,ScreenUpdater & rScreenUpdater,const uno::Reference<presentation::XTransitionFactory> & xFactory,const SoundPlayerSharedPtr & pSoundPlayer,EventMultiplexer & rEventMultiplexer)813 NumberAnimationSharedPtr createPluginTransition(
814 sal_Int16 nTransitionType,
815 sal_Int16 nTransitionSubType,
816 boost::optional<SlideSharedPtr> const& pLeavingSlide,
817 const SlideSharedPtr& pEnteringSlide,
818 const UnoViewContainer& rViewContainer,
819 ScreenUpdater& rScreenUpdater,
820 const uno::Reference<
821 presentation::XTransitionFactory>& xFactory,
822 const SoundPlayerSharedPtr& pSoundPlayer,
823 EventMultiplexer& rEventMultiplexer)
824 {
825 PluginSlideChange* pTransition =
826 new PluginSlideChange(
827 nTransitionType,
828 nTransitionSubType,
829 pLeavingSlide,
830 pEnteringSlide,
831 rViewContainer,
832 rScreenUpdater,
833 xFactory,
834 pSoundPlayer,
835 rEventMultiplexer );
836
837 if( pTransition->Success() )
838 return NumberAnimationSharedPtr( pTransition );
839 else {
840 delete pTransition;
841 return NumberAnimationSharedPtr();
842 }
843 }
844
845 } // anon namespace
846
847
createSlideTransition(const SlideSharedPtr & pLeavingSlide,const SlideSharedPtr & pEnteringSlide,const UnoViewContainer & rViewContainer,ScreenUpdater & rScreenUpdater,EventMultiplexer & rEventMultiplexer,const uno::Reference<presentation::XTransitionFactory> & xOptionalFactory,sal_Int16 nTransitionType,sal_Int16 nTransitionSubType,bool bTransitionDirection,const RGBColor & rTransitionFadeColor,const SoundPlayerSharedPtr & pSoundPlayer)848 NumberAnimationSharedPtr TransitionFactory::createSlideTransition(
849 const SlideSharedPtr& pLeavingSlide,
850 const SlideSharedPtr& pEnteringSlide,
851 const UnoViewContainer& rViewContainer,
852 ScreenUpdater& rScreenUpdater,
853 EventMultiplexer& rEventMultiplexer,
854 const uno::Reference<presentation::XTransitionFactory>& xOptionalFactory,
855 sal_Int16 nTransitionType,
856 sal_Int16 nTransitionSubType,
857 bool bTransitionDirection,
858 const RGBColor& rTransitionFadeColor,
859 const SoundPlayerSharedPtr& pSoundPlayer )
860 {
861 // xxx todo: change to TransitionType::NONE, TransitionSubType::NONE:
862 if (nTransitionType == 0 && nTransitionSubType == 0) {
863 // just play sound, no slide transition:
864 if (pSoundPlayer) {
865 pSoundPlayer->startPlayback();
866 // xxx todo: for now, presentation.cxx takes care about the slide
867 // #i50492# transition sound object, so just release it here
868 }
869 return NumberAnimationSharedPtr();
870 }
871
872 ENSURE_OR_THROW(
873 pEnteringSlide,
874 "TransitionFactory::createSlideTransition(): Invalid entering slide" );
875
876 if( xOptionalFactory.is() &&
877 xOptionalFactory->hasTransition(nTransitionType, nTransitionSubType) )
878 {
879 // #i82460# - optional plugin factory claims this transition. delegate.
880 NumberAnimationSharedPtr pTransition(
881 createPluginTransition(
882 nTransitionType,
883 nTransitionSubType,
884 comphelper::make_optional(pLeavingSlide),
885 pEnteringSlide,
886 rViewContainer,
887 rScreenUpdater,
888 xOptionalFactory,
889 pSoundPlayer,
890 rEventMultiplexer ));
891
892 if( pTransition.get() )
893 return pTransition;
894 }
895
896 const TransitionInfo* pTransitionInfo(
897 getTransitionInfo( nTransitionType, nTransitionSubType ) );
898
899 if( pTransitionInfo != NULL )
900 {
901 switch( pTransitionInfo->meTransitionClass )
902 {
903 default:
904 case TransitionInfo::TRANSITION_INVALID:
905 OSL_TRACE(
906 "TransitionFactory::createSlideTransition(): "
907 "Invalid type/subtype (%d/%d) combination encountered.",
908 nTransitionType,
909 nTransitionSubType );
910 return NumberAnimationSharedPtr();
911
912
913 case TransitionInfo::TRANSITION_CLIP_POLYPOLYGON:
914 {
915 // generate parametric poly-polygon
916 ParametricPolyPolygonSharedPtr pPoly(
917 ParametricPolyPolygonFactory::createClipPolyPolygon(
918 nTransitionType, nTransitionSubType ) );
919
920 // create a clip transition from that
921 return NumberAnimationSharedPtr(
922 new ClippedSlideChange( pEnteringSlide,
923 pPoly,
924 *pTransitionInfo,
925 rViewContainer,
926 rScreenUpdater,
927 rEventMultiplexer,
928 bTransitionDirection,
929 pSoundPlayer ));
930 }
931
932 case TransitionInfo::TRANSITION_SPECIAL:
933 {
934 switch( nTransitionType )
935 {
936 default:
937 OSL_ENSURE(
938 false,
939 "TransitionFactory::createSlideTransition(): "
940 "Unexpected transition type for "
941 "TRANSITION_SPECIAL transitions" );
942 return NumberAnimationSharedPtr();
943
944 case animations::TransitionType::RANDOM:
945 {
946 // select randomly one of the effects from the
947 // TransitionFactoryTable
948
949 const TransitionInfo* pRandomTransitionInfo(
950 getRandomTransitionInfo() );
951
952 ENSURE_OR_THROW(
953 pRandomTransitionInfo != NULL,
954 "TransitionFactory::createSlideTransition(): "
955 "Got invalid random transition info" );
956
957 ENSURE_OR_THROW(
958 pRandomTransitionInfo->mnTransitionType !=
959 animations::TransitionType::RANDOM,
960 "TransitionFactory::createSlideTransition(): "
961 "Got random again for random input!" );
962
963 // and recurse
964 return createSlideTransition(
965 pLeavingSlide,
966 pEnteringSlide,
967 rViewContainer,
968 rScreenUpdater,
969 rEventMultiplexer,
970 xOptionalFactory,
971 pRandomTransitionInfo->mnTransitionType,
972 pRandomTransitionInfo->mnTransitionSubType,
973 bTransitionDirection,
974 rTransitionFadeColor,
975 pSoundPlayer );
976 }
977
978 case animations::TransitionType::PUSHWIPE:
979 {
980 return createPushWipeTransition(
981 comphelper::make_optional(pLeavingSlide),
982 pEnteringSlide,
983 rViewContainer,
984 rScreenUpdater,
985 rEventMultiplexer,
986 nTransitionType,
987 nTransitionSubType,
988 bTransitionDirection,
989 pSoundPlayer );
990 }
991
992 case animations::TransitionType::SLIDEWIPE:
993 {
994 return createSlideWipeTransition(
995 comphelper::make_optional(pLeavingSlide),
996 pEnteringSlide,
997 rViewContainer,
998 rScreenUpdater,
999 rEventMultiplexer,
1000 nTransitionType,
1001 nTransitionSubType,
1002 bTransitionDirection,
1003 pSoundPlayer );
1004 }
1005
1006 case animations::TransitionType::FADE:
1007 {
1008 // black page:
1009 boost::optional<SlideSharedPtr> leavingSlide;
1010
1011 switch( nTransitionSubType )
1012 {
1013 case animations::TransitionSubType::CROSSFADE:
1014 // crossfade needs no further setup,
1015 // just blend new slide over existing
1016 // background.
1017 break;
1018
1019 // TODO(F1): Implement toColor/fromColor fades
1020 case animations::TransitionSubType::FADETOCOLOR:
1021 // FALLTHROUGH intended
1022 case animations::TransitionSubType::FADEFROMCOLOR:
1023 // FALLTHROUGH intended
1024 case animations::TransitionSubType::FADEOVERCOLOR:
1025 if (pLeavingSlide) {
1026 // only generate, if fade
1027 // effect really needs it.
1028 leavingSlide.reset( pLeavingSlide );
1029 }
1030 break;
1031
1032 default:
1033 ENSURE_OR_THROW( false,
1034 "SlideTransitionFactory::createSlideTransition(): Unknown FADE subtype" );
1035 }
1036
1037 return NumberAnimationSharedPtr(
1038 new FadingSlideChange(
1039 leavingSlide,
1040 pEnteringSlide,
1041 comphelper::make_optional(
1042 rTransitionFadeColor),
1043 pSoundPlayer,
1044 rViewContainer,
1045 rScreenUpdater,
1046 rEventMultiplexer ));
1047 }
1048 }
1049 }
1050 break;
1051 }
1052 }
1053
1054 // No animation generated, maybe no table entry for given
1055 // transition?
1056 OSL_TRACE(
1057 "TransitionFactory::createSlideTransition(): "
1058 "Unknown type/subtype (%d/%d) combination encountered",
1059 nTransitionType,
1060 nTransitionSubType );
1061 OSL_ENSURE(
1062 false,
1063 "TransitionFactory::createSlideTransition(): "
1064 "Unknown type/subtype combination encountered" );
1065
1066 return NumberAnimationSharedPtr();
1067 }
1068
1069 } // namespace internal
1070 } // namespace presentation
1071