1*70f497fbSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*70f497fbSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*70f497fbSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*70f497fbSAndrew Rist  * distributed with this work for additional information
6*70f497fbSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*70f497fbSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*70f497fbSAndrew Rist  * "License"); you may not use this file except in compliance
9*70f497fbSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*70f497fbSAndrew Rist  *
11*70f497fbSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*70f497fbSAndrew Rist  *
13*70f497fbSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*70f497fbSAndrew Rist  * software distributed under the License is distributed on an
15*70f497fbSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*70f497fbSAndrew Rist  * KIND, either express or implied.  See the License for the
17*70f497fbSAndrew Rist  * specific language governing permissions and limitations
18*70f497fbSAndrew Rist  * under the License.
19*70f497fbSAndrew Rist  *
20*70f497fbSAndrew Rist  *************************************************************/
21*70f497fbSAndrew Rist 
22*70f497fbSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_slideshow.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <canvas/debug.hxx>
28cdf0e10cSrcweir #include <tools/diagnose_ex.h>
29cdf0e10cSrcweir #include <canvas/elapsedtime.hxx>
30cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx>
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include <comphelper/anytostring.hxx>
33cdf0e10cSrcweir #include <cppuhelper/exc_hlp.hxx>
34cdf0e10cSrcweir 
35cdf0e10cSrcweir #include <rtl/math.hxx>
36cdf0e10cSrcweir #include <vcl/metric.hxx>
37cdf0e10cSrcweir #include <vcl/salbtype.hxx>
38cdf0e10cSrcweir #include <vcl/canvastools.hxx>
39cdf0e10cSrcweir #include <vcl/metaact.hxx>
40cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp>
41cdf0e10cSrcweir #include <com/sun/star/drawing/TextAnimationKind.hpp>
42cdf0e10cSrcweir #include <com/sun/star/drawing/TextAnimationDirection.hpp>
43cdf0e10cSrcweir #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
44cdf0e10cSrcweir #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
45cdf0e10cSrcweir #include <com/sun/star/drawing/HomogenMatrix3.hpp>
46cdf0e10cSrcweir #include <com/sun/star/awt/Rectangle.hpp>
47cdf0e10cSrcweir 
48cdf0e10cSrcweir #include "activity.hxx"
49cdf0e10cSrcweir #include "wakeupevent.hxx"
50cdf0e10cSrcweir #include "eventqueue.hxx"
51cdf0e10cSrcweir #include "drawshapesubsetting.hxx"
52cdf0e10cSrcweir #include "drawshape.hxx"
53cdf0e10cSrcweir #include "shapesubset.hxx"
54cdf0e10cSrcweir #include "shapeattributelayerholder.hxx"
55cdf0e10cSrcweir #include "slideshowcontext.hxx"
56cdf0e10cSrcweir #include "tools.hxx"
57cdf0e10cSrcweir #include "gdimtftools.hxx"
58cdf0e10cSrcweir #include "eventmultiplexer.hxx"
59cdf0e10cSrcweir #include "intrinsicanimationactivity.hxx"
60cdf0e10cSrcweir #include "intrinsicanimationeventhandler.hxx"
61cdf0e10cSrcweir 
62cdf0e10cSrcweir #include <boost/weak_ptr.hpp>
63cdf0e10cSrcweir #include <boost/enable_shared_from_this.hpp>
64cdf0e10cSrcweir #include <boost/noncopyable.hpp>
65cdf0e10cSrcweir #include <vector>
66cdf0e10cSrcweir 
67cdf0e10cSrcweir using namespace com::sun::star;
68cdf0e10cSrcweir using namespace ::slideshow::internal;
69cdf0e10cSrcweir 
70cdf0e10cSrcweir namespace {
71cdf0e10cSrcweir 
72cdf0e10cSrcweir class ScrollTextAnimNode
73cdf0e10cSrcweir {
74cdf0e10cSrcweir     sal_uInt32  mnDuration; // single duration
75cdf0e10cSrcweir     sal_uInt32  mnRepeat; // 0 -> endless
76cdf0e10cSrcweir     double      mfStart;
77cdf0e10cSrcweir     double      mfStop;
78cdf0e10cSrcweir     sal_uInt32  mnFrequency; // in ms
79cdf0e10cSrcweir     // forth and back change at mnRepeat%2:
80cdf0e10cSrcweir     bool        mbAlternate;
81cdf0e10cSrcweir 
82cdf0e10cSrcweir public:
ScrollTextAnimNode(sal_uInt32 nDuration,sal_uInt32 nRepeat,double fStart,double fStop,sal_uInt32 nFrequency,bool bAlternate)83cdf0e10cSrcweir     ScrollTextAnimNode(
84cdf0e10cSrcweir         sal_uInt32 nDuration, sal_uInt32 nRepeat, double fStart, double fStop,
85cdf0e10cSrcweir         sal_uInt32 nFrequency, bool bAlternate)
86cdf0e10cSrcweir         :   mnDuration(nDuration),
87cdf0e10cSrcweir             mnRepeat(nRepeat),
88cdf0e10cSrcweir             mfStart(fStart),
89cdf0e10cSrcweir             mfStop(fStop),
90cdf0e10cSrcweir             mnFrequency(nFrequency),
91cdf0e10cSrcweir             mbAlternate(bAlternate)
92cdf0e10cSrcweir         {}
93cdf0e10cSrcweir 
GetDuration() const94cdf0e10cSrcweir     sal_uInt32 GetDuration() const { return mnDuration; }
GetRepeat() const95cdf0e10cSrcweir     sal_uInt32 GetRepeat() const { return mnRepeat; }
GetFullTime() const96cdf0e10cSrcweir     sal_uInt32 GetFullTime() const { return mnDuration * mnRepeat; }
GetStart() const97cdf0e10cSrcweir     double GetStart() const { return mfStart; }
GetStop() const98cdf0e10cSrcweir     double GetStop() const { return mfStop; }
GetFrequency() const99cdf0e10cSrcweir     sal_uInt32 GetFrequency() const { return mnFrequency; }
DoAlternate() const100cdf0e10cSrcweir     bool DoAlternate() const { return mbAlternate; }
101cdf0e10cSrcweir 
102cdf0e10cSrcweir     double GetStateAtRelativeTime(sal_uInt32 nRelativeTime) const;
103cdf0e10cSrcweir };
104cdf0e10cSrcweir 
GetStateAtRelativeTime(sal_uInt32 nRelativeTime) const105cdf0e10cSrcweir double ScrollTextAnimNode::GetStateAtRelativeTime(
106cdf0e10cSrcweir     sal_uInt32 nRelativeTime) const
107cdf0e10cSrcweir {
108cdf0e10cSrcweir     // #151174# Avoid division by zero.
109cdf0e10cSrcweir     if( mnDuration == 0 )
110cdf0e10cSrcweir         return mfStop;
111cdf0e10cSrcweir 
112cdf0e10cSrcweir     if(mnRepeat)
113cdf0e10cSrcweir     {
114cdf0e10cSrcweir         // ending
115cdf0e10cSrcweir         const sal_uInt32 nRepeatCount(nRelativeTime / mnDuration);
116cdf0e10cSrcweir         sal_uInt32 nFrameTime(nRelativeTime - (nRepeatCount * mnDuration));
117cdf0e10cSrcweir 
118cdf0e10cSrcweir         if(DoAlternate() && (nRepeatCount + 1L) % 2L)
119cdf0e10cSrcweir             nFrameTime = mnDuration - nFrameTime;
120cdf0e10cSrcweir 
121cdf0e10cSrcweir         return mfStart + ((mfStop - mfStart) *
122cdf0e10cSrcweir                           (double(nFrameTime) / mnDuration));
123cdf0e10cSrcweir     }
124cdf0e10cSrcweir     else
125cdf0e10cSrcweir     {
126cdf0e10cSrcweir         // endless
127cdf0e10cSrcweir         sal_uInt32 nFrameTime(nRelativeTime % mnDuration);
128cdf0e10cSrcweir 
129cdf0e10cSrcweir         if(DoAlternate())
130cdf0e10cSrcweir         {
131cdf0e10cSrcweir             const sal_uInt32 nRepeatCount(nRelativeTime / mnDuration);
132cdf0e10cSrcweir 
133cdf0e10cSrcweir             if((nRepeatCount + 1L) % 2L)
134cdf0e10cSrcweir                 nFrameTime = mnDuration - nFrameTime;
135cdf0e10cSrcweir         }
136cdf0e10cSrcweir 
137cdf0e10cSrcweir         return mfStart + ((mfStop - mfStart) * (double(nFrameTime) / mnDuration));
138cdf0e10cSrcweir     }
139cdf0e10cSrcweir }
140cdf0e10cSrcweir 
141cdf0e10cSrcweir class ActivityImpl : public Activity,
142cdf0e10cSrcweir                      public boost::enable_shared_from_this<ActivityImpl>,
143cdf0e10cSrcweir                      private boost::noncopyable
144cdf0e10cSrcweir {
145cdf0e10cSrcweir public:
146cdf0e10cSrcweir     virtual ~ActivityImpl();
147cdf0e10cSrcweir 
148cdf0e10cSrcweir     ActivityImpl(
149cdf0e10cSrcweir         SlideShowContext const& rContext,
150cdf0e10cSrcweir         boost::shared_ptr<WakeupEvent> const& pWakeupEvent,
151cdf0e10cSrcweir         boost::shared_ptr<DrawShape> const& pDrawShape );
152cdf0e10cSrcweir 
153cdf0e10cSrcweir     bool enableAnimations();
154cdf0e10cSrcweir 
155cdf0e10cSrcweir     // Disposable:
156cdf0e10cSrcweir     virtual void dispose();
157cdf0e10cSrcweir     // Activity:
158cdf0e10cSrcweir     virtual double calcTimeLag() const;
159cdf0e10cSrcweir     virtual bool perform();
160cdf0e10cSrcweir     virtual bool isActive() const;
161cdf0e10cSrcweir     virtual void dequeued();
162cdf0e10cSrcweir     virtual void end();
163cdf0e10cSrcweir 
164cdf0e10cSrcweir private:
165cdf0e10cSrcweir     void updateShapeAttributes( double fTime,
166cdf0e10cSrcweir                                 basegfx::B2DRectangle const& parentBounds );
167cdf0e10cSrcweir 
168cdf0e10cSrcweir     // Access to VisibleWhenSTarted flags
IsVisibleWhenStarted() const169cdf0e10cSrcweir     sal_Bool IsVisibleWhenStarted() const { return mbVisibleWhenStarted; }
IsVisibleWhenStopped() const170cdf0e10cSrcweir     sal_Bool IsVisibleWhenStopped() const { return mbVisibleWhenStopped; }
171cdf0e10cSrcweir 
172cdf0e10cSrcweir     // scroll horizontal? if sal_False, scroll is vertical.
ScrollHorizontal() const173cdf0e10cSrcweir     bool ScrollHorizontal() const {
174cdf0e10cSrcweir         return (drawing::TextAnimationDirection_LEFT == meDirection ||
175cdf0e10cSrcweir                 drawing::TextAnimationDirection_RIGHT == meDirection);
176cdf0e10cSrcweir     }
177cdf0e10cSrcweir 
178cdf0e10cSrcweir     // Access to StepWidth in logical units
179cdf0e10cSrcweir     sal_uInt32 GetStepWidthLogic() const;
180cdf0e10cSrcweir 
181cdf0e10cSrcweir     // is the animation direction opposite?
DoScrollForward() const182cdf0e10cSrcweir     bool DoScrollForward() const {
183cdf0e10cSrcweir         return (drawing::TextAnimationDirection_RIGHT == meDirection ||
184cdf0e10cSrcweir                 drawing::TextAnimationDirection_DOWN == meDirection);
185cdf0e10cSrcweir     }
186cdf0e10cSrcweir 
187cdf0e10cSrcweir     // do alternate text directions?
DoAlternate() const188cdf0e10cSrcweir     bool DoAlternate() const { return mbAlternate; }
189cdf0e10cSrcweir 
190cdf0e10cSrcweir     // do scroll in?
DoScrollIn() const191cdf0e10cSrcweir     bool DoScrollIn() const { return mbScrollIn; }
192cdf0e10cSrcweir 
193cdf0e10cSrcweir     // Scroll helper methods
194cdf0e10cSrcweir     void ImpForceScrollTextAnimNodes();
195cdf0e10cSrcweir     ScrollTextAnimNode* ImpGetScrollTextAnimNode(
196cdf0e10cSrcweir         sal_uInt32 nTime, sal_uInt32& rRelativeTime );
197cdf0e10cSrcweir     sal_uInt32 ImpRegisterAgainScrollTextMixerState(
198cdf0e10cSrcweir         sal_uInt32 nTime);
199cdf0e10cSrcweir 
200cdf0e10cSrcweir     // calculate the MixerState value for given time
201cdf0e10cSrcweir     double GetMixerState(sal_uInt32 nTime);
202cdf0e10cSrcweir 
203cdf0e10cSrcweir     ////////////////////////////////////////////////////////////////////
204cdf0e10cSrcweir 
205cdf0e10cSrcweir     SlideShowContext                            maContext;
206cdf0e10cSrcweir     boost::shared_ptr<WakeupEvent>              mpWakeupEvent;
207cdf0e10cSrcweir     boost::weak_ptr<DrawShape>                  mpParentDrawShape;
208cdf0e10cSrcweir     DrawShapeSharedPtr                          mpDrawShape;
209cdf0e10cSrcweir     ShapeAttributeLayerHolder                   maShapeAttrLayer;
210cdf0e10cSrcweir     GDIMetaFileSharedPtr                        mpMetaFile;
211cdf0e10cSrcweir     IntrinsicAnimationEventHandlerSharedPtr     mpListener;
212cdf0e10cSrcweir     canvas::tools::ElapsedTime                  maTimer;
213cdf0e10cSrcweir     double                                      mfRotationAngle;
214cdf0e10cSrcweir     bool                                        mbIsShapeAnimated;
215cdf0e10cSrcweir     bool                                        mbIsDisposed;
216cdf0e10cSrcweir     bool                                        mbIsActive;
217cdf0e10cSrcweir     drawing::TextAnimationKind                  meAnimKind;
218cdf0e10cSrcweir 
219cdf0e10cSrcweir     // The blink frequency in ms
220cdf0e10cSrcweir     sal_uInt32                                  mnFrequency;
221cdf0e10cSrcweir 
222cdf0e10cSrcweir     // The repeat count, init to 0L which means endless
223cdf0e10cSrcweir     sal_uInt32                                  mnRepeat;
224cdf0e10cSrcweir 
225cdf0e10cSrcweir     // Flag to decide if text will be shown when animation has ended
226cdf0e10cSrcweir     bool                                        mbVisibleWhenStopped;
227cdf0e10cSrcweir     bool                                        mbVisibleWhenStarted;
228cdf0e10cSrcweir 
229cdf0e10cSrcweir     // Flag decides if TextScroll alternates. Default is sal_False.
230cdf0e10cSrcweir     bool                                        mbAlternate;
231cdf0e10cSrcweir 
232cdf0e10cSrcweir     // Flag to remember if this is a simple scrollin text
233cdf0e10cSrcweir     bool                                        mbScrollIn;
234cdf0e10cSrcweir 
235cdf0e10cSrcweir     // start time for this animation
236cdf0e10cSrcweir     sal_uInt32                                  mnStartTime;
237cdf0e10cSrcweir 
238cdf0e10cSrcweir     // The AnimationDirection
239cdf0e10cSrcweir     drawing::TextAnimationDirection             meDirection;
240cdf0e10cSrcweir 
241cdf0e10cSrcweir     // Get width per Step. Negative means pixel, positive logical units
242cdf0e10cSrcweir     sal_Int32                                   mnStepWidth;
243cdf0e10cSrcweir 
244cdf0e10cSrcweir     // The single anim steps
245cdf0e10cSrcweir     std::vector< ScrollTextAnimNode >           maVector;
246cdf0e10cSrcweir 
247cdf0e10cSrcweir     // the scroll rectangle
248cdf0e10cSrcweir     Rectangle                                   maScrollRectangleLogic;
249cdf0e10cSrcweir 
250cdf0e10cSrcweir     // the paint rectangle
251cdf0e10cSrcweir     Rectangle                                   maPaintRectangleLogic;
252cdf0e10cSrcweir };
253cdf0e10cSrcweir 
254cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////
255cdf0e10cSrcweir 
256cdf0e10cSrcweir class IntrinsicAnimationListener : public IntrinsicAnimationEventHandler,
257cdf0e10cSrcweir                                    private boost::noncopyable
258cdf0e10cSrcweir {
259cdf0e10cSrcweir public:
IntrinsicAnimationListener(ActivityImpl & rActivity)260cdf0e10cSrcweir     explicit IntrinsicAnimationListener( ActivityImpl& rActivity ) :
261cdf0e10cSrcweir         mrActivity( rActivity )
262cdf0e10cSrcweir     {}
263cdf0e10cSrcweir 
264cdf0e10cSrcweir private:
265cdf0e10cSrcweir 
enableAnimations()266cdf0e10cSrcweir     virtual bool enableAnimations() { return mrActivity.enableAnimations(); }
disableAnimations()267cdf0e10cSrcweir     virtual bool disableAnimations() { mrActivity.end(); return true; }
268cdf0e10cSrcweir 
269cdf0e10cSrcweir     ActivityImpl& mrActivity;
270cdf0e10cSrcweir };
271cdf0e10cSrcweir 
272cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////
273cdf0e10cSrcweir 
GetMixerState(sal_uInt32 nTime)274cdf0e10cSrcweir double ActivityImpl::GetMixerState( sal_uInt32 nTime )
275cdf0e10cSrcweir {
276cdf0e10cSrcweir     if( meAnimKind == drawing::TextAnimationKind_BLINK )
277cdf0e10cSrcweir     {
278cdf0e10cSrcweir         // from AInfoBlinkText:
279cdf0e10cSrcweir         double fRetval(0.0);
280cdf0e10cSrcweir         sal_Bool bDone(sal_False);
281cdf0e10cSrcweir         const sal_uInt32 nLoopTime(2 * mnFrequency);
282cdf0e10cSrcweir 
283cdf0e10cSrcweir         if(mnRepeat)
284cdf0e10cSrcweir         {
285cdf0e10cSrcweir             const sal_uInt32 nEndTime(mnRepeat * nLoopTime);
286cdf0e10cSrcweir 
287cdf0e10cSrcweir             if(nTime >= nEndTime)
288cdf0e10cSrcweir             {
289cdf0e10cSrcweir                 if(mbVisibleWhenStopped)
290cdf0e10cSrcweir                     fRetval = 0.0;
291cdf0e10cSrcweir                 else
292cdf0e10cSrcweir                     fRetval = 1.0;
293cdf0e10cSrcweir 
294cdf0e10cSrcweir                 bDone = sal_True;
295cdf0e10cSrcweir             }
296cdf0e10cSrcweir         }
297cdf0e10cSrcweir 
298cdf0e10cSrcweir         if(!bDone)
299cdf0e10cSrcweir         {
300cdf0e10cSrcweir             sal_uInt32 nTimeInLoop(nTime % nLoopTime);
301cdf0e10cSrcweir             fRetval = double(nTimeInLoop) / nLoopTime;
302cdf0e10cSrcweir         }
303cdf0e10cSrcweir 
304cdf0e10cSrcweir         return fRetval;
305cdf0e10cSrcweir     }
306cdf0e10cSrcweir     else
307cdf0e10cSrcweir     {
308cdf0e10cSrcweir         // from AInfoScrollText:
309cdf0e10cSrcweir         double fRetval(0.0);
310cdf0e10cSrcweir         ImpForceScrollTextAnimNodes();
311cdf0e10cSrcweir 
312cdf0e10cSrcweir         if(!maVector.empty())
313cdf0e10cSrcweir         {
314cdf0e10cSrcweir             sal_uInt32 nRelativeTime;
315cdf0e10cSrcweir             ScrollTextAnimNode* pNode =
316cdf0e10cSrcweir                 ImpGetScrollTextAnimNode(nTime, nRelativeTime);
317cdf0e10cSrcweir 
318cdf0e10cSrcweir             if(pNode)
319cdf0e10cSrcweir             {
320cdf0e10cSrcweir                 // use node
321cdf0e10cSrcweir                 fRetval = pNode->GetStateAtRelativeTime(nRelativeTime);
322cdf0e10cSrcweir             }
323cdf0e10cSrcweir             else
324cdf0e10cSrcweir             {
325cdf0e10cSrcweir                 // end of animation, take last entry's end
326cdf0e10cSrcweir                 fRetval = maVector[maVector.size() - 1L].GetStop();
327cdf0e10cSrcweir             }
328cdf0e10cSrcweir         }
329cdf0e10cSrcweir 
330cdf0e10cSrcweir         return fRetval;
331cdf0e10cSrcweir     }
332cdf0e10cSrcweir }
333cdf0e10cSrcweir 
334cdf0e10cSrcweir // Access to StepWidth in logical units
GetStepWidthLogic() const335cdf0e10cSrcweir sal_uInt32 ActivityImpl::GetStepWidthLogic() const
336cdf0e10cSrcweir {
337cdf0e10cSrcweir     // #i69847# Assuming higher DPI
338cdf0e10cSrcweir     sal_uInt32 const PIXEL_TO_LOGIC = 30;
339cdf0e10cSrcweir 
340cdf0e10cSrcweir     sal_uInt32 nRetval(0L);
341cdf0e10cSrcweir 
342cdf0e10cSrcweir     if(mnStepWidth < 0L)
343cdf0e10cSrcweir     {
344cdf0e10cSrcweir         // is in pixels, convert to logical units
345cdf0e10cSrcweir         nRetval = (-mnStepWidth * PIXEL_TO_LOGIC);
346cdf0e10cSrcweir     }
347cdf0e10cSrcweir     else if(mnStepWidth > 0L)
348cdf0e10cSrcweir     {
349cdf0e10cSrcweir         // is in logical units
350cdf0e10cSrcweir         nRetval = mnStepWidth;
351cdf0e10cSrcweir     }
352cdf0e10cSrcweir 
353cdf0e10cSrcweir     if(0L == nRetval)
354cdf0e10cSrcweir     {
355cdf0e10cSrcweir         // step 1 pixel, canned value
356cdf0e10cSrcweir 
357cdf0e10cSrcweir         // #128389# with very high DPIs like in PDF export, this can
358cdf0e10cSrcweir         // still get zero.  for that cases, set a default, too (taken
359cdf0e10cSrcweir         // from ainfoscrolltext.cxx)
360cdf0e10cSrcweir         nRetval = 100L;
361cdf0e10cSrcweir     }
362cdf0e10cSrcweir 
363cdf0e10cSrcweir     return nRetval;
364cdf0e10cSrcweir }
365cdf0e10cSrcweir 
ImpForceScrollTextAnimNodes()366cdf0e10cSrcweir void ActivityImpl::ImpForceScrollTextAnimNodes()
367cdf0e10cSrcweir {
368cdf0e10cSrcweir     if(maVector.empty())
369cdf0e10cSrcweir     {
370cdf0e10cSrcweir         // prepare values
371cdf0e10cSrcweir         sal_uInt32 nLoopTime;
372cdf0e10cSrcweir         double fZeroLogic, fOneLogic, fInitLogic, fDistanceLogic;
373cdf0e10cSrcweir         double fZeroLogicAlternate = 0.0, fOneLogicAlternate = 0.0;
374cdf0e10cSrcweir         double fZeroRelative, fOneRelative, fInitRelative,fDistanceRelative;
375cdf0e10cSrcweir 
376cdf0e10cSrcweir         if(ScrollHorizontal())
377cdf0e10cSrcweir         {
378cdf0e10cSrcweir             if(DoAlternate())
379cdf0e10cSrcweir             {
380cdf0e10cSrcweir                 if(maPaintRectangleLogic.GetWidth() >
381cdf0e10cSrcweir                    maScrollRectangleLogic.GetWidth())
382cdf0e10cSrcweir                 {
383cdf0e10cSrcweir                     fZeroLogicAlternate = maScrollRectangleLogic.Right() - maPaintRectangleLogic.GetWidth();
384cdf0e10cSrcweir                     fOneLogicAlternate = maScrollRectangleLogic.Left();
385cdf0e10cSrcweir                 }
386cdf0e10cSrcweir                 else
387cdf0e10cSrcweir                 {
388cdf0e10cSrcweir                     fZeroLogicAlternate = maScrollRectangleLogic.Left();
389cdf0e10cSrcweir                     fOneLogicAlternate = maScrollRectangleLogic.Right() - maPaintRectangleLogic.GetWidth();
390cdf0e10cSrcweir                 }
391cdf0e10cSrcweir             }
392cdf0e10cSrcweir 
393cdf0e10cSrcweir             fZeroLogic = maScrollRectangleLogic.Left() - maPaintRectangleLogic.GetWidth();
394cdf0e10cSrcweir             fOneLogic = maScrollRectangleLogic.Right();
395cdf0e10cSrcweir             fInitLogic = maPaintRectangleLogic.Left();
396cdf0e10cSrcweir         }
397cdf0e10cSrcweir         else
398cdf0e10cSrcweir         {
399cdf0e10cSrcweir             if(DoAlternate())
400cdf0e10cSrcweir             {
401cdf0e10cSrcweir                 if(maPaintRectangleLogic.GetHeight() > maScrollRectangleLogic.GetHeight())
402cdf0e10cSrcweir                 {
403cdf0e10cSrcweir                     fZeroLogicAlternate = maScrollRectangleLogic.Bottom() - maPaintRectangleLogic.GetHeight();
404cdf0e10cSrcweir                     fOneLogicAlternate = maScrollRectangleLogic.Top();
405cdf0e10cSrcweir                 }
406cdf0e10cSrcweir                 else
407cdf0e10cSrcweir                 {
408cdf0e10cSrcweir                     fZeroLogicAlternate = maScrollRectangleLogic.Top();
409cdf0e10cSrcweir                     fOneLogicAlternate = maScrollRectangleLogic.Bottom() - maPaintRectangleLogic.GetHeight();
410cdf0e10cSrcweir                 }
411cdf0e10cSrcweir             }
412cdf0e10cSrcweir 
413cdf0e10cSrcweir             fZeroLogic = maScrollRectangleLogic.Top() - maPaintRectangleLogic.GetHeight();
414cdf0e10cSrcweir             fOneLogic = maScrollRectangleLogic.Bottom();
415cdf0e10cSrcweir             fInitLogic = maPaintRectangleLogic.Top();
416cdf0e10cSrcweir         }
417cdf0e10cSrcweir 
418cdf0e10cSrcweir         fDistanceLogic = fOneLogic - fZeroLogic;
419cdf0e10cSrcweir         fInitRelative = (fInitLogic - fZeroLogic) / fDistanceLogic;
420cdf0e10cSrcweir 
421cdf0e10cSrcweir         if(DoAlternate())
422cdf0e10cSrcweir         {
423cdf0e10cSrcweir             fZeroRelative =
424cdf0e10cSrcweir                 (fZeroLogicAlternate - fZeroLogic) / fDistanceLogic;
425cdf0e10cSrcweir             fOneRelative =
426cdf0e10cSrcweir                 (fOneLogicAlternate - fZeroLogic) / fDistanceLogic;
427cdf0e10cSrcweir             fDistanceRelative = fOneRelative - fZeroRelative;
428cdf0e10cSrcweir         }
429cdf0e10cSrcweir         else
430cdf0e10cSrcweir         {
431cdf0e10cSrcweir             fZeroRelative = 0.0;
432cdf0e10cSrcweir             fOneRelative = 1.0;
433cdf0e10cSrcweir             fDistanceRelative = 1.0;
434cdf0e10cSrcweir         }
435cdf0e10cSrcweir 
436cdf0e10cSrcweir         if(mnStartTime)
437cdf0e10cSrcweir         {
438cdf0e10cSrcweir             // Start time loop
439cdf0e10cSrcweir             ScrollTextAnimNode aStartNode(
440cdf0e10cSrcweir                 mnStartTime, 1L, 0.0, 0.0, mnStartTime, false);
441cdf0e10cSrcweir             maVector.push_back(aStartNode);
442cdf0e10cSrcweir         }
443cdf0e10cSrcweir 
444cdf0e10cSrcweir         if(IsVisibleWhenStarted())
445cdf0e10cSrcweir         {
446cdf0e10cSrcweir             double fRelativeStartValue, fRelativeEndValue,fRelativeDistance;
447cdf0e10cSrcweir 
448cdf0e10cSrcweir             if(DoScrollForward())
449cdf0e10cSrcweir             {
450cdf0e10cSrcweir                 fRelativeStartValue = fInitRelative;
451cdf0e10cSrcweir                 fRelativeEndValue = fOneRelative;
452cdf0e10cSrcweir                 fRelativeDistance = fRelativeEndValue - fRelativeStartValue;
453cdf0e10cSrcweir             }
454cdf0e10cSrcweir             else
455cdf0e10cSrcweir             {
456cdf0e10cSrcweir                 fRelativeStartValue = fInitRelative;
457cdf0e10cSrcweir                 fRelativeEndValue = fZeroRelative;
458cdf0e10cSrcweir                 fRelativeDistance = fRelativeStartValue - fRelativeEndValue;
459cdf0e10cSrcweir             }
460cdf0e10cSrcweir 
461cdf0e10cSrcweir             const double fNumberSteps =
462cdf0e10cSrcweir                 (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic();
463cdf0e10cSrcweir             nLoopTime = FRound(fNumberSteps * mnFrequency);
464cdf0e10cSrcweir 
465cdf0e10cSrcweir             // init loop
466cdf0e10cSrcweir             ScrollTextAnimNode aInitNode(
467cdf0e10cSrcweir                 nLoopTime, 1L,
468cdf0e10cSrcweir                 fRelativeStartValue, fRelativeEndValue,
469cdf0e10cSrcweir                 mnFrequency, false);
470cdf0e10cSrcweir             maVector.push_back(aInitNode);
471cdf0e10cSrcweir         }
472cdf0e10cSrcweir 
473cdf0e10cSrcweir         // prepare main loop values
474cdf0e10cSrcweir         {
475cdf0e10cSrcweir             double fRelativeStartValue, fRelativeEndValue, fRelativeDistance;
476cdf0e10cSrcweir 
477cdf0e10cSrcweir             if(DoScrollForward())
478cdf0e10cSrcweir             {
479cdf0e10cSrcweir                 fRelativeStartValue = fZeroRelative;
480cdf0e10cSrcweir                 fRelativeEndValue = fOneRelative;
481cdf0e10cSrcweir                 fRelativeDistance = fRelativeEndValue - fRelativeStartValue;
482cdf0e10cSrcweir             }
483cdf0e10cSrcweir             else
484cdf0e10cSrcweir             {
485cdf0e10cSrcweir                 fRelativeStartValue = fOneRelative;
486cdf0e10cSrcweir                 fRelativeEndValue = fZeroRelative;
487cdf0e10cSrcweir                 fRelativeDistance = fRelativeStartValue - fRelativeEndValue;
488cdf0e10cSrcweir             }
489cdf0e10cSrcweir 
490cdf0e10cSrcweir             const double fNumberSteps =
491cdf0e10cSrcweir                 (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic();
492cdf0e10cSrcweir             nLoopTime = FRound(fNumberSteps * mnFrequency);
493cdf0e10cSrcweir 
494cdf0e10cSrcweir             if(0L == mnRepeat)
495cdf0e10cSrcweir             {
496cdf0e10cSrcweir                 if(!DoScrollIn())
497cdf0e10cSrcweir                 {
498cdf0e10cSrcweir                     // endless main loop
499cdf0e10cSrcweir                     ScrollTextAnimNode aMainNode(
500cdf0e10cSrcweir                         nLoopTime, 0L,
501cdf0e10cSrcweir                         fRelativeStartValue, fRelativeEndValue,
502cdf0e10cSrcweir                         mnFrequency, DoAlternate());
503cdf0e10cSrcweir                     maVector.push_back(aMainNode);
504cdf0e10cSrcweir                 }
505cdf0e10cSrcweir             }
506cdf0e10cSrcweir             else
507cdf0e10cSrcweir             {
508cdf0e10cSrcweir                 sal_uInt32 nNumRepeat(mnRepeat);
509cdf0e10cSrcweir 
510cdf0e10cSrcweir                 if(DoAlternate() && (nNumRepeat + 1L) % 2L)
511cdf0e10cSrcweir                     nNumRepeat += 1L;
512cdf0e10cSrcweir 
513cdf0e10cSrcweir                 // ending main loop
514cdf0e10cSrcweir                 ScrollTextAnimNode aMainNode(
515cdf0e10cSrcweir                     nLoopTime, nNumRepeat,
516cdf0e10cSrcweir                     fRelativeStartValue, fRelativeEndValue,
517cdf0e10cSrcweir                     mnFrequency, DoAlternate());
518cdf0e10cSrcweir                 maVector.push_back(aMainNode);
519cdf0e10cSrcweir             }
520cdf0e10cSrcweir         }
521cdf0e10cSrcweir 
522cdf0e10cSrcweir         if(IsVisibleWhenStopped())
523cdf0e10cSrcweir         {
524cdf0e10cSrcweir             double fRelativeStartValue, fRelativeEndValue, fRelativeDistance;
525cdf0e10cSrcweir 
526cdf0e10cSrcweir             if(DoScrollForward())
527cdf0e10cSrcweir             {
528cdf0e10cSrcweir                 fRelativeStartValue = fZeroRelative;
529cdf0e10cSrcweir                 fRelativeEndValue = fInitRelative;
530cdf0e10cSrcweir                 fRelativeDistance = fRelativeEndValue - fRelativeStartValue;
531cdf0e10cSrcweir             }
532cdf0e10cSrcweir             else
533cdf0e10cSrcweir             {
534cdf0e10cSrcweir                 fRelativeStartValue = fOneRelative;
535cdf0e10cSrcweir                 fRelativeEndValue = fInitRelative;
536cdf0e10cSrcweir                 fRelativeDistance = fRelativeStartValue - fRelativeEndValue;
537cdf0e10cSrcweir             }
538cdf0e10cSrcweir 
539cdf0e10cSrcweir             const double fNumberSteps =
540cdf0e10cSrcweir                 (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic();
541cdf0e10cSrcweir             nLoopTime = FRound(fNumberSteps * mnFrequency);
542cdf0e10cSrcweir 
543cdf0e10cSrcweir             // exit loop
544cdf0e10cSrcweir             ScrollTextAnimNode aExitNode(
545cdf0e10cSrcweir                 nLoopTime, 1L,
546cdf0e10cSrcweir                 fRelativeStartValue, fRelativeEndValue, mnFrequency, false);
547cdf0e10cSrcweir             maVector.push_back(aExitNode);
548cdf0e10cSrcweir         }
549cdf0e10cSrcweir     }
550cdf0e10cSrcweir }
551cdf0e10cSrcweir 
ImpGetScrollTextAnimNode(sal_uInt32 nTime,sal_uInt32 & rRelativeTime)552cdf0e10cSrcweir ScrollTextAnimNode* ActivityImpl::ImpGetScrollTextAnimNode(
553cdf0e10cSrcweir     sal_uInt32 nTime, sal_uInt32& rRelativeTime )
554cdf0e10cSrcweir {
555cdf0e10cSrcweir     ScrollTextAnimNode* pRetval = 0L;
556cdf0e10cSrcweir     ImpForceScrollTextAnimNodes();
557cdf0e10cSrcweir 
558cdf0e10cSrcweir     if(!maVector.empty())
559cdf0e10cSrcweir     {
560cdf0e10cSrcweir         rRelativeTime = nTime;
561cdf0e10cSrcweir 
562cdf0e10cSrcweir         for(sal_uInt32 a(0L); !pRetval && a < maVector.size(); a++)
563cdf0e10cSrcweir         {
564cdf0e10cSrcweir             ScrollTextAnimNode & rNode = maVector[a];
565cdf0e10cSrcweir             if(!rNode.GetRepeat())
566cdf0e10cSrcweir             {
567cdf0e10cSrcweir                 // endless loop, use it
568cdf0e10cSrcweir                 pRetval = &rNode;
569cdf0e10cSrcweir             }
570cdf0e10cSrcweir             else if(rNode.GetFullTime() > rRelativeTime)
571cdf0e10cSrcweir             {
572cdf0e10cSrcweir                 // ending node
573cdf0e10cSrcweir                 pRetval = &rNode;
574cdf0e10cSrcweir             }
575cdf0e10cSrcweir             else
576cdf0e10cSrcweir             {
577cdf0e10cSrcweir                 // look at next
578cdf0e10cSrcweir                 rRelativeTime -= rNode.GetFullTime();
579cdf0e10cSrcweir             }
580cdf0e10cSrcweir         }
581cdf0e10cSrcweir     }
582cdf0e10cSrcweir 
583cdf0e10cSrcweir     return pRetval;
584cdf0e10cSrcweir }
585cdf0e10cSrcweir 
ImpRegisterAgainScrollTextMixerState(sal_uInt32 nTime)586cdf0e10cSrcweir sal_uInt32 ActivityImpl::ImpRegisterAgainScrollTextMixerState(sal_uInt32 nTime)
587cdf0e10cSrcweir {
588cdf0e10cSrcweir     sal_uInt32 nRetval(0L);
589cdf0e10cSrcweir     ImpForceScrollTextAnimNodes();
590cdf0e10cSrcweir 
591cdf0e10cSrcweir     if(maVector.size())
592cdf0e10cSrcweir     {
593cdf0e10cSrcweir         sal_uInt32 nRelativeTime;
594cdf0e10cSrcweir         ScrollTextAnimNode* pNode = ImpGetScrollTextAnimNode(nTime, nRelativeTime);
595cdf0e10cSrcweir 
596cdf0e10cSrcweir         if(pNode)
597cdf0e10cSrcweir         {
598cdf0e10cSrcweir             // take register time
599cdf0e10cSrcweir             nRetval = pNode->GetFrequency();
600cdf0e10cSrcweir         }
601cdf0e10cSrcweir     }
602cdf0e10cSrcweir     else
603cdf0e10cSrcweir     {
604cdf0e10cSrcweir         // #i38135# not initialized, return default
605cdf0e10cSrcweir         nRetval = mnFrequency;
606cdf0e10cSrcweir     }
607cdf0e10cSrcweir 
608cdf0e10cSrcweir     return nRetval;
609cdf0e10cSrcweir }
610cdf0e10cSrcweir 
updateShapeAttributes(double fTime,basegfx::B2DRectangle const & parentBounds)611cdf0e10cSrcweir void ActivityImpl::updateShapeAttributes(
612cdf0e10cSrcweir     double fTime, basegfx::B2DRectangle const& parentBounds )
613cdf0e10cSrcweir {
614cdf0e10cSrcweir     OSL_ASSERT( meAnimKind != drawing::TextAnimationKind_NONE );
615cdf0e10cSrcweir     if( meAnimKind == drawing::TextAnimationKind_NONE )
616cdf0e10cSrcweir         return;
617cdf0e10cSrcweir 
618cdf0e10cSrcweir     double const fMixerState = GetMixerState(
619cdf0e10cSrcweir         static_cast<sal_uInt32>(fTime * 1000.0) );
620cdf0e10cSrcweir 
621cdf0e10cSrcweir     if( meAnimKind == drawing::TextAnimationKind_BLINK )
622cdf0e10cSrcweir     {
623cdf0e10cSrcweir         // show/hide text:
624cdf0e10cSrcweir         maShapeAttrLayer.get()->setVisibility( fMixerState < 0.5 );
625cdf0e10cSrcweir     }
626cdf0e10cSrcweir     else if(mpMetaFile) // scroll mode:
627cdf0e10cSrcweir     {
628cdf0e10cSrcweir         //
629cdf0e10cSrcweir         // keep care: the below code is highly sensible to changes...
630cdf0e10cSrcweir         //
631cdf0e10cSrcweir 
632cdf0e10cSrcweir         // rectangle of the pure text:
633cdf0e10cSrcweir         double const fPaintWidth = maPaintRectangleLogic.GetWidth();
634cdf0e10cSrcweir         double const fPaintHeight = maPaintRectangleLogic.GetHeight();
635cdf0e10cSrcweir         // rectangle where the scrolling takes place (-> clipping):
636cdf0e10cSrcweir         double const fScrollWidth = maScrollRectangleLogic.GetWidth();
637cdf0e10cSrcweir         double const fScrollHeight = maScrollRectangleLogic.GetHeight();
638cdf0e10cSrcweir 
639cdf0e10cSrcweir         basegfx::B2DPoint pos, clipPos;
640cdf0e10cSrcweir 
641cdf0e10cSrcweir         if(ScrollHorizontal())
642cdf0e10cSrcweir         {
643cdf0e10cSrcweir             double const fOneEquiv( fScrollWidth );
644cdf0e10cSrcweir             double const fZeroEquiv( -fPaintWidth );
645cdf0e10cSrcweir 
646cdf0e10cSrcweir             pos.setX( fZeroEquiv + (fMixerState * (fOneEquiv - fZeroEquiv)) );
647cdf0e10cSrcweir 
648cdf0e10cSrcweir             clipPos.setX( -pos.getX() );
649cdf0e10cSrcweir             clipPos.setY( -pos.getY() );
650cdf0e10cSrcweir 
651cdf0e10cSrcweir             // #i69844# Compensation for text-wider-than-shape case
652cdf0e10cSrcweir             if( fPaintWidth > fScrollWidth )
653cdf0e10cSrcweir                 pos.setX( pos.getX() + (fPaintWidth-fScrollWidth) / 2.0 );
654cdf0e10cSrcweir         }
655cdf0e10cSrcweir         else
656cdf0e10cSrcweir         {
657cdf0e10cSrcweir             // scroll vertical:
658cdf0e10cSrcweir             double const fOneEquiv( fScrollHeight );
659cdf0e10cSrcweir             double const fZeroEquiv( -fPaintHeight );
660cdf0e10cSrcweir 
661cdf0e10cSrcweir             pos.setY( fZeroEquiv + (fMixerState * (fOneEquiv - fZeroEquiv)) );
662cdf0e10cSrcweir 
663cdf0e10cSrcweir             clipPos.setX( -pos.getX() );
664cdf0e10cSrcweir             clipPos.setY( -pos.getY() );
665cdf0e10cSrcweir 
666cdf0e10cSrcweir             // #i69844# Compensation for text-higher-than-shape case
667cdf0e10cSrcweir             if( fPaintHeight > fScrollHeight )
668cdf0e10cSrcweir                 pos.setY( pos.getY() + (fPaintHeight-fScrollHeight) / 2.0 );
669cdf0e10cSrcweir         }
670cdf0e10cSrcweir 
671cdf0e10cSrcweir         basegfx::B2DPolygon clipPoly(
672cdf0e10cSrcweir             basegfx::tools::createPolygonFromRect(
673cdf0e10cSrcweir                 basegfx::B2DRectangle( clipPos.getX(),
674cdf0e10cSrcweir                                        clipPos.getY(),
675cdf0e10cSrcweir                                        clipPos.getX() + fScrollWidth,
676cdf0e10cSrcweir                                        clipPos.getY() + fScrollHeight ) ) );
677cdf0e10cSrcweir 
678cdf0e10cSrcweir         if( !::basegfx::fTools::equalZero( mfRotationAngle ))
679cdf0e10cSrcweir         {
680cdf0e10cSrcweir             maShapeAttrLayer.get()->setRotationAngle( mfRotationAngle );
681cdf0e10cSrcweir             double const fRotate = (mfRotationAngle * M_PI / 180.0);
682cdf0e10cSrcweir             basegfx::B2DHomMatrix aTransform;
683cdf0e10cSrcweir             // position:
684cdf0e10cSrcweir             aTransform.rotate( fRotate );
685cdf0e10cSrcweir             pos *= aTransform;
686cdf0e10cSrcweir         }
687cdf0e10cSrcweir 
688cdf0e10cSrcweir         pos += parentBounds.getCenter();
689cdf0e10cSrcweir         maShapeAttrLayer.get()->setPosition( pos );
690cdf0e10cSrcweir         maShapeAttrLayer.get()->setClip( basegfx::B2DPolyPolygon(clipPoly) );
691cdf0e10cSrcweir     }
692cdf0e10cSrcweir }
693cdf0e10cSrcweir 
perform()694cdf0e10cSrcweir bool ActivityImpl::perform()
695cdf0e10cSrcweir {
696cdf0e10cSrcweir     if( !isActive() )
697cdf0e10cSrcweir         return false;
698cdf0e10cSrcweir 
699cdf0e10cSrcweir     ENSURE_OR_RETURN_FALSE(
700cdf0e10cSrcweir         mpDrawShape,
701cdf0e10cSrcweir         "ActivityImpl::perform(): still active, but NULL draw shape" );
702cdf0e10cSrcweir 
703cdf0e10cSrcweir     DrawShapeSharedPtr const pParentDrawShape( mpParentDrawShape );
704cdf0e10cSrcweir     if( !pParentDrawShape )
705cdf0e10cSrcweir         return false; // parent has vanished
706cdf0e10cSrcweir 
707cdf0e10cSrcweir     if( pParentDrawShape->isVisible() )
708cdf0e10cSrcweir     {
709cdf0e10cSrcweir         if( !mbIsShapeAnimated )
710cdf0e10cSrcweir         {
711cdf0e10cSrcweir             mpDrawShape->setVisibility(true); // shape may be initially hidden
712cdf0e10cSrcweir             maContext.mpSubsettableShapeManager->enterAnimationMode( mpDrawShape );
713cdf0e10cSrcweir             maTimer.reset();
714cdf0e10cSrcweir             mbIsShapeAnimated = true;
715cdf0e10cSrcweir         }
716cdf0e10cSrcweir         // update attributes related to current time:
717cdf0e10cSrcweir         basegfx::B2DRectangle const parentBounds(
718cdf0e10cSrcweir             pParentDrawShape->getBounds() );
719cdf0e10cSrcweir 
720cdf0e10cSrcweir         const double nCurrTime( maTimer.getElapsedTime() );
721cdf0e10cSrcweir         updateShapeAttributes( nCurrTime, parentBounds );
722cdf0e10cSrcweir 
723cdf0e10cSrcweir         const sal_uInt32 nFrequency(
724cdf0e10cSrcweir             ImpRegisterAgainScrollTextMixerState(
725cdf0e10cSrcweir                 static_cast<sal_uInt32>(nCurrTime * 1000.0)) );
726cdf0e10cSrcweir 
727cdf0e10cSrcweir         if(nFrequency)
728cdf0e10cSrcweir         {
729cdf0e10cSrcweir             mpWakeupEvent->start();
730cdf0e10cSrcweir             mpWakeupEvent->setNextTimeout(
731cdf0e10cSrcweir                 std::max(0.1,nFrequency/1000.0) );
732cdf0e10cSrcweir             maContext.mrEventQueue.addEvent( mpWakeupEvent );
733cdf0e10cSrcweir 
734cdf0e10cSrcweir             if( mpDrawShape->isContentChanged() )
735cdf0e10cSrcweir                 maContext.mpSubsettableShapeManager->notifyShapeUpdate( mpDrawShape );
736cdf0e10cSrcweir         }
737cdf0e10cSrcweir         // else: finished, not need to wake up again.
738cdf0e10cSrcweir     }
739cdf0e10cSrcweir     else
740cdf0e10cSrcweir     {
741cdf0e10cSrcweir         // busy-wait, until parent shape gets visible
742cdf0e10cSrcweir         mpWakeupEvent->start();
743cdf0e10cSrcweir         mpWakeupEvent->setNextTimeout( 2.0 );
744cdf0e10cSrcweir     }
745cdf0e10cSrcweir 
746cdf0e10cSrcweir     // don't reinsert, WakeupEvent will perform that after the given timeout:
747cdf0e10cSrcweir     return false;
748cdf0e10cSrcweir }
749cdf0e10cSrcweir 
ActivityImpl(SlideShowContext const & rContext,boost::shared_ptr<WakeupEvent> const & pWakeupEvent,boost::shared_ptr<DrawShape> const & pParentDrawShape)750cdf0e10cSrcweir ActivityImpl::ActivityImpl(
751cdf0e10cSrcweir     SlideShowContext const& rContext,
752cdf0e10cSrcweir     boost::shared_ptr<WakeupEvent> const& pWakeupEvent,
753cdf0e10cSrcweir     boost::shared_ptr<DrawShape> const& pParentDrawShape )
754cdf0e10cSrcweir     : maContext(rContext),
755cdf0e10cSrcweir       mpWakeupEvent(pWakeupEvent),
756cdf0e10cSrcweir       mpParentDrawShape(pParentDrawShape),
757cdf0e10cSrcweir       mpListener( new IntrinsicAnimationListener(*this) ),
758cdf0e10cSrcweir       maTimer(rContext.mrEventQueue.getTimer()),
759cdf0e10cSrcweir       mbIsShapeAnimated(false),
760cdf0e10cSrcweir       mbIsDisposed(false),
761cdf0e10cSrcweir       mbIsActive(true),
762cdf0e10cSrcweir       meAnimKind(drawing::TextAnimationKind_NONE),
763cdf0e10cSrcweir       mnStartTime(0L)
764cdf0e10cSrcweir {
765cdf0e10cSrcweir     // get doctreenode:
766cdf0e10cSrcweir     sal_Int32 const nNodes = pParentDrawShape->getNumberOfTreeNodes(
767cdf0e10cSrcweir         DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH );
768cdf0e10cSrcweir 
769cdf0e10cSrcweir     DocTreeNode scrollTextNode(
770cdf0e10cSrcweir         pParentDrawShape->getTreeNode(
771cdf0e10cSrcweir             0, DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ));
772cdf0e10cSrcweir     // xxx todo: remove this hack
773cdf0e10cSrcweir     if( nNodes > 1 )
774cdf0e10cSrcweir         scrollTextNode.setEndIndex(
775cdf0e10cSrcweir             pParentDrawShape->getTreeNode(
776cdf0e10cSrcweir                 nNodes - 1,
777cdf0e10cSrcweir                 DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ).getEndIndex());
778cdf0e10cSrcweir 
779cdf0e10cSrcweir     // TODO(Q3): Doing this manually, instead of using
780cdf0e10cSrcweir     // ShapeSubset. This is because of lifetime issues (ShapeSubset
781cdf0e10cSrcweir     // generates circular references to parent shape)
782cdf0e10cSrcweir     mpDrawShape = boost::dynamic_pointer_cast<DrawShape>(
783cdf0e10cSrcweir         maContext.mpSubsettableShapeManager->getSubsetShape(
784cdf0e10cSrcweir             pParentDrawShape,
785cdf0e10cSrcweir             scrollTextNode ));
786cdf0e10cSrcweir 
787cdf0e10cSrcweir     mpMetaFile = mpDrawShape->forceScrollTextMetaFile();
788cdf0e10cSrcweir 
789cdf0e10cSrcweir     // make scroll text invisible for slide transition bitmaps
790cdf0e10cSrcweir     mpDrawShape->setVisibility(false);
791cdf0e10cSrcweir 
792cdf0e10cSrcweir     basegfx::B2DRectangle aScrollRect, aPaintRect;
793cdf0e10cSrcweir     ENSURE_OR_THROW( getRectanglesFromScrollMtf( aScrollRect,
794cdf0e10cSrcweir                                                   aPaintRect,
795cdf0e10cSrcweir                                                   mpMetaFile ),
796cdf0e10cSrcweir                       "ActivityImpl::ActivityImpl(): Could not extract "
797cdf0e10cSrcweir                       "scroll anim rectangles from mtf" );
798cdf0e10cSrcweir 
799cdf0e10cSrcweir     maScrollRectangleLogic = vcl::unotools::rectangleFromB2DRectangle(
800cdf0e10cSrcweir         aScrollRect );
801cdf0e10cSrcweir     maPaintRectangleLogic = vcl::unotools::rectangleFromB2DRectangle(
802cdf0e10cSrcweir         aPaintRect );
803cdf0e10cSrcweir 
804cdf0e10cSrcweir     maShapeAttrLayer.createAttributeLayer(mpDrawShape);
805cdf0e10cSrcweir 
806cdf0e10cSrcweir     uno::Reference<drawing::XShape> const xShape( mpDrawShape->getXShape() );
807cdf0e10cSrcweir     uno::Reference<beans::XPropertySet> const xProps( xShape, uno::UNO_QUERY_THROW );
808cdf0e10cSrcweir 
809cdf0e10cSrcweir     getPropertyValue( meAnimKind, xProps, OUSTR("TextAnimationKind") );
810cdf0e10cSrcweir     OSL_ASSERT( meAnimKind != drawing::TextAnimationKind_NONE );
811cdf0e10cSrcweir     mbAlternate = (meAnimKind == drawing::TextAnimationKind_ALTERNATE);
812cdf0e10cSrcweir     mbScrollIn = (meAnimKind == drawing::TextAnimationKind_SLIDE);
813cdf0e10cSrcweir 
814cdf0e10cSrcweir     // adopted from in AInfoBlinkText::ImplInit():
815cdf0e10cSrcweir     sal_Int16 nRepeat(0);
816cdf0e10cSrcweir     getPropertyValue( nRepeat, xProps, OUSTR("TextAnimationCount") );
817cdf0e10cSrcweir     mnRepeat = nRepeat;
818cdf0e10cSrcweir 
819cdf0e10cSrcweir     if(mbAlternate)
820cdf0e10cSrcweir     {
821cdf0e10cSrcweir         // force visible when started for scroll-forth-and-back, because
822cdf0e10cSrcweir         // slide has been coming in with visible text in the middle:
823cdf0e10cSrcweir         mbVisibleWhenStarted = true;
824cdf0e10cSrcweir     }
825cdf0e10cSrcweir     else
826cdf0e10cSrcweir     {
827cdf0e10cSrcweir         getPropertyValue( mbVisibleWhenStarted, xProps,
828cdf0e10cSrcweir                           OUSTR("TextAnimationStartInside") );
829cdf0e10cSrcweir     }
830cdf0e10cSrcweir 
831cdf0e10cSrcweir     // set visible when stopped
832cdf0e10cSrcweir     getPropertyValue( mbVisibleWhenStopped, xProps,
833cdf0e10cSrcweir                       OUSTR("TextAnimatiogonStopInside") );
834cdf0e10cSrcweir     // rotation:
835cdf0e10cSrcweir     getPropertyValue( mfRotationAngle, xProps,
836cdf0e10cSrcweir                       OUSTR("RotateAngle") );
837cdf0e10cSrcweir     mfRotationAngle /= -100.0; // (switching direction)
838cdf0e10cSrcweir 
839cdf0e10cSrcweir     // set frequency
840cdf0e10cSrcweir     sal_Int16 nDelay(0);
841cdf0e10cSrcweir     getPropertyValue( nDelay, xProps, OUSTR("TextAnimationDelay") );
842cdf0e10cSrcweir     // set delay if not automatic
843cdf0e10cSrcweir     mnFrequency = (nDelay ? nDelay :
844cdf0e10cSrcweir                    // default:
845cdf0e10cSrcweir                    meAnimKind == drawing::TextAnimationKind_BLINK
846cdf0e10cSrcweir                    ? 250L : 50L );
847cdf0e10cSrcweir 
848cdf0e10cSrcweir     // adopted from in AInfoScrollText::ImplInit():
849cdf0e10cSrcweir 
850cdf0e10cSrcweir     // If it is a simple m_bScrollIn, reset some parameters
851cdf0e10cSrcweir     if( DoScrollIn() )
852cdf0e10cSrcweir     {
853cdf0e10cSrcweir         // most parameters are set correctly from the dialog logic, but
854cdf0e10cSrcweir         // eg VisisbleWhenStopped is grayed out and needs to be corrected here.
855cdf0e10cSrcweir         mbVisibleWhenStopped = true;
856cdf0e10cSrcweir         mbVisibleWhenStarted = false;
857cdf0e10cSrcweir         mnRepeat = 0L;
858cdf0e10cSrcweir     }
859cdf0e10cSrcweir 
860cdf0e10cSrcweir     // Get animation direction
861cdf0e10cSrcweir     getPropertyValue( meDirection, xProps, OUSTR("TextAnimationDirection") );
862cdf0e10cSrcweir 
863cdf0e10cSrcweir     // Get step width. Negative means pixel, positive logical units
864cdf0e10cSrcweir     getPropertyValue( mnStepWidth, xProps, OUSTR("TextAnimationAmount") );
865cdf0e10cSrcweir 
866cdf0e10cSrcweir     maContext.mpSubsettableShapeManager->addIntrinsicAnimationHandler(
867cdf0e10cSrcweir         mpListener );
868cdf0e10cSrcweir }
869cdf0e10cSrcweir 
enableAnimations()870cdf0e10cSrcweir bool ActivityImpl::enableAnimations()
871cdf0e10cSrcweir {
872cdf0e10cSrcweir     mbIsActive = true;
873cdf0e10cSrcweir     return maContext.mrActivitiesQueue.addActivity(
874cdf0e10cSrcweir         shared_from_this() );
875cdf0e10cSrcweir }
876cdf0e10cSrcweir 
~ActivityImpl()877cdf0e10cSrcweir ActivityImpl::~ActivityImpl()
878cdf0e10cSrcweir {
879cdf0e10cSrcweir }
880cdf0e10cSrcweir 
dispose()881cdf0e10cSrcweir void ActivityImpl::dispose()
882cdf0e10cSrcweir {
883cdf0e10cSrcweir     if( !mbIsDisposed )
884cdf0e10cSrcweir     {
885cdf0e10cSrcweir         end();
886cdf0e10cSrcweir 
887cdf0e10cSrcweir         // only remove subset here, since end() is called on slide end
888cdf0e10cSrcweir         // (and we must not spoil the slide preview bitmap with scroll
889cdf0e10cSrcweir         // text)
890cdf0e10cSrcweir         maShapeAttrLayer.reset();
891cdf0e10cSrcweir         if( mpDrawShape )
892cdf0e10cSrcweir         {
893cdf0e10cSrcweir             // TODO(Q3): Doing this manually, instead of using
894cdf0e10cSrcweir             // ShapeSubset. This is because of lifetime issues
895cdf0e10cSrcweir             // (ShapeSubset generates circular references to parent
896cdf0e10cSrcweir             // shape)
897cdf0e10cSrcweir             DrawShapeSharedPtr pParent( mpParentDrawShape.lock() );
898cdf0e10cSrcweir             if( pParent )
899cdf0e10cSrcweir                 maContext.mpSubsettableShapeManager->revokeSubset(
900cdf0e10cSrcweir                     pParent,
901cdf0e10cSrcweir                     mpDrawShape );
902cdf0e10cSrcweir         }
903cdf0e10cSrcweir 
904cdf0e10cSrcweir         mpMetaFile.reset();
905cdf0e10cSrcweir         mpDrawShape.reset();
906cdf0e10cSrcweir         mpParentDrawShape.reset();
907cdf0e10cSrcweir         mpWakeupEvent.reset();
908cdf0e10cSrcweir         maContext.dispose();
909cdf0e10cSrcweir         mbIsDisposed = true;
910cdf0e10cSrcweir 
911cdf0e10cSrcweir         maContext.mpSubsettableShapeManager->removeIntrinsicAnimationHandler(
912cdf0e10cSrcweir             mpListener );
913cdf0e10cSrcweir     }
914cdf0e10cSrcweir }
915cdf0e10cSrcweir 
calcTimeLag() const916cdf0e10cSrcweir double ActivityImpl::calcTimeLag() const
917cdf0e10cSrcweir {
918cdf0e10cSrcweir     return 0.0;
919cdf0e10cSrcweir }
920cdf0e10cSrcweir 
isActive() const921cdf0e10cSrcweir bool ActivityImpl::isActive() const
922cdf0e10cSrcweir {
923cdf0e10cSrcweir     return mbIsActive;
924cdf0e10cSrcweir }
925cdf0e10cSrcweir 
dequeued()926cdf0e10cSrcweir void ActivityImpl::dequeued()
927cdf0e10cSrcweir {
928cdf0e10cSrcweir     // not used here
929cdf0e10cSrcweir }
930cdf0e10cSrcweir 
end()931cdf0e10cSrcweir void ActivityImpl::end()
932cdf0e10cSrcweir {
933cdf0e10cSrcweir     // not used here
934cdf0e10cSrcweir     mbIsActive = false;
935cdf0e10cSrcweir 
936cdf0e10cSrcweir     if( mbIsShapeAnimated )
937cdf0e10cSrcweir     {
938cdf0e10cSrcweir         maContext.mpSubsettableShapeManager->leaveAnimationMode( mpDrawShape );
939cdf0e10cSrcweir         mbIsShapeAnimated = false;
940cdf0e10cSrcweir     }
941cdf0e10cSrcweir }
942cdf0e10cSrcweir 
943cdf0e10cSrcweir } // anon namespace
944cdf0e10cSrcweir 
945cdf0e10cSrcweir namespace slideshow {
946cdf0e10cSrcweir namespace internal {
947cdf0e10cSrcweir 
createDrawingLayerAnimActivity(SlideShowContext const & rContext,boost::shared_ptr<DrawShape> const & pDrawShape)948cdf0e10cSrcweir boost::shared_ptr<Activity> createDrawingLayerAnimActivity(
949cdf0e10cSrcweir     SlideShowContext const& rContext,
950cdf0e10cSrcweir     boost::shared_ptr<DrawShape> const& pDrawShape )
951cdf0e10cSrcweir {
952cdf0e10cSrcweir     boost::shared_ptr<Activity> pActivity;
953cdf0e10cSrcweir 
954cdf0e10cSrcweir     try
955cdf0e10cSrcweir     {
956cdf0e10cSrcweir         boost::shared_ptr<WakeupEvent> const pWakeupEvent(
957cdf0e10cSrcweir             new WakeupEvent( rContext.mrEventQueue.getTimer(),
958cdf0e10cSrcweir                              rContext.mrActivitiesQueue ) );
959cdf0e10cSrcweir         pActivity.reset( new ActivityImpl( rContext, pWakeupEvent, pDrawShape ) );
960cdf0e10cSrcweir         pWakeupEvent->setActivity( pActivity );
961cdf0e10cSrcweir     }
962cdf0e10cSrcweir     catch( uno::RuntimeException& )
963cdf0e10cSrcweir     {
964cdf0e10cSrcweir         throw;
965cdf0e10cSrcweir     }
966cdf0e10cSrcweir     catch( uno::Exception& )
967cdf0e10cSrcweir     {
968cdf0e10cSrcweir         // translate any error into empty factory product.
969cdf0e10cSrcweir         OSL_ENSURE( false,
970cdf0e10cSrcweir                     rtl::OUStringToOString(
971cdf0e10cSrcweir                         comphelper::anyToString( cppu::getCaughtException() ),
972cdf0e10cSrcweir                         RTL_TEXTENCODING_UTF8 ).getStr() );
973cdf0e10cSrcweir     }
974cdf0e10cSrcweir 
975cdf0e10cSrcweir     return pActivity;
976cdf0e10cSrcweir }
977cdf0e10cSrcweir 
978cdf0e10cSrcweir } // namespace internal
979cdf0e10cSrcweir } // namespace presentation
980cdf0e10cSrcweir 
981