fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / slideshow / source / engine / shapes / drawinglayeranimation.cxx
blob5657f2b6c21ca7aeba1ede3bbbea53db81d57548
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <canvas/debug.hxx>
22 #include <tools/diagnose_ex.h>
23 #include <tools/helpers.hxx>
24 #include <canvas/elapsedtime.hxx>
25 #include <basegfx/polygon/b2dpolygontools.hxx>
27 #include <comphelper/anytostring.hxx>
28 #include <cppuhelper/exc_hlp.hxx>
30 #include <rtl/math.hxx>
31 #include <vcl/metric.hxx>
32 #include <vcl/canvastools.hxx>
33 #include <vcl/metaact.hxx>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/drawing/TextAnimationKind.hpp>
36 #include <com/sun/star/drawing/TextAnimationDirection.hpp>
37 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
38 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
39 #include <com/sun/star/drawing/HomogenMatrix3.hpp>
40 #include <com/sun/star/awt/Rectangle.hpp>
42 #include "activity.hxx"
43 #include "wakeupevent.hxx"
44 #include "eventqueue.hxx"
45 #include "drawinglayeranimation.hxx"
46 #include "drawshapesubsetting.hxx"
47 #include "drawshape.hxx"
48 #include "shapesubset.hxx"
49 #include "shapeattributelayerholder.hxx"
50 #include "slideshowcontext.hxx"
51 #include "tools.hxx"
52 #include "gdimtftools.hxx"
53 #include "eventmultiplexer.hxx"
54 #include "intrinsicanimationactivity.hxx"
55 #include "intrinsicanimationeventhandler.hxx"
57 #include <boost/weak_ptr.hpp>
58 #include <boost/enable_shared_from_this.hpp>
59 #include <boost/noncopyable.hpp>
60 #include <vector>
62 using namespace com::sun::star;
63 using namespace ::slideshow::internal;
65 namespace {
67 class ScrollTextAnimNode
69 sal_uInt32 mnDuration; // single duration
70 sal_uInt32 mnRepeat; // 0 -> endless
71 double mfStart;
72 double mfStop;
73 sal_uInt32 mnFrequency; // in ms
74 // forth and back change at mnRepeat%2:
75 bool mbAlternate;
77 public:
78 ScrollTextAnimNode(
79 sal_uInt32 nDuration, sal_uInt32 nRepeat, double fStart, double fStop,
80 sal_uInt32 nFrequency, bool bAlternate)
81 : mnDuration(nDuration),
82 mnRepeat(nRepeat),
83 mfStart(fStart),
84 mfStop(fStop),
85 mnFrequency(nFrequency),
86 mbAlternate(bAlternate)
89 sal_uInt32 GetRepeat() const { return mnRepeat; }
90 sal_uInt32 GetFullTime() const { return mnDuration * mnRepeat; }
91 double GetStop() const { return mfStop; }
92 sal_uInt32 GetFrequency() const { return mnFrequency; }
93 bool DoAlternate() const { return mbAlternate; }
95 double GetStateAtRelativeTime(sal_uInt32 nRelativeTime) const;
98 double ScrollTextAnimNode::GetStateAtRelativeTime(
99 sal_uInt32 nRelativeTime) const
101 // Avoid division by zero.
102 if( mnDuration == 0 )
103 return mfStop;
105 if(mnRepeat)
107 // ending
108 const sal_uInt32 nRepeatCount(nRelativeTime / mnDuration);
109 sal_uInt32 nFrameTime(nRelativeTime - (nRepeatCount * mnDuration));
111 if(DoAlternate() && (nRepeatCount + 1L) % 2L)
112 nFrameTime = mnDuration - nFrameTime;
114 return mfStart + ((mfStop - mfStart) *
115 (double(nFrameTime) / mnDuration));
117 else
119 // endless
120 sal_uInt32 nFrameTime(nRelativeTime % mnDuration);
122 if(DoAlternate())
124 const sal_uInt32 nRepeatCount(nRelativeTime / mnDuration);
126 if((nRepeatCount + 1L) % 2L)
127 nFrameTime = mnDuration - nFrameTime;
130 return mfStart + ((mfStop - mfStart) * (double(nFrameTime) / mnDuration));
134 class ActivityImpl : public Activity,
135 public boost::enable_shared_from_this<ActivityImpl>,
136 private boost::noncopyable
138 public:
139 virtual ~ActivityImpl();
141 ActivityImpl(
142 SlideShowContext const& rContext,
143 boost::shared_ptr<WakeupEvent> const& pWakeupEvent,
144 boost::shared_ptr<DrawShape> const& pDrawShape );
146 bool enableAnimations();
148 // Disposable:
149 virtual void dispose() SAL_OVERRIDE;
150 // Activity:
151 virtual double calcTimeLag() const SAL_OVERRIDE;
152 virtual bool perform() SAL_OVERRIDE;
153 virtual bool isActive() const SAL_OVERRIDE;
154 virtual void dequeued() SAL_OVERRIDE;
155 virtual void end() SAL_OVERRIDE;
157 private:
158 void updateShapeAttributes( double fTime,
159 basegfx::B2DRectangle const& parentBounds );
161 // Access to VisibleWhenSTarted flags
162 bool IsVisibleWhenStarted() const { return mbVisibleWhenStarted; }
163 bool IsVisibleWhenStopped() const { return mbVisibleWhenStopped; }
165 // scroll horizontal? if sal_False, scroll is vertical.
166 bool ScrollHorizontal() const {
167 return (drawing::TextAnimationDirection_LEFT == meDirection ||
168 drawing::TextAnimationDirection_RIGHT == meDirection);
171 // Access to StepWidth in logical units
172 sal_uInt32 GetStepWidthLogic() const;
174 // is the animation direction opposite?
175 bool DoScrollForward() const {
176 return (drawing::TextAnimationDirection_RIGHT == meDirection ||
177 drawing::TextAnimationDirection_DOWN == meDirection);
180 // do alternate text directions?
181 bool DoAlternate() const { return mbAlternate; }
183 // do scroll in?
184 bool DoScrollIn() const { return mbScrollIn; }
186 // Scroll helper methods
187 void ImpForceScrollTextAnimNodes();
188 ScrollTextAnimNode* ImpGetScrollTextAnimNode(
189 sal_uInt32 nTime, sal_uInt32& rRelativeTime );
190 sal_uInt32 ImpRegisterAgainScrollTextMixerState(
191 sal_uInt32 nTime);
193 // calculate the MixerState value for given time
194 double GetMixerState(sal_uInt32 nTime);
198 SlideShowContext maContext;
199 boost::shared_ptr<WakeupEvent> mpWakeupEvent;
200 boost::weak_ptr<DrawShape> mpParentDrawShape;
201 DrawShapeSharedPtr mpDrawShape;
202 ShapeAttributeLayerHolder maShapeAttrLayer;
203 GDIMetaFileSharedPtr mpMetaFile;
204 IntrinsicAnimationEventHandlerSharedPtr mpListener;
205 canvas::tools::ElapsedTime maTimer;
206 double mfRotationAngle;
207 bool mbIsShapeAnimated;
208 bool mbIsDisposed;
209 bool mbIsActive;
210 drawing::TextAnimationKind meAnimKind;
212 // The blink frequency in ms
213 sal_uInt32 mnFrequency;
215 // The repeat count, init to 0L which means endless
216 sal_uInt32 mnRepeat;
218 // Flag to decide if text will be shown when animation has ended
219 bool mbVisibleWhenStopped;
220 bool mbVisibleWhenStarted;
222 // Flag decides if TextScroll alternates. Default is sal_False.
223 bool mbAlternate;
225 // Flag to remember if this is a simple scrollin text
226 bool mbScrollIn;
228 // start time for this animation
229 sal_uInt32 mnStartTime;
231 // The AnimationDirection
232 drawing::TextAnimationDirection meDirection;
234 // Get width per Step. Negative means pixel, positive logical units
235 sal_Int32 mnStepWidth;
237 // The single anim steps
238 std::vector< ScrollTextAnimNode > maVector;
240 // the scroll rectangle
241 Rectangle maScrollRectangleLogic;
243 // the paint rectangle
244 Rectangle maPaintRectangleLogic;
249 class IntrinsicAnimationListener : public IntrinsicAnimationEventHandler,
250 private boost::noncopyable
252 public:
253 explicit IntrinsicAnimationListener( ActivityImpl& rActivity ) :
254 mrActivity( rActivity )
257 private:
259 virtual bool enableAnimations() SAL_OVERRIDE { return mrActivity.enableAnimations(); }
260 virtual bool disableAnimations() SAL_OVERRIDE { mrActivity.end(); return true; }
262 ActivityImpl& mrActivity;
267 double ActivityImpl::GetMixerState( sal_uInt32 nTime )
269 if( meAnimKind == drawing::TextAnimationKind_BLINK )
271 // from AInfoBlinkText:
272 double fRetval(0.0);
273 bool bDone(false);
274 const sal_uInt32 nLoopTime(2 * mnFrequency);
276 if(mnRepeat)
278 const sal_uInt32 nEndTime(mnRepeat * nLoopTime);
280 if(nTime >= nEndTime)
282 if(mbVisibleWhenStopped)
283 fRetval = 0.0;
284 else
285 fRetval = 1.0;
287 bDone = true;
291 if(!bDone)
293 sal_uInt32 nTimeInLoop(nTime % nLoopTime);
294 fRetval = double(nTimeInLoop) / nLoopTime;
297 return fRetval;
299 else
301 // from AInfoScrollText:
302 double fRetval(0.0);
303 ImpForceScrollTextAnimNodes();
305 if(!maVector.empty())
307 sal_uInt32 nRelativeTime;
308 ScrollTextAnimNode* pNode =
309 ImpGetScrollTextAnimNode(nTime, nRelativeTime);
311 if(pNode)
313 // use node
314 fRetval = pNode->GetStateAtRelativeTime(nRelativeTime);
316 else
318 // end of animation, take last entry's end
319 fRetval = maVector[maVector.size() - 1L].GetStop();
323 return fRetval;
327 // Access to StepWidth in logical units
328 sal_uInt32 ActivityImpl::GetStepWidthLogic() const
330 // #i69847# Assuming higher DPI
331 sal_uInt32 const PIXEL_TO_LOGIC = 30;
333 sal_uInt32 nRetval(0L);
335 if(mnStepWidth < 0L)
337 // is in pixels, convert to logical units
338 nRetval = (-mnStepWidth * PIXEL_TO_LOGIC);
340 else if(mnStepWidth > 0L)
342 // is in logical units
343 nRetval = mnStepWidth;
346 if(0L == nRetval)
348 // step 1 pixel, canned value
350 // with very high DPIs like in PDF export, this can
351 // still get zero. for that cases, set a default, too (taken
352 // from ainfoscrolltext.cxx)
353 nRetval = 100L;
356 return nRetval;
359 void ActivityImpl::ImpForceScrollTextAnimNodes()
361 if(maVector.empty())
363 // prepare values
364 sal_uInt32 nLoopTime;
365 double fZeroLogic, fOneLogic, fInitLogic, fDistanceLogic;
366 double fZeroLogicAlternate = 0.0, fOneLogicAlternate = 0.0;
367 double fZeroRelative, fOneRelative, fInitRelative;
369 if(ScrollHorizontal())
371 if(DoAlternate())
373 if(maPaintRectangleLogic.GetWidth() >
374 maScrollRectangleLogic.GetWidth())
376 fZeroLogicAlternate = maScrollRectangleLogic.Right() - maPaintRectangleLogic.GetWidth();
377 fOneLogicAlternate = maScrollRectangleLogic.Left();
379 else
381 fZeroLogicAlternate = maScrollRectangleLogic.Left();
382 fOneLogicAlternate = maScrollRectangleLogic.Right() - maPaintRectangleLogic.GetWidth();
386 fZeroLogic = maScrollRectangleLogic.Left() - maPaintRectangleLogic.GetWidth();
387 fOneLogic = maScrollRectangleLogic.Right();
388 fInitLogic = maPaintRectangleLogic.Left();
390 else
392 if(DoAlternate())
394 if(maPaintRectangleLogic.GetHeight() > maScrollRectangleLogic.GetHeight())
396 fZeroLogicAlternate = maScrollRectangleLogic.Bottom() - maPaintRectangleLogic.GetHeight();
397 fOneLogicAlternate = maScrollRectangleLogic.Top();
399 else
401 fZeroLogicAlternate = maScrollRectangleLogic.Top();
402 fOneLogicAlternate = maScrollRectangleLogic.Bottom() - maPaintRectangleLogic.GetHeight();
406 fZeroLogic = maScrollRectangleLogic.Top() - maPaintRectangleLogic.GetHeight();
407 fOneLogic = maScrollRectangleLogic.Bottom();
408 fInitLogic = maPaintRectangleLogic.Top();
411 fDistanceLogic = fOneLogic - fZeroLogic;
412 fInitRelative = (fInitLogic - fZeroLogic) / fDistanceLogic;
414 if(DoAlternate())
416 fZeroRelative =
417 (fZeroLogicAlternate - fZeroLogic) / fDistanceLogic;
418 fOneRelative =
419 (fOneLogicAlternate - fZeroLogic) / fDistanceLogic;
421 else
423 fZeroRelative = 0.0;
424 fOneRelative = 1.0;
427 if(mnStartTime)
429 // Start time loop
430 ScrollTextAnimNode aStartNode(
431 mnStartTime, 1L, 0.0, 0.0, mnStartTime, false);
432 maVector.push_back(aStartNode);
435 if(IsVisibleWhenStarted())
437 double fRelativeStartValue, fRelativeEndValue,fRelativeDistance;
439 if(DoScrollForward())
441 fRelativeStartValue = fInitRelative;
442 fRelativeEndValue = fOneRelative;
443 fRelativeDistance = fRelativeEndValue - fRelativeStartValue;
445 else
447 fRelativeStartValue = fInitRelative;
448 fRelativeEndValue = fZeroRelative;
449 fRelativeDistance = fRelativeStartValue - fRelativeEndValue;
452 const double fNumberSteps =
453 (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic();
454 nLoopTime = FRound(fNumberSteps * mnFrequency);
456 // init loop
457 ScrollTextAnimNode aInitNode(
458 nLoopTime, 1L,
459 fRelativeStartValue, fRelativeEndValue,
460 mnFrequency, false);
461 maVector.push_back(aInitNode);
464 // prepare main loop values
466 double fRelativeStartValue, fRelativeEndValue, fRelativeDistance;
468 if(DoScrollForward())
470 fRelativeStartValue = fZeroRelative;
471 fRelativeEndValue = fOneRelative;
472 fRelativeDistance = fRelativeEndValue - fRelativeStartValue;
474 else
476 fRelativeStartValue = fOneRelative;
477 fRelativeEndValue = fZeroRelative;
478 fRelativeDistance = fRelativeStartValue - fRelativeEndValue;
481 const double fNumberSteps =
482 (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic();
483 nLoopTime = FRound(fNumberSteps * mnFrequency);
485 if(0L == mnRepeat)
487 if(!DoScrollIn())
489 // endless main loop
490 ScrollTextAnimNode aMainNode(
491 nLoopTime, 0L,
492 fRelativeStartValue, fRelativeEndValue,
493 mnFrequency, DoAlternate());
494 maVector.push_back(aMainNode);
497 else
499 sal_uInt32 nNumRepeat(mnRepeat);
501 if(DoAlternate() && (nNumRepeat + 1L) % 2L)
502 nNumRepeat += 1L;
504 // ending main loop
505 ScrollTextAnimNode aMainNode(
506 nLoopTime, nNumRepeat,
507 fRelativeStartValue, fRelativeEndValue,
508 mnFrequency, DoAlternate());
509 maVector.push_back(aMainNode);
513 if(IsVisibleWhenStopped())
515 double fRelativeStartValue, fRelativeEndValue, fRelativeDistance;
517 if(DoScrollForward())
519 fRelativeStartValue = fZeroRelative;
520 fRelativeEndValue = fInitRelative;
521 fRelativeDistance = fRelativeEndValue - fRelativeStartValue;
523 else
525 fRelativeStartValue = fOneRelative;
526 fRelativeEndValue = fInitRelative;
527 fRelativeDistance = fRelativeStartValue - fRelativeEndValue;
530 const double fNumberSteps =
531 (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic();
532 nLoopTime = FRound(fNumberSteps * mnFrequency);
534 // exit loop
535 ScrollTextAnimNode aExitNode(
536 nLoopTime, 1L,
537 fRelativeStartValue, fRelativeEndValue, mnFrequency, false);
538 maVector.push_back(aExitNode);
543 ScrollTextAnimNode* ActivityImpl::ImpGetScrollTextAnimNode(
544 sal_uInt32 nTime, sal_uInt32& rRelativeTime )
546 ScrollTextAnimNode* pRetval = 0L;
547 ImpForceScrollTextAnimNodes();
549 if(!maVector.empty())
551 rRelativeTime = nTime;
553 for(sal_uInt32 a(0L); !pRetval && a < maVector.size(); a++)
555 ScrollTextAnimNode & rNode = maVector[a];
556 if(!rNode.GetRepeat())
558 // endless loop, use it
559 pRetval = &rNode;
561 else if(rNode.GetFullTime() > rRelativeTime)
563 // ending node
564 pRetval = &rNode;
566 else
568 // look at next
569 rRelativeTime -= rNode.GetFullTime();
574 return pRetval;
577 sal_uInt32 ActivityImpl::ImpRegisterAgainScrollTextMixerState(sal_uInt32 nTime)
579 sal_uInt32 nRetval(0L);
580 ImpForceScrollTextAnimNodes();
582 if(!maVector.empty())
584 sal_uInt32 nRelativeTime;
585 ScrollTextAnimNode* pNode = ImpGetScrollTextAnimNode(nTime, nRelativeTime);
587 if(pNode)
589 // take register time
590 nRetval = pNode->GetFrequency();
593 else
595 // #i38135# not initialized, return default
596 nRetval = mnFrequency;
599 return nRetval;
602 void ActivityImpl::updateShapeAttributes(
603 double fTime, basegfx::B2DRectangle const& parentBounds )
605 OSL_ASSERT( meAnimKind != drawing::TextAnimationKind_NONE );
606 if( meAnimKind == drawing::TextAnimationKind_NONE )
607 return;
609 double const fMixerState = GetMixerState(
610 static_cast<sal_uInt32>(fTime * 1000.0) );
612 if( meAnimKind == drawing::TextAnimationKind_BLINK )
614 // show/hide text:
615 maShapeAttrLayer.get()->setVisibility( fMixerState < 0.5 );
617 else if(mpMetaFile) // scroll mode:
620 // keep care: the below code is highly sensible to changes...
623 // rectangle of the pure text:
624 double const fPaintWidth = maPaintRectangleLogic.GetWidth();
625 double const fPaintHeight = maPaintRectangleLogic.GetHeight();
626 // rectangle where the scrolling takes place (-> clipping):
627 double const fScrollWidth = maScrollRectangleLogic.GetWidth();
628 double const fScrollHeight = maScrollRectangleLogic.GetHeight();
630 basegfx::B2DPoint pos, clipPos;
632 if(ScrollHorizontal())
634 double const fOneEquiv( fScrollWidth );
635 double const fZeroEquiv( -fPaintWidth );
637 pos.setX( fZeroEquiv + (fMixerState * (fOneEquiv - fZeroEquiv)) );
639 clipPos.setX( -pos.getX() );
640 clipPos.setY( -pos.getY() );
642 // #i69844# Compensation for text-wider-than-shape case
643 if( fPaintWidth > fScrollWidth )
644 pos.setX( pos.getX() + (fPaintWidth-fScrollWidth) / 2.0 );
646 else
648 // scroll vertical:
649 double const fOneEquiv( fScrollHeight );
650 double const fZeroEquiv( -fPaintHeight );
652 pos.setY( fZeroEquiv + (fMixerState * (fOneEquiv - fZeroEquiv)) );
654 clipPos.setX( -pos.getX() );
655 clipPos.setY( -pos.getY() );
657 // #i69844# Compensation for text-higher-than-shape case
658 if( fPaintHeight > fScrollHeight )
659 pos.setY( pos.getY() + (fPaintHeight-fScrollHeight) / 2.0 );
662 basegfx::B2DPolygon clipPoly(
663 basegfx::tools::createPolygonFromRect(
664 basegfx::B2DRectangle( clipPos.getX(),
665 clipPos.getY(),
666 clipPos.getX() + fScrollWidth,
667 clipPos.getY() + fScrollHeight ) ) );
669 if( !::basegfx::fTools::equalZero( mfRotationAngle ))
671 maShapeAttrLayer.get()->setRotationAngle( mfRotationAngle );
672 double const fRotate = (mfRotationAngle * M_PI / 180.0);
673 basegfx::B2DHomMatrix aTransform;
674 // position:
675 aTransform.rotate( fRotate );
676 pos *= aTransform;
679 pos += parentBounds.getCenter();
680 maShapeAttrLayer.get()->setPosition( pos );
681 maShapeAttrLayer.get()->setClip( basegfx::B2DPolyPolygon(clipPoly) );
685 bool ActivityImpl::perform()
687 if( !isActive() )
688 return false;
690 ENSURE_OR_RETURN_FALSE(
691 mpDrawShape,
692 "ActivityImpl::perform(): still active, but NULL draw shape" );
694 DrawShapeSharedPtr const pParentDrawShape( mpParentDrawShape );
695 if( !pParentDrawShape )
696 return false; // parent has vanished
698 if( pParentDrawShape->isVisible() )
700 if( !mbIsShapeAnimated )
702 mpDrawShape->setVisibility(true); // shape may be initially hidden
703 maContext.mpSubsettableShapeManager->enterAnimationMode( mpDrawShape );
704 maTimer.reset();
705 mbIsShapeAnimated = true;
707 // update attributes related to current time:
708 basegfx::B2DRectangle const parentBounds(
709 pParentDrawShape->getBounds() );
711 const double nCurrTime( maTimer.getElapsedTime() );
712 updateShapeAttributes( nCurrTime, parentBounds );
714 const sal_uInt32 nFrequency(
715 ImpRegisterAgainScrollTextMixerState(
716 static_cast<sal_uInt32>(nCurrTime * 1000.0)) );
718 if(nFrequency)
720 mpWakeupEvent->start();
721 mpWakeupEvent->setNextTimeout(
722 std::max(0.1,nFrequency/1000.0) );
723 maContext.mrEventQueue.addEvent( mpWakeupEvent );
725 if( mpDrawShape->isContentChanged() )
726 maContext.mpSubsettableShapeManager->notifyShapeUpdate( mpDrawShape );
728 // else: finished, not need to wake up again.
730 else
732 // busy-wait, until parent shape gets visible
733 mpWakeupEvent->start();
734 mpWakeupEvent->setNextTimeout( 2.0 );
737 // don't reinsert, WakeupEvent will perform that after the given timeout:
738 return false;
741 ActivityImpl::ActivityImpl(
742 SlideShowContext const& rContext,
743 boost::shared_ptr<WakeupEvent> const& pWakeupEvent,
744 boost::shared_ptr<DrawShape> const& pParentDrawShape )
745 : maContext(rContext),
746 mpWakeupEvent(pWakeupEvent),
747 mpParentDrawShape(pParentDrawShape),
748 mpListener( new IntrinsicAnimationListener(*this) ),
749 maTimer(rContext.mrEventQueue.getTimer()),
750 mfRotationAngle(0.0),
751 mbIsShapeAnimated(false),
752 mbIsDisposed(false),
753 mbIsActive(true),
754 meAnimKind(drawing::TextAnimationKind_NONE),
755 mbVisibleWhenStopped(false),
756 mbVisibleWhenStarted(false),
757 mnStartTime(0L),
758 mnStepWidth(0)
760 // get doctreenode:
761 sal_Int32 const nNodes = pParentDrawShape->getNumberOfTreeNodes(
762 DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH );
764 DocTreeNode scrollTextNode(
765 pParentDrawShape->getTreeNode(
766 0, DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ));
767 // xxx todo: remove this hack
768 if( nNodes > 1 )
769 scrollTextNode.setEndIndex(
770 pParentDrawShape->getTreeNode(
771 nNodes - 1,
772 DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ).getEndIndex());
774 // TODO(Q3): Doing this manually, instead of using
775 // ShapeSubset. This is because of lifetime issues (ShapeSubset
776 // generates circular references to parent shape)
777 mpDrawShape = boost::dynamic_pointer_cast<DrawShape>(
778 maContext.mpSubsettableShapeManager->getSubsetShape(
779 pParentDrawShape,
780 scrollTextNode ));
782 mpMetaFile = mpDrawShape->forceScrollTextMetaFile();
784 // make scroll text invisible for slide transition bitmaps
785 mpDrawShape->setVisibility(false);
787 basegfx::B2DRectangle aScrollRect, aPaintRect;
788 ENSURE_OR_THROW( getRectanglesFromScrollMtf( aScrollRect,
789 aPaintRect,
790 mpMetaFile ),
791 "ActivityImpl::ActivityImpl(): Could not extract "
792 "scroll anim rectangles from mtf" );
794 maScrollRectangleLogic = vcl::unotools::rectangleFromB2DRectangle(
795 aScrollRect );
796 maPaintRectangleLogic = vcl::unotools::rectangleFromB2DRectangle(
797 aPaintRect );
799 maShapeAttrLayer.createAttributeLayer(mpDrawShape);
801 uno::Reference<drawing::XShape> const xShape( mpDrawShape->getXShape() );
802 uno::Reference<beans::XPropertySet> const xProps( xShape, uno::UNO_QUERY_THROW );
804 getPropertyValue( meAnimKind, xProps, "TextAnimationKind" );
805 OSL_ASSERT( meAnimKind != drawing::TextAnimationKind_NONE );
806 mbAlternate = (meAnimKind == drawing::TextAnimationKind_ALTERNATE);
807 mbScrollIn = (meAnimKind == drawing::TextAnimationKind_SLIDE);
809 // adopted from in AInfoBlinkText::ImplInit():
810 sal_Int16 nRepeat(0);
811 getPropertyValue( nRepeat, xProps, "TextAnimationCount" );
812 mnRepeat = nRepeat;
814 if(mbAlternate)
816 // force visible when started for scroll-forth-and-back, because
817 // slide has been coming in with visible text in the middle:
818 mbVisibleWhenStarted = true;
820 else
822 getPropertyValue( mbVisibleWhenStarted, xProps,
823 "TextAnimationStartInside" );
826 // set visible when stopped
827 getPropertyValue( mbVisibleWhenStopped, xProps,
828 "TextAnimatiogonStopInside" );
829 // rotation:
830 getPropertyValue( mfRotationAngle, xProps,
831 "RotateAngle" );
832 mfRotationAngle /= -100.0; // (switching direction)
834 // set frequency
835 sal_Int16 nDelay(0);
836 getPropertyValue( nDelay, xProps, "TextAnimationDelay" );
837 // set delay if not automatic
838 mnFrequency = (nDelay ? nDelay :
839 // default:
840 meAnimKind == drawing::TextAnimationKind_BLINK
841 ? 250L : 50L );
843 // adopted from in AInfoScrollText::ImplInit():
845 // If it is a simple m_bScrollIn, reset some parameters
846 if( DoScrollIn() )
848 // most parameters are set correctly from the dialog logic, but
849 // eg VisisbleWhenStopped is grayed out and needs to be corrected here.
850 mbVisibleWhenStopped = true;
851 mbVisibleWhenStarted = false;
852 mnRepeat = 0L;
855 // Get animation direction
856 getPropertyValue( meDirection, xProps, "TextAnimationDirection" );
858 // Get step width. Negative means pixel, positive logical units
859 getPropertyValue( mnStepWidth, xProps, "TextAnimationAmount" );
861 maContext.mpSubsettableShapeManager->addIntrinsicAnimationHandler(
862 mpListener );
865 bool ActivityImpl::enableAnimations()
867 mbIsActive = true;
868 return maContext.mrActivitiesQueue.addActivity(
869 shared_from_this() );
872 ActivityImpl::~ActivityImpl()
876 void ActivityImpl::dispose()
878 if( !mbIsDisposed )
880 end();
882 // only remove subset here, since end() is called on slide end
883 // (and we must not spoil the slide preview bitmap with scroll
884 // text)
885 maShapeAttrLayer.reset();
886 if( mpDrawShape )
888 // TODO(Q3): Doing this manually, instead of using
889 // ShapeSubset. This is because of lifetime issues
890 // (ShapeSubset generates circular references to parent
891 // shape)
892 DrawShapeSharedPtr pParent( mpParentDrawShape.lock() );
893 if( pParent )
894 maContext.mpSubsettableShapeManager->revokeSubset(
895 pParent,
896 mpDrawShape );
899 mpMetaFile.reset();
900 mpDrawShape.reset();
901 mpParentDrawShape.reset();
902 mpWakeupEvent.reset();
903 maContext.dispose();
904 mbIsDisposed = true;
906 maContext.mpSubsettableShapeManager->removeIntrinsicAnimationHandler(
907 mpListener );
911 double ActivityImpl::calcTimeLag() const
913 return 0.0;
916 bool ActivityImpl::isActive() const
918 return mbIsActive;
921 void ActivityImpl::dequeued()
923 // not used here
926 void ActivityImpl::end()
928 // not used here
929 mbIsActive = false;
931 if( mbIsShapeAnimated )
933 maContext.mpSubsettableShapeManager->leaveAnimationMode( mpDrawShape );
934 mbIsShapeAnimated = false;
938 } // anon namespace
940 namespace slideshow {
941 namespace internal {
943 boost::shared_ptr<Activity> createDrawingLayerAnimActivity(
944 SlideShowContext const& rContext,
945 boost::shared_ptr<DrawShape> const& pDrawShape )
947 boost::shared_ptr<Activity> pActivity;
951 boost::shared_ptr<WakeupEvent> const pWakeupEvent(
952 new WakeupEvent( rContext.mrEventQueue.getTimer(),
953 rContext.mrActivitiesQueue ) );
954 pActivity.reset( new ActivityImpl( rContext, pWakeupEvent, pDrawShape ) );
955 pWakeupEvent->setActivity( pActivity );
957 catch( uno::RuntimeException& )
959 throw;
961 catch( uno::Exception& )
963 // translate any error into empty factory product.
964 OSL_FAIL( OUStringToOString(
965 comphelper::anyToString( cppu::getCaughtException() ),
966 RTL_TEXTENCODING_UTF8 ).getStr() );
969 return pActivity;
972 } // namespace internal
973 } // namespace presentation
975 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */