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