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