1 /*
2 * Copyright (c) 2021-2023 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 "animation/rs_interpolator.h"
17
18 #include <algorithm>
19 #include <cmath>
20
21 #include "sandbox_utils.h"
22
23 #include "animation/rs_animation_common.h"
24 #include "animation/rs_cubic_bezier_interpolator.h"
25 #include "animation/rs_spring_interpolator.h"
26 #include "animation/rs_steps_interpolator.h"
27 #include "platform/common/rs_log.h"
28 #include "transaction/rs_marshalling_helper.h"
29
30 namespace OHOS {
31 namespace Rosen {
32
33 static pid_t pid_ = GetRealPid();
34
35 const std::shared_ptr<RSInterpolator> RSInterpolator::DEFAULT =
36 std::make_shared<RSCubicBezierInterpolator>(0.42f, 0.0f, 0.58f, 1.0f);
37
RSInterpolator()38 RSInterpolator::RSInterpolator() : id_(GenerateId()) {}
39
Init()40 void RSInterpolator::Init()
41 {
42 pid_ = GetRealPid();
43 }
44
GenerateId()45 uint64_t RSInterpolator::GenerateId()
46 {
47 if (pid_ == 0) {
48 pid_ = GetRealPid();
49 }
50 static std::atomic<uint32_t> currentId_ = 0;
51
52 auto currentId = currentId_.fetch_add(1, std::memory_order_relaxed);
53 if (currentId == UINT32_MAX) {
54 ROSEN_LOGE("RSInterpolator Id overflow");
55 }
56
57 // concat two 32-bit numbers to one 64-bit number
58 return ((AnimationId)pid_ << 32) | (currentId);
59 }
60
Interpolate(float input)61 float RSInterpolator::Interpolate(float input)
62 {
63 if (input == prevInput_) {
64 return prevOutput_;
65 }
66 prevInput_ = input;
67 prevOutput_ = InterpolateImpl(input);
68 return prevOutput_;
69 }
70
RSCustomInterpolator(uint64_t id,const std::vector<float> && times,const std::vector<float> && values)71 RSCustomInterpolator::RSCustomInterpolator(
72 uint64_t id, const std::vector<float>&& times, const std::vector<float>&& values)
73 : RSInterpolator(id), times_(times), values_(values)
74 {}
75
RSCustomInterpolator(const std::function<float (float)> & func,int duration)76 RSCustomInterpolator::RSCustomInterpolator(const std::function<float(float)>& func, int duration)
77 : interpolateFunc_(func)
78 {
79 Convert(duration);
80 }
81
Convert(int duration)82 void RSCustomInterpolator::Convert(int duration)
83 {
84 if (interpolateFunc_ == nullptr) {
85 ROSEN_LOGE("RSCustomInterpolator::Convert, interpolateFunc_ is nullptr");
86 return;
87 }
88 constexpr uint64_t frameInterval = 16666667;
89 int numAnim = static_cast<int>(std::ceil(static_cast<double>(duration * MS_TO_NS) / frameInterval));
90 numAnim = std::clamp(numAnim, MIN_SAMPLE_POINTS, MAX_SAMPLE_POINTS);
91 float lastAnimFrame = numAnim - 1;
92 if (lastAnimFrame <= 0.0f) {
93 ROSEN_LOGE("RSCustomInterpolator::Convert, lastAnimFrame is invalid.");
94 return;
95 }
96 for (int i = 0; i < numAnim; i++) {
97 float time = i / lastAnimFrame;
98 float value = interpolateFunc_(time);
99 times_.push_back(time);
100 values_.push_back(value);
101 }
102 }
103
InterpolateImpl(float input) const104 float RSCustomInterpolator::InterpolateImpl(float input) const
105 {
106 if (times_.size() <= 0) {
107 ROSEN_LOGE("RSCustomInterpolator::InterpolateImpl, times_ vector is empty.");
108 return 0.0f;
109 }
110 if (times_.size() != values_.size()) {
111 ROSEN_LOGE("RSCustomInterpolator::InterpolateImpl, times_ and values_ have different sizes.");
112 return 0.0f;
113 }
114 auto firstGreatValueIterator = std::upper_bound(times_.begin(), times_.end(), input);
115 if (firstGreatValueIterator == times_.end()) {
116 return values_.back();
117 }
118 if (firstGreatValueIterator == times_.begin()) {
119 return values_.front();
120 }
121 auto endLocation = std::distance(times_.begin(), firstGreatValueIterator);
122 int startLocation = endLocation - 1;
123 float number = times_[endLocation] - times_[startLocation];
124 if (ROSEN_LE(number, 0.f)) {
125 ROSEN_LOGE("RSCustomInterpolator::Interpolate, time between startLocation and endLocation is less than zero.");
126 return 0.0f;
127 }
128 float fraction = (input - times_[startLocation]) / number;
129 float ret = fraction * (values_[endLocation] - values_[startLocation]) + values_[startLocation];
130 return ret;
131 }
132 } // namespace Rosen
133 } // namespace OHOS
134