• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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