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