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