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