1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
24 #include <comphelper/diagnose_ex.hxx>
26 #include "activitybase.hxx"
29 namespace slideshow::internal
31 // TODO(P1): Elide some virtual function calls, by templifying this
34 ActivityBase::ActivityBase( const ActivityParameters
& rParms
) :
35 mpEndEvent( rParms
.mrEndEvent
),
36 mrEventQueue( rParms
.mrEventQueue
),
39 maRepeats( rParms
.mrRepeats
),
40 mnAccelerationFraction( rParms
.mnAccelerationFraction
),
41 mnDecelerationFraction( rParms
.mnDecelerationFraction
),
42 mbAutoReverse( rParms
.mbAutoReverse
),
43 mbFirstPerformCall( true ),
46 void ActivityBase::dispose()
53 mpEndEvent
->dispose();
58 mpAttributeLayer
.reset();
61 double ActivityBase::calcTimeLag() const
63 // TODO(Q1): implement different init process!
64 if (isActive() && mbFirstPerformCall
)
66 mbFirstPerformCall
= false;
68 // notify derived classes that we're
70 const_cast<ActivityBase
*>(this)->startAnimation();
75 bool ActivityBase::perform()
79 return false; // no, early exit.
81 OSL_ASSERT( ! mbFirstPerformCall
);
86 bool ActivityBase::isActive() const
91 void ActivityBase::setTargets( const AnimatableShapeSharedPtr
& rShape
,
92 const ShapeAttributeLayerSharedPtr
& rAttrLayer
)
94 ENSURE_OR_THROW( rShape
,
95 "ActivityBase::setTargets(): Invalid shape" );
96 ENSURE_OR_THROW( rAttrLayer
,
97 "ActivityBase::setTargets(): Invalid attribute layer" );
100 mpAttributeLayer
= rAttrLayer
;
103 void ActivityBase::endActivity()
105 // this is a regular activity end
108 // Activity is ending, queue event, then
110 mrEventQueue
.addEvent( mpEndEvent
);
112 // release references
116 void ActivityBase::dequeued()
119 // // ignored here, if we're still active. Discrete
120 // // activities are dequeued after every perform() call,
121 // // thus, the call is only significant when isActive() ==
127 void ActivityBase::end()
129 if (!isActive() || isDisposed())
131 // assure animation is started:
132 if (mbFirstPerformCall
) {
133 mbFirstPerformCall
= false;
134 // notify derived classes that we're starting now
138 performEnd(); // calling private virtual
143 double ActivityBase::calcAcceleratedTime( double nT
) const
145 // Handle acceleration/deceleration
146 // ================================
148 // clamp nT to permissible [0,1] range
149 nT
= std::clamp( nT
, 0.0, 1.0 );
151 // take acceleration/deceleration into account. if the sum
152 // of mnAccelerationFraction and mnDecelerationFraction
153 // exceeds 1.0, ignore both (that's according to SMIL spec)
154 if( (mnAccelerationFraction
> 0.0 ||
155 mnDecelerationFraction
> 0.0) &&
156 mnAccelerationFraction
+ mnDecelerationFraction
<= 1.0 )
159 // calc accelerated/decelerated time.
161 // We have three intervals:
164 // 3 [d,1] (with a and d being acceleration/deceleration
167 // The change rate during interval 1 is constantly
168 // increasing, reaching 1 at a. It then stays at 1,
169 // starting a linear decrease at d, ending with 0 at
170 // time 1. The integral of this function is the
171 // required new time nT'.
173 // As we arbitrarily assumed 1 as the upper value of
174 // the change rate, the integral must be normalized to
175 // reach nT'=1 at the end of the interval. This
176 // normalization constant is:
178 // c = 1 - 0.5a - 0.5d
180 // The integral itself then amounts to:
182 // 0.5 nT^2 / a + (nT-a) + (nT - 0.5 nT^2 / d)
184 // (where each of the three summands correspond to the
185 // three intervals above, and are applied only if nT
186 // has reached the corresponding interval)
188 // The graph of the change rate is a trapezoid:
191 // 1| /--------------\
195 // -----------------------------
199 const double nC( 1.0 - 0.5*mnAccelerationFraction
- 0.5*mnDecelerationFraction
);
201 // this variable accumulates the new time value
204 if( nT
< mnAccelerationFraction
)
206 nTPrime
+= 0.5*nT
*nT
/mnAccelerationFraction
; // partial first interval
210 nTPrime
+= 0.5*mnAccelerationFraction
; // full first interval
212 if( nT
<= 1.0-mnDecelerationFraction
)
214 nTPrime
+= nT
-mnAccelerationFraction
; // partial second interval
218 nTPrime
+= 1.0 - mnAccelerationFraction
- mnDecelerationFraction
; // full second interval
220 const double nTRelative( nT
- 1.0 + mnDecelerationFraction
);
222 nTPrime
+= nTRelative
- 0.5*nTRelative
*nTRelative
/ mnDecelerationFraction
;
226 // normalize, and assign to work variable
234 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */