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 .
21 #include <tools/diagnose_ex.h>
22 #include <tools/helpers.hxx>
23 #include <canvas/elapsedtime.hxx>
24 #include <basegfx/polygon/b2dpolygontools.hxx>
26 #include <comphelper/anytostring.hxx>
27 #include <cppuhelper/exc_hlp.hxx>
29 #include <rtl/math.hxx>
30 #include <vcl/metric.hxx>
31 #include <vcl/canvastools.hxx>
32 #include <vcl/metaact.hxx>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/drawing/TextAnimationKind.hpp>
35 #include <com/sun/star/drawing/TextAnimationDirection.hpp>
36 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
37 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
38 #include <com/sun/star/drawing/HomogenMatrix3.hpp>
39 #include <com/sun/star/awt/Rectangle.hpp>
41 #include <activity.hxx>
42 #include <wakeupevent.hxx>
43 #include <eventqueue.hxx>
44 #include "drawinglayeranimation.hxx"
45 #include "drawshapesubsetting.hxx"
46 #include "drawshape.hxx"
47 #include <shapesubset.hxx>
48 #include <shapeattributelayerholder.hxx>
49 #include <slideshowcontext.hxx>
51 #include "gdimtftools.hxx"
52 #include <eventmultiplexer.hxx>
53 #include "intrinsicanimationactivity.hxx"
54 #include <intrinsicanimationeventhandler.hxx>
59 using namespace com::sun::star
;
60 using namespace ::slideshow::internal
;
64 class ScrollTextAnimNode
66 sal_uInt32 mnDuration
; // single duration
67 sal_uInt32 mnRepeat
; // 0 -> endless
70 sal_uInt32 mnFrequency
; // in ms
71 // forth and back change at mnRepeat%2:
76 sal_uInt32 nDuration
, sal_uInt32 nRepeat
, double fStart
, double fStop
,
77 sal_uInt32 nFrequency
, bool bAlternate
)
78 : mnDuration(nDuration
),
82 mnFrequency(nFrequency
),
83 mbAlternate(bAlternate
)
86 sal_uInt32
GetRepeat() const { return mnRepeat
; }
87 sal_uInt32
GetFullTime() const { return mnDuration
* mnRepeat
; }
88 double GetStop() const { return mfStop
; }
89 sal_uInt32
GetFrequency() const { return mnFrequency
; }
90 bool DoAlternate() const { return mbAlternate
; }
92 double GetStateAtRelativeTime(sal_uInt32 nRelativeTime
) const;
95 double ScrollTextAnimNode::GetStateAtRelativeTime(
96 sal_uInt32 nRelativeTime
) const
98 // Avoid division by zero.
105 const sal_uInt32
nRepeatCount(nRelativeTime
/ mnDuration
);
106 sal_uInt32
nFrameTime(nRelativeTime
- (nRepeatCount
* mnDuration
));
108 if(DoAlternate() && (nRepeatCount
+ 1) % 2L)
109 nFrameTime
= mnDuration
- nFrameTime
;
111 return mfStart
+ ((mfStop
- mfStart
) *
112 (double(nFrameTime
) / mnDuration
));
117 sal_uInt32
nFrameTime(nRelativeTime
% mnDuration
);
121 const sal_uInt32
nRepeatCount(nRelativeTime
/ mnDuration
);
123 if((nRepeatCount
+ 1) % 2L)
124 nFrameTime
= mnDuration
- nFrameTime
;
127 return mfStart
+ ((mfStop
- mfStart
) * (double(nFrameTime
) / mnDuration
));
131 class ActivityImpl
: public Activity
135 SlideShowContext
const& rContext
,
136 std::shared_ptr
<WakeupEvent
> const& pWakeupEvent
,
137 std::shared_ptr
<DrawShape
> const& pDrawShape
);
139 ActivityImpl(const ActivityImpl
&) = delete;
140 ActivityImpl
& operator=(const ActivityImpl
&) = delete;
142 bool enableAnimations();
145 virtual void dispose() override
;
147 virtual double calcTimeLag() const override
;
148 virtual bool perform() override
;
149 virtual bool isActive() const override
;
150 virtual void dequeued() override
;
151 virtual void end() override
;
154 void updateShapeAttributes( double fTime
,
155 basegfx::B2DRectangle
const& parentBounds
);
157 // scroll horizontal? if sal_False, scroll is vertical.
158 bool ScrollHorizontal() const {
159 return (drawing::TextAnimationDirection_LEFT
== meDirection
||
160 drawing::TextAnimationDirection_RIGHT
== meDirection
);
163 // Access to StepWidth in logical units
164 sal_uInt32
GetStepWidthLogic() const;
166 // is the animation direction opposite?
167 bool DoScrollForward() const {
168 return (drawing::TextAnimationDirection_RIGHT
== meDirection
||
169 drawing::TextAnimationDirection_DOWN
== meDirection
);
172 // do alternate text directions?
173 bool DoAlternate() const { return mbAlternate
; }
176 bool DoScrollIn() const { return mbScrollIn
; }
178 // Scroll helper methods
179 void ImpForceScrollTextAnimNodes();
180 ScrollTextAnimNode
* ImpGetScrollTextAnimNode(
181 sal_uInt32 nTime
, sal_uInt32
& rRelativeTime
);
182 sal_uInt32
ImpRegisterAgainScrollTextMixerState(
185 // calculate the MixerState value for given time
186 double GetMixerState(sal_uInt32 nTime
);
189 SlideShowContext maContext
;
190 std::shared_ptr
<WakeupEvent
> mpWakeupEvent
;
191 std::weak_ptr
<DrawShape
> mpParentDrawShape
;
192 DrawShapeSharedPtr mpDrawShape
;
193 ShapeAttributeLayerHolder maShapeAttrLayer
;
194 GDIMetaFileSharedPtr mpMetaFile
;
195 IntrinsicAnimationEventHandlerSharedPtr mpListener
;
196 canvas::tools::ElapsedTime maTimer
;
197 double mfRotationAngle
;
198 bool mbIsShapeAnimated
;
201 drawing::TextAnimationKind meAnimKind
;
203 // The blink frequency in ms
204 sal_uInt32 mnFrequency
;
206 // The repeat count, init to 0L which means endless
209 // Flag to decide if text will be shown when animation has ended
210 bool mbVisibleWhenStopped
;
211 bool mbVisibleWhenStarted
;
213 // Flag decides if TextScroll alternates. Default is sal_False.
216 // Flag to remember if this is a simple scrolling text
219 // The AnimationDirection
220 drawing::TextAnimationDirection meDirection
;
222 // Get width per Step. Negative means pixel, positive logical units
223 sal_Int32 mnStepWidth
;
225 // The single anim steps
226 std::vector
< ScrollTextAnimNode
> maVector
;
228 // the scroll rectangle
229 tools::Rectangle maScrollRectangleLogic
;
231 // the paint rectangle
232 tools::Rectangle maPaintRectangleLogic
;
236 class IntrinsicAnimationListener
: public IntrinsicAnimationEventHandler
239 explicit IntrinsicAnimationListener( ActivityImpl
& rActivity
) :
240 mrActivity( rActivity
)
243 IntrinsicAnimationListener(const IntrinsicAnimationListener
&) = delete;
244 IntrinsicAnimationListener
& operator=(const IntrinsicAnimationListener
&) = delete;
248 virtual bool enableAnimations() override
{ return mrActivity
.enableAnimations(); }
249 virtual bool disableAnimations() override
{ mrActivity
.end(); return true; }
251 ActivityImpl
& mrActivity
;
255 double ActivityImpl::GetMixerState( sal_uInt32 nTime
)
257 if( meAnimKind
== drawing::TextAnimationKind_BLINK
)
259 // from AInfoBlinkText:
262 const sal_uInt32
nLoopTime(2 * mnFrequency
);
266 const sal_uInt32
nEndTime(mnRepeat
* nLoopTime
);
268 if(nTime
>= nEndTime
)
270 if(mbVisibleWhenStopped
)
281 sal_uInt32
nTimeInLoop(nTime
% nLoopTime
);
282 fRetval
= double(nTimeInLoop
) / nLoopTime
;
289 // from AInfoScrollText:
291 ImpForceScrollTextAnimNodes();
293 if(!maVector
.empty())
295 sal_uInt32 nRelativeTime
;
296 ScrollTextAnimNode
* pNode
=
297 ImpGetScrollTextAnimNode(nTime
, nRelativeTime
);
302 fRetval
= pNode
->GetStateAtRelativeTime(nRelativeTime
);
306 // end of animation, take last entry's end
307 fRetval
= maVector
[maVector
.size() - 1].GetStop();
315 // Access to StepWidth in logical units
316 sal_uInt32
ActivityImpl::GetStepWidthLogic() const
318 // #i69847# Assuming higher DPI
319 sal_uInt32
const PIXEL_TO_LOGIC
= 30;
321 sal_uInt32
nRetval(0);
325 // is in pixels, convert to logical units
326 nRetval
= (-mnStepWidth
* PIXEL_TO_LOGIC
);
328 else if(mnStepWidth
> 0)
330 // is in logical units
331 nRetval
= mnStepWidth
;
336 // step 1 pixel, canned value
338 // with very high DPIs like in PDF export, this can
339 // still get zero. for that cases, set a default, too (taken
340 // from ainfoscrolltext.cxx)
347 void ActivityImpl::ImpForceScrollTextAnimNodes()
352 sal_uInt32 nLoopTime
;
353 double fZeroLogic
, fOneLogic
, fInitLogic
, fDistanceLogic
;
354 double fZeroLogicAlternate
= 0.0, fOneLogicAlternate
= 0.0;
355 double fZeroRelative
, fOneRelative
, fInitRelative
;
357 if(ScrollHorizontal())
361 if(maPaintRectangleLogic
.GetWidth() >
362 maScrollRectangleLogic
.GetWidth())
364 fZeroLogicAlternate
= maScrollRectangleLogic
.Right() - maPaintRectangleLogic
.GetWidth();
365 fOneLogicAlternate
= maScrollRectangleLogic
.Left();
369 fZeroLogicAlternate
= maScrollRectangleLogic
.Left();
370 fOneLogicAlternate
= maScrollRectangleLogic
.Right() - maPaintRectangleLogic
.GetWidth();
374 fZeroLogic
= maScrollRectangleLogic
.Left() - maPaintRectangleLogic
.GetWidth();
375 fOneLogic
= maScrollRectangleLogic
.Right();
376 fInitLogic
= maPaintRectangleLogic
.Left();
382 if(maPaintRectangleLogic
.GetHeight() > maScrollRectangleLogic
.GetHeight())
384 fZeroLogicAlternate
= maScrollRectangleLogic
.Bottom() - maPaintRectangleLogic
.GetHeight();
385 fOneLogicAlternate
= maScrollRectangleLogic
.Top();
389 fZeroLogicAlternate
= maScrollRectangleLogic
.Top();
390 fOneLogicAlternate
= maScrollRectangleLogic
.Bottom() - maPaintRectangleLogic
.GetHeight();
394 fZeroLogic
= maScrollRectangleLogic
.Top() - maPaintRectangleLogic
.GetHeight();
395 fOneLogic
= maScrollRectangleLogic
.Bottom();
396 fInitLogic
= maPaintRectangleLogic
.Top();
399 fDistanceLogic
= fOneLogic
- fZeroLogic
;
400 fInitRelative
= (fInitLogic
- fZeroLogic
) / fDistanceLogic
;
405 (fZeroLogicAlternate
- fZeroLogic
) / fDistanceLogic
;
407 (fOneLogicAlternate
- fZeroLogic
) / fDistanceLogic
;
415 if(mbVisibleWhenStarted
)
417 double fRelativeStartValue
, fRelativeEndValue
,fRelativeDistance
;
419 if(DoScrollForward())
421 fRelativeStartValue
= fInitRelative
;
422 fRelativeEndValue
= fOneRelative
;
423 fRelativeDistance
= fRelativeEndValue
- fRelativeStartValue
;
427 fRelativeStartValue
= fInitRelative
;
428 fRelativeEndValue
= fZeroRelative
;
429 fRelativeDistance
= fRelativeStartValue
- fRelativeEndValue
;
432 const double fNumberSteps
=
433 (fRelativeDistance
* fDistanceLogic
) / GetStepWidthLogic();
434 nLoopTime
= FRound(fNumberSteps
* mnFrequency
);
437 ScrollTextAnimNode
aInitNode(
439 fRelativeStartValue
, fRelativeEndValue
,
441 maVector
.push_back(aInitNode
);
444 // prepare main loop values
446 double fRelativeStartValue
, fRelativeEndValue
, fRelativeDistance
;
448 if(DoScrollForward())
450 fRelativeStartValue
= fZeroRelative
;
451 fRelativeEndValue
= fOneRelative
;
452 fRelativeDistance
= fRelativeEndValue
- fRelativeStartValue
;
456 fRelativeStartValue
= fOneRelative
;
457 fRelativeEndValue
= fZeroRelative
;
458 fRelativeDistance
= fRelativeStartValue
- fRelativeEndValue
;
461 const double fNumberSteps
=
462 (fRelativeDistance
* fDistanceLogic
) / GetStepWidthLogic();
463 nLoopTime
= FRound(fNumberSteps
* mnFrequency
);
470 ScrollTextAnimNode
aMainNode(
472 fRelativeStartValue
, fRelativeEndValue
,
473 mnFrequency
, DoAlternate());
474 maVector
.push_back(aMainNode
);
479 sal_uInt32
nNumRepeat(mnRepeat
);
481 if(DoAlternate() && (nNumRepeat
+ 1) % 2L)
485 ScrollTextAnimNode
aMainNode(
486 nLoopTime
, nNumRepeat
,
487 fRelativeStartValue
, fRelativeEndValue
,
488 mnFrequency
, DoAlternate());
489 maVector
.push_back(aMainNode
);
493 if(mbVisibleWhenStopped
)
495 double fRelativeStartValue
, fRelativeEndValue
, fRelativeDistance
;
497 if(DoScrollForward())
499 fRelativeStartValue
= fZeroRelative
;
500 fRelativeEndValue
= fInitRelative
;
501 fRelativeDistance
= fRelativeEndValue
- fRelativeStartValue
;
505 fRelativeStartValue
= fOneRelative
;
506 fRelativeEndValue
= fInitRelative
;
507 fRelativeDistance
= fRelativeStartValue
- fRelativeEndValue
;
510 const double fNumberSteps
=
511 (fRelativeDistance
* fDistanceLogic
) / GetStepWidthLogic();
512 nLoopTime
= FRound(fNumberSteps
* mnFrequency
);
515 ScrollTextAnimNode
aExitNode(
517 fRelativeStartValue
, fRelativeEndValue
, mnFrequency
, false);
518 maVector
.push_back(aExitNode
);
523 ScrollTextAnimNode
* ActivityImpl::ImpGetScrollTextAnimNode(
524 sal_uInt32 nTime
, sal_uInt32
& rRelativeTime
)
526 ScrollTextAnimNode
* pRetval
= nullptr;
527 ImpForceScrollTextAnimNodes();
529 if(!maVector
.empty())
531 rRelativeTime
= nTime
;
533 for(ScrollTextAnimNode
& rNode
: maVector
)
535 if(!rNode
.GetRepeat())
537 // endless loop, use it
540 else if(rNode
.GetFullTime() > rRelativeTime
)
548 rRelativeTime
-= rNode
.GetFullTime();
556 sal_uInt32
ActivityImpl::ImpRegisterAgainScrollTextMixerState(sal_uInt32 nTime
)
558 sal_uInt32
nRetval(0);
559 ImpForceScrollTextAnimNodes();
561 if(!maVector
.empty())
563 sal_uInt32 nRelativeTime
;
564 ScrollTextAnimNode
* pNode
= ImpGetScrollTextAnimNode(nTime
, nRelativeTime
);
568 // take register time
569 nRetval
= pNode
->GetFrequency();
574 // #i38135# not initialized, return default
575 nRetval
= mnFrequency
;
581 void ActivityImpl::updateShapeAttributes(
582 double fTime
, basegfx::B2DRectangle
const& parentBounds
)
584 OSL_ASSERT( meAnimKind
!= drawing::TextAnimationKind_NONE
);
585 if( meAnimKind
== drawing::TextAnimationKind_NONE
)
588 double const fMixerState
= GetMixerState(
589 static_cast<sal_uInt32
>(fTime
* 1000.0) );
591 if( meAnimKind
== drawing::TextAnimationKind_BLINK
)
594 maShapeAttrLayer
.get()->setVisibility( fMixerState
< 0.5 );
596 else if(mpMetaFile
) // scroll mode:
599 // keep care: the below code is highly sensible to changes...
602 // rectangle of the pure text:
603 double const fPaintWidth
= maPaintRectangleLogic
.GetWidth();
604 double const fPaintHeight
= maPaintRectangleLogic
.GetHeight();
605 // rectangle where the scrolling takes place (-> clipping):
606 double const fScrollWidth
= maScrollRectangleLogic
.GetWidth();
607 double const fScrollHeight
= maScrollRectangleLogic
.GetHeight();
609 basegfx::B2DPoint pos
, clipPos
;
611 if(ScrollHorizontal())
613 double const fOneEquiv( fScrollWidth
);
614 double const fZeroEquiv( -fPaintWidth
);
616 pos
.setX( fZeroEquiv
+ (fMixerState
* (fOneEquiv
- fZeroEquiv
)) );
618 clipPos
.setX( -pos
.getX() );
619 clipPos
.setY( -pos
.getY() );
621 // #i69844# Compensation for text-wider-than-shape case
622 if( fPaintWidth
> fScrollWidth
)
623 pos
.setX( pos
.getX() + (fPaintWidth
-fScrollWidth
) / 2.0 );
628 double const fOneEquiv( fScrollHeight
);
629 double const fZeroEquiv( -fPaintHeight
);
631 pos
.setY( fZeroEquiv
+ (fMixerState
* (fOneEquiv
- fZeroEquiv
)) );
633 clipPos
.setX( -pos
.getX() );
634 clipPos
.setY( -pos
.getY() );
636 // #i69844# Compensation for text-higher-than-shape case
637 if( fPaintHeight
> fScrollHeight
)
638 pos
.setY( pos
.getY() + (fPaintHeight
-fScrollHeight
) / 2.0 );
641 basegfx::B2DPolygon
clipPoly(
642 basegfx::utils::createPolygonFromRect(
643 basegfx::B2DRectangle( clipPos
.getX(),
645 clipPos
.getX() + fScrollWidth
,
646 clipPos
.getY() + fScrollHeight
) ) );
648 if( !::basegfx::fTools::equalZero( mfRotationAngle
))
650 maShapeAttrLayer
.get()->setRotationAngle( mfRotationAngle
);
651 double const fRotate
= (mfRotationAngle
* M_PI
/ 180.0);
652 basegfx::B2DHomMatrix aTransform
;
654 aTransform
.rotate( fRotate
);
658 pos
+= parentBounds
.getCenter();
659 maShapeAttrLayer
.get()->setPosition( pos
);
660 maShapeAttrLayer
.get()->setClip( basegfx::B2DPolyPolygon(clipPoly
) );
664 bool ActivityImpl::perform()
669 ENSURE_OR_RETURN_FALSE(
671 "ActivityImpl::perform(): still active, but NULL draw shape" );
673 DrawShapeSharedPtr
const pParentDrawShape( mpParentDrawShape
);
674 if( !pParentDrawShape
)
675 return false; // parent has vanished
677 if( pParentDrawShape
->isVisible() )
679 if( !mbIsShapeAnimated
)
681 mpDrawShape
->setVisibility(true); // shape may be initially hidden
682 maContext
.mpSubsettableShapeManager
->enterAnimationMode( mpDrawShape
);
684 mbIsShapeAnimated
= true;
686 // update attributes related to current time:
687 basegfx::B2DRectangle
const parentBounds(
688 pParentDrawShape
->getBounds() );
690 const double nCurrTime( maTimer
.getElapsedTime() );
691 updateShapeAttributes( nCurrTime
, parentBounds
);
693 const sal_uInt32
nFrequency(
694 ImpRegisterAgainScrollTextMixerState(
695 static_cast<sal_uInt32
>(nCurrTime
* 1000.0)) );
699 mpWakeupEvent
->start();
700 mpWakeupEvent
->setNextTimeout(
701 std::max(0.1,nFrequency
/1000.0) );
702 maContext
.mrEventQueue
.addEvent( mpWakeupEvent
);
704 if( mpDrawShape
->isContentChanged() )
705 maContext
.mpSubsettableShapeManager
->notifyShapeUpdate( mpDrawShape
);
707 // else: finished, not need to wake up again.
711 // busy-wait, until parent shape gets visible
712 mpWakeupEvent
->start();
713 mpWakeupEvent
->setNextTimeout( 2.0 );
716 // don't reinsert, WakeupEvent will perform that after the given timeout:
720 ActivityImpl::ActivityImpl(
721 SlideShowContext
const& rContext
,
722 std::shared_ptr
<WakeupEvent
> const& pWakeupEvent
,
723 std::shared_ptr
<DrawShape
> const& pParentDrawShape
)
724 : maContext(rContext
),
725 mpWakeupEvent(pWakeupEvent
),
726 mpParentDrawShape(pParentDrawShape
),
727 mpListener( new IntrinsicAnimationListener(*this) ),
728 maTimer(rContext
.mrEventQueue
.getTimer()),
729 mfRotationAngle(0.0),
730 mbIsShapeAnimated(false),
733 meAnimKind(drawing::TextAnimationKind_NONE
),
734 mbVisibleWhenStopped(false),
735 mbVisibleWhenStarted(false),
739 sal_Int32
const nNodes
= pParentDrawShape
->getNumberOfTreeNodes(
740 DocTreeNode::NodeType::LogicalParagraph
);
742 DocTreeNode
scrollTextNode(
743 pParentDrawShape
->getTreeNode(
744 0, DocTreeNode::NodeType::LogicalParagraph
));
745 // xxx todo: remove this hack
747 scrollTextNode
.setEndIndex(
748 pParentDrawShape
->getTreeNode(
750 DocTreeNode::NodeType::LogicalParagraph
).getEndIndex());
752 // TODO(Q3): Doing this manually, instead of using
753 // ShapeSubset. This is because of lifetime issues (ShapeSubset
754 // generates circular references to parent shape)
755 mpDrawShape
= std::dynamic_pointer_cast
<DrawShape
>(
756 maContext
.mpSubsettableShapeManager
->getSubsetShape(
760 mpMetaFile
= mpDrawShape
->forceScrollTextMetaFile();
762 // make scroll text invisible for slide transition bitmaps
763 mpDrawShape
->setVisibility(false);
765 basegfx::B2DRectangle aScrollRect
, aPaintRect
;
766 ENSURE_OR_THROW( getRectanglesFromScrollMtf( aScrollRect
,
769 "ActivityImpl::ActivityImpl(): Could not extract "
770 "scroll anim rectangles from mtf" );
772 maScrollRectangleLogic
= vcl::unotools::rectangleFromB2DRectangle(
774 maPaintRectangleLogic
= vcl::unotools::rectangleFromB2DRectangle(
777 maShapeAttrLayer
.createAttributeLayer(mpDrawShape
);
779 uno::Reference
<drawing::XShape
> const xShape( mpDrawShape
->getXShape() );
780 uno::Reference
<beans::XPropertySet
> const xProps( xShape
, uno::UNO_QUERY_THROW
);
782 getPropertyValue( meAnimKind
, xProps
, "TextAnimationKind" );
783 OSL_ASSERT( meAnimKind
!= drawing::TextAnimationKind_NONE
);
784 mbAlternate
= (meAnimKind
== drawing::TextAnimationKind_ALTERNATE
);
785 mbScrollIn
= (meAnimKind
== drawing::TextAnimationKind_SLIDE
);
787 // adopted from in AInfoBlinkText::ImplInit():
788 sal_Int16
nRepeat(0);
789 getPropertyValue( nRepeat
, xProps
, "TextAnimationCount" );
794 // force visible when started for scroll-forth-and-back, because
795 // slide has been coming in with visible text in the middle:
796 mbVisibleWhenStarted
= true;
800 getPropertyValue( mbVisibleWhenStarted
, xProps
,
801 "TextAnimationStartInside" );
804 // set visible when stopped
805 getPropertyValue( mbVisibleWhenStopped
, xProps
,
806 "TextAnimatiogonStopInside" );
808 getPropertyValue( mfRotationAngle
, xProps
,
810 mfRotationAngle
/= -100.0; // (switching direction)
814 getPropertyValue( nDelay
, xProps
, "TextAnimationDelay" );
815 // set delay if not automatic
816 mnFrequency
= (nDelay
? nDelay
:
818 meAnimKind
== drawing::TextAnimationKind_BLINK
821 // adopted from in AInfoScrollText::ImplInit():
823 // If it is a simple m_bScrollIn, reset some parameters
826 // most parameters are set correctly from the dialog logic, but
827 // eg VisibleWhenStopped is grayed out and needs to be corrected here.
828 mbVisibleWhenStopped
= true;
829 mbVisibleWhenStarted
= false;
833 // Get animation direction
834 getPropertyValue( meDirection
, xProps
, "TextAnimationDirection" );
836 // Get step width. Negative means pixel, positive logical units
837 getPropertyValue( mnStepWidth
, xProps
, "TextAnimationAmount" );
839 maContext
.mpSubsettableShapeManager
->addIntrinsicAnimationHandler(
843 bool ActivityImpl::enableAnimations()
846 return maContext
.mrActivitiesQueue
.addActivity( std::dynamic_pointer_cast
<Activity
>(shared_from_this()) );
849 void ActivityImpl::dispose()
855 // only remove subset here, since end() is called on slide end
856 // (and we must not spoil the slide preview bitmap with scroll
858 maShapeAttrLayer
.reset();
861 // TODO(Q3): Doing this manually, instead of using
862 // ShapeSubset. This is because of lifetime issues
863 // (ShapeSubset generates circular references to parent
865 DrawShapeSharedPtr
pParent( mpParentDrawShape
.lock() );
867 maContext
.mpSubsettableShapeManager
->revokeSubset(
874 mpParentDrawShape
.reset();
875 mpWakeupEvent
.reset();
879 maContext
.mpSubsettableShapeManager
->removeIntrinsicAnimationHandler(
884 double ActivityImpl::calcTimeLag() const
889 bool ActivityImpl::isActive() const
894 void ActivityImpl::dequeued()
899 void ActivityImpl::end()
904 if( mbIsShapeAnimated
)
906 maContext
.mpSubsettableShapeManager
->leaveAnimationMode( mpDrawShape
);
907 mbIsShapeAnimated
= false;
913 namespace slideshow
{
916 std::shared_ptr
<Activity
> createDrawingLayerAnimActivity(
917 SlideShowContext
const& rContext
,
918 std::shared_ptr
<DrawShape
> const& pDrawShape
)
920 std::shared_ptr
<Activity
> pActivity
;
924 std::shared_ptr
<WakeupEvent
> const pWakeupEvent(
925 new WakeupEvent( rContext
.mrEventQueue
.getTimer(),
926 rContext
.mrActivitiesQueue
) );
927 pActivity
.reset( new ActivityImpl( rContext
, pWakeupEvent
, pDrawShape
) );
928 pWakeupEvent
->setActivity( pActivity
);
930 catch( uno::RuntimeException
& )
934 catch( uno::Exception
& )
936 // translate any error into empty factory product.
937 SAL_WARN( "slideshow", comphelper::anyToString( cppu::getCaughtException() ) );
943 } // namespace internal
944 } // namespace presentation
946 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */