1 /*
2 * Copyright (c) 2020-2021 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 "transition_impl.h"
17 #include <stdlib.h>
18 #include "ace_log.h"
19 #include "ace_mem_base.h"
20 #include "easing_equation.h"
21 #include "root_view.h"
22 #include "securec.h"
23
24 namespace OHOS {
25 namespace ACELite {
Init()26 void TransitionImpl::Init()
27 {
28 if (animator_ != nullptr) {
29 return;
30 }
31 animator_ = new Animator(this, view_, 0, true);
32 if (animator_ == nullptr) {
33 HILOG_ERROR(HILOG_MODULE_ACE, "animator create failed");
34 return;
35 }
36 }
37
Callback(UIView * view)38 void TransitionImpl::Callback(UIView *view)
39 {
40 (void)(view);
41 if (animator_ == nullptr) {
42 HILOG_ERROR(HILOG_MODULE_ACE, "animator is nullptr");
43 return;
44 }
45 int32_t elapsedTime = animator_->GetRunTime() - params_.delay; // animation execution time
46 if (elapsedTime <= 0) {
47 return;
48 }
49 if (elapsedTime >= params_.during) {
50 timeArrivaled_ = true;
51 }
52
53 Perform(elapsedTime);
54 }
55
Start()56 void TransitionImpl::Start()
57 {
58 if (animator_ == nullptr) {
59 HILOG_INFO(HILOG_MODULE_ACE, "animator not initial or has been started");
60 return;
61 }
62 uint8_t state = animator_->GetState();
63 if (((state == Animator::STOP) || (state == Animator::PAUSE)) && (params_.during > 0)) {
64 RecordViewStatus();
65 InitTransitionParams();
66 animator_->Start();
67 }
68 }
69
Stop() const70 void TransitionImpl::Stop() const
71 {
72 if (animator_ == nullptr) {
73 HILOG_INFO(HILOG_MODULE_ACE, "animator not initial or is not running");
74 return;
75 }
76 uint8_t state = animator_->GetState();
77 if (state == Animator::START || state == Animator::RUNNING) {
78 animator_->Stop();
79 }
80 }
81
InitTransitionParams()82 void TransitionImpl::InitTransitionParams()
83 {
84 InitTransitionParamsStyle();
85 InitTransitionParamsTransform();
86 InitTransitionParamsEasing();
87 }
88
InitTransitionParamsStyle()89 void TransitionImpl::InitTransitionParamsStyle()
90 {
91 params_.delay = (params_.delay <= 0) ? 0 : params_.delay;
92 params_.during = (params_.during <= 0) ? 0 : params_.during;
93 oriIteration_ = params_.iterations;
94
95 if (params_.fill == OptionsFill::FORWARDS) {
96 fill_ = OptionsFill::FORWARDS;
97 }
98
99 if (params_.height_from >= 0 && params_.height_to >= 0) {
100 isTransitionSet_[GeneralType::IS_HEIGHT_TRANSITION_SET] = true;
101 heightSrc_ = params_.height_from;
102 }
103 if (params_.width_from >= 0 && params_.width_to >= 0) {
104 isTransitionSet_[GeneralType::IS_WIDTH_TRANSITION_SET] = true;
105 widthSrc_ = params_.width_from;
106 }
107 if (params_.opacity_from >= 0 && params_.opacity_to >= 0) {
108 isTransitionSet_[GeneralType::IS_OPACITY_TRANSITION_SET] = true;
109 opacitySrc_ = (params_.opacity_from <= OPA_OPAQUE) ? params_.opacity_from : OPA_OPAQUE;
110 params_.opacity_to = (params_.opacity_to <= OPA_OPAQUE) ? params_.opacity_to : OPA_OPAQUE;
111 }
112
113 const uint32_t rgbValueMax = 0xFFFFFF;
114 if ((params_.background_color_from <= rgbValueMax) && (params_.background_color_to <= rgbValueMax)) {
115 isTransitionSet_[GeneralType::IS_BACKGROUND_COLOR_TRANSITION_SET] = true;
116 GetRGB(params_.background_color_from, rSrc_, gSrc_, bSrc_);
117 GetRGB(params_.background_color_to, rTo_, gTo_, bTo_);
118 steps_ = params_.during / INTERVAL;
119 }
120 }
121
InitTransitionParamsTransform()122 void TransitionImpl::InitTransitionParamsTransform()
123 {
124 if (params_.transformType == nullptr) {
125 HILOG_INFO(HILOG_MODULE_ACE, "transformType not set");
126 return;
127 }
128 if (!strcmp(params_.transformType, TRANSITION_TRANSFORM_X)) {
129 transformType_ = TransformType::TRANSLATE_X;
130 xSrc_ = viewStatus_.x + params_.transform_from;
131 } else if (!strcmp(params_.transformType, TRANSITION_TRANSFORM_Y)) {
132 transformType_ = TransformType::TRANSLATE_Y;
133 ySrc_ = viewStatus_.y + params_.transform_from;
134 } else if (!strcmp(params_.transformType, TRANSITION_ROTATE)) {
135 transformType_ = TransformType::ROTATE;
136 rotateSrc_ = params_.transform_from;
137 }
138 }
139
InitTransitionParamsEasing()140 void TransitionImpl::InitTransitionParamsEasing()
141 {
142 switch (params_.easing) {
143 case EasingType::EASE_IN:
144 easingType_[EasingType::EASE_IN] = true;
145 break;
146 case EasingType::EASE_OUT:
147 easingType_[EasingType::EASE_OUT] = true;
148 break;
149 case EasingType::EASE_IN_OUT:
150 easingType_[EasingType::EASE_IN_OUT] = true;
151 break;
152 default:
153 easingType_[EasingType::LINEAR] = true;
154 break;
155 }
156 }
157
GetRGB(const uint32_t color,uint8_t & r,uint8_t & g,uint8_t & b) const158 void TransitionImpl::GetRGB(const uint32_t color, uint8_t &r, uint8_t &g, uint8_t &b) const
159 {
160 r = uint8_t((color & TEXT_RED_COLOR_MASK) >> RED_COLOR_START_BIT);
161 g = uint8_t((color & TEXT_GREEN_COLOR_MASK) >> GREEN_COLOR_START_BIT);
162 b = uint8_t((color & TEXT_BLUE_COLOR_MASK));
163 }
164
GetNextFrameValue(int16_t from,int16_t to,int32_t elapsedTime) const165 int16_t TransitionImpl::GetNextFrameValue(int16_t from, int16_t to, int32_t elapsedTime) const
166 {
167 int16_t nextPoint;
168 if (easingType_[EasingType::EASE_IN]) {
169 nextPoint = EasingEquation::CubicEaseIn(from, to, elapsedTime, params_.during);
170 } else if (easingType_[EasingType::EASE_OUT]) {
171 nextPoint = EasingEquation::CubicEaseOut(from, to, elapsedTime, params_.during);
172 } else if (easingType_[EasingType::EASE_IN_OUT]) {
173 nextPoint = EasingEquation::CubicEaseInOut(from, to, elapsedTime, params_.during);
174 } else {
175 nextPoint = EasingEquation::LinearEaseNone(from, to, elapsedTime, params_.during);
176 }
177
178 return nextPoint;
179 }
180
SetTransformSrcPosition()181 void TransitionImpl::SetTransformSrcPosition()
182 {
183 if (params_.transformType == nullptr) {
184 return;
185 }
186 if (!strcmp(params_.transformType, TRANSITION_TRANSFORM_X)) {
187 view_->SetPosition(xSrc_, viewStatus_.y);
188 view_->GetParent()->Invalidate();
189 } else if (!strcmp(params_.transformType, TRANSITION_TRANSFORM_Y)) {
190 view_->SetPosition(viewStatus_.x, ySrc_);
191 view_->GetParent()->Invalidate();
192 } else if (!strcmp(params_.transformType, TRANSITION_ROTATE)) {
193 RotateAroundCenterPoint(rotateSrc_);
194 } else {
195 // do nothing
196 }
197 }
198
RotateAroundCenterPoint(int16_t angle)199 void TransitionImpl::RotateAroundCenterPoint(int16_t angle)
200 {
201 TransformMap transMap(view_->GetOrigRect());
202 const int circleRate = 360;
203 angle = angle % circleRate;
204 float halfVal = 2.0f;
205 pivot_.x_ = (view_->GetWidth() - 1) / halfVal;
206 pivot_.y_ = (view_->GetHeight() - 1) / halfVal;
207 transMap.Rotate((angle), pivot_);
208 view_->SetTransformMap(transMap);
209 }
210
Perform(int32_t elapsedTime)211 void TransitionImpl::Perform(int32_t elapsedTime)
212 {
213 if (timeArrivaled_) {
214 if (!RepeatAnimator()) {
215 this->Stop();
216 }
217 }
218
219 if (!isTransformSrcSet_) {
220 SetTransformSrcPosition();
221 isTransformSrcSet_ = true;
222 }
223
224 if (transformType_ == TransformType::TRANSLATE_X) {
225 PerformTransition(params_.transform_from, params_.transform_to, TransitionType::TTRANSLATE_X, xSrc_,
226 elapsedTime);
227 } else if (transformType_ == TransformType::TRANSLATE_Y) {
228 PerformTransition(params_.transform_from, params_.transform_to, TransitionType::TTRANSLATE_Y, ySrc_,
229 elapsedTime);
230 } else if (transformType_ == TransformType::ROTATE) {
231 PerformTransition(params_.transform_from, params_.transform_to, TransitionType::TROTATE, rotateSrc_,
232 elapsedTime);
233 }
234
235 if (isTransitionSet_[GeneralType::IS_HEIGHT_TRANSITION_SET]) {
236 PerformTransition(params_.height_from, params_.height_to, TransitionType::HEIGHT, heightSrc_, elapsedTime);
237 }
238 if (isTransitionSet_[GeneralType::IS_WIDTH_TRANSITION_SET]) {
239 PerformTransition(params_.width_from, params_.width_to, TransitionType::WIDTH, widthSrc_, elapsedTime);
240 }
241
242 if (isTransitionSet_[GeneralType::IS_OPACITY_TRANSITION_SET]) {
243 PerformTransition(params_.opacity_from, params_.opacity_to, TransitionType::OPACITY, opacitySrc_, elapsedTime);
244 }
245
246 if (isTransitionSet_[GeneralType::IS_BACKGROUND_COLOR_TRANSITION_SET]) {
247 PerformTransitionBgColorLinear(elapsedTime);
248 }
249
250 if ((fill_ == OptionsFill::FNONE) && timeArrivaled_) {
251 RecoveryViewStatus(view_->GetRect());
252 }
253
254 if (timeArrivaled_) {
255 ResetRepeatParam();
256 }
257 }
258
PerformTransitionBgColorLinear(int32_t elapsedTime)259 void TransitionImpl::PerformTransitionBgColorLinear(int32_t elapsedTime)
260 {
261 if (timeArrivaled_) {
262 HILOG_DEBUG(HILOG_MODULE_ACE, "time arrived");
263 view_->SetStyle(STYLE_BACKGROUND_COLOR, Color::GetColorFromRGB(rTo_, gTo_, bTo_).full);
264 return;
265 }
266 if ((steps_ != 0) && (count_ <= steps_) && (elapsedTime <= params_.during)) {
267 if ((elapsedTime - bgcolorTimeSrc_) > INTERVAL) {
268 ColorType color = Color::GetColorFromRGB(rSrc_ + (rTo_ - rSrc_) * count_ / steps_,
269 gSrc_ + (gTo_ - gSrc_) * count_ / steps_,
270 bSrc_ + (bTo_ - bSrc_) * count_ / steps_);
271 view_->SetStyle(STYLE_BACKGROUND_COLOR, color.full);
272 view_->Invalidate();
273 bgcolorTimeSrc_ = elapsedTime;
274 count_++;
275 }
276 }
277 }
278
PerformTransition(int16_t from,int16_t to,TransitionType transitionType,int16_t & updateAttrValue,int32_t elapsedTime)279 void TransitionImpl::PerformTransition(int16_t from,
280 int16_t to,
281 TransitionType transitionType,
282 int16_t &updateAttrValue,
283 int32_t elapsedTime)
284 {
285 if (timeArrivaled_) {
286 updateAttrValue = to;
287 } else {
288 int16_t prefetchedValue = 0;
289 prefetchedValue = GetNextFrameValue(from, to, elapsedTime);
290 int16_t diffDistance = prefetchedValue - updateAttrValue;
291 if (((diffDistance < 1) && (diffDistance > -1)) || (elapsedTime > params_.during)) {
292 return;
293 }
294 updateAttrValue = static_cast<int16_t>(prefetchedValue);
295 }
296
297 Rect invalidatedArea = view_->GetRect();
298 switch (transitionType) {
299 case TransitionType::TTRANSLATE_X:
300 view_->SetPosition((updateAttrValue + viewStatus_.x), viewStatus_.y);
301 break;
302 case TransitionType::TTRANSLATE_Y:
303 view_->SetPosition(viewStatus_.x, (updateAttrValue + viewStatus_.y));
304 break;
305 case TransitionType::TROTATE: {
306 RotateAroundCenterPoint(updateAttrValue);
307 break;
308 }
309 case TransitionType::HEIGHT:
310 view_->SetHeight(updateAttrValue);
311 break;
312 case TransitionType::WIDTH:
313 view_->SetWidth(updateAttrValue);
314 break;
315 case TransitionType::OPACITY: {
316 double rate = (double)updateAttrValue / ALPHA_MAX;
317 view_->SetStyle(STYLE_BACKGROUND_OPA, static_cast<int64_t>(viewStatus_.rectOpacity * rate));
318 view_->SetStyle(STYLE_IMAGE_OPA, static_cast<int64_t>(viewStatus_.imageOpacity * rate));
319 view_->SetStyle(STYLE_LINE_OPA, static_cast<int64_t>(viewStatus_.lineOpacity * rate));
320 view_->SetStyle(STYLE_TEXT_OPA, static_cast<int64_t>(viewStatus_.textOpacity * rate));
321 break;
322 }
323 default:
324 HILOG_INFO(HILOG_MODULE_ACE, "animation nothing to do.");
325 break;
326 }
327
328 invalidatedArea.Join(invalidatedArea, view_->GetRect());
329 view_->InvalidateRect(invalidatedArea);
330 }
GetNumIterations(const char * iterations)331 int8_t TransitionImpl::GetNumIterations(const char *iterations)
332 {
333 int8_t min = 1;
334 int8_t max = 127;
335 if (iterations == nullptr) {
336 return min;
337 }
338 if (!strcmp(iterations, "infinite")) {
339 return TransitionImpl::ITERATIONS_INFINITY;
340 }
341 long value = strtol(iterations, nullptr, DEC);
342 if ((value < min) || (value > max)) {
343 HILOG_ERROR(HILOG_MODULE_ACE, "animation iterations should set between 1 and 127");
344 return min;
345 }
346 return (int8_t)value;
347 }
348
IsEndWith(const char * src,const char * end)349 bool TransitionImpl::IsEndWith(const char *src, const char *end)
350 {
351 if ((src == nullptr) || (end == nullptr)) {
352 return false;
353 }
354
355 size_t strLen = strlen(src);
356 size_t endLen = strlen(end);
357 if ((strLen < endLen) || (strLen == 0) || (endLen == 0)) {
358 return false;
359 }
360
361 while (endLen > 0) {
362 if (src[strLen - 1] != end[endLen - 1]) {
363 return false;
364 }
365 endLen--;
366 strLen--;
367 }
368 return true;
369 }
370
RepeatAnimator()371 bool TransitionImpl::RepeatAnimator()
372 {
373 if (oriIteration_ != TransitionImpl::ITERATIONS_INFINITY) {
374 oriIteration_--;
375 if (oriIteration_ == 0) {
376 oriIteration_ = params_.iterations;
377 return false;
378 }
379 }
380 HILOG_DEBUG(HILOG_MODULE_ACE, "repeat");
381 return true;
382 }
383
ResetRepeatParam()384 void TransitionImpl::ResetRepeatParam()
385 {
386 if (animator_ != nullptr) {
387 animator_->SetRunTime(0); // reset animation executing time
388 }
389 timeArrivaled_ = false; // reset timeArrivaled flag
390 bgcolorTimeSrc_ = 0; // reset bg-color last update time
391 count_ = 1; // reset bg-color update number of times
392 }
393
RecordViewStatus()394 void TransitionImpl::RecordViewStatus()
395 {
396 viewStatus_.x = view_->GetX();
397 viewStatus_.y = view_->GetY();
398 viewStatus_.oriRect = view_->GetOrigRect();
399 viewStatus_.height = view_->GetHeight();
400 viewStatus_.width = view_->GetWidth();
401 viewStatus_.background_color.full = view_->GetStyle(STYLE_BACKGROUND_COLOR);
402 viewStatus_.rectOpacity = view_->GetStyle(STYLE_BACKGROUND_OPA);
403 viewStatus_.imageOpacity = view_->GetStyle(STYLE_IMAGE_OPA);
404 viewStatus_.lineOpacity = view_->GetStyle(STYLE_LINE_OPA);
405 viewStatus_.textOpacity = view_->GetStyle(STYLE_TEXT_OPA);
406 }
407
RecoveryViewStatus(Rect invalidatedAreaBefore) const408 void TransitionImpl::RecoveryViewStatus(Rect invalidatedAreaBefore) const
409 {
410 view_->SetX(viewStatus_.x);
411 view_->SetY(viewStatus_.y);
412 view_->SetHeight(viewStatus_.height);
413 view_->SetWidth(viewStatus_.width);
414 TransformMap &transMap = view_->GetTransformMap();
415 Polygon polygon(Rect(0, 0, 0, 0));
416 transMap.SetPolygon(polygon);
417 view_->SetStyle(STYLE_BACKGROUND_COLOR, viewStatus_.background_color.full);
418 view_->SetStyle(STYLE_BACKGROUND_OPA, viewStatus_.rectOpacity);
419 view_->SetStyle(STYLE_IMAGE_OPA, viewStatus_.imageOpacity);
420 view_->SetStyle(STYLE_LINE_OPA, viewStatus_.lineOpacity);
421 view_->SetStyle(STYLE_TEXT_OPA, viewStatus_.textOpacity);
422 invalidatedAreaBefore.Join(invalidatedAreaBefore, view_->GetRect());
423 view_->InvalidateRect(invalidatedAreaBefore);
424 }
425 } // namespace ACELite
426 } // namespace OHOS
427