2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5 // Licensed under the Flora License, Version 1.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://floralicense.org/license/
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an AS IS BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
19 * @file FUiCtrl_FlickAnimation.cpp
20 * @brief This is the implementation file for _FlickAnimation class.
22 * This file contains the implementation of _FlickAnimation class.
25 #include <FBaseSysLog.h>
26 #include "FUiCtrl_FlickAnimation.h"
28 #ifdef MEMORY_LEAK_CHECK
29 #include "mem_leak_check.h"
32 namespace Tizen { namespace Ui { namespace Controls
35 const int FLK_REF_RESOL_PXL[2] = {480, 800}; // Reference Pixel
44 _FlickAnimation::_FlickAnimation(void)
46 __flickDirection = FD_VERTICAL;
48 __dimension[_X] = 0; // 42
49 __dimension[_Y] = 0; // 70
51 __resolution[_X] = 240;
52 __resolution[_Y] = 320;
54 __align[_X] = __resolution[_X] / FLK_ANI_DEFAULT_ALIGN_RATIO;
55 __align[_Y] = __resolution[_Y] / FLK_ANI_DEFAULT_ALIGN_RATIO;
60 __flickAnimationFPS = 25;
61 __flickAnimationFPSRef = 20;
62 __flickAnimaionTimeMin = FLK_ANI_TIME_MIN_MSEC * __flickAnimationFPS / 1000;
63 __flickAnimationTimeMax = FLK_ANI_TIME_MAX_MSEC * __flickAnimationFPS / 1000;
70 __frictionMin[_X] = 5;
71 __frictionMin[_Y] = 5;
72 __velocityMin[_X] = 0;
73 __velocityMin[_Y] = 0;
75 __acceleration[_X] = 0;
76 __acceleration[_Y] = 0;
79 __tensionStatus[_X] = TENSION_DONE;
80 __tensionStatus[_Y] = TENSION_DONE;
81 __tensionDistMax[_X] = 0;
82 __tensionDistMax[_Y] = 0;
85 _FlickAnimation::~_FlickAnimation(void)
90 _FlickAnimation::SetSizeInformation(int resW, int resH, int mmW, int mmH)
92 if (resW > 0 && resH > 0 && mmW > 0 && mmH > 0)
94 __resolution[_X] = resW;
95 __resolution[_Y] = resH;
97 __dimension[_X] = mmW;
98 __dimension[_Y] = mmH;
103 _FlickAnimation::SetAlignInformation(int alignW, int alignH)
105 // Align Value < 0 then Resolution * 1/n
108 __align[_X] = alignW;
112 __align[_X] = __resolution[_X] / FLK_ANI_DEFAULT_ALIGN_RATIO;
117 __align[_Y] = alignH;
121 __align[_Y] = __resolution[_Y] / FLK_ANI_DEFAULT_ALIGN_RATIO;
125 __margin[_X] = __align[_X] / 20;
126 __margin[_Y] = __align[_Y] / 20;
129 // sensitivity increases, the larger the distance but, less than fps.
131 _FlickAnimation::SetSensitivity(int fps, int sensitivity)
135 __flickAnimationFPS = fps;
137 // max sensitivity is fps
138 if (0 < sensitivity && sensitivity < fps)
140 __flickAnimationFPSRef = sensitivity;
144 __flickAnimationFPSRef = fps;
148 __flickAnimaionTimeMin = FLK_ANI_TIME_MIN_MSEC * __flickAnimationFPS / 1000;
149 __flickAnimationTimeMax = FLK_ANI_TIME_MAX_MSEC * __flickAnimationFPS / 1000;
154 _FlickAnimation::SetDirection(int dir)
156 __flickDirection = dir;
160 _FlickAnimation::SetTensionEnable(bool enableX, bool enableY)
164 __tensionStatus[_X] = TENSION_DONE;
168 __tensionStatus[_X] = TENSION_NA;
173 __tensionStatus[_Y] = TENSION_DONE;
177 __tensionStatus[_Y] = TENSION_NA;
182 _FlickAnimation::IsItemExecutable(int flickX, int flickY)
184 bool returnValue = (__velocity[_X] == 0 && __velocity[_Y] == 0 && flickX == 0 && flickY == 0);
190 _FlickAnimation::CalculateInitializeVelocity(int flickX, int flickY, int flickTime, int* pFlkVelX, int* pFlkVelY)
192 if (flickTime < 1) // {{110726 lsw2000}} Prevent 'Divide by 0'
197 // Calculateulate Velocity
198 int velX = flickX * 1000 / flickTime; // in pixel unit
199 int velY = flickY * 1000 / flickTime; // in pixel unit
200 // int velX = flickX * 1000/flickTime * m_nMmW/m_nResW; // in mm unit
201 // int velY = flickY * 1000/flickTime * m_nMmH/m_nResH; // in mm unit
203 // Calculateulate Flick Amount using velocity and distance
204 // (input in mm) = (input in pixel) * (mm/resolution)
205 // (output in pixel) = (input in mm) * (alpha * resolution) <= (alpha = pixel output per mm input depends on resoultion)
206 // then (output in pixel) = (input in pixel) * (mm) * (alpha)
207 // *pFlkVelX = (velX*FLK_WEIGHT_VEL + flickX*FLK_WEIGHT_DIST)*m_nMmW/FLK_ALPHA_PER_MM;
208 // *pFlkVelY = (velY*FLK_WEIGHT_VEL + flickY*FLK_WEIGHT_DIST)*m_nMmH/FLK_ALPHA_PER_MM;
209 *pFlkVelX = (velX * FLK_WEIGHT_VEL + flickX * FLK_WEIGHT_DIST) / FLK_ALPHA_PER_PIXEL;
210 *pFlkVelY = (velY * FLK_WEIGHT_VEL + flickY * FLK_WEIGHT_DIST) / FLK_ALPHA_PER_PIXEL;
214 _FlickAnimation::EstimateInitializeVelocity(int totalDist, int idx)
218 bool minusFlag = (totalDist < 0);
219 totalDist = ((totalDist < 0) ? (-totalDist) : (totalDist));
221 // totalDist => vel => FlkVel
222 int velMax = __align[idx] * 2 / 3 * __flickAnimationFPSRef;
223 int distMax = velMax / __flickAnimationFPS;
224 int thres1 = distMax * __flickAnimaionTimeMin / 2;
225 int thres2 = distMax * __flickAnimationTimeMax / 2;
227 if (totalDist < thres1)
229 int velMin = velMax / FLK_ANI_SPEED_MIN_RATIO;
230 vel = totalDist * __flickAnimationFPS * 2 / __flickAnimaionTimeMin;
231 flkVel = (vel - velMin) * (FLK_SPEED_THRES1 - FLK_SPEED_MIN) / (velMax - velMin) + FLK_SPEED_MIN;
233 else if (totalDist < thres2)
235 flkVel = (totalDist * 2 / distMax - __flickAnimaionTimeMin)
236 * (FLK_SPEED_THRES2 - FLK_SPEED_THRES1) / (__flickAnimationTimeMax - __flickAnimaionTimeMin) + FLK_SPEED_THRES1;
240 int totalDistRemain = totalDist - thres2;
241 int alpha = __align[idx] * (FLK_ANI_OVERSPEED_END_CNT - FLK_ANI_OVERSPEED_START_CNT - 1);
242 int accel = (totalDistRemain + alpha / 2) / alpha;
243 flkVel = FLK_SPEED_THRES2 + accel * FLK_OVERSPEED_STEP;
254 // Set Flick Animation Variables from Flick Algorithm result
256 _FlickAnimation::InitializeFlickAmount(int flkVelX, int flkVelY)
258 InitializeFlick(flkVelX, flkVelY);
262 _FlickAnimation::InitializeFlickAmount(int flkVel)
264 switch (__flickDirection)
267 InitializeFlick(0, flkVel);
271 InitializeFlick(flkVel, 0);
281 _FlickAnimation::InitializeFlick(int flkVelX, int flkVelY)
285 __acceleration[_X] = 0;
286 __acceleration[_Y] = 0;
289 if (flkVelX == 0 && flkVelY == 0)
299 if (__flickDirection == FD_VERTICAL)
306 InitializeFlickXY(flkVelY, _Y);
313 if (__flickDirection == FD_HORIZONTAL)
320 InitializeFlickXY(flkVelX, _X);
325 _FlickAnimation::InitializeFlickXY(int flkVel, int idx)
327 bool minusFlag = (flkVel < 0);
328 flkVel = ((flkVel < 0) ? (-flkVel) : (flkVel));
330 if (flkVel < FLK_SPEED_MIN)
332 flkVel = FLK_SPEED_MIN;
335 // calculate __velocity & __friction based on FlkVel
336 /**************************************************************************
337 FlkVel | Vmin ~ Vth1 | Vth1 ~ Vth2 | > Vth2
338 __velocity | 0 ~ velMax | velMax | velMax + Accel
339 Time | Tmin | Tmin ~ Tmax | Tmax
340 __acceleration | 0 | 0 | (flkVel-Vth2)/Step
341 **************************************************************************/
342 int velMax = __align[idx] * 2 / 3 * __flickAnimationFPSRef;
344 if (flkVel < FLK_SPEED_THRES1)
346 int velMin = velMax / FLK_ANI_SPEED_MIN_RATIO;
347 __velocity[idx] = (flkVel - FLK_SPEED_MIN) * (velMax - velMin) / (FLK_SPEED_THRES1 - FLK_SPEED_MIN) + velMin;
348 __friction[idx] = __velocity[idx] / __flickAnimaionTimeMin;
350 else if (flkVel < FLK_SPEED_THRES2)
352 __velocity[idx] = velMax;
353 __friction[idx] = velMax /
354 ((__flickAnimationTimeMax -
355 __flickAnimaionTimeMin) *
356 (flkVel - FLK_SPEED_THRES1) / (FLK_SPEED_THRES2 - FLK_SPEED_THRES1) + __flickAnimaionTimeMin);
360 __velocity[idx] = velMax;
361 __friction[idx] = velMax / __flickAnimationTimeMax;
362 __acceleration[idx] = (flkVel - FLK_SPEED_THRES2 + FLK_OVERSPEED_STEP / 2) / FLK_OVERSPEED_STEP;
367 __velocity[idx] *= -1;
368 __acceleration[idx] *= -1;
371 // calculate Minimum Velocity, Friction for slowdown
372 int deltaMin = 8 * __flickAnimationFPSRef / __flickAnimationFPS * __resolution[idx] / FLK_REF_RESOL_PXL[idx];
373 __velocityMin[idx] = deltaMin * __flickAnimationFPS;
374 __frictionMin[idx] = velMax / __flickAnimationTimeMax * 1 / 2;
376 if (__frictionMin[idx] > __friction[idx])
378 __frictionMin[idx] = __friction[idx];
381 if (__friction[idx] == 0)
387 // Return next step distance and update Velocity.
389 _FlickAnimation::CalculateNextMove(int* pMoveX, int* pMoveY)
391 *pMoveX = CalculateNextMoveXY(_X);
392 *pMoveY = CalculateNextMoveXY(_Y);
396 if (*pMoveX == 0 && *pMoveY == 0)
407 _FlickAnimation::CalculateNextMove(void)
411 switch (__flickDirection)
414 moved = CalculateNextMoveXY(_Y);
418 moved = CalculateNextMoveXY(_X);
431 _FlickAnimation::CalculateNextMoveXY(int idx)
433 if (__velocity[idx] == 0)
438 int delta = __velocity[idx] / __flickAnimationFPS;
440 // removal reverse Flick effect
441 if (delta >= __align[idx] / 2 - __margin[idx])
443 delta = __align[idx] / 2 - __margin[idx];
445 else if (delta <= -(__align[idx] / 2 - __margin[idx]))
447 delta = -(__align[idx] / 2 - __margin[idx]);
450 // adding start accelerate effect when fast Flick
451 if (__acceleration[idx] && __drawCount > FLK_ANI_OVERSPEED_START_CNT && __drawCount < FLK_ANI_OVERSPEED_END_CNT)
453 delta += __align[idx] * __acceleration[idx];
457 int deltaNew = delta;
459 // if (deltaNew > 10 && deltaNew%(m_alignH/12))
460 // deltaNew = (deltaNew/(m_alignH/12)+1)*(m_alignH/12);
462 // if (__velocity && delta == 0)
463 // deltaNew = m_alignH/24;
468 // ceiling RoundOff for smooth stop
471 if (__velocity[idx] > 0)
475 else if (__velocity[idx] < 0)
481 // if (delta == 1 && m_nSlowStopCnt < __flickAnimationFPS)
486 // Velocity Decrease according to Friction Coefficient
487 // V(i+1)= V(i) - u*g*dT
488 if (__velocity[idx] > __velocityMin[idx] + __friction[idx])
490 __velocity[idx] -= __friction[idx];
492 else if (__velocity[idx] > __velocityMin[idx])
494 __velocity[idx] = __velocityMin[idx];
495 __friction[idx] = __frictionMin[idx];
497 else if (__velocity[idx] > __friction[idx])
499 __velocity[idx] -= __friction[idx];
501 else if (__velocity[idx] < -__velocityMin[idx] - __friction[idx])
503 __velocity[idx] += __friction[idx];
505 else if (__velocity[idx] < -__velocityMin[idx])
507 __velocity[idx] = -__velocityMin[idx];
508 __friction[idx] = __frictionMin[idx];
510 else if (__velocity[idx] < -__friction[idx])
512 __velocity[idx] += __friction[idx];
523 _FlickAnimation::InitializeTension(void)
525 if (__tensionStatus[_X] != TENSION_NA)
527 __tensionStatus[_X] = TENSION_DONE;
530 if (__tensionStatus[_Y] != TENSION_NA)
532 __tensionStatus[_Y] = TENSION_DONE;
536 // start Tension effect and return true upon reaching the end of both.
538 _FlickAnimation::StartTensionEffect(int pos, int end, int idx)
540 if (__tensionStatus[idx] == TENSION_NA)
545 bool reachEndFlag = false;
550 switch (__tensionStatus[idx])
553 // Tension start => calculate final distance (max : Resolution * 1/3)
554 __tensionDistMax[idx] = __resolution[idx] / 3 * __velocity[idx] / (__align[idx] * 2 / 3 * __flickAnimationFPSRef);
555 __acceleration[idx] = 0;
556 __tensionStatus[idx] = TENSION_COMPRESS;
559 case TENSION_COMPRESS:
560 vel = (__tensionDistMax[idx] - pos) * __flickAnimationFPS;
562 if (vel < __velocity[idx])
564 __velocity[idx] = vel;
567 // Before Reaching End (delta > 0)
568 if (__velocity[idx] / __flickAnimationFPS > 0)
573 // After Reaching End, Tension Release Start
574 __tensionStatus[idx] = TENSION_RELEASE;
578 case TENSION_RELEASE:
579 __velocity[idx] = -(pos * __flickAnimationFPS / 2);
581 if (__velocity[idx] > -__flickAnimationFPS)
583 __velocity[idx] = -__flickAnimationFPS; // Adjust final position is 0.
591 else if (pos < end && pos < 0)
604 switch (__tensionStatus[idx])
607 __tensionDistMax[idx] = __resolution[idx] / 3 * __velocity[idx] / (__align[idx] * 2 / 3 * __flickAnimationFPSRef);
608 __acceleration[idx] = 0;
609 __tensionStatus[idx] = TENSION_COMPRESS;
612 case TENSION_COMPRESS:
613 vel = (__tensionDistMax[idx] - delta) * __flickAnimationFPS;
615 if (vel > __velocity[idx])
617 __velocity[idx] = vel;
620 // Before Reaching End (delta > 0)
621 if (__velocity[idx] / __flickAnimationFPS < 0)
626 // After Reaching End, Tension Release Start
627 __tensionStatus[idx] = TENSION_RELEASE;
631 case TENSION_RELEASE:
632 __velocity[idx] = -(delta * __flickAnimationFPS / 2);
634 if (__velocity[idx] < __flickAnimationFPS)
636 __velocity[idx] = __flickAnimationFPS;
645 if (__velocity[idx] == 0)
647 __tensionStatus[idx] = TENSION_DONE;
654 _FlickAnimation::GetCurVelocity(int idx) const
656 return __velocity[idx];
660 _FlickAnimation::GetCurFriction(int idx) const
662 return __friction[idx];
665 }}} // Tizen::Ui::Controls