merge the formfield patch from ooo-build
[ooovba.git] / slideshow / source / engine / transitions / slidechangebase.cxx
blobcc18bce71de5c5e1d384570c53dad9573c83f5fd
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: slidechangebase.cxx,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_slideshow.hxx"
34 #include <canvas/debug.hxx>
35 #include <tools/diagnose_ex.h>
36 #include <canvas/canvastools.hxx>
37 #include <basegfx/numeric/ftools.hxx>
38 #include <basegfx/polygon/b2dpolygontools.hxx>
39 #include <basegfx/polygon/b2dpolypolygontools.hxx>
40 #include <cppcanvas/basegfxfactory.hxx>
42 #include "slidechangebase.hxx"
43 #include "tools.hxx"
45 #include <boost/bind.hpp>
46 #include <algorithm>
48 using namespace com::sun::star;
50 namespace slideshow {
51 namespace internal {
53 SlideChangeBase::SlideChangeBase( boost::optional<SlideSharedPtr> const & leavingSlide,
54 const SlideSharedPtr& pEnteringSlide,
55 const SoundPlayerSharedPtr& pSoundPlayer,
56 const UnoViewContainer& rViewContainer,
57 ScreenUpdater& rScreenUpdater,
58 EventMultiplexer& rEventMultiplexer,
59 bool bCreateLeavingSprites,
60 bool bCreateEnteringSprites ) :
61 mpSoundPlayer( pSoundPlayer ),
62 mrEventMultiplexer(rEventMultiplexer),
63 mrScreenUpdater(rScreenUpdater),
64 maLeavingSlide( leavingSlide ),
65 mpEnteringSlide( pEnteringSlide ),
66 maViewData(),
67 mrViewContainer(rViewContainer),
68 mbCreateLeavingSprites(bCreateLeavingSprites),
69 mbCreateEnteringSprites(bCreateEnteringSprites),
70 mbSpritesVisible(false),
71 mbFinished(false),
72 mbPrefetched(false)
74 ENSURE_OR_THROW(
75 pEnteringSlide,
76 "SlideChangeBase::SlideChangeBase(): Invalid entering slide!" );
79 SlideBitmapSharedPtr SlideChangeBase::getLeavingBitmap( const ViewEntry& rViewEntry ) const
81 if( !rViewEntry.mpLeavingBitmap )
82 rViewEntry.mpLeavingBitmap = createBitmap(rViewEntry.mpView,
83 maLeavingSlide);
85 return rViewEntry.mpLeavingBitmap;
88 SlideBitmapSharedPtr SlideChangeBase::getEnteringBitmap( const ViewEntry& rViewEntry ) const
90 if( !rViewEntry.mpEnteringBitmap )
91 rViewEntry.mpEnteringBitmap = createBitmap( rViewEntry.mpView,
92 boost::optional<SlideSharedPtr>(mpEnteringSlide) );
94 return rViewEntry.mpEnteringBitmap;
97 SlideBitmapSharedPtr SlideChangeBase::createBitmap( const UnoViewSharedPtr& rView,
98 const boost::optional<SlideSharedPtr>& rSlide ) const
100 SlideBitmapSharedPtr pRet;
101 if( !rSlide )
102 return pRet;
104 SlideSharedPtr const & pSlide = *rSlide;
105 if( !pSlide )
107 // TODO(P3): No need to generate a bitmap here. This only made
108 // the code more uniform. Faster would be to simply clear the
109 // sprite to black.
111 // create empty, black-filled bitmap
112 const basegfx::B2ISize slideSizePixel(
113 getSlideSizePixel( mpEnteringSlide->getSlideSize(),
114 rView ));
116 cppcanvas::CanvasSharedPtr pCanvas( rView->getCanvas() );
118 // create a bitmap of appropriate size
119 cppcanvas::BitmapSharedPtr pBitmap(
120 cppcanvas::BaseGfxFactory::getInstance().createBitmap(
121 pCanvas,
122 slideSizePixel ) );
124 ENSURE_OR_THROW(
125 pBitmap,
126 "SlideChangeBase::createBitmap(): Cannot create page bitmap" );
128 cppcanvas::BitmapCanvasSharedPtr pBitmapCanvas(
129 pBitmap->getBitmapCanvas() );
131 ENSURE_OR_THROW( pBitmapCanvas,
132 "SlideChangeBase::createBitmap(): "
133 "Cannot create page bitmap canvas" );
135 // set transformation to identitiy (->device pixel)
136 pBitmapCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
138 // clear bitmap to black
139 fillRect( pBitmapCanvas,
140 ::basegfx::B2DRectangle( 0.0, 0.0,
141 slideSizePixel.getX(),
142 slideSizePixel.getY() ),
143 0x000000FFU );
145 pRet.reset( new SlideBitmap( pBitmap ));
147 else
149 pRet = pSlide->getCurrentSlideBitmap( rView );
152 return pRet;
155 ::basegfx::B2ISize SlideChangeBase::getEnteringSlideSizePixel( const UnoViewSharedPtr& pView ) const
157 return getSlideSizePixel( mpEnteringSlide->getSlideSize(),
158 pView );
161 ::basegfx::B2ISize SlideChangeBase::getLeavingSlideSizePixel( const UnoViewSharedPtr& pView ) const
163 return getSlideSizePixel( (*maLeavingSlide)->getSlideSize(),
164 pView );
168 void SlideChangeBase::renderBitmap(
169 SlideBitmapSharedPtr const & pSlideBitmap,
170 cppcanvas::CanvasSharedPtr const & pCanvas )
172 if( pSlideBitmap && pCanvas )
174 // need to render without any transformation (we
175 // assume device units):
176 const basegfx::B2DHomMatrix viewTransform(
177 pCanvas->getTransformation() );
178 const basegfx::B2DPoint pageOrigin(
179 viewTransform * basegfx::B2DPoint() );
180 const cppcanvas::CanvasSharedPtr pDevicePixelCanvas(
181 pCanvas->clone() );
182 basegfx::B2DHomMatrix transform;
183 // render at output position, don't modify bitmap object (no move!):
184 transform.translate( pageOrigin.getX(), pageOrigin.getY() );
186 pDevicePixelCanvas->setTransformation( transform );
187 pSlideBitmap->draw( pDevicePixelCanvas );
191 void SlideChangeBase::prefetch( const AnimatableShapeSharedPtr&,
192 const ShapeAttributeLayerSharedPtr& )
194 // we're a one-shot activity, and already finished
195 if( mbFinished || mbPrefetched )
196 return;
198 // register ourselves for view change events
199 mrEventMultiplexer.addViewHandler( shared_from_this() );
201 // init views and create slide bitmaps
202 std::for_each( mrViewContainer.begin(),
203 mrViewContainer.end(),
204 boost::bind( &SlideChangeBase::viewAdded,
205 this,
206 _1 ));
208 mbPrefetched = true;
211 void SlideChangeBase::start( const AnimatableShapeSharedPtr& rShape,
212 const ShapeAttributeLayerSharedPtr& rLayer )
214 // we're a one-shot activity, and already finished
215 if( mbFinished )
216 return;
218 prefetch(rShape,rLayer); // no-op, if already done
220 // start accompanying sound effect, if any
221 if( mpSoundPlayer )
223 mpSoundPlayer->startPlayback();
224 // xxx todo: for now, presentation.cxx takes care about the slide
225 // #i50492# transition sound object, so just release it here
226 mpSoundPlayer.reset();
230 void SlideChangeBase::end()
232 // we're a one-shot activity, and already finished
233 if( mbFinished )
234 return;
238 // draw fully entered bitmap:
239 ViewsVecT::const_iterator aCurr( beginViews() );
240 const ViewsVecT::const_iterator aEnd( endViews() );
241 while( aCurr != aEnd )
243 // fully clear view content to background color
244 aCurr->mpView->clearAll();
246 const SlideBitmapSharedPtr pSlideBitmap( getEnteringBitmap( *aCurr ));
247 pSlideBitmap->clip( basegfx::B2DPolyPolygon() /* no clipping */ );
248 renderBitmap( pSlideBitmap,
249 aCurr->mpView->getCanvas() );
251 ++aCurr;
254 catch( uno::Exception& )
256 // make sure releasing below happens
259 // swap changes to screen
260 mrScreenUpdater.notifyUpdate();
262 // make object dysfunctional
263 mbFinished = true;
264 ViewsVecT().swap(maViewData);
265 maLeavingSlide.reset();
266 mpEnteringSlide.reset();
268 // sprites have been binned above
269 mbSpritesVisible = false;
271 // remove also from event multiplexer, we're dead anyway
272 mrEventMultiplexer.removeViewHandler( shared_from_this() );
275 bool SlideChangeBase::operator()( double nValue )
277 if( mbFinished )
278 return false;
280 const std::size_t nEntries( maViewData.size() );
281 bool bSpritesVisible( mbSpritesVisible );
283 for( ::std::size_t i=0; i<nEntries; ++i )
285 // calc sprite offsets. The enter/leaving bitmaps are only
286 // as large as the actual slides. For scaled-down
287 // presentations, we have to move the left, top edge of
288 // those bitmaps to the actual position, governed by the
289 // given view transform. The aSpritePosPixel local
290 // variable is already in device coordinate space
291 // (i.e. pixel).
293 ViewEntry& rViewEntry( maViewData[i] );
294 const ::cppcanvas::CanvasSharedPtr& rCanvas( rViewEntry.mpView->getCanvas() );
295 ::cppcanvas::CustomSpriteSharedPtr& rInSprite( rViewEntry.mpInSprite );
296 ::cppcanvas::CustomSpriteSharedPtr& rOutSprite( rViewEntry.mpOutSprite );
298 // TODO(F2): Properly respect clip here.
300 // Might have to be transformed, too.
301 const ::basegfx::B2DHomMatrix aViewTransform(
302 rViewEntry.mpView->getTransformation() );
303 const ::basegfx::B2DPoint aSpritePosPixel(
304 aViewTransform * ::basegfx::B2DPoint() );
306 // move sprite to final output position, in
307 // device coordinates
308 if( rOutSprite )
309 rOutSprite->movePixel( aSpritePosPixel );
310 if( rInSprite )
311 rInSprite->movePixel( aSpritePosPixel );
313 if( !mbSpritesVisible )
315 if( rOutSprite )
317 // only render once: clipping is done
318 // exclusively with the sprite
319 const ::cppcanvas::CanvasSharedPtr pOutContentCanvas(
320 rOutSprite->getContentCanvas() );
321 if( pOutContentCanvas)
323 // TODO(Q2): Use basegfx bitmaps here
325 // TODO(F1): SlideBitmap is not fully portable
326 // between different canvases!
328 // render the content
329 OSL_ASSERT( getLeavingBitmap( rViewEntry ) );
330 if( getLeavingBitmap( rViewEntry ) )
331 getLeavingBitmap( rViewEntry )->draw( pOutContentCanvas );
335 if( rInSprite )
337 // only render once: clipping is done
338 // exclusively with the sprite
339 const ::cppcanvas::CanvasSharedPtr pInContentCanvas(
340 rInSprite->getContentCanvas() );
341 if( pInContentCanvas )
343 // TODO(Q2): Use basegfx bitmaps here
345 // TODO(F1): SlideBitmap is not fully portable
346 // between different canvases!
348 // render the content
349 getEnteringBitmap( rViewEntry )->draw( pInContentCanvas );
354 if( rOutSprite )
355 performOut( rOutSprite, rViewEntry, rCanvas, nValue );
356 if( rInSprite )
357 performIn( rInSprite, rViewEntry, rCanvas, nValue );
359 // finishing deeds for first run.
360 if( !mbSpritesVisible)
362 // enable sprites:
363 if( rOutSprite )
364 rOutSprite->show();
365 if( rInSprite )
366 rInSprite->show();
367 bSpritesVisible = true;
369 } // for_each( sprite )
371 mbSpritesVisible = bSpritesVisible;
372 mrScreenUpdater.notifyUpdate();
374 return true;
377 void SlideChangeBase::performIn(
378 const cppcanvas::CustomSpriteSharedPtr& /*rSprite*/,
379 const ViewEntry& /*rViewEntry*/,
380 const cppcanvas::CanvasSharedPtr& /*rDestinationCanvas*/,
381 double /*t*/ )
385 void SlideChangeBase::performOut(
386 const cppcanvas::CustomSpriteSharedPtr& /*rSprite*/,
387 const ViewEntry& /*rViewEntry*/,
388 const cppcanvas::CanvasSharedPtr& /*rDestinationCanvas*/,
389 double /*t*/ )
393 double SlideChangeBase::getUnderlyingValue() const
395 return 0.0; // though this should be used in concert with
396 // ActivitiesFactory::createSimpleActivity, better
397 // explicitely name our start value.
398 // Permissible range for operator() above is [0,1]
401 void SlideChangeBase::viewAdded( const UnoViewSharedPtr& rView )
403 // we're a one-shot activity, and already finished
404 if( mbFinished )
405 return;
407 maViewData.push_back( ViewEntry(rView) );
409 ViewEntry& rEntry( maViewData.back() );
410 getEnteringBitmap( rEntry );
411 getLeavingBitmap( rEntry );
412 addSprites( rEntry );
415 void SlideChangeBase::viewRemoved( const UnoViewSharedPtr& rView )
417 // we're a one-shot activity, and already finished
418 if( mbFinished )
419 return;
421 // erase corresponding entry from maViewData
422 maViewData.erase(
423 std::remove_if(
424 maViewData.begin(),
425 maViewData.end(),
426 boost::bind(
427 std::equal_to<UnoViewSharedPtr>(),
428 rView,
429 // select view:
430 boost::bind( &ViewEntry::getView, _1 ))),
431 maViewData.end() );
434 void SlideChangeBase::viewChanged( const UnoViewSharedPtr& rView )
436 // we're a one-shot activity, and already finished
437 if( mbFinished )
438 return;
440 // find entry corresponding to modified view
441 ViewsVecT::iterator aModifiedEntry(
442 std::find_if(
443 maViewData.begin(),
444 maViewData.end(),
445 boost::bind(
446 std::equal_to<UnoViewSharedPtr>(),
447 rView,
448 // select view:
449 boost::bind( &ViewEntry::getView, _1 ) )));
451 OSL_ASSERT( aModifiedEntry != maViewData.end() );
452 if( aModifiedEntry == maViewData.end() )
453 return;
455 // clear stale info (both bitmaps and sprites prolly need a
456 // resize)
457 clearViewEntry( *aModifiedEntry );
458 addSprites( *aModifiedEntry );
461 void SlideChangeBase::viewsChanged()
463 // we're a one-shot activity, and already finished
464 if( mbFinished )
465 return;
467 ViewsVecT::iterator aIter( maViewData.begin() );
468 ViewsVecT::iterator const aEnd ( maViewData.end() );
469 while( aIter != aEnd )
471 // clear stale info (both bitmaps and sprites prolly need a
472 // resize)
473 clearViewEntry( *aIter );
474 addSprites( *aIter );
476 ++aIter;
480 cppcanvas::CustomSpriteSharedPtr SlideChangeBase::createSprite(
481 UnoViewSharedPtr const & pView,
482 basegfx::B2DSize const & rSpriteSize,
483 double nPrio ) const
485 // TODO(P2): change to bitmapsprite once that's working
486 const cppcanvas::CustomSpriteSharedPtr pSprite(
487 pView->createSprite( rSpriteSize,
488 nPrio ));
490 // alpha default is 0.0, which seems to be
491 // a bad idea when viewing content...
492 pSprite->setAlpha( 1.0 );
493 if (mbSpritesVisible)
494 pSprite->show();
496 return pSprite;
499 void SlideChangeBase::addSprites( ViewEntry& rEntry )
501 if( mbCreateLeavingSprites && maLeavingSlide )
503 // create leaving sprite:
504 const basegfx::B2ISize leavingSlideSizePixel(
505 getLeavingBitmap( rEntry )->getSize() );
507 rEntry.mpOutSprite = createSprite( rEntry.mpView,
508 leavingSlideSizePixel,
509 100 );
512 if( mbCreateEnteringSprites )
514 // create entering sprite:
515 const basegfx::B2ISize enteringSlideSizePixel(
516 getSlideSizePixel( mpEnteringSlide->getSlideSize(),
517 rEntry.mpView ));
519 rEntry.mpInSprite = createSprite( rEntry.mpView,
520 enteringSlideSizePixel,
521 101 );
525 void SlideChangeBase::clearViewEntry( ViewEntry& rEntry )
527 // clear stale info (both bitmaps and sprites prolly need a
528 // resize)
529 rEntry.mpEnteringBitmap.reset();
530 rEntry.mpLeavingBitmap.reset();
531 rEntry.mpInSprite.reset();
532 rEntry.mpOutSprite.reset();
535 } // namespace internal
536 } // namespace presentation