1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <canvas/debug.hxx>
21 #include <tools/diagnose_ex.h>
22 #include <canvas/canvastools.hxx>
24 #include "eventqueue.hxx"
25 #include "eventmultiplexer.hxx"
26 #include "slideview.hxx"
27 #include "delayevent.hxx"
28 #include "unoview.hxx"
30 #include <rtl/instance.hxx>
31 #include <cppuhelper/basemutex.hxx>
32 #include <cppuhelper/compbase2.hxx>
33 #include <cppuhelper/implementationentry.hxx>
34 #include <cppuhelper/interfacecontainer.h>
35 #include <comphelper/make_shared_from_uno.hxx>
37 #include <cppcanvas/spritecanvas.hxx>
38 #include <cppcanvas/customsprite.hxx>
39 #include <cppcanvas/vclfactory.hxx>
40 #include <cppcanvas/basegfxfactory.hxx>
42 #include <tools/debug.hxx>
44 #include <basegfx/range/b1drange.hxx>
45 #include <basegfx/range/b2drange.hxx>
46 #include <basegfx/range/b2irange.hxx>
47 #include <basegfx/point/b2dpoint.hxx>
48 #include <basegfx/polygon/b2dpolygon.hxx>
49 #include <basegfx/matrix/b2dhommatrix.hxx>
50 #include <basegfx/polygon/b2dpolygontools.hxx>
51 #include <basegfx/polygon/b2dpolypolygontools.hxx>
52 #include <basegfx/tools/canvastools.hxx>
53 #include <basegfx/polygon/b2dpolygonclipper.hxx>
54 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
56 #include <com/sun/star/presentation/XSlideShow.hpp>
58 #include <boost/noncopyable.hpp>
59 #include <boost/bind.hpp>
60 #include <boost/weak_ptr.hpp>
66 using namespace com::sun::star
;
73 struct StaticUnitRectPoly
: public rtl::StaticWithInit
<basegfx::B2DPolygon
, StaticUnitRectPoly
>
75 basegfx::B2DPolygon
operator()()
77 return basegfx::tools::createUnitPolygon();
81 /** Sprite entry, to store sprite plus priority
83 The operator<() defines a strict weak ordering of sprites, sort
84 key is the sprite priority.
88 SpriteEntry( const cppcanvas::CustomSpriteSharedPtr
& rSprite
,
95 bool operator<(const SpriteEntry
& rRHS
) const
97 return mnPriority
< rRHS
.mnPriority
;
100 boost::weak_ptr
< cppcanvas::CustomSprite
> mpSprite
;
104 typedef std::vector
< SpriteEntry
> SpriteVector
;
107 /** Create a clip polygon for slide views
110 Clip to set (can be empty)
113 Canvas to create the clip polygon for
116 The size of the view. Note that the returned clip will
117 <em>always</em> clip to at least the rect defined herein.
119 @return the view clip polygon, in view coordinates, which is
120 guaranteed to at least clip to the view size.
122 basegfx::B2DPolyPolygon
createClipPolygon( const basegfx::B2DPolyPolygon
& rClip
,
123 const cppcanvas::CanvasSharedPtr
& /*rCanvas*/,
124 const basegfx::B2DSize
& rUserSize
)
126 // setup canvas clipping
127 // =====================
130 const basegfx::B2DRange
aClipRange(0, 0, rUserSize
.getX(), rUserSize
.getY());
134 return basegfx::tools::clipPolyPolygonOnRange(rClip
, aClipRange
, true, false);
138 return basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(aClipRange
));
142 /** Prepare given clip polygon to be stored as the current clip
144 Note that this is separate from createClipPolygon(), to allow
145 SlideView implementations to store this intermediate result
146 (createClipPolygon() has to be called every time the view size
149 basegfx::B2DPolyPolygon
prepareClip( const basegfx::B2DPolyPolygon
& rClip
)
151 basegfx::B2DPolyPolygon
aClip( rClip
);
153 // TODO(P2): unnecessary, once XCanvas is correctly handling this
154 // AW: Should be no longer necessary; tools are now bezier-safe
155 if( aClip
.areControlPointsUsed() )
156 aClip
= basegfx::tools::adaptiveSubdivideByAngle( aClip
);
158 // normalize polygon, preparation for clipping
160 aClip
= basegfx::tools::correctOrientations(aClip
);
161 aClip
= basegfx::tools::solveCrossovers(aClip
);
162 aClip
= basegfx::tools::stripNeutralPolygons(aClip
);
163 aClip
= basegfx::tools::stripDispensablePolygons(aClip
, false);
169 void clearRect( ::cppcanvas::CanvasSharedPtr
const& pCanvas
,
170 basegfx::B2IRange
const& rArea
)
172 // convert clip polygon to device coordinate system
173 ::basegfx::B2DPolyPolygon
const* pClipPoly( pCanvas
->getClip() );
176 ::basegfx::B2DPolyPolygon
aClipPoly( *pClipPoly
);
177 aClipPoly
.transform( pCanvas
->getTransformation() );
178 pCanvas
->setClip( aClipPoly
);
181 // set transformation to identitiy (->device pixel)
182 pCanvas
->setTransformation( ::basegfx::B2DHomMatrix() );
184 // #i42440# Fill the _full_ background in
185 // black. Since we had to extend the bitmap by one
186 // pixel, and the bitmap is initialized white,
187 // depending on the slide content a one pixel wide
188 // line will show to the bottom and the right.
189 const ::basegfx::B2DPolygon
aPoly(
190 ::basegfx::tools::createPolygonFromRect(
191 basegfx::B2DRange(rArea
)));
193 ::cppcanvas::PolyPolygonSharedPtr
pPolyPoly(
194 ::cppcanvas::BaseGfxFactory::getInstance().createPolyPolygon( pCanvas
,
199 pPolyPoly
->setCompositeOp( cppcanvas::CanvasGraphic::SOURCE
);
200 pPolyPoly
->setRGBAFillColor( 0xFFFFFF00U
);
204 #if OSL_DEBUG_LEVEL >= 2 && defined(DBG_UTIL)
205 ::cppcanvas::CanvasSharedPtr
pCliplessCanvas( pCanvas
->clone() );
206 pCliplessCanvas
->setClip();
208 if( pCanvas
->getClip() )
210 ::cppcanvas::PolyPolygonSharedPtr
pPolyPoly2(
211 ::cppcanvas::BaseGfxFactory::getInstance().createPolyPolygon( pCliplessCanvas
,
215 pPolyPoly2
->setRGBALineColor( 0x008000FFU
);
222 /** Get bounds in pixel
225 Bound rect, in user space coordinates
227 @param rTransformation
228 User space to device pixel transformation
230 @return the layer bounds in pixel, extended by one pixel to the
233 basegfx::B2IRange
getLayerBoundsPixel( basegfx::B2DRange
const& rLayerBounds
,
234 basegfx::B2DHomMatrix
const& rTransformation
)
236 ::basegfx::B2DRange aTmpRect
;
237 ::canvas::tools::calcTransformedRectBounds( aTmpRect
,
241 if( aTmpRect
.isEmpty() )
242 return ::basegfx::B2IRange();
244 // #i42440# Returned layer size is one pixel too small, as
245 // rendering happens one pixel to the right and below the
246 // actual bound rect.
247 return ::basegfx::B2IRange( ::basegfx::fround(aTmpRect
.getMinX()),
248 ::basegfx::fround(aTmpRect
.getMinY()),
249 ::basegfx::fround(aTmpRect
.getMaxX()) + 1,
250 ::basegfx::fround(aTmpRect
.getMaxY()) + 1 );
254 // ----------------------------------------------------------------
256 /** Container class for sprites issued by a ViewLayer
258 This class handles the sprite prioritization issues, that are
259 needed for layer sprites (e.g. the need to re-prioritize sprites
260 when the layer changes prio).
262 class LayerSpriteContainer
264 /** Max fill level of maSprites, before we try to prune it from
267 enum{ SPRITE_ULLAGE
=256 };
269 /** All sprites that have been issued by this container (pruned
270 from time to time, for invalid references). This vector is
271 kept sorted with increasing sprite priority.
273 SpriteVector maSprites
;
275 /// Priority of this layer, relative to other view layers
276 basegfx::B1DRange maLayerPrioRange
;
278 double getSpritePriority( std::size_t nSpriteNum
) const
280 // divide the available layer range equally between all
281 // sprites, assign upper bound of individual sprite range as
282 // sprite prio (the layer itself gets assigned the lower bound
283 // of sprite 0's individual range):
285 // | layer 0 | layer 1 | ...
286 // | sprite 0 | sprite 1 | sprite 0 | sprite 1 | ...
287 return maLayerPrioRange
.getMinimum() + maLayerPrioRange
.getRange()*(nSpriteNum
+1)/(maSprites
.size()+1);
290 /** Rescan sprite vector, and remove deceased sprites (and reset
294 Iterator to the first entry to rescan
298 SpriteVector aValidSprites
;
300 // check all sprites for validity and set new priority
301 SpriteVector::iterator
aCurrSprite( maSprites
.begin() );
302 const SpriteVector::iterator
aEnd( maSprites
.end() );
303 while( aCurrSprite
!= aEnd
)
305 cppcanvas::CustomSpriteSharedPtr
pCurrSprite( aCurrSprite
->mpSprite
.lock() );
309 // only copy still valid sprites over to the refreshed
311 aValidSprites
.push_back( *aCurrSprite
);
313 pCurrSprite
->setPriority(
314 getSpritePriority( aValidSprites
.size()-1 ));
320 // replace sprite list with pruned one
321 maSprites
.swap( aValidSprites
);
325 LayerSpriteContainer() :
331 basegfx::B1DRange
getLayerPriority() const
333 return maLayerPrioRange
;
336 void setLayerPriority( const basegfx::B1DRange
& rRange
)
338 if( rRange
!= maLayerPrioRange
)
340 maLayerPrioRange
= rRange
;
342 // prune and recalc sprite prios
347 void addSprite( const cppcanvas::CustomSpriteSharedPtr
& pSprite
,
353 SpriteEntry
aEntry( pSprite
,nPriority
);
355 // insert new sprite, such that vector stays sorted
356 SpriteVector::iterator
aInsertPos(
358 std::lower_bound( maSprites
.begin(),
363 const std::size_t nNumSprites( maSprites
.size() );
364 if( nNumSprites
> SPRITE_ULLAGE
||
365 maSprites
.end() - aInsertPos
> 1 )
367 // updateSprites() also updates all sprite prios
372 // added sprite to the end, and not too many sprites in
373 // vector - perform optimized update (only need to set
374 // prio). This basically caters for the common case of
375 // iterated character animations, which generate lots of
376 // sprites, all added to the end.
377 pSprite
->setPriority(
378 getSpritePriority( nNumSprites
-1 ));
389 // ----------------------------------------------------------------
392 /** This class provides layers for a slide view
394 Layers are used to render animations with the correct z order -
395 because sprites are always in front of the static canvas
396 background, shapes that must appear <em<before</em> an animation
397 must also be displayed as a sprite.
399 Each layer has a priority assigned to it (valid range [0,1]), which
400 also affects all sprites created for this specific layer - i.e. if
401 the layer priority changes, the sprites change z order together
404 class SlideViewLayer
: public ViewLayer
,
405 private boost::noncopyable
407 /// Smart container for all sprites issued by this layer
408 mutable LayerSpriteContainer maSpriteContainer
;
410 /// Bounds of this layer in user space coordinates
411 basegfx::B2DRange maLayerBounds
;
413 /// Bounds of this layer in device pixel
414 mutable basegfx::B2IRange maLayerBoundsPixel
;
416 /// Current clip polygon in user coordinates
417 basegfx::B2DPolyPolygon maClip
;
419 /// Current size of the view in user coordinates
420 basegfx::B2DSize maUserSize
;
422 /// Current overall view transformation
423 basegfx::B2DHomMatrix maTransformation
;
425 /// 'parent' canvas, this viewlayer is associated with
426 const cppcanvas::SpriteCanvasSharedPtr mpSpriteCanvas
;
428 /** output surface (necessarily a sprite, won't otherwise be able
429 to display anything <em>before</em> other sprites)
431 mutable cppcanvas::CustomSpriteSharedPtr mpSprite
;
433 /// actual output canvas retrieved from a sprite
434 mutable cppcanvas::CanvasSharedPtr mpOutputCanvas
;
436 /// ptr back to owning view. needed for isOnView() method
437 View
const* const mpParentView
;
440 /** Create a new layer
443 Sprite canvas to create the layer on
446 Initial overall canvas transformation
449 Initial layer bounds, in view coordinate system
451 SlideViewLayer( const cppcanvas::SpriteCanvasSharedPtr
& pCanvas
,
452 const basegfx::B2DHomMatrix
& rTransform
,
453 const basegfx::B2DRange
& rLayerBounds
,
454 const basegfx::B2DSize
& rUserSize
,
455 View
const* const pParentView
) :
457 maLayerBounds(rLayerBounds
),
458 maLayerBoundsPixel(),
460 maUserSize(rUserSize
),
461 maTransformation(rTransform
),
462 mpSpriteCanvas(pCanvas
),
465 mpParentView(pParentView
)
469 void updateView( const basegfx::B2DHomMatrix
& rMatrix
,
470 const basegfx::B2DSize
& rUserSize
)
472 maTransformation
= rMatrix
;
473 maUserSize
= rUserSize
;
475 // limit layer bounds to visible screen
476 maLayerBounds
.intersect( basegfx::B2DRange(0.0,
479 maUserSize
.getY()) );
481 basegfx::B2IRange
const& rNewLayerPixel(
482 getLayerBoundsPixel(maLayerBounds
,
484 if( rNewLayerPixel
!= maLayerBoundsPixel
)
486 // re-gen sprite with new size
487 mpOutputCanvas
.reset();
493 // ViewLayer interface
494 // ----------------------------------------------
496 virtual cppcanvas::CustomSpriteSharedPtr
createSprite(
497 const ::basegfx::B2DSize
& rSpriteSizePixel
,
498 double nPriority
) const
500 cppcanvas::CustomSpriteSharedPtr
pSprite(
501 mpSpriteCanvas
->createCustomSprite( rSpriteSizePixel
) );
503 maSpriteContainer
.addSprite( pSprite
,
509 virtual void setPriority( const basegfx::B1DRange
& rRange
)
511 OSL_ENSURE( !rRange
.isEmpty() &&
512 rRange
.getMinimum() >= 1.0,
513 "SlideViewLayer::setPriority(): prio MUST be larger than 1.0 (because "
514 "the background layer already lies there)" );
516 maSpriteContainer
.setLayerPriority( rRange
);
519 mpSprite
->setPriority( rRange
.getMinimum() );
522 virtual basegfx::B2DHomMatrix
getTransformation() const
524 // Offset given transformation by left, top border of given
525 // range (after transformation through given transformation)
526 basegfx::B2DRectangle aTmpRect
;
527 canvas::tools::calcTransformedRectBounds( aTmpRect
,
531 basegfx::B2DHomMatrix
aMatrix( maTransformation
);
533 // Add translation according to the origin of aTmpRect. Ignore the
534 // translation when aTmpRect was not properly initialized.
535 if ( ! aTmpRect
.isEmpty())
537 aMatrix
.translate( -basegfx::fround(aTmpRect
.getMinX()),
538 -basegfx::fround(aTmpRect
.getMinY()) );
544 virtual basegfx::B2DHomMatrix
getSpriteTransformation() const
546 return maTransformation
;
549 virtual void clear() const
551 // grab canvas - that also lazy-initializes maLayerBoundsPixel
552 cppcanvas::CanvasSharedPtr pCanvas
=getCanvas()->clone();
554 // clear whole canvas
555 const basegfx::B2I64Tuple
& rSpriteSize(maLayerBoundsPixel
.getRange());
557 basegfx::B2IRange(0,0,rSpriteSize
.getX(),rSpriteSize
.getY()));
560 virtual void clearAll() const
562 // grab canvas - that also lazy-initializes maLayerBoundsPixel
563 ::cppcanvas::CanvasSharedPtr
pCanvas( getCanvas()->clone() );
565 // clear layer clip, to clear whole area
568 // clear whole canvas
569 const basegfx::B2I64Tuple
& rSpriteSize(maLayerBoundsPixel
.getRange());
571 basegfx::B2IRange(0,0,rSpriteSize
.getX(),rSpriteSize
.getY()));
574 virtual bool isOnView(boost::shared_ptr
<View
> const& rView
) const
576 return rView
.get() == mpParentView
;
579 virtual cppcanvas::CanvasSharedPtr
getCanvas() const
581 if( !mpOutputCanvas
)
585 maLayerBoundsPixel
= getLayerBoundsPixel(maLayerBounds
,
588 // HACK: ensure at least 1x1 pixel size. clients might
589 // need an actual canvas (e.g. for bound rect
590 // calculations) without rendering anything. Better
591 // solution: introduce something like a reference
592 // canvas for ViewLayers, which is always available.
593 if( maLayerBoundsPixel
.isEmpty() )
594 maLayerBoundsPixel
= basegfx::B2IRange(0,0,1,1);
596 const basegfx::B2I64Tuple
& rSpriteSize(maLayerBoundsPixel
.getRange());
597 mpSprite
= mpSpriteCanvas
->createCustomSprite(
598 basegfx::B2DVector(sal::static_int_cast
<sal_Int32
>(rSpriteSize
.getX()),
599 sal::static_int_cast
<sal_Int32
>(rSpriteSize
.getY())) );
601 mpSprite
->setPriority(
602 maSpriteContainer
.getLayerPriority().getMinimum() );
604 #if OSL_DEBUG_LEVEL >= 2 && defined(DBG_UTIL)
606 basegfx::B2DPoint(maLayerBoundsPixel
.getMinimum()) +
607 basegfx::B2DPoint(10,10) );
609 mpSprite
->setAlpha(0.5);
612 basegfx::B2DPoint(maLayerBoundsPixel
.getMinimum()) );
614 mpSprite
->setAlpha(1.0);
619 ENSURE_OR_THROW( mpSprite
,
620 "SlideViewLayer::getCanvas(): no layer sprite" );
622 mpOutputCanvas
= mpSprite
->getContentCanvas();
624 ENSURE_OR_THROW( mpOutputCanvas
,
625 "SlideViewLayer::getCanvas(): sprite doesn't yield a canvas" );
627 // new canvas retrieved - setup transformation and clip
628 mpOutputCanvas
->setTransformation( getTransformation() );
629 mpOutputCanvas
->setClip(
630 createClipPolygon( maClip
,
635 return mpOutputCanvas
;
638 virtual void setClip( const basegfx::B2DPolyPolygon
& rClip
)
640 basegfx::B2DPolyPolygon aNewClip
= prepareClip( rClip
);
642 if( aNewClip
!= maClip
)
647 mpOutputCanvas
->setClip(
648 createClipPolygon( maClip
,
654 virtual bool resize( const ::basegfx::B2DRange
& rArea
)
656 const bool bRet( maLayerBounds
!= rArea
);
657 maLayerBounds
= rArea
;
658 updateView( maTransformation
,
666 // ---------------------------------------------------------
668 typedef cppu::WeakComponentImplHelper2
<
669 ::com::sun::star::util::XModifyListener
,
670 ::com::sun::star::awt::XPaintListener
> SlideViewBase
;
674 This class implements the View interface, encapsulating
675 <em>one</em> view a slideshow is displayed on.
677 class SlideView
: private cppu::BaseMutex
,
678 public SlideViewBase
,
682 SlideView( const uno::Reference
<presentation::XSlideShowView
>& xView
,
683 EventQueue
& rEventQueue
,
684 EventMultiplexer
& rEventMultiplexer
);
689 virtual ViewLayerSharedPtr
createViewLayer( const basegfx::B2DRange
& rLayerBounds
) const;
690 virtual bool updateScreen() const;
691 virtual bool paintScreen() const;
692 virtual void setViewSize( const ::basegfx::B2DSize
& );
693 virtual void setCursorShape( sal_Int16 nPointerShape
);
695 // ViewLayer interface
696 virtual bool isOnView(boost::shared_ptr
<View
> const& rView
) const;
697 virtual void clear() const;
698 virtual void clearAll() const;
699 virtual cppcanvas::CanvasSharedPtr
getCanvas() const;
700 virtual cppcanvas::CustomSpriteSharedPtr
createSprite( const ::basegfx::B2DSize
& rSpriteSizePixel
,
701 double nPriority
) const;
702 virtual void setPriority( const basegfx::B1DRange
& rRange
);
703 virtual ::basegfx::B2DHomMatrix
getTransformation() const;
704 virtual basegfx::B2DHomMatrix
getSpriteTransformation() const;
705 virtual void setClip( const ::basegfx::B2DPolyPolygon
& rClip
);
706 virtual bool resize( const ::basegfx::B2DRange
& rArea
);
709 virtual void _dispose();
710 virtual uno::Reference
<presentation::XSlideShowView
> getUnoView()const;
711 virtual void setIsSoundEnabled (const bool bValue
);
712 virtual bool isSoundEnabled (void) const;
715 virtual void SAL_CALL
disposing( lang::EventObject
const& evt
)
716 throw (uno::RuntimeException
);
718 virtual void SAL_CALL
modified( const lang::EventObject
& aEvent
)
719 throw (uno::RuntimeException
);
721 virtual void SAL_CALL
windowPaint( const awt::PaintEvent
& e
)
722 throw (uno::RuntimeException
);
724 // WeakComponentImplHelperBase:
725 virtual void SAL_CALL
disposing();
730 typedef std::vector
< boost::weak_ptr
<SlideViewLayer
> > ViewLayerVector
;
732 /// Prune viewlayers from deceased ones, optionally update them
733 void pruneLayers( bool bWithViewLayerUpdate
=false ) const;
735 /** Max fill level of maViewLayers, before we try to prune it from
738 enum{ LAYER_ULLAGE
=8 };
740 uno::Reference
<presentation::XSlideShowView
> mxView
;
741 cppcanvas::SpriteCanvasSharedPtr mpCanvas
;
743 EventMultiplexer
& mrEventMultiplexer
;
744 EventQueue
& mrEventQueue
;
746 mutable LayerSpriteContainer maSprites
;
747 mutable ViewLayerVector maViewLayers
;
749 basegfx::B2DPolyPolygon maClip
;
751 basegfx::B2DHomMatrix maViewTransform
;
752 basegfx::B2DSize maUserSize
;
753 bool mbIsSoundEnabled
;
757 SlideView::SlideView( const uno::Reference
<presentation::XSlideShowView
>& xView
,
758 EventQueue
& rEventQueue
,
759 EventMultiplexer
& rEventMultiplexer
) :
760 SlideViewBase( m_aMutex
),
763 mrEventMultiplexer( rEventMultiplexer
),
764 mrEventQueue( rEventQueue
),
769 maUserSize( 1.0, 1.0 ), // default size: one-by-one rectangle
770 mbIsSoundEnabled(true)
772 // take care not constructing any UNO references to this _inside_
773 // ctor, shift that code to createSlideView()!
774 ENSURE_OR_THROW( mxView
.is(),
775 "SlideView::SlideView(): Invalid view" );
777 mpCanvas
= cppcanvas::VCLFactory::getInstance().createSpriteCanvas(
778 xView
->getCanvas() );
779 ENSURE_OR_THROW( mpCanvas
,
780 "Could not create cppcanvas" );
782 geometry::AffineMatrix2D
aViewTransform(
783 xView
->getTransformation() );
785 if( basegfx::fTools::equalZero(
786 basegfx::B2DVector(aViewTransform
.m00
,
787 aViewTransform
.m10
).getLength()) ||
788 basegfx::fTools::equalZero(
789 basegfx::B2DVector(aViewTransform
.m01
,
790 aViewTransform
.m11
).getLength()) )
792 OSL_FAIL( "SlideView::SlideView(): Singular matrix!" );
794 canvas::tools::setIdentityAffineMatrix2D(aViewTransform
);
797 basegfx::unotools::homMatrixFromAffineMatrix(
798 maViewTransform
, aViewTransform
);
800 // once and forever: set fixed prio to this 'layer' (we're always
801 // the background layer)
802 maSprites
.setLayerPriority( basegfx::B1DRange(0.0,1.0) );
805 void SlideView::disposing()
807 osl::MutexGuard
aGuard( m_aMutex
);
809 maViewLayers
.clear();
813 // additionally, also de-register from XSlideShowView
816 mxView
->removeTransformationChangedListener( this );
817 mxView
->removePaintListener( this );
822 ViewLayerSharedPtr
SlideView::createViewLayer( const basegfx::B2DRange
& rLayerBounds
) const
824 osl::MutexGuard
aGuard( m_aMutex
);
826 ENSURE_OR_THROW( mpCanvas
,
827 "SlideView::createViewLayer(): Disposed" );
829 const std::size_t nNumLayers( maViewLayers
.size() );
831 // avoid filling up layer vector with lots of deceased layer weak
833 if( nNumLayers
> LAYER_ULLAGE
)
836 boost::shared_ptr
<SlideViewLayer
> pViewLayer( new SlideViewLayer(mpCanvas
,
841 maViewLayers
.push_back( pViewLayer
);
846 bool SlideView::updateScreen() const
848 osl::MutexGuard
aGuard( m_aMutex
);
850 ENSURE_OR_RETURN_FALSE( mpCanvas
.get(),
851 "SlideView::updateScreen(): Disposed" );
853 return mpCanvas
->updateScreen( false );
856 bool SlideView::paintScreen() const
858 osl::MutexGuard
aGuard( m_aMutex
);
860 ENSURE_OR_RETURN_FALSE( mpCanvas
.get(),
861 "SlideView::paintScreen(): Disposed" );
863 return mpCanvas
->updateScreen( true );
866 void SlideView::clear() const
868 osl::MutexGuard
aGuard( m_aMutex
);
870 OSL_ENSURE( mxView
.is() && mpCanvas
,
871 "SlideView::clear(): Disposed" );
872 if( !mxView
.is() || !mpCanvas
)
876 clearRect(getCanvas()->clone(),
878 basegfx::B2DRange(0,0,
881 getTransformation()));
884 void SlideView::clearAll() const
886 osl::MutexGuard
aGuard( m_aMutex
);
888 OSL_ENSURE( mxView
.is() && mpCanvas
,
889 "SlideView::clear(): Disposed" );
890 if( !mxView
.is() || !mpCanvas
)
897 void SlideView::setViewSize( const basegfx::B2DSize
& rSize
)
899 osl::MutexGuard
aGuard( m_aMutex
);
905 void SlideView::setCursorShape( sal_Int16 nPointerShape
)
907 osl::MutexGuard
const guard( m_aMutex
);
910 mxView
->setMouseCursor( nPointerShape
);
913 bool SlideView::isOnView(boost::shared_ptr
<View
> const& rView
) const
915 return rView
.get() == this;
918 cppcanvas::CanvasSharedPtr
SlideView::getCanvas() const
920 osl::MutexGuard
aGuard( m_aMutex
);
922 ENSURE_OR_THROW( mpCanvas
,
923 "SlideView::getCanvas(): Disposed" );
928 cppcanvas::CustomSpriteSharedPtr
SlideView::createSprite(
929 const basegfx::B2DSize
& rSpriteSizePixel
,
930 double nPriority
) const
932 osl::MutexGuard
aGuard( m_aMutex
);
934 ENSURE_OR_THROW( mpCanvas
, "SlideView::createSprite(): Disposed" );
936 cppcanvas::CustomSpriteSharedPtr
pSprite(
937 mpCanvas
->createCustomSprite( rSpriteSizePixel
) );
939 maSprites
.addSprite( pSprite
,
945 void SlideView::setPriority( const basegfx::B1DRange
& /*rRange*/ )
947 osl::MutexGuard
aGuard( m_aMutex
);
949 OSL_FAIL( "SlideView::setPriority() is a NOOP for slide view - "
950 "content will always be shown in the background" );
953 basegfx::B2DHomMatrix
SlideView::getTransformation() const
955 osl::MutexGuard
aGuard( m_aMutex
);
957 basegfx::B2DHomMatrix aMatrix
;
958 aMatrix
.scale( 1.0/maUserSize
.getX(), 1.0/maUserSize
.getY() );
960 return maViewTransform
* aMatrix
;
963 basegfx::B2DHomMatrix
SlideView::getSpriteTransformation() const
965 return getTransformation();
968 void SlideView::setClip( const basegfx::B2DPolyPolygon
& rClip
)
970 osl::MutexGuard
aGuard( m_aMutex
);
972 basegfx::B2DPolyPolygon aNewClip
= prepareClip( rClip
);
974 if( aNewClip
!= maClip
)
982 bool SlideView::resize( const ::basegfx::B2DRange
& /*rArea*/ )
984 osl::MutexGuard
aGuard( m_aMutex
);
986 OSL_FAIL( "SlideView::resize(): ignored for the View, can't change size "
987 "effectively, anyway" );
992 uno::Reference
<presentation::XSlideShowView
> SlideView::getUnoView() const
994 osl::MutexGuard
aGuard( m_aMutex
);
998 void SlideView::setIsSoundEnabled (const bool bValue
)
1000 mbIsSoundEnabled
= bValue
;
1003 bool SlideView::isSoundEnabled (void) const
1005 return mbIsSoundEnabled
;
1008 void SlideView::_dispose()
1014 void SlideView::disposing( lang::EventObject
const& evt
)
1015 throw (uno::RuntimeException
)
1019 // no deregistration necessary anymore, XView has left:
1020 osl::MutexGuard
const guard( m_aMutex
);
1024 OSL_ASSERT( evt
.Source
== mxView
);
1032 void SlideView::modified( const lang::EventObject
& /*aEvent*/ )
1033 throw (uno::RuntimeException
)
1035 osl::MutexGuard
const guard( m_aMutex
);
1037 OSL_ENSURE( mxView
.is(), "SlideView::modified(): "
1038 "Disposed, but event received from XSlideShowView?!");
1043 geometry::AffineMatrix2D
aViewTransform(
1044 mxView
->getTransformation() );
1046 if( basegfx::fTools::equalZero(
1047 basegfx::B2DVector(aViewTransform
.m00
,
1048 aViewTransform
.m10
).getLength()) ||
1049 basegfx::fTools::equalZero(
1050 basegfx::B2DVector(aViewTransform
.m01
,
1051 aViewTransform
.m11
).getLength()) )
1053 OSL_FAIL( "SlideView::modified(): Singular matrix!" );
1055 canvas::tools::setIdentityAffineMatrix2D(aViewTransform
);
1058 // view transformation really changed?
1059 basegfx::B2DHomMatrix aNewTransform
;
1060 basegfx::unotools::homMatrixFromAffineMatrix(
1064 if( aNewTransform
== maViewTransform
)
1065 return; // No change, nothing to do
1067 maViewTransform
= aNewTransform
;
1071 // notify view change. Don't call EventMultiplexer directly, this
1072 // might not be the main thread!
1073 mrEventQueue
.addEvent(
1074 makeEvent( boost::bind( (bool (EventMultiplexer::*)(
1075 const uno::Reference
<presentation::XSlideShowView
>&))
1076 &EventMultiplexer::notifyViewChanged
,
1077 boost::ref(mrEventMultiplexer
), mxView
),
1078 "EventMultiplexer::notifyViewChanged"));
1082 void SlideView::windowPaint( const awt::PaintEvent
& /*e*/ )
1083 throw (uno::RuntimeException
)
1085 osl::MutexGuard
aGuard( m_aMutex
);
1087 OSL_ENSURE( mxView
.is() && mpCanvas
, "Disposed, but event received?!" );
1089 // notify view clobbering. Don't call EventMultiplexer directly,
1090 // this might not be the main thread!
1091 mrEventQueue
.addEvent(
1092 makeEvent( boost::bind( &EventMultiplexer::notifyViewClobbered
,
1093 boost::ref(mrEventMultiplexer
), mxView
),
1094 "EventMultiplexer::notifyViewClobbered") );
1097 void SlideView::updateCanvas()
1099 OSL_ENSURE( mpCanvas
,
1100 "SlideView::updateCanvasTransform(): Disposed" );
1102 if( !mpCanvas
|| !mxView
.is())
1105 mpCanvas
->clear(); // this is unnecessary, strictly speaking. but
1106 // it makes the SlideView behave exactly like a
1107 // sprite-based SlideViewLayer, because those
1108 // are created from scratch after a resize
1110 mpCanvas
->setTransformation( getTransformation() );
1112 createClipPolygon( maClip
,
1116 // forward update to viewlayers
1117 pruneLayers( true );
1120 void SlideView::updateClip()
1122 OSL_ENSURE( mpCanvas
,
1123 "SlideView::updateClip(): Disposed" );
1129 createClipPolygon( maClip
,
1133 pruneLayers( false );
1136 void SlideView::pruneLayers( bool bWithViewLayerUpdate
) const
1138 ViewLayerVector aValidLayers
;
1140 const basegfx::B2DHomMatrix
& rCurrTransform(
1141 getTransformation() );
1143 // check all layers for validity, and retain only the live ones
1144 ViewLayerVector::const_iterator
aCurr( maViewLayers
.begin() );
1145 const ViewLayerVector::const_iterator
aEnd( maViewLayers
.end() );
1146 while( aCurr
!= aEnd
)
1148 boost::shared_ptr
< SlideViewLayer
> pCurrLayer( aCurr
->lock() );
1152 aValidLayers
.push_back( pCurrLayer
);
1154 if( bWithViewLayerUpdate
)
1155 pCurrLayer
->updateView( rCurrTransform
,
1162 // replace layer list with pruned one
1163 maViewLayers
.swap( aValidLayers
);
1166 } // anonymous namespace
1168 UnoViewSharedPtr
createSlideView( uno::Reference
< presentation::XSlideShowView
> const& xView
,
1169 EventQueue
& rEventQueue
,
1170 EventMultiplexer
& rEventMultiplexer
)
1172 boost::shared_ptr
<SlideView
> const that(
1173 comphelper::make_shared_from_UNO(
1174 new SlideView(xView
,
1176 rEventMultiplexer
)));
1178 // register listeners with XSlideShowView
1179 xView
->addTransformationChangedListener( that
.get() );
1180 xView
->addPaintListener( that
.get() );
1182 // set new transformation
1183 that
->updateCanvas();
1188 } // namespace internal
1189 } // namespace slideshow
1191 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */