merge the formfield patch from ooo-build
[ooovba.git] / slideshow / source / engine / shapes / drawinglayeranimation.cxx
blob9aa1624823e5c6b6ceb1f1dfac2e6854d07fd072
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: drawinglayeranimation.cxx,v $
10 * $Revision: 1.5.10.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_slideshow.hxx"
34 #include <canvas/debug.hxx>
35 #include <tools/diagnose_ex.h>
36 #include <canvas/elapsedtime.hxx>
37 #include <basegfx/polygon/b2dpolygontools.hxx>
39 #include <comphelper/anytostring.hxx>
40 #include <cppuhelper/exc_hlp.hxx>
42 #include <rtl/math.hxx>
43 #include <vcl/metric.hxx>
44 #include <vcl/salbtype.hxx>
45 #include <vcl/canvastools.hxx>
46 #include <vcl/metaact.hxx>
47 #include <com/sun/star/beans/XPropertySet.hpp>
48 #include <com/sun/star/drawing/TextAnimationKind.hpp>
49 #include <com/sun/star/drawing/TextAnimationDirection.hpp>
50 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
51 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
52 #include <com/sun/star/drawing/HomogenMatrix3.hpp>
53 #include <com/sun/star/awt/Rectangle.hpp>
55 #include "activity.hxx"
56 #include "wakeupevent.hxx"
57 #include "eventqueue.hxx"
58 #include "drawshapesubsetting.hxx"
59 #include "drawshape.hxx"
60 #include "shapesubset.hxx"
61 #include "shapeattributelayerholder.hxx"
62 #include "slideshowcontext.hxx"
63 #include "tools.hxx"
64 #include "gdimtftools.hxx"
65 #include "eventmultiplexer.hxx"
66 #include "intrinsicanimationactivity.hxx"
67 #include "intrinsicanimationeventhandler.hxx"
69 #include <boost/weak_ptr.hpp>
70 #include <boost/enable_shared_from_this.hpp>
71 #include <boost/noncopyable.hpp>
72 #include <vector>
74 using namespace com::sun::star;
75 using namespace ::slideshow::internal;
77 namespace {
79 class ScrollTextAnimNode
81 sal_uInt32 mnDuration; // single duration
82 sal_uInt32 mnRepeat; // 0 -> endless
83 double mfStart;
84 double mfStop;
85 sal_uInt32 mnFrequency; // in ms
86 // forth and back change at mnRepeat%2:
87 bool mbAlternate;
89 public:
90 ScrollTextAnimNode(
91 sal_uInt32 nDuration, sal_uInt32 nRepeat, double fStart, double fStop,
92 sal_uInt32 nFrequency, bool bAlternate)
93 : mnDuration(nDuration),
94 mnRepeat(nRepeat),
95 mfStart(fStart),
96 mfStop(fStop),
97 mnFrequency(nFrequency),
98 mbAlternate(bAlternate)
101 sal_uInt32 GetDuration() const { return mnDuration; }
102 sal_uInt32 GetRepeat() const { return mnRepeat; }
103 sal_uInt32 GetFullTime() const { return mnDuration * mnRepeat; }
104 double GetStart() const { return mfStart; }
105 double GetStop() const { return mfStop; }
106 sal_uInt32 GetFrequency() const { return mnFrequency; }
107 bool DoAlternate() const { return mbAlternate; }
109 double GetStateAtRelativeTime(sal_uInt32 nRelativeTime) const;
112 double ScrollTextAnimNode::GetStateAtRelativeTime(
113 sal_uInt32 nRelativeTime) const
115 // #151174# Avoid division by zero.
116 if( mnDuration == 0 )
117 return mfStop;
119 if(mnRepeat)
121 // ending
122 const sal_uInt32 nRepeatCount(nRelativeTime / mnDuration);
123 sal_uInt32 nFrameTime(nRelativeTime - (nRepeatCount * mnDuration));
125 if(DoAlternate() && (nRepeatCount + 1L) % 2L)
126 nFrameTime = mnDuration - nFrameTime;
128 return mfStart + ((mfStop - mfStart) *
129 (double(nFrameTime) / mnDuration));
131 else
133 // endless
134 sal_uInt32 nFrameTime(nRelativeTime % mnDuration);
136 if(DoAlternate())
138 const sal_uInt32 nRepeatCount(nRelativeTime / mnDuration);
140 if((nRepeatCount + 1L) % 2L)
141 nFrameTime = mnDuration - nFrameTime;
144 return mfStart + ((mfStop - mfStart) * (double(nFrameTime) / mnDuration));
148 class ActivityImpl : public Activity,
149 public boost::enable_shared_from_this<ActivityImpl>,
150 private boost::noncopyable
152 public:
153 virtual ~ActivityImpl();
155 ActivityImpl(
156 SlideShowContext const& rContext,
157 boost::shared_ptr<WakeupEvent> const& pWakeupEvent,
158 boost::shared_ptr<DrawShape> const& pDrawShape );
160 bool enableAnimations();
162 // Disposable:
163 virtual void dispose();
164 // Activity:
165 virtual double calcTimeLag() const;
166 virtual bool perform();
167 virtual bool isActive() const;
168 virtual void dequeued();
169 virtual void end();
171 private:
172 void updateShapeAttributes( double fTime,
173 basegfx::B2DRectangle const& parentBounds );
175 // Access to VisibleWhenSTarted flags
176 sal_Bool IsVisibleWhenStarted() const { return mbVisibleWhenStarted; }
177 sal_Bool IsVisibleWhenStopped() const { return mbVisibleWhenStopped; }
179 // scroll horizontal? if sal_False, scroll is vertical.
180 bool ScrollHorizontal() const {
181 return (drawing::TextAnimationDirection_LEFT == meDirection ||
182 drawing::TextAnimationDirection_RIGHT == meDirection);
185 // Access to StepWidth in logical units
186 sal_uInt32 GetStepWidthLogic() const;
188 // is the animation direction opposite?
189 bool DoScrollForward() const {
190 return (drawing::TextAnimationDirection_RIGHT == meDirection ||
191 drawing::TextAnimationDirection_DOWN == meDirection);
194 // do alternate text directions?
195 bool DoAlternate() const { return mbAlternate; }
197 // do scroll in?
198 bool DoScrollIn() const { return mbScrollIn; }
200 // Scroll helper methods
201 void ImpForceScrollTextAnimNodes();
202 ScrollTextAnimNode* ImpGetScrollTextAnimNode(
203 sal_uInt32 nTime, sal_uInt32& rRelativeTime );
204 sal_uInt32 ImpRegisterAgainScrollTextMixerState(
205 sal_uInt32 nTime);
207 // calculate the MixerState value for given time
208 double GetMixerState(sal_uInt32 nTime);
210 ////////////////////////////////////////////////////////////////////
212 SlideShowContext maContext;
213 boost::shared_ptr<WakeupEvent> mpWakeupEvent;
214 boost::weak_ptr<DrawShape> mpParentDrawShape;
215 DrawShapeSharedPtr mpDrawShape;
216 ShapeAttributeLayerHolder maShapeAttrLayer;
217 GDIMetaFileSharedPtr mpMetaFile;
218 IntrinsicAnimationEventHandlerSharedPtr mpListener;
219 canvas::tools::ElapsedTime maTimer;
220 double mfRotationAngle;
221 bool mbIsShapeAnimated;
222 bool mbIsDisposed;
223 bool mbIsActive;
224 drawing::TextAnimationKind meAnimKind;
226 // The blink frequency in ms
227 sal_uInt32 mnFrequency;
229 // The repeat count, init to 0L which means endless
230 sal_uInt32 mnRepeat;
232 // Flag to decide if text will be shown when animation has ended
233 bool mbVisibleWhenStopped;
234 bool mbVisibleWhenStarted;
236 // Flag decides if TextScroll alternates. Default is sal_False.
237 bool mbAlternate;
239 // Flag to remember if this is a simple scrollin text
240 bool mbScrollIn;
242 // start time for this animation
243 sal_uInt32 mnStartTime;
245 // The AnimationDirection
246 drawing::TextAnimationDirection meDirection;
248 // Get width per Step. Negative means pixel, positive logical units
249 sal_Int32 mnStepWidth;
251 // The single anim steps
252 std::vector< ScrollTextAnimNode > maVector;
254 // the scroll rectangle
255 Rectangle maScrollRectangleLogic;
257 // the paint rectangle
258 Rectangle maPaintRectangleLogic;
261 //////////////////////////////////////////////////////////////////////
263 class IntrinsicAnimationListener : public IntrinsicAnimationEventHandler,
264 private boost::noncopyable
266 public:
267 explicit IntrinsicAnimationListener( ActivityImpl& rActivity ) :
268 mrActivity( rActivity )
271 private:
273 virtual bool enableAnimations() { return mrActivity.enableAnimations(); }
274 virtual bool disableAnimations() { mrActivity.end(); return true; }
276 ActivityImpl& mrActivity;
279 //////////////////////////////////////////////////////////////////////
281 double ActivityImpl::GetMixerState( sal_uInt32 nTime )
283 if( meAnimKind == drawing::TextAnimationKind_BLINK )
285 // from AInfoBlinkText:
286 double fRetval(0.0);
287 sal_Bool bDone(sal_False);
288 const sal_uInt32 nLoopTime(2 * mnFrequency);
290 if(mnRepeat)
292 const sal_uInt32 nEndTime(mnRepeat * nLoopTime);
294 if(nTime >= nEndTime)
296 if(mbVisibleWhenStopped)
297 fRetval = 0.0;
298 else
299 fRetval = 1.0;
301 bDone = sal_True;
305 if(!bDone)
307 sal_uInt32 nTimeInLoop(nTime % nLoopTime);
308 fRetval = double(nTimeInLoop) / nLoopTime;
311 return fRetval;
313 else
315 // from AInfoScrollText:
316 double fRetval(0.0);
317 ImpForceScrollTextAnimNodes();
319 if(!maVector.empty())
321 sal_uInt32 nRelativeTime;
322 ScrollTextAnimNode* pNode =
323 ImpGetScrollTextAnimNode(nTime, nRelativeTime);
325 if(pNode)
327 // use node
328 fRetval = pNode->GetStateAtRelativeTime(nRelativeTime);
330 else
332 // end of animation, take last entry's end
333 fRetval = maVector[maVector.size() - 1L].GetStop();
337 return fRetval;
341 // Access to StepWidth in logical units
342 sal_uInt32 ActivityImpl::GetStepWidthLogic() const
344 // #i69847# Assuming higher DPI
345 sal_uInt32 const PIXEL_TO_LOGIC = 30;
347 sal_uInt32 nRetval(0L);
349 if(mnStepWidth < 0L)
351 // is in pixels, convert to logical units
352 nRetval = (-mnStepWidth * PIXEL_TO_LOGIC);
354 else if(mnStepWidth > 0L)
356 // is in logical units
357 nRetval = mnStepWidth;
360 if(0L == nRetval)
362 // step 1 pixel, canned value
364 // #128389# with very high DPIs like in PDF export, this can
365 // still get zero. for that cases, set a default, too (taken
366 // from ainfoscrolltext.cxx)
367 nRetval = 100L;
370 return nRetval;
373 void ActivityImpl::ImpForceScrollTextAnimNodes()
375 if(maVector.empty())
377 // prepare values
378 sal_uInt32 nLoopTime;
379 double fZeroLogic, fOneLogic, fInitLogic, fDistanceLogic;
380 double fZeroLogicAlternate = 0.0, fOneLogicAlternate = 0.0;
381 double fZeroRelative, fOneRelative, fInitRelative,fDistanceRelative;
383 if(ScrollHorizontal())
385 if(DoAlternate())
387 if(maPaintRectangleLogic.GetWidth() >
388 maScrollRectangleLogic.GetWidth())
390 fZeroLogicAlternate = maScrollRectangleLogic.Right() - maPaintRectangleLogic.GetWidth();
391 fOneLogicAlternate = maScrollRectangleLogic.Left();
393 else
395 fZeroLogicAlternate = maScrollRectangleLogic.Left();
396 fOneLogicAlternate = maScrollRectangleLogic.Right() - maPaintRectangleLogic.GetWidth();
400 fZeroLogic = maScrollRectangleLogic.Left() - maPaintRectangleLogic.GetWidth();
401 fOneLogic = maScrollRectangleLogic.Right();
402 fInitLogic = maPaintRectangleLogic.Left();
404 else
406 if(DoAlternate())
408 if(maPaintRectangleLogic.GetHeight() > maScrollRectangleLogic.GetHeight())
410 fZeroLogicAlternate = maScrollRectangleLogic.Bottom() - maPaintRectangleLogic.GetHeight();
411 fOneLogicAlternate = maScrollRectangleLogic.Top();
413 else
415 fZeroLogicAlternate = maScrollRectangleLogic.Top();
416 fOneLogicAlternate = maScrollRectangleLogic.Bottom() - maPaintRectangleLogic.GetHeight();
420 fZeroLogic = maScrollRectangleLogic.Top() - maPaintRectangleLogic.GetHeight();
421 fOneLogic = maScrollRectangleLogic.Bottom();
422 fInitLogic = maPaintRectangleLogic.Top();
425 fDistanceLogic = fOneLogic - fZeroLogic;
426 fInitRelative = (fInitLogic - fZeroLogic) / fDistanceLogic;
428 if(DoAlternate())
430 fZeroRelative =
431 (fZeroLogicAlternate - fZeroLogic) / fDistanceLogic;
432 fOneRelative =
433 (fOneLogicAlternate - fZeroLogic) / fDistanceLogic;
434 fDistanceRelative = fOneRelative - fZeroRelative;
436 else
438 fZeroRelative = 0.0;
439 fOneRelative = 1.0;
440 fDistanceRelative = 1.0;
443 if(mnStartTime)
445 // Start time loop
446 ScrollTextAnimNode aStartNode(
447 mnStartTime, 1L, 0.0, 0.0, mnStartTime, false);
448 maVector.push_back(aStartNode);
451 if(IsVisibleWhenStarted())
453 double fRelativeStartValue, fRelativeEndValue,fRelativeDistance;
455 if(DoScrollForward())
457 fRelativeStartValue = fInitRelative;
458 fRelativeEndValue = fOneRelative;
459 fRelativeDistance = fRelativeEndValue - fRelativeStartValue;
461 else
463 fRelativeStartValue = fInitRelative;
464 fRelativeEndValue = fZeroRelative;
465 fRelativeDistance = fRelativeStartValue - fRelativeEndValue;
468 const double fNumberSteps =
469 (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic();
470 nLoopTime = FRound(fNumberSteps * mnFrequency);
472 // init loop
473 ScrollTextAnimNode aInitNode(
474 nLoopTime, 1L,
475 fRelativeStartValue, fRelativeEndValue,
476 mnFrequency, false);
477 maVector.push_back(aInitNode);
480 // prepare main loop values
482 double fRelativeStartValue, fRelativeEndValue, fRelativeDistance;
484 if(DoScrollForward())
486 fRelativeStartValue = fZeroRelative;
487 fRelativeEndValue = fOneRelative;
488 fRelativeDistance = fRelativeEndValue - fRelativeStartValue;
490 else
492 fRelativeStartValue = fOneRelative;
493 fRelativeEndValue = fZeroRelative;
494 fRelativeDistance = fRelativeStartValue - fRelativeEndValue;
497 const double fNumberSteps =
498 (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic();
499 nLoopTime = FRound(fNumberSteps * mnFrequency);
501 if(0L == mnRepeat)
503 if(!DoScrollIn())
505 // endless main loop
506 ScrollTextAnimNode aMainNode(
507 nLoopTime, 0L,
508 fRelativeStartValue, fRelativeEndValue,
509 mnFrequency, DoAlternate());
510 maVector.push_back(aMainNode);
513 else
515 sal_uInt32 nNumRepeat(mnRepeat);
517 if(DoAlternate() && (nNumRepeat + 1L) % 2L)
518 nNumRepeat += 1L;
520 // ending main loop
521 ScrollTextAnimNode aMainNode(
522 nLoopTime, nNumRepeat,
523 fRelativeStartValue, fRelativeEndValue,
524 mnFrequency, DoAlternate());
525 maVector.push_back(aMainNode);
529 if(IsVisibleWhenStopped())
531 double fRelativeStartValue, fRelativeEndValue, fRelativeDistance;
533 if(DoScrollForward())
535 fRelativeStartValue = fZeroRelative;
536 fRelativeEndValue = fInitRelative;
537 fRelativeDistance = fRelativeEndValue - fRelativeStartValue;
539 else
541 fRelativeStartValue = fOneRelative;
542 fRelativeEndValue = fInitRelative;
543 fRelativeDistance = fRelativeStartValue - fRelativeEndValue;
546 const double fNumberSteps =
547 (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic();
548 nLoopTime = FRound(fNumberSteps * mnFrequency);
550 // exit loop
551 ScrollTextAnimNode aExitNode(
552 nLoopTime, 1L,
553 fRelativeStartValue, fRelativeEndValue, mnFrequency, false);
554 maVector.push_back(aExitNode);
559 ScrollTextAnimNode* ActivityImpl::ImpGetScrollTextAnimNode(
560 sal_uInt32 nTime, sal_uInt32& rRelativeTime )
562 ScrollTextAnimNode* pRetval = 0L;
563 ImpForceScrollTextAnimNodes();
565 if(!maVector.empty())
567 rRelativeTime = nTime;
569 for(sal_uInt32 a(0L); !pRetval && a < maVector.size(); a++)
571 ScrollTextAnimNode & rNode = maVector[a];
572 if(!rNode.GetRepeat())
574 // endless loop, use it
575 pRetval = &rNode;
577 else if(rNode.GetFullTime() > rRelativeTime)
579 // ending node
580 pRetval = &rNode;
582 else
584 // look at next
585 rRelativeTime -= rNode.GetFullTime();
590 return pRetval;
593 sal_uInt32 ActivityImpl::ImpRegisterAgainScrollTextMixerState(sal_uInt32 nTime)
595 sal_uInt32 nRetval(0L);
596 ImpForceScrollTextAnimNodes();
598 if(maVector.size())
600 sal_uInt32 nRelativeTime;
601 ScrollTextAnimNode* pNode = ImpGetScrollTextAnimNode(nTime, nRelativeTime);
603 if(pNode)
605 // take register time
606 nRetval = pNode->GetFrequency();
609 else
611 // #i38135# not initialized, return default
612 nRetval = mnFrequency;
615 return nRetval;
618 void ActivityImpl::updateShapeAttributes(
619 double fTime, basegfx::B2DRectangle const& parentBounds )
621 OSL_ASSERT( meAnimKind != drawing::TextAnimationKind_NONE );
622 if( meAnimKind == drawing::TextAnimationKind_NONE )
623 return;
625 double const fMixerState = GetMixerState(
626 static_cast<sal_uInt32>(fTime * 1000.0) );
628 if( meAnimKind == drawing::TextAnimationKind_BLINK )
630 // show/hide text:
631 maShapeAttrLayer.get()->setVisibility( fMixerState < 0.5 );
633 else if(mpMetaFile) // scroll mode:
636 // keep care: the below code is highly sensible to changes...
639 // rectangle of the pure text:
640 double const fPaintWidth = maPaintRectangleLogic.GetWidth();
641 double const fPaintHeight = maPaintRectangleLogic.GetHeight();
642 // rectangle where the scrolling takes place (-> clipping):
643 double const fScrollWidth = maScrollRectangleLogic.GetWidth();
644 double const fScrollHeight = maScrollRectangleLogic.GetHeight();
646 basegfx::B2DPoint pos, clipPos;
648 if(ScrollHorizontal())
650 double const fOneEquiv( fScrollWidth );
651 double const fZeroEquiv( -fPaintWidth );
653 pos.setX( fZeroEquiv + (fMixerState * (fOneEquiv - fZeroEquiv)) );
655 clipPos.setX( -pos.getX() );
656 clipPos.setY( -pos.getY() );
658 // #i69844# Compensation for text-wider-than-shape case
659 if( fPaintWidth > fScrollWidth )
660 pos.setX( pos.getX() + (fPaintWidth-fScrollWidth) / 2.0 );
662 else
664 // scroll vertical:
665 double const fOneEquiv( fScrollHeight );
666 double const fZeroEquiv( -fPaintHeight );
668 pos.setY( fZeroEquiv + (fMixerState * (fOneEquiv - fZeroEquiv)) );
670 clipPos.setX( -pos.getX() );
671 clipPos.setY( -pos.getY() );
673 // #i69844# Compensation for text-higher-than-shape case
674 if( fPaintHeight > fScrollHeight )
675 pos.setY( pos.getY() + (fPaintHeight-fScrollHeight) / 2.0 );
678 basegfx::B2DPolygon clipPoly(
679 basegfx::tools::createPolygonFromRect(
680 basegfx::B2DRectangle( clipPos.getX(),
681 clipPos.getY(),
682 clipPos.getX() + fScrollWidth,
683 clipPos.getY() + fScrollHeight ) ) );
685 if( !::basegfx::fTools::equalZero( mfRotationAngle ))
687 maShapeAttrLayer.get()->setRotationAngle( mfRotationAngle );
688 double const fRotate = (mfRotationAngle * M_PI / 180.0);
689 basegfx::B2DHomMatrix aTransform;
690 // position:
691 aTransform.rotate( fRotate );
692 pos *= aTransform;
695 pos += parentBounds.getCenter();
696 maShapeAttrLayer.get()->setPosition( pos );
697 maShapeAttrLayer.get()->setClip( basegfx::B2DPolyPolygon(clipPoly) );
701 bool ActivityImpl::perform()
703 if( !isActive() )
704 return false;
706 ENSURE_OR_RETURN(
707 mpDrawShape,
708 "ActivityImpl::perform(): still active, but NULL draw shape" );
710 DrawShapeSharedPtr const pParentDrawShape( mpParentDrawShape );
711 if( !pParentDrawShape )
712 return false; // parent has vanished
714 if( pParentDrawShape->isVisible() )
716 if( !mbIsShapeAnimated )
718 mpDrawShape->setVisibility(true); // shape may be initially hidden
719 maContext.mpSubsettableShapeManager->enterAnimationMode( mpDrawShape );
720 maTimer.reset();
721 mbIsShapeAnimated = true;
723 // update attributes related to current time:
724 basegfx::B2DRectangle const parentBounds(
725 pParentDrawShape->getBounds() );
727 const double nCurrTime( maTimer.getElapsedTime() );
728 updateShapeAttributes( nCurrTime, parentBounds );
730 const sal_uInt32 nFrequency(
731 ImpRegisterAgainScrollTextMixerState(
732 static_cast<sal_uInt32>(nCurrTime * 1000.0)) );
734 if(nFrequency)
736 mpWakeupEvent->start();
737 mpWakeupEvent->setNextTimeout(
738 std::max(0.1,nFrequency/1000.0) );
739 maContext.mrEventQueue.addEvent( mpWakeupEvent );
741 if( mpDrawShape->isContentChanged() )
742 maContext.mpSubsettableShapeManager->notifyShapeUpdate( mpDrawShape );
744 // else: finished, not need to wake up again.
746 else
748 // busy-wait, until parent shape gets visible
749 mpWakeupEvent->start();
750 mpWakeupEvent->setNextTimeout( 2.0 );
753 // don't reinsert, WakeupEvent will perform that after the given timeout:
754 return false;
757 ActivityImpl::ActivityImpl(
758 SlideShowContext const& rContext,
759 boost::shared_ptr<WakeupEvent> const& pWakeupEvent,
760 boost::shared_ptr<DrawShape> const& pParentDrawShape )
761 : maContext(rContext),
762 mpWakeupEvent(pWakeupEvent),
763 mpParentDrawShape(pParentDrawShape),
764 mpListener( new IntrinsicAnimationListener(*this) ),
765 maTimer(rContext.mrEventQueue.getTimer()),
766 mbIsShapeAnimated(false),
767 mbIsDisposed(false),
768 mbIsActive(true),
769 meAnimKind(drawing::TextAnimationKind_NONE),
770 mnStartTime(0L)
772 // get doctreenode:
773 sal_Int32 const nNodes = pParentDrawShape->getNumberOfTreeNodes(
774 DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH );
776 DocTreeNode scrollTextNode(
777 pParentDrawShape->getTreeNode(
778 0, DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ));
779 // xxx todo: remove this hack
780 if( nNodes > 1 )
781 scrollTextNode.setEndIndex(
782 pParentDrawShape->getTreeNode(
783 nNodes - 1,
784 DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ).getEndIndex());
786 // TODO(Q3): Doing this manually, instead of using
787 // ShapeSubset. This is because of lifetime issues (ShapeSubset
788 // generates circular references to parent shape)
789 mpDrawShape = boost::dynamic_pointer_cast<DrawShape>(
790 maContext.mpSubsettableShapeManager->getSubsetShape(
791 pParentDrawShape,
792 scrollTextNode ));
794 mpMetaFile = mpDrawShape->forceScrollTextMetaFile();
796 // make scroll text invisible for slide transition bitmaps
797 mpDrawShape->setVisibility(false);
799 basegfx::B2DRectangle aScrollRect, aPaintRect;
800 ENSURE_OR_THROW( getRectanglesFromScrollMtf( aScrollRect,
801 aPaintRect,
802 mpMetaFile ),
803 "ActivityImpl::ActivityImpl(): Could not extract "
804 "scroll anim rectangles from mtf" );
806 maScrollRectangleLogic = vcl::unotools::rectangleFromB2DRectangle(
807 aScrollRect );
808 maPaintRectangleLogic = vcl::unotools::rectangleFromB2DRectangle(
809 aPaintRect );
811 maShapeAttrLayer.createAttributeLayer(mpDrawShape);
813 uno::Reference<drawing::XShape> const xShape( mpDrawShape->getXShape() );
814 uno::Reference<beans::XPropertySet> const xProps( xShape, uno::UNO_QUERY_THROW );
816 getPropertyValue( meAnimKind, xProps, OUSTR("TextAnimationKind") );
817 OSL_ASSERT( meAnimKind != drawing::TextAnimationKind_NONE );
818 mbAlternate = (meAnimKind == drawing::TextAnimationKind_ALTERNATE);
819 mbScrollIn = (meAnimKind == drawing::TextAnimationKind_SLIDE);
821 // adopted from in AInfoBlinkText::ImplInit():
822 sal_Int16 nRepeat(0);
823 getPropertyValue( nRepeat, xProps, OUSTR("TextAnimationCount") );
824 mnRepeat = nRepeat;
826 if(mbAlternate)
828 // force visible when started for scroll-forth-and-back, because
829 // slide has been coming in with visible text in the middle:
830 mbVisibleWhenStarted = true;
832 else
834 getPropertyValue( mbVisibleWhenStarted, xProps,
835 OUSTR("TextAnimationStartInside") );
838 // set visible when stopped
839 getPropertyValue( mbVisibleWhenStopped, xProps,
840 OUSTR("TextAnimatiogonStopInside") );
841 // rotation:
842 getPropertyValue( mfRotationAngle, xProps,
843 OUSTR("RotateAngle") );
844 mfRotationAngle /= -100.0; // (switching direction)
846 // set frequency
847 sal_Int16 nDelay(0);
848 getPropertyValue( nDelay, xProps, OUSTR("TextAnimationDelay") );
849 // set delay if not automatic
850 mnFrequency = (nDelay ? nDelay :
851 // default:
852 meAnimKind == drawing::TextAnimationKind_BLINK
853 ? 250L : 50L );
855 // adopted from in AInfoScrollText::ImplInit():
857 // If it is a simple m_bScrollIn, reset some parameters
858 if( DoScrollIn() )
860 // most parameters are set correctly from the dialog logic, but
861 // eg VisisbleWhenStopped is grayed out and needs to be corrected here.
862 mbVisibleWhenStopped = true;
863 mbVisibleWhenStarted = false;
864 mnRepeat = 0L;
867 // Get animation direction
868 getPropertyValue( meDirection, xProps, OUSTR("TextAnimationDirection") );
870 // Get step width. Negative means pixel, positive logical units
871 getPropertyValue( mnStepWidth, xProps, OUSTR("TextAnimationAmount") );
873 maContext.mpSubsettableShapeManager->addIntrinsicAnimationHandler(
874 mpListener );
877 bool ActivityImpl::enableAnimations()
879 mbIsActive = true;
880 return maContext.mrActivitiesQueue.addActivity(
881 shared_from_this() );
884 ActivityImpl::~ActivityImpl()
888 void ActivityImpl::dispose()
890 if( !mbIsDisposed )
892 end();
894 // only remove subset here, since end() is called on slide end
895 // (and we must not spoil the slide preview bitmap with scroll
896 // text)
897 maShapeAttrLayer.reset();
898 if( mpDrawShape )
900 // TODO(Q3): Doing this manually, instead of using
901 // ShapeSubset. This is because of lifetime issues
902 // (ShapeSubset generates circular references to parent
903 // shape)
904 DrawShapeSharedPtr pParent( mpParentDrawShape.lock() );
905 if( pParent )
906 maContext.mpSubsettableShapeManager->revokeSubset(
907 pParent,
908 mpDrawShape );
911 mpMetaFile.reset();
912 mpDrawShape.reset();
913 mpParentDrawShape.reset();
914 mpWakeupEvent.reset();
915 maContext.dispose();
916 mbIsDisposed = true;
918 maContext.mpSubsettableShapeManager->removeIntrinsicAnimationHandler(
919 mpListener );
923 double ActivityImpl::calcTimeLag() const
925 return 0.0;
928 bool ActivityImpl::isActive() const
930 return mbIsActive;
933 void ActivityImpl::dequeued()
935 // not used here
938 void ActivityImpl::end()
940 // not used here
941 mbIsActive = false;
943 if( mbIsShapeAnimated )
945 maContext.mpSubsettableShapeManager->leaveAnimationMode( mpDrawShape );
946 mbIsShapeAnimated = false;
950 } // anon namespace
952 namespace slideshow {
953 namespace internal {
955 boost::shared_ptr<Activity> createDrawingLayerAnimActivity(
956 SlideShowContext const& rContext,
957 boost::shared_ptr<DrawShape> const& pDrawShape )
959 boost::shared_ptr<Activity> pActivity;
963 boost::shared_ptr<WakeupEvent> const pWakeupEvent(
964 new WakeupEvent( rContext.mrEventQueue.getTimer(),
965 rContext.mrActivitiesQueue ) );
966 pActivity.reset( new ActivityImpl( rContext, pWakeupEvent, pDrawShape ) );
967 pWakeupEvent->setActivity( pActivity );
969 catch( uno::RuntimeException& )
971 throw;
973 catch( uno::Exception& )
975 // translate any error into empty factory product.
976 OSL_ENSURE( false,
977 rtl::OUStringToOString(
978 comphelper::anyToString( cppu::getCaughtException() ),
979 RTL_TEXTENCODING_UTF8 ).getStr() );
982 return pActivity;
985 } // namespace internal
986 } // namespace presentation