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 <comphelper/diagnose_ex.hxx>
22 #include <tools/gen.hxx>
23 #include <tools/helpers.hxx>
24 #include <canvas/elapsedtime.hxx>
25 #include <basegfx/polygon/b2dpolygontools.hxx>
28 #include <vcl/canvastools.hxx>
29 #include <com/sun/star/beans/XPropertySet.hpp>
30 #include <com/sun/star/drawing/TextAnimationKind.hpp>
31 #include <com/sun/star/drawing/TextAnimationDirection.hpp>
33 #include <activity.hxx>
34 #include <wakeupevent.hxx>
35 #include <eventqueue.hxx>
36 #include "drawinglayeranimation.hxx"
37 #include "drawshapesubsetting.hxx"
38 #include "drawshape.hxx"
39 #include <shapeattributelayerholder.hxx>
40 #include <slideshowcontext.hxx>
41 #include <subsettableshapemanager.hxx>
43 #include "gdimtftools.hxx"
44 #include <intrinsicanimationeventhandler.hxx>
49 using namespace com::sun::star
;
50 using namespace ::slideshow::internal
;
54 class ScrollTextAnimNode
56 sal_uInt32 mnDuration
; // single duration
57 sal_uInt32 mnRepeat
; // 0 -> endless
60 sal_uInt32 mnFrequency
; // in ms
61 // forth and back change at mnRepeat%2:
66 sal_uInt32 nDuration
, sal_uInt32 nRepeat
, double fStart
, double fStop
,
67 sal_uInt32 nFrequency
, bool bAlternate
)
68 : mnDuration(nDuration
),
72 mnFrequency(nFrequency
),
73 mbAlternate(bAlternate
)
76 sal_uInt32
GetRepeat() const { return mnRepeat
; }
77 sal_uInt32
GetFullTime() const { return mnDuration
* mnRepeat
; }
78 double GetStop() const { return mfStop
; }
79 sal_uInt32
GetFrequency() const { return mnFrequency
; }
80 bool DoAlternate() const { return mbAlternate
; }
82 double GetStateAtRelativeTime(sal_uInt32 nRelativeTime
) const;
85 double ScrollTextAnimNode::GetStateAtRelativeTime(
86 sal_uInt32 nRelativeTime
) const
88 // Avoid division by zero.
95 const sal_uInt32
nRepeatCount(nRelativeTime
/ mnDuration
);
96 sal_uInt32
nFrameTime(nRelativeTime
- (nRepeatCount
* mnDuration
));
98 if(DoAlternate() && (nRepeatCount
+ 1) % 2L)
99 nFrameTime
= mnDuration
- nFrameTime
;
101 return mfStart
+ ((mfStop
- mfStart
) *
102 (double(nFrameTime
) / mnDuration
));
107 sal_uInt32
nFrameTime(nRelativeTime
% mnDuration
);
111 const sal_uInt32
nRepeatCount(nRelativeTime
/ mnDuration
);
113 if((nRepeatCount
+ 1) % 2L)
114 nFrameTime
= mnDuration
- nFrameTime
;
117 return mfStart
+ ((mfStop
- mfStart
) * (double(nFrameTime
) / mnDuration
));
121 class ActivityImpl
: public Activity
125 SlideShowContext
const& rContext
,
126 std::shared_ptr
<WakeupEvent
> pWakeupEvent
,
127 std::shared_ptr
<DrawShape
> const& pDrawShape
);
129 ActivityImpl(const ActivityImpl
&) = delete;
130 ActivityImpl
& operator=(const ActivityImpl
&) = delete;
132 bool enableAnimations();
135 virtual void dispose() override
;
137 virtual double calcTimeLag() const override
;
138 virtual bool perform() override
;
139 virtual bool isActive() const override
;
140 virtual void dequeued() override
;
141 virtual void end() override
;
144 void updateShapeAttributes( double fTime
,
145 basegfx::B2DRectangle
const& parentBounds
);
147 // scroll horizontal? if sal_False, scroll is vertical.
148 bool ScrollHorizontal() const {
149 return (drawing::TextAnimationDirection_LEFT
== meDirection
||
150 drawing::TextAnimationDirection_RIGHT
== meDirection
);
153 // Access to StepWidth in logical units
154 sal_uInt32
GetStepWidthLogic() const;
156 // is the animation direction opposite?
157 bool DoScrollForward() const {
158 return (drawing::TextAnimationDirection_RIGHT
== meDirection
||
159 drawing::TextAnimationDirection_DOWN
== meDirection
);
162 // do alternate text directions?
163 bool DoAlternate() const { return mbAlternate
; }
166 bool DoScrollIn() const { return mbScrollIn
; }
168 // Scroll helper methods
169 void ImpForceScrollTextAnimNodes();
170 ScrollTextAnimNode
* ImpGetScrollTextAnimNode(
171 sal_uInt32 nTime
, sal_uInt32
& rRelativeTime
);
172 sal_uInt32
ImpRegisterAgainScrollTextMixerState(
175 // calculate the MixerState value for given time
176 double GetMixerState(sal_uInt32 nTime
);
179 SlideShowContext maContext
;
180 std::shared_ptr
<WakeupEvent
> mpWakeupEvent
;
181 std::weak_ptr
<DrawShape
> mpParentDrawShape
;
182 DrawShapeSharedPtr mpDrawShape
;
183 ShapeAttributeLayerHolder maShapeAttrLayer
;
184 GDIMetaFileSharedPtr mpMetaFile
;
185 IntrinsicAnimationEventHandlerSharedPtr mpListener
;
186 canvas::tools::ElapsedTime maTimer
;
187 double mfRotationAngle
;
188 bool mbIsShapeAnimated
;
191 drawing::TextAnimationKind meAnimKind
;
193 // The blink frequency in ms
194 sal_uInt32 mnFrequency
;
196 // The repeat count, init to 0L which means endless
199 // Flag to decide if text will be shown when animation has ended
200 bool mbVisibleWhenStopped
;
201 bool mbVisibleWhenStarted
;
203 // Flag decides if TextScroll alternates. Default is sal_False.
206 // Flag to remember if this is a simple scrolling text
209 // The AnimationDirection
210 drawing::TextAnimationDirection meDirection
;
212 // Get width per Step. Negative means pixel, positive logical units
213 sal_Int32 mnStepWidth
;
215 // The single anim steps
216 std::vector
< ScrollTextAnimNode
> maVector
;
218 // the scroll rectangle
219 tools::Rectangle maScrollRectangleLogic
;
221 // the paint rectangle
222 tools::Rectangle maPaintRectangleLogic
;
226 class IntrinsicAnimationListener
: public IntrinsicAnimationEventHandler
229 explicit IntrinsicAnimationListener( ActivityImpl
& rActivity
) :
230 mrActivity( rActivity
)
233 IntrinsicAnimationListener(const IntrinsicAnimationListener
&) = delete;
234 IntrinsicAnimationListener
& operator=(const IntrinsicAnimationListener
&) = delete;
238 virtual bool enableAnimations() override
{ return mrActivity
.enableAnimations(); }
239 virtual bool disableAnimations() override
{ mrActivity
.end(); return true; }
241 ActivityImpl
& mrActivity
;
245 double ActivityImpl::GetMixerState( sal_uInt32 nTime
)
247 if( meAnimKind
== drawing::TextAnimationKind_BLINK
)
249 // from AInfoBlinkText:
252 const sal_uInt32
nLoopTime(2 * mnFrequency
);
256 const sal_uInt32
nEndTime(mnRepeat
* nLoopTime
);
258 if(nTime
>= nEndTime
)
260 if(mbVisibleWhenStopped
)
271 sal_uInt32
nTimeInLoop(nTime
% nLoopTime
);
272 fRetval
= double(nTimeInLoop
) / nLoopTime
;
279 // from AInfoScrollText:
281 ImpForceScrollTextAnimNodes();
283 if(!maVector
.empty())
285 sal_uInt32 nRelativeTime
;
286 ScrollTextAnimNode
* pNode
=
287 ImpGetScrollTextAnimNode(nTime
, nRelativeTime
);
292 fRetval
= pNode
->GetStateAtRelativeTime(nRelativeTime
);
296 // end of animation, take last entry's end
297 fRetval
= maVector
[maVector
.size() - 1].GetStop();
305 // Access to StepWidth in logical units
306 sal_uInt32
ActivityImpl::GetStepWidthLogic() const
308 // #i69847# Assuming higher DPI
309 constexpr sal_uInt32 PIXEL_TO_LOGIC
= 30;
311 sal_uInt32
nRetval(0);
315 // is in pixels, convert to logical units
316 nRetval
= (-mnStepWidth
* PIXEL_TO_LOGIC
);
318 else if(mnStepWidth
> 0)
320 // is in logical units
321 nRetval
= mnStepWidth
;
326 // step 1 pixel, canned value
328 // with very high DPIs like in PDF export, this can
329 // still get zero. for that cases, set a default, too (taken
330 // from ainfoscrolltext.cxx)
337 void ActivityImpl::ImpForceScrollTextAnimNodes()
339 if(!maVector
.empty())
343 sal_uInt32 nLoopTime
;
344 double fZeroLogic
, fOneLogic
, fInitLogic
, fDistanceLogic
;
345 double fZeroLogicAlternate
= 0.0, fOneLogicAlternate
= 0.0;
346 double fZeroRelative
, fOneRelative
, fInitRelative
;
348 if(ScrollHorizontal())
352 if(maPaintRectangleLogic
.GetWidth() >
353 maScrollRectangleLogic
.GetWidth())
355 fZeroLogicAlternate
= maScrollRectangleLogic
.Right() - maPaintRectangleLogic
.GetWidth();
356 fOneLogicAlternate
= maScrollRectangleLogic
.Left();
360 fZeroLogicAlternate
= maScrollRectangleLogic
.Left();
361 fOneLogicAlternate
= maScrollRectangleLogic
.Right() - maPaintRectangleLogic
.GetWidth();
365 fZeroLogic
= maScrollRectangleLogic
.Left() - maPaintRectangleLogic
.GetWidth();
366 fOneLogic
= maScrollRectangleLogic
.Right();
367 fInitLogic
= maPaintRectangleLogic
.Left();
373 if(maPaintRectangleLogic
.GetHeight() > maScrollRectangleLogic
.GetHeight())
375 fZeroLogicAlternate
= maScrollRectangleLogic
.Bottom() - maPaintRectangleLogic
.GetHeight();
376 fOneLogicAlternate
= maScrollRectangleLogic
.Top();
380 fZeroLogicAlternate
= maScrollRectangleLogic
.Top();
381 fOneLogicAlternate
= maScrollRectangleLogic
.Bottom() - maPaintRectangleLogic
.GetHeight();
385 fZeroLogic
= maScrollRectangleLogic
.Top() - maPaintRectangleLogic
.GetHeight();
386 fOneLogic
= maScrollRectangleLogic
.Bottom();
387 fInitLogic
= maPaintRectangleLogic
.Top();
390 fDistanceLogic
= fOneLogic
- fZeroLogic
;
391 fInitRelative
= (fInitLogic
- fZeroLogic
) / fDistanceLogic
;
396 (fZeroLogicAlternate
- fZeroLogic
) / fDistanceLogic
;
398 (fOneLogicAlternate
- fZeroLogic
) / fDistanceLogic
;
406 if(mbVisibleWhenStarted
)
408 double fRelativeStartValue
, fRelativeEndValue
,fRelativeDistance
;
410 if(DoScrollForward())
412 fRelativeStartValue
= fInitRelative
;
413 fRelativeEndValue
= fOneRelative
;
414 fRelativeDistance
= fRelativeEndValue
- fRelativeStartValue
;
418 fRelativeStartValue
= fInitRelative
;
419 fRelativeEndValue
= fZeroRelative
;
420 fRelativeDistance
= fRelativeStartValue
- fRelativeEndValue
;
423 const double fNumberSteps
=
424 (fRelativeDistance
* fDistanceLogic
) / GetStepWidthLogic();
425 nLoopTime
= basegfx::fround
<sal_uInt32
>(fNumberSteps
* mnFrequency
);
428 ScrollTextAnimNode
aInitNode(
430 fRelativeStartValue
, fRelativeEndValue
,
432 maVector
.push_back(aInitNode
);
435 // prepare main loop values
437 double fRelativeStartValue
, fRelativeEndValue
, fRelativeDistance
;
439 if(DoScrollForward())
441 fRelativeStartValue
= fZeroRelative
;
442 fRelativeEndValue
= fOneRelative
;
443 fRelativeDistance
= fRelativeEndValue
- fRelativeStartValue
;
447 fRelativeStartValue
= fOneRelative
;
448 fRelativeEndValue
= fZeroRelative
;
449 fRelativeDistance
= fRelativeStartValue
- fRelativeEndValue
;
452 const double fNumberSteps
=
453 (fRelativeDistance
* fDistanceLogic
) / GetStepWidthLogic();
454 nLoopTime
= basegfx::fround
<sal_uInt32
>(fNumberSteps
* mnFrequency
);
461 ScrollTextAnimNode
aMainNode(
463 fRelativeStartValue
, fRelativeEndValue
,
464 mnFrequency
, DoAlternate());
465 maVector
.push_back(aMainNode
);
470 sal_uInt32
nNumRepeat(mnRepeat
);
472 if(DoAlternate() && (nNumRepeat
+ 1) % 2L)
476 ScrollTextAnimNode
aMainNode(
477 nLoopTime
, nNumRepeat
,
478 fRelativeStartValue
, fRelativeEndValue
,
479 mnFrequency
, DoAlternate());
480 maVector
.push_back(aMainNode
);
484 if(!mbVisibleWhenStopped
)
487 double fRelativeStartValue
, fRelativeEndValue
, fRelativeDistance
;
489 if(DoScrollForward())
491 fRelativeStartValue
= fZeroRelative
;
492 fRelativeEndValue
= fInitRelative
;
493 fRelativeDistance
= fRelativeEndValue
- fRelativeStartValue
;
497 fRelativeStartValue
= fOneRelative
;
498 fRelativeEndValue
= fInitRelative
;
499 fRelativeDistance
= fRelativeStartValue
- fRelativeEndValue
;
502 const double fNumberSteps
=
503 (fRelativeDistance
* fDistanceLogic
) / GetStepWidthLogic();
504 nLoopTime
= basegfx::fround
<sal_uInt32
>(fNumberSteps
* mnFrequency
);
507 ScrollTextAnimNode
aExitNode(
509 fRelativeStartValue
, fRelativeEndValue
, mnFrequency
, false);
510 maVector
.push_back(aExitNode
);
513 ScrollTextAnimNode
* ActivityImpl::ImpGetScrollTextAnimNode(
514 sal_uInt32 nTime
, sal_uInt32
& rRelativeTime
)
516 ScrollTextAnimNode
* pRetval
= nullptr;
517 ImpForceScrollTextAnimNodes();
519 if(!maVector
.empty())
521 rRelativeTime
= nTime
;
523 for(ScrollTextAnimNode
& rNode
: maVector
)
525 if(!rNode
.GetRepeat())
527 // endless loop, use it
530 else if(rNode
.GetFullTime() > rRelativeTime
)
538 rRelativeTime
-= rNode
.GetFullTime();
546 sal_uInt32
ActivityImpl::ImpRegisterAgainScrollTextMixerState(sal_uInt32 nTime
)
548 sal_uInt32
nRetval(0);
549 ImpForceScrollTextAnimNodes();
551 if(!maVector
.empty())
553 sal_uInt32 nRelativeTime
;
554 ScrollTextAnimNode
* pNode
= ImpGetScrollTextAnimNode(nTime
, nRelativeTime
);
558 // take register time
559 nRetval
= pNode
->GetFrequency();
564 // #i38135# not initialized, return default
565 nRetval
= mnFrequency
;
571 void ActivityImpl::updateShapeAttributes(
572 double fTime
, basegfx::B2DRectangle
const& parentBounds
)
574 OSL_ASSERT( meAnimKind
!= drawing::TextAnimationKind_NONE
);
575 if( meAnimKind
== drawing::TextAnimationKind_NONE
)
578 double const fMixerState
= GetMixerState(
579 static_cast<sal_uInt32
>(fTime
* 1000.0) );
581 if( meAnimKind
== drawing::TextAnimationKind_BLINK
)
584 maShapeAttrLayer
.get()->setVisibility( fMixerState
< 0.5 );
586 else if(mpMetaFile
) // scroll mode:
589 // keep care: the below code is highly sensible to changes...
592 // rectangle of the pure text:
593 double const fPaintWidth
= maPaintRectangleLogic
.GetWidth();
594 double const fPaintHeight
= maPaintRectangleLogic
.GetHeight();
595 // rectangle where the scrolling takes place (-> clipping):
596 double const fScrollWidth
= maScrollRectangleLogic
.GetWidth();
597 double const fScrollHeight
= maScrollRectangleLogic
.GetHeight();
599 basegfx::B2DPoint pos
, clipPos
;
601 if(ScrollHorizontal())
603 double const fOneEquiv( fScrollWidth
);
604 double const fZeroEquiv( -fPaintWidth
);
606 pos
.setX( fZeroEquiv
+ (fMixerState
* (fOneEquiv
- fZeroEquiv
)) );
608 clipPos
.setX( -pos
.getX() );
609 clipPos
.setY( -pos
.getY() );
611 // #i69844# Compensation for text-wider-than-shape case
612 if( fPaintWidth
> fScrollWidth
)
613 pos
.setX( pos
.getX() + (fPaintWidth
-fScrollWidth
) / 2.0 );
618 double const fOneEquiv( fScrollHeight
);
619 double const fZeroEquiv( -fPaintHeight
);
621 pos
.setY( fZeroEquiv
+ (fMixerState
* (fOneEquiv
- fZeroEquiv
)) );
623 clipPos
.setX( -pos
.getX() );
624 clipPos
.setY( -pos
.getY() );
626 // #i69844# Compensation for text-higher-than-shape case
627 if( fPaintHeight
> fScrollHeight
)
628 pos
.setY( pos
.getY() + (fPaintHeight
-fScrollHeight
) / 2.0 );
631 basegfx::B2DPolygon
clipPoly(
632 basegfx::utils::createPolygonFromRect(
633 basegfx::B2DRectangle( clipPos
.getX(),
635 clipPos
.getX() + fScrollWidth
,
636 clipPos
.getY() + fScrollHeight
) ) );
638 if( !::basegfx::fTools::equalZero( mfRotationAngle
))
640 maShapeAttrLayer
.get()->setRotationAngle( mfRotationAngle
);
641 double const fRotate
= basegfx::deg2rad(mfRotationAngle
);
642 basegfx::B2DHomMatrix aTransform
;
644 aTransform
.rotate( fRotate
);
648 pos
+= parentBounds
.getCenter();
649 maShapeAttrLayer
.get()->setPosition( pos
);
650 maShapeAttrLayer
.get()->setClip( basegfx::B2DPolyPolygon(clipPoly
) );
654 bool ActivityImpl::perform()
659 ENSURE_OR_RETURN_FALSE(
661 "ActivityImpl::perform(): still active, but NULL draw shape" );
663 DrawShapeSharedPtr
const pParentDrawShape( mpParentDrawShape
);
664 if( !pParentDrawShape
)
665 return false; // parent has vanished
667 if( pParentDrawShape
->isVisible() )
669 if( !mbIsShapeAnimated
)
671 mpDrawShape
->setVisibility(true); // shape may be initially hidden
672 maContext
.mpSubsettableShapeManager
->enterAnimationMode( mpDrawShape
);
674 mbIsShapeAnimated
= true;
676 // update attributes related to current time:
677 basegfx::B2DRectangle
const parentBounds(
678 pParentDrawShape
->getBounds() );
680 const double nCurrTime( maTimer
.getElapsedTime() );
681 updateShapeAttributes( nCurrTime
, parentBounds
);
683 const sal_uInt32
nFrequency(
684 ImpRegisterAgainScrollTextMixerState(
685 static_cast<sal_uInt32
>(nCurrTime
* 1000.0)) );
689 mpWakeupEvent
->start();
690 mpWakeupEvent
->setNextTimeout(
691 std::max(0.1,nFrequency
/1000.0) );
692 maContext
.mrEventQueue
.addEvent( mpWakeupEvent
);
694 if( mpDrawShape
->isContentChanged() )
695 maContext
.mpSubsettableShapeManager
->notifyShapeUpdate( mpDrawShape
);
697 // else: finished, not need to wake up again.
701 // busy-wait, until parent shape gets visible
702 mpWakeupEvent
->start();
703 mpWakeupEvent
->setNextTimeout( 2.0 );
706 // don't reinsert, WakeupEvent will perform that after the given timeout:
710 ActivityImpl::ActivityImpl(
711 SlideShowContext
const& rContext
,
712 std::shared_ptr
<WakeupEvent
> pWakeupEvent
,
713 std::shared_ptr
<DrawShape
> const& pParentDrawShape
)
714 : maContext(rContext
),
715 mpWakeupEvent(std::move(pWakeupEvent
)),
716 mpParentDrawShape(pParentDrawShape
),
717 mpListener( std::make_shared
<IntrinsicAnimationListener
>(*this) ),
718 maTimer(rContext
.mrEventQueue
.getTimer()),
719 mfRotationAngle(0.0),
720 mbIsShapeAnimated(false),
723 meAnimKind(drawing::TextAnimationKind_NONE
),
724 mbVisibleWhenStopped(false),
725 mbVisibleWhenStarted(false),
729 sal_Int32
const nNodes
= pParentDrawShape
->getNumberOfTreeNodes(
730 DocTreeNode::NodeType::LogicalParagraph
);
732 DocTreeNode
scrollTextNode(
733 pParentDrawShape
->getTreeNode(
734 0, DocTreeNode::NodeType::LogicalParagraph
));
735 // xxx todo: remove this hack
737 scrollTextNode
.setEndIndex(
738 pParentDrawShape
->getTreeNode(
740 DocTreeNode::NodeType::LogicalParagraph
).getEndIndex());
742 // TODO(Q3): Doing this manually, instead of using
743 // ShapeSubset. This is because of lifetime issues (ShapeSubset
744 // generates circular references to parent shape)
745 mpDrawShape
= std::dynamic_pointer_cast
<DrawShape
>(
746 maContext
.mpSubsettableShapeManager
->getSubsetShape(
750 mpMetaFile
= mpDrawShape
->forceScrollTextMetaFile();
752 // make scroll text invisible for slide transition bitmaps
753 mpDrawShape
->setVisibility(false);
755 basegfx::B2DRectangle aScrollRect
, aPaintRect
;
756 ENSURE_OR_THROW( getRectanglesFromScrollMtf( aScrollRect
,
759 "ActivityImpl::ActivityImpl(): Could not extract "
760 "scroll anim rectangles from mtf" );
762 maScrollRectangleLogic
= vcl::unotools::rectangleFromB2DRectangle(
764 maPaintRectangleLogic
= vcl::unotools::rectangleFromB2DRectangle(
767 maShapeAttrLayer
.createAttributeLayer(mpDrawShape
);
769 uno::Reference
<drawing::XShape
> const xShape( mpDrawShape
->getXShape() );
770 uno::Reference
<beans::XPropertySet
> const xProps( xShape
, uno::UNO_QUERY_THROW
);
772 getPropertyValue( meAnimKind
, xProps
, u
"TextAnimationKind"_ustr
);
773 OSL_ASSERT( meAnimKind
!= drawing::TextAnimationKind_NONE
);
774 mbAlternate
= (meAnimKind
== drawing::TextAnimationKind_ALTERNATE
);
775 mbScrollIn
= (meAnimKind
== drawing::TextAnimationKind_SLIDE
);
777 // adopted from in AInfoBlinkText::ImplInit():
778 sal_Int16
nRepeat(0);
779 getPropertyValue( nRepeat
, xProps
, u
"TextAnimationCount"_ustr
);
784 // force visible when started for scroll-forth-and-back, because
785 // slide has been coming in with visible text in the middle:
786 mbVisibleWhenStarted
= true;
790 getPropertyValue( mbVisibleWhenStarted
, xProps
,
791 u
"TextAnimationStartInside"_ustr
);
794 // set visible when stopped
795 getPropertyValue( mbVisibleWhenStopped
, xProps
,
796 u
"TextAnimatiogonStopInside"_ustr
);
798 getPropertyValue( mfRotationAngle
, xProps
,
799 u
"RotateAngle"_ustr
);
800 mfRotationAngle
/= -100.0; // (switching direction)
804 getPropertyValue( nDelay
, xProps
, u
"TextAnimationDelay"_ustr
);
805 // set delay if not automatic
806 mnFrequency
= (nDelay
? nDelay
:
808 meAnimKind
== drawing::TextAnimationKind_BLINK
811 // adopted from in AInfoScrollText::ImplInit():
813 // If it is a simple m_bScrollIn, reset some parameters
816 // most parameters are set correctly from the dialog logic, but
817 // eg VisibleWhenStopped is grayed out and needs to be corrected here.
818 mbVisibleWhenStopped
= true;
819 mbVisibleWhenStarted
= false;
823 // Get animation direction
824 getPropertyValue( meDirection
, xProps
, u
"TextAnimationDirection"_ustr
);
826 // Get step width. Negative means pixel, positive logical units
827 getPropertyValue( mnStepWidth
, xProps
, u
"TextAnimationAmount"_ustr
);
829 maContext
.mpSubsettableShapeManager
->addIntrinsicAnimationHandler(
833 bool ActivityImpl::enableAnimations()
836 return maContext
.mrActivitiesQueue
.addActivity( std::dynamic_pointer_cast
<Activity
>(shared_from_this()) );
839 void ActivityImpl::dispose()
846 // only remove subset here, since end() is called on slide end
847 // (and we must not spoil the slide preview bitmap with scroll
849 maShapeAttrLayer
.reset();
852 // TODO(Q3): Doing this manually, instead of using
853 // ShapeSubset. This is because of lifetime issues
854 // (ShapeSubset generates circular references to parent
856 DrawShapeSharedPtr
pParent( mpParentDrawShape
.lock() );
858 maContext
.mpSubsettableShapeManager
->revokeSubset(
865 mpParentDrawShape
.reset();
866 mpWakeupEvent
.reset();
870 maContext
.mpSubsettableShapeManager
->removeIntrinsicAnimationHandler(
874 double ActivityImpl::calcTimeLag() const
879 bool ActivityImpl::isActive() const
884 void ActivityImpl::dequeued()
889 void ActivityImpl::end()
894 if( mbIsShapeAnimated
)
896 maContext
.mpSubsettableShapeManager
->leaveAnimationMode( mpDrawShape
);
897 mbIsShapeAnimated
= false;
903 namespace slideshow::internal
{
905 std::shared_ptr
<Activity
> createDrawingLayerAnimActivity(
906 SlideShowContext
const& rContext
,
907 std::shared_ptr
<DrawShape
> const& pDrawShape
)
909 std::shared_ptr
<Activity
> pActivity
;
913 auto const pWakeupEvent
= std::make_shared
<WakeupEvent
>( rContext
.mrEventQueue
.getTimer(),
914 rContext
.mrActivitiesQueue
);
915 pActivity
= std::make_shared
<ActivityImpl
>( rContext
, pWakeupEvent
, pDrawShape
);
916 pWakeupEvent
->setActivity( pActivity
);
918 catch( uno::RuntimeException
& )
922 catch( uno::Exception
& )
924 // translate any error into empty factory product.
925 TOOLS_WARN_EXCEPTION( "slideshow", "" );
931 } // namespace presentation
933 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */