29#include <com/sun/star/beans/XPropertySet.hpp>
30#include <com/sun/star/drawing/TextAnimationKind.hpp>
31#include <com/sun/star/drawing/TextAnimationDirection.hpp>
54class ScrollTextAnimNode
56 sal_uInt32 mnDuration;
60 sal_uInt32 mnFrequency;
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;
85double ScrollTextAnimNode::GetStateAtRelativeTime(
86 sal_uInt32 nRelativeTime)
const
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));
121class 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,
148 bool ScrollHorizontal()
const {
149 return (drawing::TextAnimationDirection_LEFT == meDirection ||
150 drawing::TextAnimationDirection_RIGHT == meDirection);
154 sal_uInt32 GetStepWidthLogic()
const;
157 bool DoScrollForward()
const {
158 return (drawing::TextAnimationDirection_RIGHT == meDirection ||
159 drawing::TextAnimationDirection_DOWN == meDirection);
163 bool DoAlternate()
const {
return mbAlternate; }
166 bool DoScrollIn()
const {
return mbScrollIn; }
169 void ImpForceScrollTextAnimNodes();
170 ScrollTextAnimNode* ImpGetScrollTextAnimNode(
171 sal_uInt32 nTime, sal_uInt32& rRelativeTime );
172 sal_uInt32 ImpRegisterAgainScrollTextMixerState(
176 double GetMixerState(sal_uInt32 nTime);
181 std::weak_ptr<DrawShape> mpParentDrawShape;
183 ShapeAttributeLayerHolder maShapeAttrLayer;
187 double mfRotationAngle;
188 bool mbIsShapeAnimated;
191 drawing::TextAnimationKind meAnimKind;
194 sal_uInt32 mnFrequency;
200 bool mbVisibleWhenStopped;
201 bool mbVisibleWhenStarted;
210 drawing::TextAnimationDirection meDirection;
213 sal_Int32 mnStepWidth;
216 std::vector< ScrollTextAnimNode > maVector;
226class IntrinsicAnimationListener :
public IntrinsicAnimationEventHandler
229 explicit IntrinsicAnimationListener( ActivityImpl& 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; }
245double ActivityImpl::GetMixerState( sal_uInt32 nTime )
247 if( meAnimKind == drawing::TextAnimationKind_BLINK )
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;
281 ImpForceScrollTextAnimNodes();
283 if(!maVector.empty())
285 sal_uInt32 nRelativeTime;
286 ScrollTextAnimNode* pNode =
287 ImpGetScrollTextAnimNode(nTime, nRelativeTime);
292 fRetval = pNode->GetStateAtRelativeTime(nRelativeTime);
297 fRetval = maVector[maVector.size() - 1].GetStop();
306sal_uInt32 ActivityImpl::GetStepWidthLogic()
const
309 constexpr sal_uInt32 PIXEL_TO_LOGIC = 30;
311 sal_uInt32 nRetval(0);
316 nRetval = (-mnStepWidth * PIXEL_TO_LOGIC);
318 else if(mnStepWidth > 0)
321 nRetval = mnStepWidth;
337void 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 =
FRound(fNumberSteps * mnFrequency);
428 ScrollTextAnimNode aInitNode(
430 fRelativeStartValue, fRelativeEndValue,
432 maVector.push_back(aInitNode);
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 =
FRound(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 =
FRound(fNumberSteps * mnFrequency);
507 ScrollTextAnimNode aExitNode(
509 fRelativeStartValue, fRelativeEndValue, mnFrequency,
false);
510 maVector.push_back(aExitNode);
513ScrollTextAnimNode* 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())
530 else if(rNode.GetFullTime() > rRelativeTime)
538 rRelativeTime -= rNode.GetFullTime();
546sal_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);
559 nRetval = pNode->GetFrequency();
565 nRetval = mnFrequency;
571void ActivityImpl::updateShapeAttributes(
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 );
593 double const fPaintWidth = maPaintRectangleLogic.GetWidth();
594 double const fPaintHeight = maPaintRectangleLogic.GetHeight();
596 double const fScrollWidth = maScrollRectangleLogic.GetWidth();
597 double const fScrollHeight = maScrollRectangleLogic.GetHeight();
601 if(ScrollHorizontal())
603 double const fOneEquiv( fScrollWidth );
604 double const fZeroEquiv( -fPaintWidth );
606 pos.setX( fZeroEquiv + (fMixerState * (fOneEquiv - fZeroEquiv)) );
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)) );
627 if( fPaintHeight > fScrollHeight )
628 pos.setY(
pos.getY() + (fPaintHeight-fScrollHeight) / 2.0 );
635 clipPos.
getX() + fScrollWidth,
636 clipPos.
getY() + fScrollHeight ) ) );
638 if( !::basegfx::fTools::equalZero( mfRotationAngle ))
640 maShapeAttrLayer.get()->setRotationAngle( mfRotationAngle );
644 aTransform.
rotate( fRotate );
649 maShapeAttrLayer.
get()->setPosition( pos );
654bool ActivityImpl::perform()
661 "ActivityImpl::perform(): still active, but NULL draw shape" );
664 if( !pParentDrawShape )
667 if( pParentDrawShape->isVisible() )
669 if( !mbIsShapeAnimated )
674 mbIsShapeAnimated =
true;
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)) );
691 std::max(0.1,nFrequency/1000.0) );
710ActivityImpl::ActivityImpl(
711 SlideShowContext
const& rContext,
712 std::shared_ptr<WakeupEvent> pWakeupEvent,
713 std::shared_ptr<DrawShape>
const& pParentDrawShape )
716 mpParentDrawShape(pParentDrawShape),
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 ));
737 scrollTextNode.setEndIndex(
738 pParentDrawShape->getTreeNode(
740 DocTreeNode::NodeType::LogicalParagraph ).getEndIndex());
745 mpDrawShape = std::dynamic_pointer_cast<DrawShape>(
746 maContext.mpSubsettableShapeManager->getSubsetShape(
750 mpMetaFile =
mpDrawShape->forceScrollTextMetaFile();
759 "ActivityImpl::ActivityImpl(): Could not extract "
760 "scroll anim rectangles from mtf" );
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 );
773 OSL_ASSERT( meAnimKind != drawing::TextAnimationKind_NONE );
774 mbAlternate = (meAnimKind == drawing::TextAnimationKind_ALTERNATE);
775 mbScrollIn = (meAnimKind == drawing::TextAnimationKind_SLIDE);
778 sal_Int16 nRepeat(0);
786 mbVisibleWhenStarted =
true;
791 "TextAnimationStartInside" );
796 "TextAnimatiogonStopInside" );
800 mfRotationAngle /= -100.0;
806 mnFrequency = (nDelay ? nDelay :
808 meAnimKind == drawing::TextAnimationKind_BLINK
818 mbVisibleWhenStopped =
true;
819 mbVisibleWhenStarted =
false;
829 maContext.mpSubsettableShapeManager->addIntrinsicAnimationHandler(
833bool ActivityImpl::enableAnimations()
836 return maContext.mrActivitiesQueue.addActivity( std::dynamic_pointer_cast<Activity>(shared_from_this()) );
839void ActivityImpl::dispose()
849 maShapeAttrLayer.reset();
858 maContext.mpSubsettableShapeManager->revokeSubset(
865 mpParentDrawShape.reset();
870 maContext.mpSubsettableShapeManager->removeIntrinsicAnimationHandler(
874double ActivityImpl::calcTimeLag()
const
879bool ActivityImpl::isActive()
const
884void ActivityImpl::dequeued()
889void ActivityImpl::end()
894 if( mbIsShapeAnimated )
897 mbIsShapeAnimated =
false;
907 std::shared_ptr<DrawShape>
const& pDrawShape )
909 std::shared_ptr<Activity> pActivity;
915 pActivity = std::make_shared<ActivityImpl>( rContext, pWakeupEvent, pDrawShape );
916 pWakeupEvent->setActivity( pActivity );
918 catch( uno::RuntimeException& )
922 catch( uno::Exception& )
void rotate(double fRadiant)
B2DPoint getCenter() const
std::shared_ptr< ::canvas::tools::ElapsedTime > const & getTimer() const
Gets the queue's timer object.
#define TOOLS_WARN_EXCEPTION(area, stream)
#define ENSURE_OR_RETURN_FALSE(c, m)
#define ENSURE_OR_THROW(c, m)
::std::shared_ptr< GDIMetaFile > GDIMetaFileSharedPtr
tools::Long FRound(double fVal)
IntrinsicAnimationEventHandlerSharedPtr mpListener
WakeupEventSharedPtr mpWakeupEvent
std::weak_ptr< DrawShape > mpDrawShape
IntrinsicAnimationActivity & mrActivity
SlideShowContext maContext
B2DPolygon createPolygonFromRect(const B2DRectangle &rRect, double fRadiusX, double fRadiusY)
constexpr double deg2rad(double v)
std::shared_ptr< T > make_shared(Args &&... args)
bool getPropertyValue(ValueType &rValue, css::uno::Reference< css::beans::XPropertySet > const &xPropSet, OUString const &propName)
::std::shared_ptr< DrawShape > DrawShapeSharedPtr
::std::shared_ptr< IntrinsicAnimationEventHandler > IntrinsicAnimationEventHandlerSharedPtr
std::shared_ptr< Activity > createDrawingLayerAnimActivity(SlideShowContext const &rContext, std::shared_ptr< DrawShape > const &pDrawShape)
bool getRectanglesFromScrollMtf(::basegfx::B2DRectangle &o_rScrollRect, ::basegfx::B2DRectangle &o_rPaintRect, const GDIMetaFileSharedPtr &rMtf)
Retrieve scroll text animation rectangles from given metafile.
EventQueue & mrEventQueue
Common arguments for slideshow objects.
EventQueue & mrEventQueue
ActivitiesQueue & mrActivitiesQueue