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 "components/ui_circle_progress.h"
17#include "draw/draw_arc.h"
18#include "draw/draw_line.h"
19#include "engines/gfx/gfx_engine_manager.h"
20
21namespace OHOS {
22UICircleProgress::UICircleProgress()
23    : center_({0, 0}),
24      backgroundImagePos_({0, 0}),
25      progressImagePos_({0, 0}),
26      radius_(0),
27      startAngle_(MIN_ANGLE_VALUE),
28      endAngle_(MAX_ANGLE_VALUE)
29{
30}
31
32void UICircleProgress::SetCenterPosition(int16_t x, int16_t y)
33{
34    center_.x = x;
35    center_.y = y;
36}
37
38void UICircleProgress::SetStartAngle(int16_t startAngle)
39{
40    startAngle_ = startAngle;
41}
42
43void UICircleProgress::SetEndAngle(int16_t endAngle)
44{
45    endAngle_ = endAngle;
46}
47
48void UICircleProgress::GetStartEndAngle(int16_t& start, int16_t& end) const
49{
50    if (startAngle_ > endAngle_) {
51        start = endAngle_;
52        end = startAngle_;
53    } else {
54        start = startAngle_;
55        end = endAngle_;
56    }
57}
58
59void UICircleProgress::GetAngleRange(int16_t& start, int16_t& end) const
60{
61    GetStartEndAngle(start, end);
62    DrawArc::GetInstance()->GetDrawRange(start, end);
63}
64
65void UICircleProgress::GetRedrawAngle(int16_t& start, int16_t& end) const
66{
67    GetStartEndAngle(start, end);
68
69    if (startAngle_ == endAngle_) {
70        return;
71    }
72
73    int16_t angleRange = end - start;
74    angleRange = (angleRange > CIRCLE_IN_DEGREE) ? CIRCLE_IN_DEGREE : angleRange;
75
76    int16_t angle = GetCurrentPos(angleRange);
77    if (startAngle_ > endAngle_) {
78        start = end - angle;
79    } else {
80        end = angle + start;
81    }
82    DrawArc::GetInstance()->GetDrawRange(start, end);
83}
84
85void UICircleProgress::DrawCommonCircle(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
86{
87    ArcInfo arcinfo = {{0}};
88    arcinfo.radius = radius_;
89    int16_t endAngle;
90    int16_t startAngle;
91    GetRedrawAngle(startAngle, endAngle);
92
93    int16_t start;
94    int16_t end;
95    GetAngleRange(start, end);
96    Rect rect = GetOrigRect();
97    arcinfo.center.x = center_.x + rect.GetLeft() + style_->paddingLeft_ + style_->borderWidth_;
98    arcinfo.center.y = center_.y + rect.GetTop() + style_->paddingTop_ + style_->borderWidth_;
99    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
100    if (enableBackground_ && ((start != end) || (backgroundStyle_->lineCap_ == CapType::CAP_ROUND))) {
101        arcinfo.imgPos.x = backgroundImagePos_.x + rect.GetLeft();
102        arcinfo.imgPos.y = backgroundImagePos_.y + rect.GetTop();
103        arcinfo.startAngle = start;
104        arcinfo.endAngle = end;
105        arcinfo.imgSrc = backgroundImage_;
106        baseGfxEngine->DrawArc(gfxDstBuffer, arcinfo, invalidatedArea, *backgroundStyle_, opaScale_,
107                               backgroundStyle_->lineCap_);
108    }
109
110    if ((startAngle != endAngle) || (foregroundStyle_->lineCap_ == CapType::CAP_ROUND)) {
111        arcinfo.imgPos.x = progressImagePos_.x + rect.GetLeft();
112        arcinfo.imgPos.y = progressImagePos_.y + rect.GetTop();
113        arcinfo.startAngle = startAngle;
114        arcinfo.endAngle = endAngle;
115        arcinfo.imgSrc = foregroundImage_;
116        baseGfxEngine->DrawArc(gfxDstBuffer, arcinfo, invalidatedArea, *foregroundStyle_, opaScale_,
117                               foregroundStyle_->lineCap_);
118    }
119}
120
121void UICircleProgress::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
122{
123    if (GetRangeSize() == 0) {
124        return;
125    }
126
127    BaseGfxEngine::GetInstance()->DrawRect(gfxDstBuffer, GetOrigRect(), invalidatedArea, *style_, opaScale_);
128
129    Rect trunc(invalidatedArea);
130    if (trunc.Intersect(trunc, GetOrigRect())) {
131        DrawCommonCircle(gfxDstBuffer, trunc);
132    }
133}
134} // namespace OHOS
135