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: slideview.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 ************************************************************************/
30 #include "precompiled_slideshow.hxx"
32 #include <canvas/debug.hxx>
33 #include <tools/diagnose_ex.h>
34 #include <canvas/canvastools.hxx>
36 #include "eventqueue.hxx"
37 #include "eventmultiplexer.hxx"
38 #include "slideview.hxx"
39 #include "delayevent.hxx"
40 #include "unoview.hxx"
42 #include <rtl/instance.hxx>
43 #include <cppuhelper/basemutex.hxx>
44 #include <cppuhelper/compbase2.hxx>
45 #include <cppuhelper/implementationentry.hxx>
46 #include <cppuhelper/interfacecontainer.h>
47 #include <comphelper/make_shared_from_uno.hxx>
49 #include <cppcanvas/spritecanvas.hxx>
50 #include <cppcanvas/customsprite.hxx>
51 #include <cppcanvas/vclfactory.hxx>
52 #include <cppcanvas/basegfxfactory.hxx>
54 #include <tools/debug.hxx>
56 #include <basegfx/range/b1drange.hxx>
57 #include <basegfx/range/b2drange.hxx>
58 #include <basegfx/range/b2irange.hxx>
59 #include <basegfx/point/b2dpoint.hxx>
60 #include <basegfx/polygon/b2dpolygon.hxx>
61 #include <basegfx/matrix/b2dhommatrix.hxx>
62 #include <basegfx/polygon/b2dpolygontools.hxx>
63 #include <basegfx/polygon/b2dpolypolygontools.hxx>
64 #include <basegfx/tools/canvastools.hxx>
65 #include <basegfx/polygon/b2dpolygonclipper.hxx>
66 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
68 #include <com/sun/star/presentation/XSlideShow.hpp>
70 #include <boost/noncopyable.hpp>
71 #include <boost/bind.hpp>
72 #include <boost/weak_ptr.hpp>
78 using namespace com::sun::star
;
85 struct StaticUnitRectPoly
: public rtl::StaticWithInit
<basegfx::B2DPolygon
, StaticUnitRectPoly
>
87 basegfx::B2DPolygon
operator()()
89 return basegfx::tools::createPolygonFromRect(
90 basegfx::B2DRectangle( 0.0, 0.0,
95 /** Sprite entry, to store sprite plus priority
97 The operator<() defines a strict weak ordering of sprites, sort
98 key is the sprite priority.
102 SpriteEntry( const cppcanvas::CustomSpriteSharedPtr
& rSprite
,
109 bool operator<(const SpriteEntry
& rRHS
) const
111 return mnPriority
< rRHS
.mnPriority
;
114 boost::weak_ptr
< cppcanvas::CustomSprite
> mpSprite
;
118 typedef std::vector
< SpriteEntry
> SpriteVector
;
121 /** Create a clip polygon for slide views
124 Clip to set (can be empty)
127 Canvas to create the clip polygon for
130 The size of the view. Note that the returned clip will
131 <em>always</em> clip to at least the rect defined herein.
133 @return the view clip polygon, in view coordinates, which is
134 guaranteed to at least clip to the view size.
136 basegfx::B2DPolyPolygon
createClipPolygon( const basegfx::B2DPolyPolygon
& rClip
,
137 const cppcanvas::CanvasSharedPtr
& /*rCanvas*/,
138 const basegfx::B2DSize
& rUserSize
)
140 // setup canvas clipping
141 // =====================
144 const basegfx::B2DRange
aClipRange(0, 0, rUserSize
.getX(), rUserSize
.getY());
148 return basegfx::tools::clipPolyPolygonOnRange(rClip
, aClipRange
, true, false);
152 return basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(aClipRange
));
156 /** Prepare given clip polygon to be stored as the current clip
158 Note that this is separate from createClipPolygon(), to allow
159 SlideView implementations to store this intermediate result
160 (createClipPolygon() has to be called every time the view size
163 basegfx::B2DPolyPolygon
prepareClip( const basegfx::B2DPolyPolygon
& rClip
)
165 basegfx::B2DPolyPolygon
aClip( rClip
);
167 // TODO(P2): unnecessary, once XCanvas is correctly handling this
168 // AW: Should be no longer necessary; tools are now bezier-safe
169 if( aClip
.areControlPointsUsed() )
170 aClip
= basegfx::tools::adaptiveSubdivideByAngle( aClip
);
172 // normalize polygon, preparation for clipping
174 aClip
= basegfx::tools::correctOrientations(aClip
);
175 aClip
= basegfx::tools::solveCrossovers(aClip
);
176 aClip
= basegfx::tools::stripNeutralPolygons(aClip
);
177 aClip
= basegfx::tools::stripDispensablePolygons(aClip
, false);
183 void clearRect( ::cppcanvas::CanvasSharedPtr
const& pCanvas
,
184 basegfx::B2IRange
const& rArea
)
186 // convert clip polygon to device coordinate system
187 ::basegfx::B2DPolyPolygon
const* pClipPoly( pCanvas
->getClip() );
190 ::basegfx::B2DPolyPolygon
aClipPoly( *pClipPoly
);
191 aClipPoly
.transform( pCanvas
->getTransformation() );
192 pCanvas
->setClip( aClipPoly
);
195 // set transformation to identitiy (->device pixel)
196 pCanvas
->setTransformation( ::basegfx::B2DHomMatrix() );
198 // #i42440# Fill the _full_ background in
199 // black. Since we had to extend the bitmap by one
200 // pixel, and the bitmap is initialized white,
201 // depending on the slide content a one pixel wide
202 // line will show to the bottom and the right.
203 const ::basegfx::B2DPolygon
aPoly(
204 ::basegfx::tools::createPolygonFromRect(
205 basegfx::B2DRange(rArea
)));
207 ::cppcanvas::PolyPolygonSharedPtr
pPolyPoly(
208 ::cppcanvas::BaseGfxFactory::getInstance().createPolyPolygon( pCanvas
,
213 pPolyPoly
->setCompositeOp( cppcanvas::CanvasGraphic::SOURCE
);
214 pPolyPoly
->setRGBAFillColor( 0x00000000U
);
218 #if defined(VERBOSE) && defined(DBG_UTIL)
219 ::cppcanvas::CanvasSharedPtr
pCliplessCanvas( pCanvas
->clone() );
220 pCliplessCanvas
->setClip();
222 if( pCanvas
->getClip() )
224 ::cppcanvas::PolyPolygonSharedPtr
pPolyPoly2(
225 ::cppcanvas::BaseGfxFactory::getInstance().createPolyPolygon( pCliplessCanvas
,
226 *(pCanvas
->getClip()) ));
229 pPolyPoly2
->setRGBALineColor( 0x008000FFU
);
236 /** Get bounds in pixel
239 Bound rect, in user space coordinates
241 @param rTransformation
242 User space to device pixel transformation
244 @return the layer bounds in pixel, extended by one pixel to the
247 basegfx::B2IRange
getLayerBoundsPixel( basegfx::B2DRange
const& rLayerBounds
,
248 basegfx::B2DHomMatrix
const& rTransformation
)
250 ::basegfx::B2DRange aTmpRect
;
251 ::canvas::tools::calcTransformedRectBounds( aTmpRect
,
255 if( aTmpRect
.isEmpty() )
256 return ::basegfx::B2IRange();
258 // #i42440# Returned layer size is one pixel too small, as
259 // rendering happens one pixel to the right and below the
260 // actual bound rect.
261 return ::basegfx::B2IRange( ::basegfx::fround(aTmpRect
.getMinX()),
262 ::basegfx::fround(aTmpRect
.getMinY()),
263 ::basegfx::fround(aTmpRect
.getMaxX()) + 1,
264 ::basegfx::fround(aTmpRect
.getMaxY()) + 1 );
268 // ----------------------------------------------------------------
270 /** Container class for sprites issued by a ViewLayer
272 This class handles the sprite prioritization issues, that are
273 needed for layer sprites (e.g. the need to re-prioritize sprites
274 when the layer changes prio).
276 class LayerSpriteContainer
278 /** Max fill level of maSprites, before we try to prune it from
281 enum{ SPRITE_ULLAGE
=256 };
283 /** All sprites that have been issued by this container (pruned
284 from time to time, for invalid references). This vector is
285 kept sorted with increasing sprite priority.
287 SpriteVector maSprites
;
289 /// Priority of this layer, relative to other view layers
290 basegfx::B1DRange maLayerPrioRange
;
292 double getSpritePriority( std::size_t nSpriteNum
) const
294 // divide the available layer range equally between all
295 // sprites, assign upper bound of individual sprite range as
296 // sprite prio (the layer itself gets assigned the lower bound
297 // of sprite 0's individual range):
299 // | layer 0 | layer 1 | ...
300 // | sprite 0 | sprite 1 | sprite 0 | sprite 1 | ...
301 return maLayerPrioRange
.getMinimum() + maLayerPrioRange
.getRange()*(nSpriteNum
+1)/(maSprites
.size()+1);
304 /** Rescan sprite vector, and remove deceased sprites (and reset
308 Iterator to the first entry to rescan
312 SpriteVector aValidSprites
;
314 // check all sprites for validity and set new priority
315 SpriteVector::iterator
aCurrSprite( maSprites
.begin() );
316 const SpriteVector::iterator
aEnd( maSprites
.end() );
317 while( aCurrSprite
!= aEnd
)
319 cppcanvas::CustomSpriteSharedPtr
pCurrSprite( aCurrSprite
->mpSprite
.lock() );
323 // only copy still valid sprites over to the refreshed
325 aValidSprites
.push_back( *aCurrSprite
);
327 pCurrSprite
->setPriority(
328 getSpritePriority( aValidSprites
.size()-1 ));
334 // replace sprite list with pruned one
335 maSprites
.swap( aValidSprites
);
339 LayerSpriteContainer() :
345 basegfx::B1DRange
getLayerPriority() const
347 return maLayerPrioRange
;
350 void setLayerPriority( const basegfx::B1DRange
& rRange
)
352 if( rRange
!= maLayerPrioRange
)
354 maLayerPrioRange
= rRange
;
356 // prune and recalc sprite prios
361 void addSprite( const cppcanvas::CustomSpriteSharedPtr
& pSprite
,
367 SpriteEntry
aEntry( pSprite
,nPriority
);
369 // insert new sprite, such that vector stays sorted
370 SpriteVector::iterator
aInsertPos(
372 std::lower_bound( maSprites
.begin(),
377 const std::size_t nNumSprites( maSprites
.size() );
378 if( nNumSprites
> SPRITE_ULLAGE
||
379 maSprites
.end() - aInsertPos
> 1 )
381 // updateSprites() also updates all sprite prios
386 // added sprite to the end, and not too many sprites in
387 // vector - perform optimized update (only need to set
388 // prio). This basically caters for the common case of
389 // iterated character animations, which generate lots of
390 // sprites, all added to the end.
391 pSprite
->setPriority(
392 getSpritePriority( nNumSprites
-1 ));
403 // ----------------------------------------------------------------
406 /** This class provides layers for a slide view
408 Layers are used to render animations with the correct z order -
409 because sprites are always in front of the static canvas
410 background, shapes that must appear <em<before</em> an animation
411 must also be displayed as a sprite.
413 Each layer has a priority assigned to it (valid range [0,1]), which
414 also affects all sprites created for this specific layer - i.e. if
415 the layer priority changes, the sprites change z order together
418 class SlideViewLayer
: public ViewLayer
,
419 private boost::noncopyable
421 /// Smart container for all sprites issued by this layer
422 mutable LayerSpriteContainer maSpriteContainer
;
424 /// Bounds of this layer in user space coordinates
425 basegfx::B2DRange maLayerBounds
;
427 /// Bounds of this layer in device pixel
428 mutable basegfx::B2IRange maLayerBoundsPixel
;
430 /// Current clip polygon in user coordinates
431 basegfx::B2DPolyPolygon maClip
;
433 /// Current size of the view in user coordinates
434 basegfx::B2DSize maUserSize
;
436 /// Current overall view transformation
437 basegfx::B2DHomMatrix maTransformation
;
439 /// 'parent' canvas, this viewlayer is associated with
440 const cppcanvas::SpriteCanvasSharedPtr mpSpriteCanvas
;
442 /** output surface (necessarily a sprite, won't otherwise be able
443 to display anything <em>before</em> other sprites)
445 mutable cppcanvas::CustomSpriteSharedPtr mpSprite
;
447 /// actual output canvas retrieved from a sprite
448 mutable cppcanvas::CanvasSharedPtr mpOutputCanvas
;
450 /// ptr back to owning view. needed for isOnView() method
451 View
const* const mpParentView
;
454 /** Create a new layer
457 Sprite canvas to create the layer on
460 Initial overall canvas transformation
463 Initial layer bounds, in view coordinate system
465 SlideViewLayer( const cppcanvas::SpriteCanvasSharedPtr
& pCanvas
,
466 const basegfx::B2DHomMatrix
& rTransform
,
467 const basegfx::B2DRange
& rLayerBounds
,
468 const basegfx::B2DSize
& rUserSize
,
469 View
const* const pParentView
) :
471 maLayerBounds(rLayerBounds
),
472 maLayerBoundsPixel(),
474 maUserSize(rUserSize
),
475 maTransformation(rTransform
),
476 mpSpriteCanvas(pCanvas
),
479 mpParentView(pParentView
)
483 void updateView( const basegfx::B2DHomMatrix
& rMatrix
,
484 const basegfx::B2DSize
& rUserSize
)
486 maTransformation
= rMatrix
;
487 maUserSize
= rUserSize
;
489 // limit layer bounds to visible screen
490 maLayerBounds
.intersect( basegfx::B2DRange(0.0,
493 maUserSize
.getY()) );
495 basegfx::B2IRange
const& rNewLayerPixel(
496 getLayerBoundsPixel(maLayerBounds
,
498 if( rNewLayerPixel
!= maLayerBoundsPixel
)
500 // re-gen sprite with new size
501 mpOutputCanvas
.reset();
507 // ViewLayer interface
508 // ----------------------------------------------
510 virtual cppcanvas::CustomSpriteSharedPtr
createSprite(
511 const ::basegfx::B2DSize
& rSpriteSizePixel
,
512 double nPriority
) const
514 cppcanvas::CustomSpriteSharedPtr
pSprite(
515 mpSpriteCanvas
->createCustomSprite( rSpriteSizePixel
) );
517 maSpriteContainer
.addSprite( pSprite
,
523 virtual void setPriority( const basegfx::B1DRange
& rRange
)
525 OSL_ENSURE( !rRange
.isEmpty() &&
526 rRange
.getMinimum() >= 1.0,
527 "SlideViewLayer::setPriority(): prio MUST be larger than 1.0 (because "
528 "the background layer already lies there)" );
530 maSpriteContainer
.setLayerPriority( rRange
);
533 mpSprite
->setPriority( rRange
.getMinimum() );
536 virtual basegfx::B2DHomMatrix
getTransformation() const
538 // Offset given transformation by left, top border of given
539 // range (after transformation through given transformation)
540 basegfx::B2DRectangle aTmpRect
;
541 canvas::tools::calcTransformedRectBounds( aTmpRect
,
545 basegfx::B2DHomMatrix
aMatrix( maTransformation
);
547 // Add translation according to the origin of aTmpRect. Ignore the
548 // translation when aTmpRect was not properly initialized.
549 if ( ! aTmpRect
.isEmpty())
551 aMatrix
.translate( -basegfx::fround(aTmpRect
.getMinX()),
552 -basegfx::fround(aTmpRect
.getMinY()) );
558 virtual basegfx::B2DHomMatrix
getSpriteTransformation() const
560 return maTransformation
;
563 virtual void clear() const
566 clearRect(getCanvas()->clone(),
570 virtual void clearAll() const
572 ::cppcanvas::CanvasSharedPtr
pCanvas( getCanvas()->clone() );
574 // clear layer clip, to clear whole area
581 virtual bool isOnView(boost::shared_ptr
<View
> const& rView
) const
583 return rView
.get() == mpParentView
;
586 virtual cppcanvas::CanvasSharedPtr
getCanvas() const
588 if( !mpOutputCanvas
)
592 maLayerBoundsPixel
= getLayerBoundsPixel(maLayerBounds
,
595 // HACK: ensure at least 1x1 pixel size. clients might
596 // need an actual canvas (e.g. for bound rect
597 // calculations) without rendering anything. Better
598 // solution: introduce something like a reference
599 // canvas for ViewLayers, which is always available.
600 if( maLayerBoundsPixel
.isEmpty() )
601 maLayerBoundsPixel
= basegfx::B2IRange(0,0,1,1);
603 const basegfx::B2I64Tuple
& rSpriteSize(maLayerBoundsPixel
.getRange());
604 mpSprite
= mpSpriteCanvas
->createCustomSprite(
605 basegfx::B2DVector(sal::static_int_cast
<sal_Int32
>(rSpriteSize
.getX()),
606 sal::static_int_cast
<sal_Int32
>(rSpriteSize
.getY())) );
608 mpSprite
->setPriority(
609 maSpriteContainer
.getLayerPriority().getMinimum() );
611 #if defined(VERBOSE) && defined(DBG_UTIL)
613 basegfx::B2DPoint(maLayerBoundsPixel
.getMinimum()) +
614 basegfx::B2DPoint(10,10) );
616 mpSprite
->setAlpha(0.5);
619 basegfx::B2DPoint(maLayerBoundsPixel
.getMinimum()) );
621 mpSprite
->setAlpha(1.0);
626 ENSURE_OR_THROW( mpSprite
,
627 "SlideViewLayer::getCanvas(): no layer sprite" );
629 mpOutputCanvas
= mpSprite
->getContentCanvas();
631 ENSURE_OR_THROW( mpOutputCanvas
,
632 "SlideViewLayer::getCanvas(): sprite doesn't yield a canvas" );
634 // new canvas retrieved - setup transformation and clip
635 mpOutputCanvas
->setTransformation( getTransformation() );
636 mpOutputCanvas
->setClip(
637 createClipPolygon( maClip
,
642 return mpOutputCanvas
;
645 virtual void setClip( const basegfx::B2DPolyPolygon
& rClip
)
647 basegfx::B2DPolyPolygon aNewClip
= prepareClip( rClip
);
649 if( aNewClip
!= maClip
)
654 mpOutputCanvas
->setClip(
655 createClipPolygon( maClip
,
661 virtual bool resize( const ::basegfx::B2DRange
& rArea
)
663 const bool bRet( maLayerBounds
!= rArea
);
664 maLayerBounds
= rArea
;
665 updateView( maTransformation
,
673 // ---------------------------------------------------------
675 typedef cppu::WeakComponentImplHelper2
<
676 ::com::sun::star::util::XModifyListener
,
677 ::com::sun::star::awt::XPaintListener
> SlideViewBase
;
681 This class implements the View interface, encapsulating
682 <em>one</em> view a slideshow is displayed on.
684 class SlideView
: private cppu::BaseMutex
,
685 public SlideViewBase
,
689 SlideView( const uno::Reference
<presentation::XSlideShowView
>& xView
,
690 EventQueue
& rEventQueue
,
691 EventMultiplexer
& rEventMultiplexer
);
696 virtual ViewLayerSharedPtr
createViewLayer( const basegfx::B2DRange
& rLayerBounds
) const;
697 virtual bool updateScreen() const;
698 virtual bool paintScreen() const;
699 virtual void setViewSize( const ::basegfx::B2DSize
& );
700 virtual void setCursorShape( sal_Int16 nPointerShape
);
702 // ViewLayer interface
703 virtual bool isOnView(boost::shared_ptr
<View
> const& rView
) const;
704 virtual void clear() const;
705 virtual void clearAll() const;
706 virtual cppcanvas::CanvasSharedPtr
getCanvas() const;
707 virtual cppcanvas::CustomSpriteSharedPtr
createSprite( const ::basegfx::B2DSize
& rSpriteSizePixel
,
708 double nPriority
) const;
709 virtual void setPriority( const basegfx::B1DRange
& rRange
);
710 virtual ::basegfx::B2DHomMatrix
getTransformation() const;
711 virtual basegfx::B2DHomMatrix
getSpriteTransformation() const;
712 virtual void setClip( const ::basegfx::B2DPolyPolygon
& rClip
);
713 virtual bool resize( const ::basegfx::B2DRange
& rArea
);
716 virtual void _dispose();
717 virtual uno::Reference
<presentation::XSlideShowView
> getUnoView()const;
718 virtual void setIsSoundEnabled (const bool bValue
);
719 virtual bool isSoundEnabled (void) const;
722 virtual void SAL_CALL
disposing( lang::EventObject
const& evt
)
723 throw (uno::RuntimeException
);
725 virtual void SAL_CALL
modified( const lang::EventObject
& aEvent
)
726 throw (uno::RuntimeException
);
728 virtual void SAL_CALL
windowPaint( const awt::PaintEvent
& e
)
729 throw (uno::RuntimeException
);
731 // WeakComponentImplHelperBase:
732 virtual void SAL_CALL
disposing();
737 typedef std::vector
< boost::weak_ptr
<SlideViewLayer
> > ViewLayerVector
;
739 /// Prune viewlayers from deceased ones, optionally update them
740 void pruneLayers( bool bWithViewLayerUpdate
=false ) const;
742 /** Max fill level of maViewLayers, before we try to prune it from
745 enum{ LAYER_ULLAGE
=8 };
747 uno::Reference
<presentation::XSlideShowView
> mxView
;
748 cppcanvas::SpriteCanvasSharedPtr mpCanvas
;
750 EventMultiplexer
& mrEventMultiplexer
;
751 EventQueue
& mrEventQueue
;
753 mutable LayerSpriteContainer maSprites
;
754 mutable ViewLayerVector maViewLayers
;
756 basegfx::B2DPolyPolygon maClip
;
758 basegfx::B2DHomMatrix maViewTransform
;
759 basegfx::B2DSize maUserSize
;
760 bool mbIsSoundEnabled
;
764 SlideView::SlideView( const uno::Reference
<presentation::XSlideShowView
>& xView
,
765 EventQueue
& rEventQueue
,
766 EventMultiplexer
& rEventMultiplexer
) :
767 SlideViewBase( m_aMutex
),
770 mrEventMultiplexer( rEventMultiplexer
),
771 mrEventQueue( rEventQueue
),
776 maUserSize( 1.0, 1.0 ), // default size: one-by-one rectangle
777 mbIsSoundEnabled(true)
779 // take care not constructing any UNO references to this _inside_
780 // ctor, shift that code to createSlideView()!
781 ENSURE_OR_THROW( mxView
.is(),
782 "SlideView::SlideView(): Invalid view" );
784 mpCanvas
= cppcanvas::VCLFactory::getInstance().createSpriteCanvas(
785 xView
->getCanvas() );
786 ENSURE_OR_THROW( mpCanvas
,
787 "Could not create cppcanvas" );
789 geometry::AffineMatrix2D
aViewTransform(
790 xView
->getTransformation() );
792 if( basegfx::fTools::equalZero(
793 basegfx::B2DVector(aViewTransform
.m00
,
794 aViewTransform
.m10
).getLength()) ||
795 basegfx::fTools::equalZero(
796 basegfx::B2DVector(aViewTransform
.m01
,
797 aViewTransform
.m11
).getLength()) )
800 "SlideView::SlideView(): Singular matrix!" );
802 canvas::tools::setIdentityAffineMatrix2D(aViewTransform
);
805 basegfx::unotools::homMatrixFromAffineMatrix(
806 maViewTransform
, aViewTransform
);
808 // once and forever: set fixed prio to this 'layer' (we're always
809 // the background layer)
810 maSprites
.setLayerPriority( basegfx::B1DRange(0.0,1.0) );
813 void SlideView::disposing()
815 osl::MutexGuard
aGuard( m_aMutex
);
817 maViewLayers
.clear();
821 // additionally, also de-register from XSlideShowView
824 mxView
->removeTransformationChangedListener( this );
825 mxView
->removePaintListener( this );
830 ViewLayerSharedPtr
SlideView::createViewLayer( const basegfx::B2DRange
& rLayerBounds
) const
832 osl::MutexGuard
aGuard( m_aMutex
);
834 ENSURE_OR_THROW( mpCanvas
,
835 "SlideView::createViewLayer(): Disposed" );
837 const std::size_t nNumLayers( maViewLayers
.size() );
839 // avoid filling up layer vector with lots of deceased layer weak
841 if( nNumLayers
> LAYER_ULLAGE
)
844 boost::shared_ptr
<SlideViewLayer
> pViewLayer( new SlideViewLayer(mpCanvas
,
849 maViewLayers
.push_back( pViewLayer
);
854 bool SlideView::updateScreen() const
856 osl::MutexGuard
aGuard( m_aMutex
);
858 ENSURE_OR_RETURN( mpCanvas
.get(),
859 "SlideView::updateScreen(): Disposed" );
861 return mpCanvas
->updateScreen( false );
864 bool SlideView::paintScreen() const
866 osl::MutexGuard
aGuard( m_aMutex
);
868 ENSURE_OR_RETURN( mpCanvas
.get(),
869 "SlideView::paintScreen(): Disposed" );
871 return mpCanvas
->updateScreen( true );
874 void SlideView::clear() const
876 osl::MutexGuard
aGuard( m_aMutex
);
878 OSL_ENSURE( mxView
.is() && mpCanvas
,
879 "SlideView::clear(): Disposed" );
880 if( !mxView
.is() || !mpCanvas
)
884 clearRect(getCanvas()->clone(),
886 basegfx::B2DRange(0,0,
889 getTransformation()));
892 void SlideView::clearAll() const
894 osl::MutexGuard
aGuard( m_aMutex
);
896 OSL_ENSURE( mxView
.is() && mpCanvas
,
897 "SlideView::clear(): Disposed" );
898 if( !mxView
.is() || !mpCanvas
)
905 void SlideView::setViewSize( const basegfx::B2DSize
& rSize
)
907 osl::MutexGuard
aGuard( m_aMutex
);
913 void SlideView::setCursorShape( sal_Int16 nPointerShape
)
915 osl::MutexGuard
const guard( m_aMutex
);
918 mxView
->setMouseCursor( nPointerShape
);
921 bool SlideView::isOnView(boost::shared_ptr
<View
> const& rView
) const
923 return rView
.get() == this;
926 cppcanvas::CanvasSharedPtr
SlideView::getCanvas() const
928 osl::MutexGuard
aGuard( m_aMutex
);
930 ENSURE_OR_THROW( mpCanvas
,
931 "SlideView::getCanvas(): Disposed" );
936 cppcanvas::CustomSpriteSharedPtr
SlideView::createSprite(
937 const basegfx::B2DSize
& rSpriteSizePixel
,
938 double nPriority
) const
940 osl::MutexGuard
aGuard( m_aMutex
);
942 ENSURE_OR_THROW( mpCanvas
, "SlideView::createSprite(): Disposed" );
944 cppcanvas::CustomSpriteSharedPtr
pSprite(
945 mpCanvas
->createCustomSprite( rSpriteSizePixel
) );
947 maSprites
.addSprite( pSprite
,
953 void SlideView::setPriority( const basegfx::B1DRange
& /*rRange*/ )
955 osl::MutexGuard
aGuard( m_aMutex
);
958 "SlideView::setPriority() is a NOOP for slide view - "
959 "content will always be shown in the background" );
962 basegfx::B2DHomMatrix
SlideView::getTransformation() const
964 osl::MutexGuard
aGuard( m_aMutex
);
966 basegfx::B2DHomMatrix aMatrix
;
967 aMatrix
.scale( 1.0/maUserSize
.getX(), 1.0/maUserSize
.getY() );
969 return maViewTransform
* aMatrix
;
972 basegfx::B2DHomMatrix
SlideView::getSpriteTransformation() const
974 return getTransformation();
977 void SlideView::setClip( const basegfx::B2DPolyPolygon
& rClip
)
979 osl::MutexGuard
aGuard( m_aMutex
);
981 basegfx::B2DPolyPolygon aNewClip
= prepareClip( rClip
);
983 if( aNewClip
!= maClip
)
991 bool SlideView::resize( const ::basegfx::B2DRange
& /*rArea*/ )
993 osl::MutexGuard
aGuard( m_aMutex
);
996 "SlideView::resize(): ignored for the View, can't change size "
997 "effectively, anyway" );
1002 uno::Reference
<presentation::XSlideShowView
> SlideView::getUnoView() const
1004 osl::MutexGuard
aGuard( m_aMutex
);
1008 void SlideView::setIsSoundEnabled (const bool bValue
)
1010 mbIsSoundEnabled
= bValue
;
1013 bool SlideView::isSoundEnabled (void) const
1015 return mbIsSoundEnabled
;
1018 void SlideView::_dispose()
1024 void SlideView::disposing( lang::EventObject
const& evt
)
1025 throw (uno::RuntimeException
)
1029 // no deregistration necessary anymore, XView has left:
1030 osl::MutexGuard
const guard( m_aMutex
);
1034 OSL_ASSERT( evt
.Source
== mxView
);
1042 void SlideView::modified( const lang::EventObject
& /*aEvent*/ )
1043 throw (uno::RuntimeException
)
1045 osl::MutexGuard
const guard( m_aMutex
);
1047 OSL_ENSURE( mxView
.is(), "SlideView::modified(): "
1048 "Disposed, but event received from XSlideShowView?!");
1053 geometry::AffineMatrix2D
aViewTransform(
1054 mxView
->getTransformation() );
1056 if( basegfx::fTools::equalZero(
1057 basegfx::B2DVector(aViewTransform
.m00
,
1058 aViewTransform
.m10
).getLength()) ||
1059 basegfx::fTools::equalZero(
1060 basegfx::B2DVector(aViewTransform
.m01
,
1061 aViewTransform
.m11
).getLength()) )
1064 "SlideView::modified(): Singular matrix!" );
1066 canvas::tools::setIdentityAffineMatrix2D(aViewTransform
);
1069 // view transformation really changed?
1070 basegfx::B2DHomMatrix aNewTransform
;
1071 basegfx::unotools::homMatrixFromAffineMatrix(
1075 if( aNewTransform
== maViewTransform
)
1076 return; // No change, nothing to do
1078 maViewTransform
= aNewTransform
;
1082 // notify view change. Don't call EventMultiplexer directly, this
1083 // might not be the main thread!
1084 mrEventQueue
.addEvent(
1085 makeEvent( boost::bind( (bool (EventMultiplexer::*)(
1086 const uno::Reference
<presentation::XSlideShowView
>&))
1087 &EventMultiplexer::notifyViewChanged
,
1088 boost::ref(mrEventMultiplexer
), mxView
)));
1092 void SlideView::windowPaint( const awt::PaintEvent
& /*e*/ )
1093 throw (uno::RuntimeException
)
1095 osl::MutexGuard
aGuard( m_aMutex
);
1097 OSL_ENSURE( mxView
.is() && mpCanvas
, "Disposed, but event received?!" );
1099 // notify view clobbering. Don't call EventMultiplexer directly,
1100 // this might not be the main thread!
1101 mrEventQueue
.addEvent(
1102 makeEvent( boost::bind( &EventMultiplexer::notifyViewClobbered
,
1103 boost::ref(mrEventMultiplexer
), mxView
) ) );
1106 void SlideView::updateCanvas()
1108 OSL_ENSURE( mpCanvas
,
1109 "SlideView::updateCanvasTransform(): Disposed" );
1111 if( !mpCanvas
|| !mxView
.is())
1114 mpCanvas
->clear(); // this is unnecessary, strictly speaking. but
1115 // it makes the SlideView behave exactly like a
1116 // sprite-based SlideViewLayer, because those
1117 // are created from scratch after a resize
1119 mpCanvas
->setTransformation( getTransformation() );
1121 createClipPolygon( maClip
,
1125 // forward update to viewlayers
1126 pruneLayers( true );
1129 void SlideView::updateClip()
1131 OSL_ENSURE( mpCanvas
,
1132 "SlideView::updateClip(): Disposed" );
1138 createClipPolygon( maClip
,
1142 pruneLayers( false );
1145 void SlideView::pruneLayers( bool bWithViewLayerUpdate
) const
1147 ViewLayerVector aValidLayers
;
1149 const basegfx::B2DHomMatrix
& rCurrTransform(
1150 getTransformation() );
1152 // check all layers for validity, and retain only the live ones
1153 ViewLayerVector::const_iterator
aCurr( maViewLayers
.begin() );
1154 const ViewLayerVector::const_iterator
aEnd( maViewLayers
.end() );
1155 while( aCurr
!= aEnd
)
1157 boost::shared_ptr
< SlideViewLayer
> pCurrLayer( aCurr
->lock() );
1161 aValidLayers
.push_back( pCurrLayer
);
1163 if( bWithViewLayerUpdate
)
1164 pCurrLayer
->updateView( rCurrTransform
,
1171 // replace layer list with pruned one
1172 maViewLayers
.swap( aValidLayers
);
1175 } // anonymous namespace
1177 UnoViewSharedPtr
createSlideView( uno::Reference
< presentation::XSlideShowView
> const& xView
,
1178 EventQueue
& rEventQueue
,
1179 EventMultiplexer
& rEventMultiplexer
)
1181 boost::shared_ptr
<SlideView
> const that(
1182 comphelper::make_shared_from_UNO(
1183 new SlideView(xView
,
1185 rEventMultiplexer
)));
1187 // register listeners with XSlideShowView
1188 xView
->addTransformationChangedListener( that
.get() );
1189 xView
->addPaintListener( that
.get() );
1191 // set new transformation
1192 that
->updateCanvas();
1197 } // namespace internal
1198 } // namespace slideshow