1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: slidechangebase.cxx,v $
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"
45 #include <boost/bind.hpp>
48 using namespace com::sun::star
;
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
),
67 mrViewContainer(rViewContainer
),
68 mbCreateLeavingSprites(bCreateLeavingSprites
),
69 mbCreateEnteringSprites(bCreateEnteringSprites
),
70 mbSpritesVisible(false),
76 "SlideChangeBase::SlideChangeBase(): Invalid entering slide!" );
79 SlideBitmapSharedPtr
SlideChangeBase::getLeavingBitmap( const ViewEntry
& rViewEntry
) const
81 if( !rViewEntry
.mpLeavingBitmap
)
82 rViewEntry
.mpLeavingBitmap
= createBitmap(rViewEntry
.mpView
,
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
;
104 SlideSharedPtr
const & pSlide
= *rSlide
;
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
111 // create empty, black-filled bitmap
112 const basegfx::B2ISize
slideSizePixel(
113 getSlideSizePixel( mpEnteringSlide
->getSlideSize(),
116 cppcanvas::CanvasSharedPtr
pCanvas( rView
->getCanvas() );
118 // create a bitmap of appropriate size
119 cppcanvas::BitmapSharedPtr
pBitmap(
120 cppcanvas::BaseGfxFactory::getInstance().createBitmap(
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() ),
145 pRet
.reset( new SlideBitmap( pBitmap
));
149 pRet
= pSlide
->getCurrentSlideBitmap( rView
);
155 ::basegfx::B2ISize
SlideChangeBase::getEnteringSlideSizePixel( const UnoViewSharedPtr
& pView
) const
157 return getSlideSizePixel( mpEnteringSlide
->getSlideSize(),
161 ::basegfx::B2ISize
SlideChangeBase::getLeavingSlideSizePixel( const UnoViewSharedPtr
& pView
) const
163 return getSlideSizePixel( (*maLeavingSlide
)->getSlideSize(),
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(
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
)
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
,
211 void SlideChangeBase::start( const AnimatableShapeSharedPtr
& rShape
,
212 const ShapeAttributeLayerSharedPtr
& rLayer
)
214 // we're a one-shot activity, and already finished
218 prefetch(rShape
,rLayer
); // no-op, if already done
220 // start accompanying sound effect, if any
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
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() );
254 catch( uno::Exception
& )
256 // make sure releasing below happens
259 // swap changes to screen
260 mrScreenUpdater
.notifyUpdate();
262 // make object dysfunctional
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
)
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
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
309 rOutSprite
->movePixel( aSpritePosPixel
);
311 rInSprite
->movePixel( aSpritePosPixel
);
313 if( !mbSpritesVisible
)
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
);
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
);
355 performOut( rOutSprite
, rViewEntry
, rCanvas
, nValue
);
357 performIn( rInSprite
, rViewEntry
, rCanvas
, nValue
);
359 // finishing deeds for first run.
360 if( !mbSpritesVisible
)
367 bSpritesVisible
= true;
369 } // for_each( sprite )
371 mbSpritesVisible
= bSpritesVisible
;
372 mrScreenUpdater
.notifyUpdate();
377 void SlideChangeBase::performIn(
378 const cppcanvas::CustomSpriteSharedPtr
& /*rSprite*/,
379 const ViewEntry
& /*rViewEntry*/,
380 const cppcanvas::CanvasSharedPtr
& /*rDestinationCanvas*/,
385 void SlideChangeBase::performOut(
386 const cppcanvas::CustomSpriteSharedPtr
& /*rSprite*/,
387 const ViewEntry
& /*rViewEntry*/,
388 const cppcanvas::CanvasSharedPtr
& /*rDestinationCanvas*/,
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
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
421 // erase corresponding entry from maViewData
427 std::equal_to
<UnoViewSharedPtr
>(),
430 boost::bind( &ViewEntry::getView
, _1
))),
434 void SlideChangeBase::viewChanged( const UnoViewSharedPtr
& rView
)
436 // we're a one-shot activity, and already finished
440 // find entry corresponding to modified view
441 ViewsVecT::iterator
aModifiedEntry(
446 std::equal_to
<UnoViewSharedPtr
>(),
449 boost::bind( &ViewEntry::getView
, _1
) )));
451 OSL_ASSERT( aModifiedEntry
!= maViewData
.end() );
452 if( aModifiedEntry
== maViewData
.end() )
455 // clear stale info (both bitmaps and sprites prolly need a
457 clearViewEntry( *aModifiedEntry
);
458 addSprites( *aModifiedEntry
);
461 void SlideChangeBase::viewsChanged()
463 // we're a one-shot activity, and already finished
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
473 clearViewEntry( *aIter
);
474 addSprites( *aIter
);
480 cppcanvas::CustomSpriteSharedPtr
SlideChangeBase::createSprite(
481 UnoViewSharedPtr
const & pView
,
482 basegfx::B2DSize
const & rSpriteSize
,
485 // TODO(P2): change to bitmapsprite once that's working
486 const cppcanvas::CustomSpriteSharedPtr
pSprite(
487 pView
->createSprite( rSpriteSize
,
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
)
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
,
512 if( mbCreateEnteringSprites
)
514 // create entering sprite:
515 const basegfx::B2ISize
enteringSlideSizePixel(
516 getSlideSizePixel( mpEnteringSlide
->getSlideSize(),
519 rEntry
.mpInSprite
= createSprite( rEntry
.mpView
,
520 enteringSlideSizePixel
,
525 void SlideChangeBase::clearViewEntry( ViewEntry
& rEntry
)
527 // clear stale info (both bitmaps and sprites prolly need a
529 rEntry
.mpEnteringBitmap
.reset();
530 rEntry
.mpLeavingBitmap
.reset();
531 rEntry
.mpInSprite
.reset();
532 rEntry
.mpOutSprite
.reset();
535 } // namespace internal
536 } // namespace presentation