1a3e0fd82Sopenharmony_ci/*
2a3e0fd82Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3a3e0fd82Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4a3e0fd82Sopenharmony_ci * you may not use this file except in compliance with the License.
5a3e0fd82Sopenharmony_ci * You may obtain a copy of the License at
6a3e0fd82Sopenharmony_ci *
7a3e0fd82Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8a3e0fd82Sopenharmony_ci *
9a3e0fd82Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10a3e0fd82Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11a3e0fd82Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12a3e0fd82Sopenharmony_ci * See the License for the specific language governing permissions and
13a3e0fd82Sopenharmony_ci * limitations under the License.
14a3e0fd82Sopenharmony_ci */
15a3e0fd82Sopenharmony_ci
16a3e0fd82Sopenharmony_ci#include "components/ui_button.h"
17a3e0fd82Sopenharmony_ci#include "animator/interpolation.h"
18a3e0fd82Sopenharmony_ci#include "common/image.h"
19a3e0fd82Sopenharmony_ci#include "draw/draw_image.h"
20a3e0fd82Sopenharmony_ci#include "engines/gfx/gfx_engine_manager.h"
21a3e0fd82Sopenharmony_ci#include "gfx_utils/graphic_log.h"
22a3e0fd82Sopenharmony_ci#include "gfx_utils/style.h"
23a3e0fd82Sopenharmony_ci#include "imgdecode/cache_manager.h"
24a3e0fd82Sopenharmony_ci#include "themes/theme_manager.h"
25a3e0fd82Sopenharmony_ci
26a3e0fd82Sopenharmony_cinamespace OHOS {
27a3e0fd82Sopenharmony_ciUIButton::UIButton()
28a3e0fd82Sopenharmony_ci    : defaultImgSrc_(nullptr),
29a3e0fd82Sopenharmony_ci      triggeredImgSrc_(nullptr),
30a3e0fd82Sopenharmony_ci      currentImgSrc_(ButtonImageSrc::BTN_IMAGE_DEFAULT),
31a3e0fd82Sopenharmony_ci      imgX_(0),
32a3e0fd82Sopenharmony_ci      imgY_(0),
33a3e0fd82Sopenharmony_ci      contentWidth_(0),
34a3e0fd82Sopenharmony_ci      contentHeight_(0),
35a3e0fd82Sopenharmony_ci      state_(RELEASED),
36a3e0fd82Sopenharmony_ci      styleState_(RELEASED),
37a3e0fd82Sopenharmony_ci#if DEFAULT_ANIMATION
38a3e0fd82Sopenharmony_ci      enableAnimation_(true),
39a3e0fd82Sopenharmony_ci      animator_(*this),
40a3e0fd82Sopenharmony_ci#endif
41a3e0fd82Sopenharmony_ci      buttonStyleAllocFlag_(false)
42a3e0fd82Sopenharmony_ci{
43a3e0fd82Sopenharmony_ci    touchable_ = true;
44a3e0fd82Sopenharmony_ci    SetupThemeStyles();
45a3e0fd82Sopenharmony_ci}
46a3e0fd82Sopenharmony_ci
47a3e0fd82Sopenharmony_ciUIButton::~UIButton()
48a3e0fd82Sopenharmony_ci{
49a3e0fd82Sopenharmony_ci    if (defaultImgSrc_ != nullptr) {
50a3e0fd82Sopenharmony_ci        delete defaultImgSrc_;
51a3e0fd82Sopenharmony_ci        defaultImgSrc_ = nullptr;
52a3e0fd82Sopenharmony_ci    }
53a3e0fd82Sopenharmony_ci
54a3e0fd82Sopenharmony_ci    if (triggeredImgSrc_ != nullptr) {
55a3e0fd82Sopenharmony_ci        delete triggeredImgSrc_;
56a3e0fd82Sopenharmony_ci        triggeredImgSrc_ = nullptr;
57a3e0fd82Sopenharmony_ci    }
58a3e0fd82Sopenharmony_ci
59a3e0fd82Sopenharmony_ci    if (buttonStyleAllocFlag_) {
60a3e0fd82Sopenharmony_ci        for (uint8_t i = 0; i < BTN_STATE_NUM; i++) {
61a3e0fd82Sopenharmony_ci            delete buttonStyles_[i];
62a3e0fd82Sopenharmony_ci            buttonStyles_[i] = nullptr;
63a3e0fd82Sopenharmony_ci        }
64a3e0fd82Sopenharmony_ci        buttonStyleAllocFlag_ = false;
65a3e0fd82Sopenharmony_ci    }
66a3e0fd82Sopenharmony_ci}
67a3e0fd82Sopenharmony_ci
68a3e0fd82Sopenharmony_civoid UIButton::DrawImg(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea, OpacityType opaScale)
69a3e0fd82Sopenharmony_ci{
70a3e0fd82Sopenharmony_ci    const Image* image = GetCurImageSrc();
71a3e0fd82Sopenharmony_ci    if (image == nullptr) {
72a3e0fd82Sopenharmony_ci        return;
73a3e0fd82Sopenharmony_ci    }
74a3e0fd82Sopenharmony_ci
75a3e0fd82Sopenharmony_ci    ImageHeader header = {0};
76a3e0fd82Sopenharmony_ci    image->GetHeader(header);
77a3e0fd82Sopenharmony_ci    Rect coords;
78a3e0fd82Sopenharmony_ci    Rect viewRect = GetContentRect();
79a3e0fd82Sopenharmony_ci    coords.SetLeft(viewRect.GetLeft() + GetImageX());
80a3e0fd82Sopenharmony_ci    coords.SetTop(viewRect.GetTop() + GetImageY());
81a3e0fd82Sopenharmony_ci    coords.SetWidth(header.width);
82a3e0fd82Sopenharmony_ci    coords.SetHeight(header.height);
83a3e0fd82Sopenharmony_ci
84a3e0fd82Sopenharmony_ci    Rect trunc(invalidatedArea);
85a3e0fd82Sopenharmony_ci    if (trunc.Intersect(trunc, viewRect)) {
86a3e0fd82Sopenharmony_ci        image->DrawImage(gfxDstBuffer, coords, trunc, *buttonStyles_[state_], opaScale);
87a3e0fd82Sopenharmony_ci    }
88a3e0fd82Sopenharmony_ci}
89a3e0fd82Sopenharmony_ci
90a3e0fd82Sopenharmony_civoid UIButton::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
91a3e0fd82Sopenharmony_ci{
92a3e0fd82Sopenharmony_ci    OpacityType opa = GetMixOpaScale();
93a3e0fd82Sopenharmony_ci    BaseGfxEngine::GetInstance()->DrawRect(gfxDstBuffer, GetOrigRect(), invalidatedArea, *buttonStyles_[state_], opa);
94a3e0fd82Sopenharmony_ci    DrawImg(gfxDstBuffer, invalidatedArea, opa);
95a3e0fd82Sopenharmony_ci}
96a3e0fd82Sopenharmony_ci
97a3e0fd82Sopenharmony_civoid UIButton::SetupThemeStyles()
98a3e0fd82Sopenharmony_ci{
99a3e0fd82Sopenharmony_ci    Theme* theme = ThemeManager::GetInstance().GetCurrent();
100a3e0fd82Sopenharmony_ci
101a3e0fd82Sopenharmony_ci    if (theme == nullptr) {
102a3e0fd82Sopenharmony_ci        buttonStyles_[RELEASED] = &(StyleDefault::GetButtonReleasedStyle());
103a3e0fd82Sopenharmony_ci        buttonStyles_[PRESSED] = &(StyleDefault::GetButtonPressedStyle());
104a3e0fd82Sopenharmony_ci        buttonStyles_[INACTIVE] = &(StyleDefault::GetButtonInactiveStyle());
105a3e0fd82Sopenharmony_ci    } else {
106a3e0fd82Sopenharmony_ci        buttonStyles_[RELEASED] = &(theme->GetButtonStyle().released);
107a3e0fd82Sopenharmony_ci        buttonStyles_[PRESSED] = &(theme->GetButtonStyle().pressed);
108a3e0fd82Sopenharmony_ci        buttonStyles_[INACTIVE] = &(theme->GetButtonStyle().inactive);
109a3e0fd82Sopenharmony_ci    }
110a3e0fd82Sopenharmony_ci    style_ = buttonStyles_[RELEASED];
111a3e0fd82Sopenharmony_ci}
112a3e0fd82Sopenharmony_ci
113a3e0fd82Sopenharmony_ciint64_t UIButton::GetStyle(uint8_t key) const
114a3e0fd82Sopenharmony_ci{
115a3e0fd82Sopenharmony_ci    return GetStyleForState(key, styleState_);
116a3e0fd82Sopenharmony_ci}
117a3e0fd82Sopenharmony_ci
118a3e0fd82Sopenharmony_civoid UIButton::SetStyle(uint8_t key, int64_t value)
119a3e0fd82Sopenharmony_ci{
120a3e0fd82Sopenharmony_ci    SetStyleForState(key, value, styleState_);
121a3e0fd82Sopenharmony_ci}
122a3e0fd82Sopenharmony_ci
123a3e0fd82Sopenharmony_ciint64_t UIButton::GetStyleForState(uint8_t key, ButtonState state) const
124a3e0fd82Sopenharmony_ci{
125a3e0fd82Sopenharmony_ci    if (state < BTN_STATE_NUM) {
126a3e0fd82Sopenharmony_ci        return (buttonStyles_[state])->GetStyle(key);
127a3e0fd82Sopenharmony_ci    }
128a3e0fd82Sopenharmony_ci    return 0;
129a3e0fd82Sopenharmony_ci}
130a3e0fd82Sopenharmony_ci
131a3e0fd82Sopenharmony_civoid UIButton::SetStyleForState(uint8_t key, int64_t value, ButtonState state)
132a3e0fd82Sopenharmony_ci{
133a3e0fd82Sopenharmony_ci    if (state < BTN_STATE_NUM) {
134a3e0fd82Sopenharmony_ci        if (!buttonStyleAllocFlag_) {
135a3e0fd82Sopenharmony_ci            for (uint8_t i = 0; i < BTN_STATE_NUM; i++) {
136a3e0fd82Sopenharmony_ci                Style styleSaved = *buttonStyles_[i];
137a3e0fd82Sopenharmony_ci                buttonStyles_[i] = new Style;
138a3e0fd82Sopenharmony_ci                if (buttonStyles_[i] == nullptr) {
139a3e0fd82Sopenharmony_ci                    GRAPHIC_LOGE("new Style fail");
140a3e0fd82Sopenharmony_ci                    return;
141a3e0fd82Sopenharmony_ci                }
142a3e0fd82Sopenharmony_ci                *(buttonStyles_[i]) = styleSaved;
143a3e0fd82Sopenharmony_ci            }
144a3e0fd82Sopenharmony_ci            buttonStyleAllocFlag_ = true;
145a3e0fd82Sopenharmony_ci        }
146a3e0fd82Sopenharmony_ci        style_ = buttonStyles_[RELEASED];
147a3e0fd82Sopenharmony_ci        int16_t width = GetWidth();
148a3e0fd82Sopenharmony_ci        int16_t height = GetHeight();
149a3e0fd82Sopenharmony_ci        int16_t x = GetX();
150a3e0fd82Sopenharmony_ci        int16_t y = GetY();
151a3e0fd82Sopenharmony_ci        buttonStyles_[state]->SetStyle(key, value);
152a3e0fd82Sopenharmony_ci        Rect rect(x, y, x + width - 1, y + height -  1);
153a3e0fd82Sopenharmony_ci        UpdateRectInfo(key, rect);
154a3e0fd82Sopenharmony_ci    }
155a3e0fd82Sopenharmony_ci}
156a3e0fd82Sopenharmony_ci
157a3e0fd82Sopenharmony_cibool UIButton::OnPressEvent(const PressEvent& event)
158a3e0fd82Sopenharmony_ci{
159a3e0fd82Sopenharmony_ci    currentImgSrc_ = ButtonImageSrc::BTN_IMAGE_TRIGGERED;
160a3e0fd82Sopenharmony_ci    SetState(PRESSED);
161a3e0fd82Sopenharmony_ci    Resize(contentWidth_, contentHeight_);
162a3e0fd82Sopenharmony_ci    Invalidate();
163a3e0fd82Sopenharmony_ci#if DEFAULT_ANIMATION
164a3e0fd82Sopenharmony_ci    if (enableAnimation_) {
165a3e0fd82Sopenharmony_ci        animator_.Start();
166a3e0fd82Sopenharmony_ci    }
167a3e0fd82Sopenharmony_ci#endif
168a3e0fd82Sopenharmony_ci    return UIView::OnPressEvent(event);
169a3e0fd82Sopenharmony_ci}
170a3e0fd82Sopenharmony_ci
171a3e0fd82Sopenharmony_cibool UIButton::OnReleaseEvent(const ReleaseEvent& event)
172a3e0fd82Sopenharmony_ci{
173a3e0fd82Sopenharmony_ci    currentImgSrc_ = ButtonImageSrc::BTN_IMAGE_DEFAULT;
174a3e0fd82Sopenharmony_ci    SetState(RELEASED);
175a3e0fd82Sopenharmony_ci    Resize(contentWidth_, contentHeight_);
176a3e0fd82Sopenharmony_ci    Invalidate();
177a3e0fd82Sopenharmony_ci#if DEFAULT_ANIMATION
178a3e0fd82Sopenharmony_ci    if (enableAnimation_) {
179a3e0fd82Sopenharmony_ci        animator_.Start();
180a3e0fd82Sopenharmony_ci    }
181a3e0fd82Sopenharmony_ci#endif
182a3e0fd82Sopenharmony_ci    return UIView::OnReleaseEvent(event);
183a3e0fd82Sopenharmony_ci}
184a3e0fd82Sopenharmony_ci
185a3e0fd82Sopenharmony_cibool UIButton::OnCancelEvent(const CancelEvent& event)
186a3e0fd82Sopenharmony_ci{
187a3e0fd82Sopenharmony_ci    currentImgSrc_ = ButtonImageSrc::BTN_IMAGE_DEFAULT;
188a3e0fd82Sopenharmony_ci    SetState(RELEASED);
189a3e0fd82Sopenharmony_ci    Resize(contentWidth_, contentHeight_);
190a3e0fd82Sopenharmony_ci    Invalidate();
191a3e0fd82Sopenharmony_ci#if DEFAULT_ANIMATION
192a3e0fd82Sopenharmony_ci    if (enableAnimation_) {
193a3e0fd82Sopenharmony_ci        animator_.Start();
194a3e0fd82Sopenharmony_ci    }
195a3e0fd82Sopenharmony_ci#endif
196a3e0fd82Sopenharmony_ci    return UIView::OnCancelEvent(event);
197a3e0fd82Sopenharmony_ci}
198a3e0fd82Sopenharmony_ci
199a3e0fd82Sopenharmony_ciconst Image* UIButton::GetCurImageSrc() const
200a3e0fd82Sopenharmony_ci{
201a3e0fd82Sopenharmony_ci    if (currentImgSrc_ == ButtonImageSrc::BTN_IMAGE_DEFAULT) {
202a3e0fd82Sopenharmony_ci        return defaultImgSrc_;
203a3e0fd82Sopenharmony_ci    } else if (currentImgSrc_ == ButtonImageSrc::BTN_IMAGE_TRIGGERED) {
204a3e0fd82Sopenharmony_ci        return triggeredImgSrc_;
205a3e0fd82Sopenharmony_ci    } else {
206a3e0fd82Sopenharmony_ci        return nullptr;
207a3e0fd82Sopenharmony_ci    }
208a3e0fd82Sopenharmony_ci}
209a3e0fd82Sopenharmony_ci
210a3e0fd82Sopenharmony_civoid UIButton::SetImageSrc(const char* defaultImgSrc, const char* triggeredImgSrc)
211a3e0fd82Sopenharmony_ci{
212a3e0fd82Sopenharmony_ci    if (!InitImage()) {
213a3e0fd82Sopenharmony_ci        return;
214a3e0fd82Sopenharmony_ci    }
215a3e0fd82Sopenharmony_ci    defaultImgSrc_->SetSrc(defaultImgSrc);
216a3e0fd82Sopenharmony_ci    triggeredImgSrc_->SetSrc(triggeredImgSrc);
217a3e0fd82Sopenharmony_ci}
218a3e0fd82Sopenharmony_ci
219a3e0fd82Sopenharmony_civoid UIButton::SetImageSrc(const ImageInfo* defaultImgSrc, const ImageInfo* triggeredImgSrc)
220a3e0fd82Sopenharmony_ci{
221a3e0fd82Sopenharmony_ci    if (!InitImage()) {
222a3e0fd82Sopenharmony_ci        return;
223a3e0fd82Sopenharmony_ci    }
224a3e0fd82Sopenharmony_ci    defaultImgSrc_->SetSrc(defaultImgSrc);
225a3e0fd82Sopenharmony_ci    triggeredImgSrc_->SetSrc(triggeredImgSrc);
226a3e0fd82Sopenharmony_ci}
227a3e0fd82Sopenharmony_ci
228a3e0fd82Sopenharmony_civoid UIButton::Disable()
229a3e0fd82Sopenharmony_ci{
230a3e0fd82Sopenharmony_ci    SetState(INACTIVE);
231a3e0fd82Sopenharmony_ci    touchable_ = false;
232a3e0fd82Sopenharmony_ci}
233a3e0fd82Sopenharmony_ci
234a3e0fd82Sopenharmony_civoid UIButton::Enable()
235a3e0fd82Sopenharmony_ci{
236a3e0fd82Sopenharmony_ci    SetState(RELEASED);
237a3e0fd82Sopenharmony_ci    touchable_ = true;
238a3e0fd82Sopenharmony_ci}
239a3e0fd82Sopenharmony_ci
240a3e0fd82Sopenharmony_civoid UIButton::SetState(ButtonState state)
241a3e0fd82Sopenharmony_ci{
242a3e0fd82Sopenharmony_ci    state_ = state;
243a3e0fd82Sopenharmony_ci    style_ = buttonStyles_[state_];
244a3e0fd82Sopenharmony_ci    Invalidate();
245a3e0fd82Sopenharmony_ci}
246a3e0fd82Sopenharmony_ci
247a3e0fd82Sopenharmony_cibool UIButton::InitImage()
248a3e0fd82Sopenharmony_ci{
249a3e0fd82Sopenharmony_ci    if (defaultImgSrc_ == nullptr) {
250a3e0fd82Sopenharmony_ci        defaultImgSrc_ = new Image();
251a3e0fd82Sopenharmony_ci        if (defaultImgSrc_ == nullptr) {
252a3e0fd82Sopenharmony_ci            GRAPHIC_LOGE("new Image fail");
253a3e0fd82Sopenharmony_ci            return false;
254a3e0fd82Sopenharmony_ci        }
255a3e0fd82Sopenharmony_ci    }
256a3e0fd82Sopenharmony_ci    if (triggeredImgSrc_ == nullptr) {
257a3e0fd82Sopenharmony_ci        triggeredImgSrc_ = new Image();
258a3e0fd82Sopenharmony_ci        if (triggeredImgSrc_ == nullptr) {
259a3e0fd82Sopenharmony_ci            GRAPHIC_LOGE("new Image fail");
260a3e0fd82Sopenharmony_ci            return false;
261a3e0fd82Sopenharmony_ci        }
262a3e0fd82Sopenharmony_ci    }
263a3e0fd82Sopenharmony_ci    return true;
264a3e0fd82Sopenharmony_ci}
265a3e0fd82Sopenharmony_ci
266a3e0fd82Sopenharmony_cibool UIButton::OnPreDraw(Rect& invalidatedArea) const
267a3e0fd82Sopenharmony_ci{
268a3e0fd82Sopenharmony_ci    Rect rect(GetRect());
269a3e0fd82Sopenharmony_ci    int16_t r = buttonStyles_[styleState_]->borderRadius_;
270a3e0fd82Sopenharmony_ci    if (r == COORD_MAX) {
271a3e0fd82Sopenharmony_ci        return true;
272a3e0fd82Sopenharmony_ci    }
273a3e0fd82Sopenharmony_ci
274a3e0fd82Sopenharmony_ci    if (r != 0) {
275a3e0fd82Sopenharmony_ci        r = ((r & 0x1) == 0) ? (r >> 1) : ((r + 1) >> 1);
276a3e0fd82Sopenharmony_ci        rect.SetLeft(rect.GetX() + r);
277a3e0fd82Sopenharmony_ci        rect.SetWidth(rect.GetWidth() - r);
278a3e0fd82Sopenharmony_ci        rect.SetTop(rect.GetY() + r);
279a3e0fd82Sopenharmony_ci        rect.SetHeight(rect.GetHeight() - r);
280a3e0fd82Sopenharmony_ci    }
281a3e0fd82Sopenharmony_ci    if (rect.IsContains(invalidatedArea)) {
282a3e0fd82Sopenharmony_ci        return true;
283a3e0fd82Sopenharmony_ci    }
284a3e0fd82Sopenharmony_ci    invalidatedArea.Intersect(invalidatedArea, rect);
285a3e0fd82Sopenharmony_ci    return false;
286a3e0fd82Sopenharmony_ci}
287a3e0fd82Sopenharmony_ci
288a3e0fd82Sopenharmony_ci#if DEFAULT_ANIMATION
289a3e0fd82Sopenharmony_civoid UIButton::OnPostDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
290a3e0fd82Sopenharmony_ci{
291a3e0fd82Sopenharmony_ci    if (state_ == ButtonState::PRESSED && enableAnimation_) {
292a3e0fd82Sopenharmony_ci        animator_.DrawMask(gfxDstBuffer, invalidatedArea);
293a3e0fd82Sopenharmony_ci    }
294a3e0fd82Sopenharmony_ci    UIView::OnPostDraw(gfxDstBuffer, invalidatedArea);
295a3e0fd82Sopenharmony_ci}
296a3e0fd82Sopenharmony_ci
297a3e0fd82Sopenharmony_cinamespace {
298a3e0fd82Sopenharmony_ciconstexpr float FULL_SCALE = 1.0f;
299a3e0fd82Sopenharmony_ciconstexpr float SHRINK_SCALE = 0.8f;
300a3e0fd82Sopenharmony_ciconstexpr uint32_t SHRINK_DURATION = 150;
301a3e0fd82Sopenharmony_ciconstexpr uint32_t RECOVER_DURATION = 200;
302a3e0fd82Sopenharmony_ciconstexpr int64_t MASK_OPA = 25;
303a3e0fd82Sopenharmony_ciconstexpr float BEZIER_CONTROL = 0.2f;
304a3e0fd82Sopenharmony_ci} // namespace
305a3e0fd82Sopenharmony_ci
306a3e0fd82Sopenharmony_civoid UIButton::ButtonAnimator::Start()
307a3e0fd82Sopenharmony_ci{
308a3e0fd82Sopenharmony_ci    bool isReverse = (button_.state_ == UIButton::ButtonState::PRESSED);
309a3e0fd82Sopenharmony_ci    float targetScale = isReverse ? SHRINK_SCALE : FULL_SCALE;
310a3e0fd82Sopenharmony_ci    if ((animator_.GetState() == Animator::STOP) && FloatEqual(targetScale, scale_)) {
311a3e0fd82Sopenharmony_ci        return;
312a3e0fd82Sopenharmony_ci    }
313a3e0fd82Sopenharmony_ci
314a3e0fd82Sopenharmony_ci    if (isReverse) {
315a3e0fd82Sopenharmony_ci        animator_.SetTime(SHRINK_DURATION);
316a3e0fd82Sopenharmony_ci    } else {
317a3e0fd82Sopenharmony_ci        animator_.SetTime(RECOVER_DURATION);
318a3e0fd82Sopenharmony_ci    }
319a3e0fd82Sopenharmony_ci    animator_.Start();
320a3e0fd82Sopenharmony_ci    /* reverse the animator direction */
321a3e0fd82Sopenharmony_ci    float x = isReverseAnimation_ ? (FULL_SCALE - scale_) : (scale_ - SHRINK_SCALE);
322a3e0fd82Sopenharmony_ci    float y = x / (FULL_SCALE - SHRINK_SCALE);
323a3e0fd82Sopenharmony_ci    x = Interpolation::GetBezierY(FULL_SCALE - y, 0, BEZIER_CONTROL, FULL_SCALE, BEZIER_CONTROL);
324a3e0fd82Sopenharmony_ci    animator_.SetRunTime(static_cast<uint32_t>(animator_.GetTime() * x));
325a3e0fd82Sopenharmony_ci    isReverseAnimation_ = isReverse;
326a3e0fd82Sopenharmony_ci}
327a3e0fd82Sopenharmony_ci
328a3e0fd82Sopenharmony_civoid UIButton::ButtonAnimator::DrawMask(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
329a3e0fd82Sopenharmony_ci{
330a3e0fd82Sopenharmony_ci    Style maskStyle;
331a3e0fd82Sopenharmony_ci    maskStyle.SetStyle(STYLE_BACKGROUND_COLOR, Color::White().full);
332a3e0fd82Sopenharmony_ci    maskStyle.SetStyle(STYLE_BACKGROUND_OPA, MASK_OPA);
333a3e0fd82Sopenharmony_ci    maskStyle.SetStyle(STYLE_BORDER_RADIUS, button_.GetStyle(STYLE_BORDER_RADIUS));
334a3e0fd82Sopenharmony_ci    OpacityType opa = button_.GetMixOpaScale();
335a3e0fd82Sopenharmony_ci    BaseGfxEngine::GetInstance()->DrawRect(gfxDstBuffer, button_.GetRect(), invalidatedArea, maskStyle, opa);
336a3e0fd82Sopenharmony_ci}
337a3e0fd82Sopenharmony_ci
338a3e0fd82Sopenharmony_cistatic inline void ScaleButton(UIButton& button, float scale)
339a3e0fd82Sopenharmony_ci{
340a3e0fd82Sopenharmony_ci    Vector2<float> scaleValue_ = {scale, scale};
341a3e0fd82Sopenharmony_ci    Vector2<float> centrePoint(button.GetWidth() / 2.0f, button.GetHeight() / 2.0f);
342a3e0fd82Sopenharmony_ci    button.Scale(scaleValue_, centrePoint);
343a3e0fd82Sopenharmony_ci}
344a3e0fd82Sopenharmony_ci
345a3e0fd82Sopenharmony_civoid UIButton::ButtonAnimator::Callback(UIView* view)
346a3e0fd82Sopenharmony_ci{
347a3e0fd82Sopenharmony_ci    float x = static_cast<float>(animator_.GetRunTime()) / animator_.GetTime();
348a3e0fd82Sopenharmony_ci    float offset = Interpolation::GetBezierY(x, BEZIER_CONTROL, 0, BEZIER_CONTROL, FULL_SCALE);
349a3e0fd82Sopenharmony_ci    float scale = (FULL_SCALE - SHRINK_SCALE) * offset;
350a3e0fd82Sopenharmony_ci
351a3e0fd82Sopenharmony_ci    scale_ = isReverseAnimation_ ? (FULL_SCALE - scale) : (scale + SHRINK_SCALE);
352a3e0fd82Sopenharmony_ci    ScaleButton(button_, scale_);
353a3e0fd82Sopenharmony_ci}
354a3e0fd82Sopenharmony_ci
355a3e0fd82Sopenharmony_civoid UIButton::ButtonAnimator::OnStop(UIView& view)
356a3e0fd82Sopenharmony_ci{
357a3e0fd82Sopenharmony_ci    if (isReverseAnimation_) {
358a3e0fd82Sopenharmony_ci        scale_ = SHRINK_SCALE;
359a3e0fd82Sopenharmony_ci        ScaleButton(button_, SHRINK_SCALE);
360a3e0fd82Sopenharmony_ci    } else {
361a3e0fd82Sopenharmony_ci        scale_ = FULL_SCALE;
362a3e0fd82Sopenharmony_ci        button_.ResetTransParameter();
363a3e0fd82Sopenharmony_ci    }
364a3e0fd82Sopenharmony_ci}
365a3e0fd82Sopenharmony_ci#endif
366a3e0fd82Sopenharmony_ci} // namespace OHOS
367