1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "injector_utils.h"
17
18 #include <iostream>
19 #include <map>
20
21 namespace OHOS {
22 namespace Ace {
23 namespace {
24 constexpr int32_t TIME_TRANSITION = 1000;
25 } // namespace
26
27 bool InjectorUtils::debugEnabled_ = false;
28
GetSysClockTime()29 int64_t InjectorUtils::GetSysClockTime()
30 {
31 struct timespec ts = { 0, 0 };
32 if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
33 return 0;
34 }
35 return (ts.tv_sec * TIME_TRANSITION * TIME_TRANSITION) + (ts.tv_nsec / TIME_TRANSITION);
36 }
37
CalculateNextPosValueWithLinear(int32_t startPoint,int32_t targetPoint,int32_t currentIndex,int32_t totalCount)38 int32_t InjectorUtils::CalculateNextPosValueWithLinear(
39 int32_t startPoint, int32_t targetPoint, int32_t currentIndex, int32_t totalCount)
40 {
41 if (totalCount < 1) {
42 std::cout << "too few total count" << std::endl;
43 return -1;
44 }
45
46 if (targetPoint == startPoint) {
47 // no moving
48 return targetPoint;
49 }
50
51 auto distance = targetPoint - startPoint;
52 auto possitive = (distance > 0) ? 1 : -1; // possitive means increasing
53 // distance step
54 float absStep = static_cast<float>(std::abs(distance)) / totalCount;
55 // one px at least
56 absStep = (absStep == 0) ? 1 : absStep;
57 int32_t result = startPoint + static_cast<float>((absStep * (currentIndex + 1)) * possitive);
58 if (possitive > 0) {
59 result = (result > targetPoint) ? targetPoint : result;
60 } else {
61 result = (result < targetPoint) ? targetPoint : result;
62 }
63 return result;
64 }
65
Combination(int n,int k)66 int InjectorUtils::Combination(int n, int k)
67 {
68 double result = 1.0;
69 for (int i = 1; i <= k; ++i) {
70 result *= static_cast<double>(n - i + 1) / i;
71 }
72 return result;
73 }
74
BezierCurve(const std::vector<Point> & controlPoints,double t)75 Point InjectorUtils::BezierCurve(const std::vector<Point>& controlPoints, double t)
76 {
77 Point result = { 0.0, 0.0 };
78 size_t count = controlPoints.size();
79 if (count <= 1) {
80 std::cout << "too few control points" << std::endl;
81 return result;
82 }
83
84 size_t n = count - 1;
85
86 for (size_t i = 0; i <= n; ++i) {
87 double coeff = static_cast<double>(Combination(n, i)) * pow(t, i) * pow(1 - t, n - i);
88 result.x += coeff * controlPoints[i].x;
89 result.y += coeff * controlPoints[i].y;
90 }
91
92 return result;
93 }
94
95 // cubic: x < 0.5 ? 4 * x * x * x : 1 - pow(-2 * x + 2, 3) / 2
EaseInOutCubic(double t)96 static double EaseInOutCubic(double t)
97 {
98 const double c1 = 0.5;
99 const int c2 = 4;
100 const int c3 = -2;
101 const int c4 = 2;
102 const int c5 = 3;
103 const int c6 = 2;
104 return (t < c1) ? (c2 * t * t * t) : (1 - pow(c3 * t + c4, c5) / c6);
105 }
106
107 // quart: x < 0.5 ? 8 * x * x * x * x : 1 - pow(-2 * x + 2, 4) / 2
EaseInOutQuart(double t)108 static double EaseInOutQuart(double t)
109 {
110 const double c1 = 0.5;
111 const int c2 = 8;
112 const int c3 = -2;
113 const int c4 = 2;
114 const int c5 = 4;
115 const int c6 = 2;
116 return (t < c1) ? (c2 * t * t * t * t) : (1 - pow(c3 * t + c4, c5) / c6);
117 }
118
EaseInOut(double t,EaseAlgorithm algorithm)119 double InjectorUtils::EaseInOut(double t, EaseAlgorithm algorithm)
120 {
121 static const std::map<EaseAlgorithm, double (*)(double)> easeAlgorithmMap = {
122 { EaseAlgorithm::CUBIC, EaseInOutCubic }, { EaseAlgorithm::QUART, EaseInOutQuart }
123 };
124 return easeAlgorithmMap.at(algorithm)(t);
125 }
126
CalculateNextPosValueWithBezier(std::vector<Point> & controlPoints,int32_t currentIndex,int32_t totalCount,CoordinateCurve curve)127 Point InjectorUtils::CalculateNextPosValueWithBezier(
128 std::vector<Point>& controlPoints, int32_t currentIndex, int32_t totalCount, CoordinateCurve curve)
129 {
130 Point result;
131 if (currentIndex < 0 || currentIndex > totalCount || totalCount < 1) {
132 std::cout << "wrong count given: currentIndex " << currentIndex << ", totalCount " << totalCount << std::endl;
133 return result;
134 }
135
136 if (controlPoints.empty()) {
137 std::cout << "start and target point need be given at least" << std::endl;
138 return result;
139 }
140
141 double t = static_cast<double>(currentIndex) / totalCount;
142 if (curve == CoordinateCurve::EASE_IN_OUT) {
143 t = EaseInOut(t, EaseAlgorithm::QUART);
144 }
145 return BezierCurve(controlPoints, t);
146 }
147 } // namespace Ace
148 } // namespace OHOS
149