1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_slideshow.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir // must be first
32*cdf0e10cSrcweir #include <canvas/debug.hxx>
33*cdf0e10cSrcweir #include <tools/diagnose_ex.h>
34*cdf0e10cSrcweir #include <canvas/verbosetrace.hxx>
35*cdf0e10cSrcweir #include <canvas/canvastools.hxx>
36*cdf0e10cSrcweir 
37*cdf0e10cSrcweir #include <activitybase.hxx>
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir 
40*cdf0e10cSrcweir namespace slideshow
41*cdf0e10cSrcweir {
42*cdf0e10cSrcweir     namespace internal
43*cdf0e10cSrcweir     {
44*cdf0e10cSrcweir         // TODO(P1): Elide some virtual function calls, by templifying this
45*cdf0e10cSrcweir         // static hierarchy
46*cdf0e10cSrcweir 
47*cdf0e10cSrcweir         ActivityBase::ActivityBase( const ActivityParameters& rParms ) :
48*cdf0e10cSrcweir             mpEndEvent( rParms.mrEndEvent ),
49*cdf0e10cSrcweir             mrEventQueue( rParms.mrEventQueue ),
50*cdf0e10cSrcweir             mpShape(),
51*cdf0e10cSrcweir             mpAttributeLayer(),
52*cdf0e10cSrcweir             maRepeats( rParms.mrRepeats ),
53*cdf0e10cSrcweir             mnAccelerationFraction( rParms.mnAccelerationFraction ),
54*cdf0e10cSrcweir             mnDecelerationFraction( rParms.mnDecelerationFraction ),
55*cdf0e10cSrcweir             mbAutoReverse( rParms.mbAutoReverse ),
56*cdf0e10cSrcweir             mbFirstPerformCall( true ),
57*cdf0e10cSrcweir             mbIsActive( true ) {}
58*cdf0e10cSrcweir 
59*cdf0e10cSrcweir         void ActivityBase::dispose()
60*cdf0e10cSrcweir         {
61*cdf0e10cSrcweir             // deactivate
62*cdf0e10cSrcweir             mbIsActive = false;
63*cdf0e10cSrcweir 
64*cdf0e10cSrcweir             // dispose event
65*cdf0e10cSrcweir             if( mpEndEvent )
66*cdf0e10cSrcweir                 mpEndEvent->dispose();
67*cdf0e10cSrcweir 
68*cdf0e10cSrcweir             // release references
69*cdf0e10cSrcweir             mpEndEvent.reset();
70*cdf0e10cSrcweir             mpShape.reset();
71*cdf0e10cSrcweir             mpAttributeLayer.reset();
72*cdf0e10cSrcweir         }
73*cdf0e10cSrcweir 
74*cdf0e10cSrcweir         double ActivityBase::calcTimeLag() const
75*cdf0e10cSrcweir         {
76*cdf0e10cSrcweir             // TODO(Q1): implement different init process!
77*cdf0e10cSrcweir             if (isActive() && mbFirstPerformCall)
78*cdf0e10cSrcweir             {
79*cdf0e10cSrcweir                 mbFirstPerformCall = false;
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir                 // notify derived classes that we're
82*cdf0e10cSrcweir                 // starting now
83*cdf0e10cSrcweir                 const_cast<ActivityBase *>(this)->startAnimation();
84*cdf0e10cSrcweir             }
85*cdf0e10cSrcweir             return 0.0;
86*cdf0e10cSrcweir         }
87*cdf0e10cSrcweir 
88*cdf0e10cSrcweir         bool ActivityBase::perform()
89*cdf0e10cSrcweir         {
90*cdf0e10cSrcweir             // still active?
91*cdf0e10cSrcweir             if( !isActive() )
92*cdf0e10cSrcweir                 return false; // no, early exit.
93*cdf0e10cSrcweir 
94*cdf0e10cSrcweir             OSL_ASSERT( ! mbFirstPerformCall );
95*cdf0e10cSrcweir 
96*cdf0e10cSrcweir             return true;
97*cdf0e10cSrcweir         }
98*cdf0e10cSrcweir 
99*cdf0e10cSrcweir         bool ActivityBase::isActive() const
100*cdf0e10cSrcweir         {
101*cdf0e10cSrcweir             return mbIsActive;
102*cdf0e10cSrcweir         }
103*cdf0e10cSrcweir 
104*cdf0e10cSrcweir         void ActivityBase::setTargets( const AnimatableShapeSharedPtr& 		rShape,
105*cdf0e10cSrcweir                                        const ShapeAttributeLayerSharedPtr& 	rAttrLayer )
106*cdf0e10cSrcweir         {
107*cdf0e10cSrcweir             ENSURE_OR_THROW( rShape,
108*cdf0e10cSrcweir                               "ActivityBase::setTargets(): Invalid shape" );
109*cdf0e10cSrcweir             ENSURE_OR_THROW( rAttrLayer,
110*cdf0e10cSrcweir                               "ActivityBase::setTargets(): Invalid attribute layer" );
111*cdf0e10cSrcweir 
112*cdf0e10cSrcweir             mpShape = rShape;
113*cdf0e10cSrcweir             mpAttributeLayer = rAttrLayer;
114*cdf0e10cSrcweir         }
115*cdf0e10cSrcweir 
116*cdf0e10cSrcweir         void ActivityBase::endActivity()
117*cdf0e10cSrcweir         {
118*cdf0e10cSrcweir             // this is a regular activity end
119*cdf0e10cSrcweir             mbIsActive = false;
120*cdf0e10cSrcweir 
121*cdf0e10cSrcweir             // Activity is ending, queue event, then
122*cdf0e10cSrcweir             if( mpEndEvent )
123*cdf0e10cSrcweir                 mrEventQueue.addEvent( mpEndEvent );
124*cdf0e10cSrcweir 
125*cdf0e10cSrcweir             // release references
126*cdf0e10cSrcweir             mpEndEvent.reset();
127*cdf0e10cSrcweir         }
128*cdf0e10cSrcweir 
129*cdf0e10cSrcweir         void ActivityBase::dequeued()
130*cdf0e10cSrcweir         {
131*cdf0e10cSrcweir             // xxx todo:
132*cdf0e10cSrcweir //             // ignored here, if we're still active. Discrete
133*cdf0e10cSrcweir //             // activities are dequeued after every perform() call,
134*cdf0e10cSrcweir //             // thus, the call is only significant when isActive() ==
135*cdf0e10cSrcweir //             // false.
136*cdf0e10cSrcweir             if( !isActive() )
137*cdf0e10cSrcweir                 endAnimation();
138*cdf0e10cSrcweir         }
139*cdf0e10cSrcweir 
140*cdf0e10cSrcweir         void ActivityBase::end()
141*cdf0e10cSrcweir         {
142*cdf0e10cSrcweir             if (!isActive() || isDisposed())
143*cdf0e10cSrcweir                 return;
144*cdf0e10cSrcweir             // assure animation is started:
145*cdf0e10cSrcweir             if (mbFirstPerformCall) {
146*cdf0e10cSrcweir                 mbFirstPerformCall = false;
147*cdf0e10cSrcweir                 // notify derived classes that we're starting now
148*cdf0e10cSrcweir                 this->startAnimation();
149*cdf0e10cSrcweir             }
150*cdf0e10cSrcweir 
151*cdf0e10cSrcweir             performEnd(); // calling private virtual
152*cdf0e10cSrcweir             endAnimation();
153*cdf0e10cSrcweir             endActivity();
154*cdf0e10cSrcweir         }
155*cdf0e10cSrcweir 
156*cdf0e10cSrcweir         double ActivityBase::calcAcceleratedTime( double nT ) const
157*cdf0e10cSrcweir         {
158*cdf0e10cSrcweir             // Handle acceleration/deceleration
159*cdf0e10cSrcweir             // ================================
160*cdf0e10cSrcweir 
161*cdf0e10cSrcweir             // clamp nT to permissible [0,1] range
162*cdf0e10cSrcweir             nT = ::basegfx::clamp( nT, 0.0, 1.0 );
163*cdf0e10cSrcweir 
164*cdf0e10cSrcweir             // take acceleration/deceleration into account. if the sum
165*cdf0e10cSrcweir             // of mnAccelerationFraction and mnDecelerationFraction
166*cdf0e10cSrcweir             // exceeds 1.0, ignore both (that's according to SMIL spec)
167*cdf0e10cSrcweir             if( (mnAccelerationFraction > 0.0 ||
168*cdf0e10cSrcweir                  mnDecelerationFraction > 0.0) &&
169*cdf0e10cSrcweir                 mnAccelerationFraction + mnDecelerationFraction <= 1.0 )
170*cdf0e10cSrcweir             {
171*cdf0e10cSrcweir                 /*
172*cdf0e10cSrcweir                 // calc accelerated/decelerated time.
173*cdf0e10cSrcweir                 //
174*cdf0e10cSrcweir                 // We have three intervals:
175*cdf0e10cSrcweir                 // 1 [0,a]
176*cdf0e10cSrcweir                 // 2 [a,d]
177*cdf0e10cSrcweir                 // 3 [d,1] (with a and d being acceleration/deceleration
178*cdf0e10cSrcweir                 // fraction, resp.)
179*cdf0e10cSrcweir                 //
180*cdf0e10cSrcweir                 // The change rate during interval 1 is constantly
181*cdf0e10cSrcweir                 // increasing, reaching 1 at a. It then stays at 1,
182*cdf0e10cSrcweir                 // starting a linear decrease at d, ending with 0 at
183*cdf0e10cSrcweir                 // time 1. The integral of this function is the
184*cdf0e10cSrcweir                 // required new time nT'.
185*cdf0e10cSrcweir                 //
186*cdf0e10cSrcweir                 // As we arbitrarily assumed 1 as the upper value of
187*cdf0e10cSrcweir                 // the change rate, the integral must be normalized to
188*cdf0e10cSrcweir                 // reach nT'=1 at the end of the interval. This
189*cdf0e10cSrcweir                 // normalization constant is:
190*cdf0e10cSrcweir                 //
191*cdf0e10cSrcweir                 // c = 1 - 0.5a - 0.5d
192*cdf0e10cSrcweir                 //
193*cdf0e10cSrcweir                 // The integral itself then amounts to:
194*cdf0e10cSrcweir                 //
195*cdf0e10cSrcweir                 // 0.5 nT^2 / a + (nT-a) + (nT - 0.5 nT^2 / d)
196*cdf0e10cSrcweir                 //
197*cdf0e10cSrcweir                 // (where each of the three summands correspond to the
198*cdf0e10cSrcweir                 // three intervals above, and are applied only if nT
199*cdf0e10cSrcweir                 // has reached the corresponding interval)
200*cdf0e10cSrcweir                 //
201*cdf0e10cSrcweir                 // The graph of the change rate is a trapezoid:
202*cdf0e10cSrcweir                 //
203*cdf0e10cSrcweir                 //   |
204*cdf0e10cSrcweir                 //  1|      /--------------\
205*cdf0e10cSrcweir                 //   |     /                \
206*cdf0e10cSrcweir                 //   |    /                  \
207*cdf0e10cSrcweir                 //   |   /                    \
208*cdf0e10cSrcweir                 //   -----------------------------
209*cdf0e10cSrcweir                 //      0   a              d  1
210*cdf0e10cSrcweir                 //
211*cdf0e10cSrcweir                 //*/
212*cdf0e10cSrcweir                 const double nC( 1.0 - 0.5*mnAccelerationFraction - 0.5*mnDecelerationFraction );
213*cdf0e10cSrcweir 
214*cdf0e10cSrcweir                 // this variable accumulates the new time value
215*cdf0e10cSrcweir                 double nTPrime(0.0);
216*cdf0e10cSrcweir 
217*cdf0e10cSrcweir                 if( nT < mnAccelerationFraction )
218*cdf0e10cSrcweir                 {
219*cdf0e10cSrcweir                     nTPrime += 0.5*nT*nT/mnAccelerationFraction; // partial first interval
220*cdf0e10cSrcweir                 }
221*cdf0e10cSrcweir                 else
222*cdf0e10cSrcweir                 {
223*cdf0e10cSrcweir                     nTPrime += 0.5*mnAccelerationFraction; // full first interval
224*cdf0e10cSrcweir 
225*cdf0e10cSrcweir                     if( nT <= 1.0-mnDecelerationFraction )
226*cdf0e10cSrcweir                     {
227*cdf0e10cSrcweir                         nTPrime += nT-mnAccelerationFraction; // partial second interval
228*cdf0e10cSrcweir                     }
229*cdf0e10cSrcweir                     else
230*cdf0e10cSrcweir                     {
231*cdf0e10cSrcweir                         nTPrime += 1.0 - mnAccelerationFraction - mnDecelerationFraction; // full second interval
232*cdf0e10cSrcweir 
233*cdf0e10cSrcweir                         const double nTRelative( nT - 1.0 + mnDecelerationFraction );
234*cdf0e10cSrcweir 
235*cdf0e10cSrcweir                         nTPrime += nTRelative - 0.5*nTRelative*nTRelative / mnDecelerationFraction;
236*cdf0e10cSrcweir                     }
237*cdf0e10cSrcweir                 }
238*cdf0e10cSrcweir 
239*cdf0e10cSrcweir                 // normalize, and assign to work variable
240*cdf0e10cSrcweir                 nT = nTPrime / nC;
241*cdf0e10cSrcweir             }
242*cdf0e10cSrcweir 
243*cdf0e10cSrcweir             return nT;
244*cdf0e10cSrcweir         }
245*cdf0e10cSrcweir     }
246*cdf0e10cSrcweir }
247