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