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_chart.h"
17a3e0fd82Sopenharmony_ci#include "engines/gfx/gfx_engine_manager.h"
18a3e0fd82Sopenharmony_ci#include "securec.h"
19a3e0fd82Sopenharmony_ci
20a3e0fd82Sopenharmony_cinamespace OHOS {
21a3e0fd82Sopenharmony_ciUIChart::~UIChart()
22a3e0fd82Sopenharmony_ci{
23a3e0fd82Sopenharmony_ci    if (mixData_ != nullptr) {
24a3e0fd82Sopenharmony_ci        UIFree(mixData_);
25a3e0fd82Sopenharmony_ci        mixData_ = nullptr;
26a3e0fd82Sopenharmony_ci    }
27a3e0fd82Sopenharmony_ci    ClearDataSerial();
28a3e0fd82Sopenharmony_ci    Remove(&xAxis_);
29a3e0fd82Sopenharmony_ci    Remove(&yAxis_);
30a3e0fd82Sopenharmony_ci}
31a3e0fd82Sopenharmony_ci
32a3e0fd82Sopenharmony_civoid UIChart::SetHeight(int16_t height)
33a3e0fd82Sopenharmony_ci{
34a3e0fd82Sopenharmony_ci    if (GetHeight() == height) {
35a3e0fd82Sopenharmony_ci        return;
36a3e0fd82Sopenharmony_ci    }
37a3e0fd82Sopenharmony_ci
38a3e0fd82Sopenharmony_ci    if (height > 0) {
39a3e0fd82Sopenharmony_ci        needRefresh_ = true;
40a3e0fd82Sopenharmony_ci    }
41a3e0fd82Sopenharmony_ci
42a3e0fd82Sopenharmony_ci    UIView::SetHeight(height);
43a3e0fd82Sopenharmony_ci    xAxis_.SetHeight(height);
44a3e0fd82Sopenharmony_ci    xAxis_.UpdateAxis();
45a3e0fd82Sopenharmony_ci    yAxis_.SetHeight(height);
46a3e0fd82Sopenharmony_ci    yAxis_.UpdateAxis();
47a3e0fd82Sopenharmony_ci}
48a3e0fd82Sopenharmony_ci
49a3e0fd82Sopenharmony_civoid UIChart::SetWidth(int16_t width)
50a3e0fd82Sopenharmony_ci{
51a3e0fd82Sopenharmony_ci    UIView::SetWidth(width);
52a3e0fd82Sopenharmony_ci    xAxis_.SetWidth(width);
53a3e0fd82Sopenharmony_ci    yAxis_.SetWidth(width);
54a3e0fd82Sopenharmony_ci    xAxis_.UpdateAxis();
55a3e0fd82Sopenharmony_ci    yAxis_.UpdateAxis();
56a3e0fd82Sopenharmony_ci}
57a3e0fd82Sopenharmony_ci
58a3e0fd82Sopenharmony_civoid UIChart::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
59a3e0fd82Sopenharmony_ci{
60a3e0fd82Sopenharmony_ci    UIViewGroup::OnDraw(gfxDstBuffer, invalidatedArea);
61a3e0fd82Sopenharmony_ci    DrawDataSerials(gfxDstBuffer, invalidatedArea);
62a3e0fd82Sopenharmony_ci}
63a3e0fd82Sopenharmony_ci
64a3e0fd82Sopenharmony_cibool UIChart::AddDataSerial(UIChartDataSerial* dataSerial)
65a3e0fd82Sopenharmony_ci{
66a3e0fd82Sopenharmony_ci    if (dataSerial == nullptr) {
67a3e0fd82Sopenharmony_ci        return false;
68a3e0fd82Sopenharmony_ci    }
69a3e0fd82Sopenharmony_ci
70a3e0fd82Sopenharmony_ci    ListNode<UIChartDataSerial*>* serialNode = list_.Head();
71a3e0fd82Sopenharmony_ci    while (serialNode != list_.End()) {
72a3e0fd82Sopenharmony_ci        if (serialNode->data_ == dataSerial) {
73a3e0fd82Sopenharmony_ci            return false;
74a3e0fd82Sopenharmony_ci        }
75a3e0fd82Sopenharmony_ci        serialNode = serialNode->next_;
76a3e0fd82Sopenharmony_ci    }
77a3e0fd82Sopenharmony_ci    list_.PushBack(dataSerial);
78a3e0fd82Sopenharmony_ci    dataSerial->BindToChart(this);
79a3e0fd82Sopenharmony_ci    return true;
80a3e0fd82Sopenharmony_ci}
81a3e0fd82Sopenharmony_ci
82a3e0fd82Sopenharmony_cibool UIChart::DeleteDataSerial(UIChartDataSerial* dataSerial)
83a3e0fd82Sopenharmony_ci{
84a3e0fd82Sopenharmony_ci    if ((dataSerial == nullptr) || list_.IsEmpty()) {
85a3e0fd82Sopenharmony_ci        return false;
86a3e0fd82Sopenharmony_ci    }
87a3e0fd82Sopenharmony_ci
88a3e0fd82Sopenharmony_ci    bool findSerial = false;
89a3e0fd82Sopenharmony_ci    ListNode<UIChartDataSerial*>* serialNode = list_.Head();
90a3e0fd82Sopenharmony_ci    while (serialNode != list_.End()) {
91a3e0fd82Sopenharmony_ci        if (serialNode->data_ == dataSerial) {
92a3e0fd82Sopenharmony_ci            dataSerial->BindToChart(nullptr);
93a3e0fd82Sopenharmony_ci            list_.Remove(serialNode);
94a3e0fd82Sopenharmony_ci            findSerial = true;
95a3e0fd82Sopenharmony_ci            break;
96a3e0fd82Sopenharmony_ci        }
97a3e0fd82Sopenharmony_ci        serialNode = serialNode->next_;
98a3e0fd82Sopenharmony_ci    }
99a3e0fd82Sopenharmony_ci
100a3e0fd82Sopenharmony_ci    return findSerial;
101a3e0fd82Sopenharmony_ci}
102a3e0fd82Sopenharmony_ci
103a3e0fd82Sopenharmony_civoid UIChart::ClearDataSerial()
104a3e0fd82Sopenharmony_ci{
105a3e0fd82Sopenharmony_ci    if (list_.IsEmpty()) {
106a3e0fd82Sopenharmony_ci        return;
107a3e0fd82Sopenharmony_ci    }
108a3e0fd82Sopenharmony_ci
109a3e0fd82Sopenharmony_ci    ListNode<UIChartDataSerial*>* serialNode = list_.Head();
110a3e0fd82Sopenharmony_ci    while (serialNode != list_.End()) {
111a3e0fd82Sopenharmony_ci        serialNode->data_->BindToChart(nullptr);
112a3e0fd82Sopenharmony_ci        ListNode<UIChartDataSerial*>* tempNode = serialNode;
113a3e0fd82Sopenharmony_ci        serialNode = serialNode->next_;
114a3e0fd82Sopenharmony_ci        list_.Remove(tempNode);
115a3e0fd82Sopenharmony_ci    }
116a3e0fd82Sopenharmony_ci    list_.Clear();
117a3e0fd82Sopenharmony_ci}
118a3e0fd82Sopenharmony_ci
119a3e0fd82Sopenharmony_ciUIChartDataSerial::UIChartDataSerial()
120a3e0fd82Sopenharmony_ci    : maxCount_(0),
121a3e0fd82Sopenharmony_ci      pointArray_(nullptr),
122a3e0fd82Sopenharmony_ci      serialColor_(Color::White()),
123a3e0fd82Sopenharmony_ci      fillColor_(Color::White()),
124a3e0fd82Sopenharmony_ci      dataCount_(0),
125a3e0fd82Sopenharmony_ci      peakPointIndex_(0),
126a3e0fd82Sopenharmony_ci      peakData_(0),
127a3e0fd82Sopenharmony_ci      valleyData_(0),
128a3e0fd82Sopenharmony_ci      valleyPointIndex_(0),
129a3e0fd82Sopenharmony_ci      lastPointIndex_(0),
130a3e0fd82Sopenharmony_ci      latestIndex_(0),
131a3e0fd82Sopenharmony_ci      hideIndex_(0),
132a3e0fd82Sopenharmony_ci      hideCount_(0),
133a3e0fd82Sopenharmony_ci      smooth_(false),
134a3e0fd82Sopenharmony_ci      enableGradient_(false),
135a3e0fd82Sopenharmony_ci      enableHeadPoint_(false),
136a3e0fd82Sopenharmony_ci      enableTopPoint_(false),
137a3e0fd82Sopenharmony_ci      enableBottomPoint_(false),
138a3e0fd82Sopenharmony_ci      chart_(nullptr),
139a3e0fd82Sopenharmony_ci      invalidateRect_(0, 0, 0, 0)
140a3e0fd82Sopenharmony_ci{
141a3e0fd82Sopenharmony_ci    PointStyle style;
142a3e0fd82Sopenharmony_ci    style.radius = DEFAULT_POINT_RADIUS;
143a3e0fd82Sopenharmony_ci    style.strokeWidth = 1;
144a3e0fd82Sopenharmony_ci    style.fillColor = Color::White();
145a3e0fd82Sopenharmony_ci    style.strokeColor = Color::White();
146a3e0fd82Sopenharmony_ci    topPointStyle_ = style;
147a3e0fd82Sopenharmony_ci    bottomPointStyle_ = style;
148a3e0fd82Sopenharmony_ci    headPointStyle_ = style;
149a3e0fd82Sopenharmony_ci}
150a3e0fd82Sopenharmony_ci
151a3e0fd82Sopenharmony_cibool UIChartDataSerial::SetMaxDataCount(uint16_t maxCount)
152a3e0fd82Sopenharmony_ci{
153a3e0fd82Sopenharmony_ci    if (maxCount > MAX_POINTS_COUNT) {
154a3e0fd82Sopenharmony_ci        maxCount = MAX_POINTS_COUNT;
155a3e0fd82Sopenharmony_ci    }
156a3e0fd82Sopenharmony_ci
157a3e0fd82Sopenharmony_ci    if (maxCount == maxCount_) {
158a3e0fd82Sopenharmony_ci        return true;
159a3e0fd82Sopenharmony_ci    }
160a3e0fd82Sopenharmony_ci
161a3e0fd82Sopenharmony_ci    if (pointArray_ != nullptr) {
162a3e0fd82Sopenharmony_ci        UIFree(pointArray_);
163a3e0fd82Sopenharmony_ci        pointArray_ = nullptr;
164a3e0fd82Sopenharmony_ci    }
165a3e0fd82Sopenharmony_ci
166a3e0fd82Sopenharmony_ci    maxCount_ = maxCount;
167a3e0fd82Sopenharmony_ci    if (maxCount_ == 0) {
168a3e0fd82Sopenharmony_ci        return true;
169a3e0fd82Sopenharmony_ci    }
170a3e0fd82Sopenharmony_ci
171a3e0fd82Sopenharmony_ci    pointArray_ = static_cast<Point*>(UIMalloc(sizeof(Point) * maxCount_));
172a3e0fd82Sopenharmony_ci    if (pointArray_ == nullptr) {
173a3e0fd82Sopenharmony_ci        maxCount_ = 0;
174a3e0fd82Sopenharmony_ci        return false;
175a3e0fd82Sopenharmony_ci    }
176a3e0fd82Sopenharmony_ci    return true;
177a3e0fd82Sopenharmony_ci}
178a3e0fd82Sopenharmony_ci
179a3e0fd82Sopenharmony_cibool UIChartDataSerial::ModifyPoint(uint16_t index, const Point& point)
180a3e0fd82Sopenharmony_ci{
181a3e0fd82Sopenharmony_ci    if ((index >= maxCount_) || (pointArray_ == nullptr)) {
182a3e0fd82Sopenharmony_ci        return false;
183a3e0fd82Sopenharmony_ci    }
184a3e0fd82Sopenharmony_ci
185a3e0fd82Sopenharmony_ci    pointArray_[index].x = point.x;
186a3e0fd82Sopenharmony_ci    pointArray_[index].y = point.y;
187a3e0fd82Sopenharmony_ci    if (point.y > peakData_) {
188a3e0fd82Sopenharmony_ci        if (enableTopPoint_) {
189a3e0fd82Sopenharmony_ci            RefreshInvalidateRect(peakPointIndex_, topPointStyle_);
190a3e0fd82Sopenharmony_ci        }
191a3e0fd82Sopenharmony_ci        peakPointIndex_ = index;
192a3e0fd82Sopenharmony_ci        peakData_ = point.y;
193a3e0fd82Sopenharmony_ci    } else if (point.y < valleyData_) {
194a3e0fd82Sopenharmony_ci        if (enableBottomPoint_) {
195a3e0fd82Sopenharmony_ci            RefreshInvalidateRect(valleyPointIndex_, bottomPointStyle_);
196a3e0fd82Sopenharmony_ci        }
197a3e0fd82Sopenharmony_ci        valleyPointIndex_ = index;
198a3e0fd82Sopenharmony_ci        valleyData_ = point.y;
199a3e0fd82Sopenharmony_ci    } else if ((index == peakPointIndex_) || (index == valleyPointIndex_)) {
200a3e0fd82Sopenharmony_ci        UpdatePeakAndValley(0, dataCount_);
201a3e0fd82Sopenharmony_ci    }
202a3e0fd82Sopenharmony_ci
203a3e0fd82Sopenharmony_ci    latestIndex_ = index;
204a3e0fd82Sopenharmony_ci    uint16_t startIndex = (index == 0) ? index : (index - 1);
205a3e0fd82Sopenharmony_ci    RefreshInvalidateRect(startIndex, index + 1);
206a3e0fd82Sopenharmony_ci    return true;
207a3e0fd82Sopenharmony_ci}
208a3e0fd82Sopenharmony_ci
209a3e0fd82Sopenharmony_cibool UIChartDataSerial::GetPoint(uint16_t index, Point& point)
210a3e0fd82Sopenharmony_ci{
211a3e0fd82Sopenharmony_ci    if ((index >= dataCount_) || (pointArray_ == nullptr)) {
212a3e0fd82Sopenharmony_ci        return false;
213a3e0fd82Sopenharmony_ci    }
214a3e0fd82Sopenharmony_ci    point = pointArray_[index];
215a3e0fd82Sopenharmony_ci    if (chart_ != nullptr) {
216a3e0fd82Sopenharmony_ci        chart_->GetXAxis().TranslateToPixel(point.x);
217a3e0fd82Sopenharmony_ci        chart_->GetYAxis().TranslateToPixel(point.y);
218a3e0fd82Sopenharmony_ci    }
219a3e0fd82Sopenharmony_ci    return true;
220a3e0fd82Sopenharmony_ci}
221a3e0fd82Sopenharmony_ci
222a3e0fd82Sopenharmony_cibool UIChartDataSerial::GetOriginalPoint(uint16_t index, Point& point)
223a3e0fd82Sopenharmony_ci{
224a3e0fd82Sopenharmony_ci    if ((index >= dataCount_) || (pointArray_ == nullptr)) {
225a3e0fd82Sopenharmony_ci        return false;
226a3e0fd82Sopenharmony_ci    }
227a3e0fd82Sopenharmony_ci    point = pointArray_[index];
228a3e0fd82Sopenharmony_ci    return true;
229a3e0fd82Sopenharmony_ci}
230a3e0fd82Sopenharmony_ci
231a3e0fd82Sopenharmony_cibool UIChartDataSerial::PointArrayDup(Point** pointArrayBack)
232a3e0fd82Sopenharmony_ci{
233a3e0fd82Sopenharmony_ci    *pointArrayBack = pointArray_;
234a3e0fd82Sopenharmony_ci    pointArray_ = static_cast<Point*>(UIMalloc(sizeof(Point) * maxCount_));
235a3e0fd82Sopenharmony_ci    return memcpy_s(pointArray_, dataCount_ * sizeof(Point), *pointArrayBack, dataCount_ * sizeof(Point)) != EOK;
236a3e0fd82Sopenharmony_ci}
237a3e0fd82Sopenharmony_ci
238a3e0fd82Sopenharmony_civoid UIChartDataSerial::HidePoint(uint16_t index, uint16_t count)
239a3e0fd82Sopenharmony_ci{
240a3e0fd82Sopenharmony_ci    hideIndex_ = index;
241a3e0fd82Sopenharmony_ci    hideCount_ = count;
242a3e0fd82Sopenharmony_ci    RefreshInvalidateRect(hideIndex_, hideIndex_ + hideCount_);
243a3e0fd82Sopenharmony_ci}
244a3e0fd82Sopenharmony_ci
245a3e0fd82Sopenharmony_civoid UIChartDataSerial::RefreshInvalidateRect(uint16_t pointIndex, const PointStyle& style)
246a3e0fd82Sopenharmony_ci{
247a3e0fd82Sopenharmony_ci    Point point;
248a3e0fd82Sopenharmony_ci    if (GetPoint(pointIndex, point)) {
249a3e0fd82Sopenharmony_ci        uint16_t width = style.radius + style.strokeWidth;
250a3e0fd82Sopenharmony_ci        Rect refresh(point.x - width, 0, point.x + width, 0);
251a3e0fd82Sopenharmony_ci        if ((invalidateRect_.GetLeft() == 0) && (invalidateRect_.GetRight() == 0)) {
252a3e0fd82Sopenharmony_ci            invalidateRect_ = refresh;
253a3e0fd82Sopenharmony_ci        } else {
254a3e0fd82Sopenharmony_ci            invalidateRect_.Join(invalidateRect_, refresh);
255a3e0fd82Sopenharmony_ci        }
256a3e0fd82Sopenharmony_ci    }
257a3e0fd82Sopenharmony_ci}
258a3e0fd82Sopenharmony_ci
259a3e0fd82Sopenharmony_civoid UIChartDataSerial::RefreshInvalidateRect(uint16_t startIndex, uint16_t endIndex)
260a3e0fd82Sopenharmony_ci{
261a3e0fd82Sopenharmony_ci    Point start;
262a3e0fd82Sopenharmony_ci    GetPoint(startIndex, start);
263a3e0fd82Sopenharmony_ci    Point end;
264a3e0fd82Sopenharmony_ci    endIndex = (endIndex >= dataCount_) ? (dataCount_ - 1) : endIndex;
265a3e0fd82Sopenharmony_ci    GetPoint(endIndex, end);
266a3e0fd82Sopenharmony_ci    int16_t xMin = MATH_MIN(start.x, end.x);
267a3e0fd82Sopenharmony_ci    int16_t xMax = MATH_MAX(start.x, end.x);
268a3e0fd82Sopenharmony_ci    Rect refresh(xMin, 0, xMax, 0);
269a3e0fd82Sopenharmony_ci    if ((invalidateRect_.GetLeft() == 0) && (invalidateRect_.GetRight() == 0)) {
270a3e0fd82Sopenharmony_ci        invalidateRect_ = refresh;
271a3e0fd82Sopenharmony_ci        return;
272a3e0fd82Sopenharmony_ci    }
273a3e0fd82Sopenharmony_ci    invalidateRect_.Join(invalidateRect_, refresh);
274a3e0fd82Sopenharmony_ci}
275a3e0fd82Sopenharmony_ci
276a3e0fd82Sopenharmony_cibool UIChartDataSerial::UpdatePeakAndValley(uint16_t startPos, uint16_t endPos)
277a3e0fd82Sopenharmony_ci{
278a3e0fd82Sopenharmony_ci    if ((startPos >= endPos) || (endPos > dataCount_) || (pointArray_ == nullptr)) {
279a3e0fd82Sopenharmony_ci        return false;
280a3e0fd82Sopenharmony_ci    }
281a3e0fd82Sopenharmony_ci
282a3e0fd82Sopenharmony_ci    if (startPos == 0) {
283a3e0fd82Sopenharmony_ci        peakData_ = pointArray_[startPos].y;
284a3e0fd82Sopenharmony_ci        valleyData_ = pointArray_[startPos].y;
285a3e0fd82Sopenharmony_ci    }
286a3e0fd82Sopenharmony_ci
287a3e0fd82Sopenharmony_ci    for (uint16_t i = startPos; i < endPos; i++) {
288a3e0fd82Sopenharmony_ci        if (pointArray_[i].y > peakData_) {
289a3e0fd82Sopenharmony_ci            if (enableTopPoint_) {
290a3e0fd82Sopenharmony_ci                RefreshInvalidateRect(peakPointIndex_, topPointStyle_);
291a3e0fd82Sopenharmony_ci                RefreshInvalidateRect(i, topPointStyle_);
292a3e0fd82Sopenharmony_ci            }
293a3e0fd82Sopenharmony_ci            peakPointIndex_ = i;
294a3e0fd82Sopenharmony_ci            peakData_ = pointArray_[i].y;
295a3e0fd82Sopenharmony_ci        }
296a3e0fd82Sopenharmony_ci
297a3e0fd82Sopenharmony_ci        if (pointArray_[i].y < valleyData_) {
298a3e0fd82Sopenharmony_ci            if (enableBottomPoint_) {
299a3e0fd82Sopenharmony_ci                RefreshInvalidateRect(valleyPointIndex_, bottomPointStyle_);
300a3e0fd82Sopenharmony_ci                RefreshInvalidateRect(i, bottomPointStyle_);
301a3e0fd82Sopenharmony_ci            }
302a3e0fd82Sopenharmony_ci            valleyPointIndex_ = i;
303a3e0fd82Sopenharmony_ci            valleyData_ = pointArray_[i].y;
304a3e0fd82Sopenharmony_ci        }
305a3e0fd82Sopenharmony_ci    }
306a3e0fd82Sopenharmony_ci    return true;
307a3e0fd82Sopenharmony_ci}
308a3e0fd82Sopenharmony_ci
309a3e0fd82Sopenharmony_cibool UIChartDataSerial::AddPoints(const Point* data, uint16_t count)
310a3e0fd82Sopenharmony_ci{
311a3e0fd82Sopenharmony_ci    if ((maxCount_ <= dataCount_) || (count == 0) || (pointArray_ == nullptr) || (data == nullptr)) {
312a3e0fd82Sopenharmony_ci        return false;
313a3e0fd82Sopenharmony_ci    }
314a3e0fd82Sopenharmony_ci
315a3e0fd82Sopenharmony_ci    if (count > (maxCount_ - dataCount_)) {
316a3e0fd82Sopenharmony_ci        count = maxCount_ - dataCount_;
317a3e0fd82Sopenharmony_ci    }
318a3e0fd82Sopenharmony_ci
319a3e0fd82Sopenharmony_ci    Point* current = pointArray_ + dataCount_;
320a3e0fd82Sopenharmony_ci    if (memcpy_s(current, (maxCount_ - dataCount_) * sizeof(Point), data, count * sizeof(Point)) != EOK) {
321a3e0fd82Sopenharmony_ci        return false;
322a3e0fd82Sopenharmony_ci    }
323a3e0fd82Sopenharmony_ci    uint16_t i = dataCount_;
324a3e0fd82Sopenharmony_ci    dataCount_ += count;
325a3e0fd82Sopenharmony_ci    UpdatePeakAndValley(i, dataCount_);
326a3e0fd82Sopenharmony_ci    latestIndex_ = dataCount_ - 1;
327a3e0fd82Sopenharmony_ci    uint16_t startIndex = (i == 0) ? i : (i - 1);
328a3e0fd82Sopenharmony_ci    RefreshInvalidateRect(startIndex, latestIndex_);
329a3e0fd82Sopenharmony_ci    return true;
330a3e0fd82Sopenharmony_ci}
331a3e0fd82Sopenharmony_ci
332a3e0fd82Sopenharmony_civoid UIChartDataSerial::ClearData()
333a3e0fd82Sopenharmony_ci{
334a3e0fd82Sopenharmony_ci    RefreshInvalidateRect(0, dataCount_ - 1);
335a3e0fd82Sopenharmony_ci    if (pointArray_ != nullptr) {
336a3e0fd82Sopenharmony_ci        if (memset_s(pointArray_, maxCount_ * sizeof(Point), 0, maxCount_ * sizeof(Point)) != EOK) {
337a3e0fd82Sopenharmony_ci            return;
338a3e0fd82Sopenharmony_ci        }
339a3e0fd82Sopenharmony_ci    }
340a3e0fd82Sopenharmony_ci    dataCount_ = 0;
341a3e0fd82Sopenharmony_ci    valleyPointIndex_ = 0;
342a3e0fd82Sopenharmony_ci    peakPointIndex_ = 0;
343a3e0fd82Sopenharmony_ci    latestIndex_ = 0;
344a3e0fd82Sopenharmony_ci}
345a3e0fd82Sopenharmony_ci
346a3e0fd82Sopenharmony_civoid UIChartDataSerial::DoDrawPoint(BufferInfo& gfxDstBuffer,
347a3e0fd82Sopenharmony_ci                                    const Point& center,
348a3e0fd82Sopenharmony_ci                                    const PointStyle& style,
349a3e0fd82Sopenharmony_ci                                    const Rect& mask)
350a3e0fd82Sopenharmony_ci{
351a3e0fd82Sopenharmony_ci    Style drawStyle = StyleDefault::GetDefaultStyle();
352a3e0fd82Sopenharmony_ci    drawStyle.lineOpa_ = OPA_OPAQUE;
353a3e0fd82Sopenharmony_ci    drawStyle.lineColor_ = style.fillColor;
354a3e0fd82Sopenharmony_ci
355a3e0fd82Sopenharmony_ci    ArcInfo arcinfo = {{0}};
356a3e0fd82Sopenharmony_ci    arcinfo.center = center;
357a3e0fd82Sopenharmony_ci    arcinfo.imgPos = Point{0, 0};
358a3e0fd82Sopenharmony_ci    arcinfo.radius = style.radius + style.strokeWidth;
359a3e0fd82Sopenharmony_ci    arcinfo.startAngle = 0;
360a3e0fd82Sopenharmony_ci    arcinfo.endAngle = CIRCLE_IN_DEGREE;
361a3e0fd82Sopenharmony_ci    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
362a3e0fd82Sopenharmony_ci    if (style.fillColor.full == style.strokeColor.full) {
363a3e0fd82Sopenharmony_ci        drawStyle.lineWidth_ = style.radius + style.strokeWidth;
364a3e0fd82Sopenharmony_ci        baseGfxEngine->DrawArc(gfxDstBuffer, arcinfo, mask, drawStyle, OPA_OPAQUE, CapType::CAP_NONE);
365a3e0fd82Sopenharmony_ci        return;
366a3e0fd82Sopenharmony_ci    }
367a3e0fd82Sopenharmony_ci    drawStyle.lineWidth_ = style.radius;
368a3e0fd82Sopenharmony_ci    arcinfo.radius = style.radius;
369a3e0fd82Sopenharmony_ci    baseGfxEngine->DrawArc(gfxDstBuffer, arcinfo, mask, drawStyle, OPA_OPAQUE, CapType::CAP_NONE);
370a3e0fd82Sopenharmony_ci
371a3e0fd82Sopenharmony_ci    drawStyle.lineWidth_ = style.strokeWidth;
372a3e0fd82Sopenharmony_ci    drawStyle.lineColor_ = style.strokeColor;
373a3e0fd82Sopenharmony_ci    arcinfo.radius = style.radius + style.strokeWidth;
374a3e0fd82Sopenharmony_ci    baseGfxEngine->DrawArc(gfxDstBuffer, arcinfo, mask, drawStyle, OPA_OPAQUE, CapType::CAP_NONE);
375a3e0fd82Sopenharmony_ci}
376a3e0fd82Sopenharmony_ci
377a3e0fd82Sopenharmony_civoid UIChartDataSerial::DrawPoint(BufferInfo& gfxDstBuffer, const Rect& mask)
378a3e0fd82Sopenharmony_ci{
379a3e0fd82Sopenharmony_ci    Point center;
380a3e0fd82Sopenharmony_ci    if (enableTopPoint_) {
381a3e0fd82Sopenharmony_ci        if (GetPoint(peakPointIndex_, center)) {
382a3e0fd82Sopenharmony_ci            DoDrawPoint(gfxDstBuffer, center, topPointStyle_, mask);
383a3e0fd82Sopenharmony_ci        }
384a3e0fd82Sopenharmony_ci    }
385a3e0fd82Sopenharmony_ci
386a3e0fd82Sopenharmony_ci    if (enableBottomPoint_) {
387a3e0fd82Sopenharmony_ci        if (GetPoint(valleyPointIndex_, center)) {
388a3e0fd82Sopenharmony_ci            DoDrawPoint(gfxDstBuffer, center, bottomPointStyle_, mask);
389a3e0fd82Sopenharmony_ci        }
390a3e0fd82Sopenharmony_ci    }
391a3e0fd82Sopenharmony_ci
392a3e0fd82Sopenharmony_ci    if (enableHeadPoint_) {
393a3e0fd82Sopenharmony_ci        if (GetPoint(latestIndex_, center)) {
394a3e0fd82Sopenharmony_ci            DoDrawPoint(gfxDstBuffer, center, headPointStyle_, mask);
395a3e0fd82Sopenharmony_ci            lastPointIndex_ = latestIndex_;
396a3e0fd82Sopenharmony_ci        }
397a3e0fd82Sopenharmony_ci    }
398a3e0fd82Sopenharmony_ci}
399a3e0fd82Sopenharmony_ci
400a3e0fd82Sopenharmony_civoid UIChartDataSerial::Refresh()
401a3e0fd82Sopenharmony_ci{
402a3e0fd82Sopenharmony_ci    if (chart_ != nullptr) {
403a3e0fd82Sopenharmony_ci        Rect refresh = chart_->GetContentRect();
404a3e0fd82Sopenharmony_ci        refresh.SetLeft(invalidateRect_.GetLeft() - headPointStyle_.radius - headPointStyle_.strokeWidth);
405a3e0fd82Sopenharmony_ci        refresh.SetRight(invalidateRect_.GetRight() + headPointStyle_.radius + headPointStyle_.strokeWidth);
406a3e0fd82Sopenharmony_ci        invalidateRect_.SetRect(0, 0, 0, 0);
407a3e0fd82Sopenharmony_ci        chart_->InvalidateRect(refresh);
408a3e0fd82Sopenharmony_ci
409a3e0fd82Sopenharmony_ci        if (enableHeadPoint_ && (lastPointIndex_ != latestIndex_)) {
410a3e0fd82Sopenharmony_ci            RefreshInvalidateRect(lastPointIndex_, headPointStyle_);
411a3e0fd82Sopenharmony_ci            refresh.SetLeft(invalidateRect_.GetLeft());
412a3e0fd82Sopenharmony_ci            refresh.SetRight(invalidateRect_.GetRight());
413a3e0fd82Sopenharmony_ci            chart_->InvalidateRect(refresh);
414a3e0fd82Sopenharmony_ci            invalidateRect_.SetRect(0, 0, 0, 0);
415a3e0fd82Sopenharmony_ci        }
416a3e0fd82Sopenharmony_ci    }
417a3e0fd82Sopenharmony_ci}
418a3e0fd82Sopenharmony_ci
419a3e0fd82Sopenharmony_civoid UIChartPillar::RefreshChart()
420a3e0fd82Sopenharmony_ci{
421a3e0fd82Sopenharmony_ci    ListNode<UIChartDataSerial*>* iter = list_.Begin();
422a3e0fd82Sopenharmony_ci    Rect rect = GetContentRect();
423a3e0fd82Sopenharmony_ci    for (; iter != list_.End(); iter = iter->next_) {
424a3e0fd82Sopenharmony_ci        UIChartDataSerial* data = iter->data_;
425a3e0fd82Sopenharmony_ci        if (data == nullptr) {
426a3e0fd82Sopenharmony_ci            break;
427a3e0fd82Sopenharmony_ci        }
428a3e0fd82Sopenharmony_ci        uint16_t dataCount = data->GetDataCount();
429a3e0fd82Sopenharmony_ci        if (dataCount <= 1) {
430a3e0fd82Sopenharmony_ci            break;
431a3e0fd82Sopenharmony_ci        }
432a3e0fd82Sopenharmony_ci
433a3e0fd82Sopenharmony_ci        uint16_t index = data->GetLastPointIndex();
434a3e0fd82Sopenharmony_ci        if (index >= dataCount) {
435a3e0fd82Sopenharmony_ci            break;
436a3e0fd82Sopenharmony_ci        }
437a3e0fd82Sopenharmony_ci
438a3e0fd82Sopenharmony_ci        Point current;
439a3e0fd82Sopenharmony_ci        data->GetPoint(index, current);
440a3e0fd82Sopenharmony_ci        Point last;
441a3e0fd82Sopenharmony_ci        data->GetPoint(dataCount - 1, last);
442a3e0fd82Sopenharmony_ci        Rect refresh(current.x, rect.GetTop(), last.x, rect.GetBottom());
443a3e0fd82Sopenharmony_ci        InvalidateRect(refresh);
444a3e0fd82Sopenharmony_ci        data->SetLastPointIndex(dataCount - 1);
445a3e0fd82Sopenharmony_ci    }
446a3e0fd82Sopenharmony_ci}
447a3e0fd82Sopenharmony_ci
448a3e0fd82Sopenharmony_civoid UIChartPillar::DrawDataSerials(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
449a3e0fd82Sopenharmony_ci{
450a3e0fd82Sopenharmony_ci    xAxis_.UpdateAxisPoints();
451a3e0fd82Sopenharmony_ci    yAxis_.UpdateAxisPoints();
452a3e0fd82Sopenharmony_ci    uint16_t minXStep = static_cast<uint16_t>(xAxis_.GetMarkInterval());
453a3e0fd82Sopenharmony_ci    Point xStart = xAxis_.GetStartPoint();
454a3e0fd82Sopenharmony_ci    uint16_t dataSerialCount = list_.Size();
455a3e0fd82Sopenharmony_ci    if (dataSerialCount == 0) {
456a3e0fd82Sopenharmony_ci        return;
457a3e0fd82Sopenharmony_ci    }
458a3e0fd82Sopenharmony_ci    uint16_t width = minXStep / dataSerialCount;
459a3e0fd82Sopenharmony_ci    uint8_t dataSerialIndex = 0;
460a3e0fd82Sopenharmony_ci    uint16_t barWidth = static_cast<uint16_t>(width - DEFAULT_MARK_PERCENTAGE * (width << 1));
461a3e0fd82Sopenharmony_ci
462a3e0fd82Sopenharmony_ci    for (ListNode<UIChartDataSerial*>* iter = list_.Begin(); iter != list_.End(); iter = iter->next_) {
463a3e0fd82Sopenharmony_ci        UIChartDataSerial* data = iter->data_;
464a3e0fd82Sopenharmony_ci        uint16_t dataSerialWidth = width * dataSerialIndex;
465a3e0fd82Sopenharmony_ci        int16_t x = dataSerialWidth + (width >> 1);
466a3e0fd82Sopenharmony_ci        for (uint16_t index = 0; index < data->GetDataCount(); index++) {
467a3e0fd82Sopenharmony_ci            Point current;
468a3e0fd82Sopenharmony_ci            data->GetPoint(index, current);
469a3e0fd82Sopenharmony_ci            if (current.y == xStart.y) {
470a3e0fd82Sopenharmony_ci                continue;
471a3e0fd82Sopenharmony_ci            }
472a3e0fd82Sopenharmony_ci            current.x += x;
473a3e0fd82Sopenharmony_ci            xStart.x = current.x;
474a3e0fd82Sopenharmony_ci            BaseGfxEngine::GetInstance()->DrawLine(gfxDstBuffer, current, xStart, invalidatedArea, barWidth,
475a3e0fd82Sopenharmony_ci                                                   data->GetFillColor(), style_->lineOpa_);
476a3e0fd82Sopenharmony_ci        }
477a3e0fd82Sopenharmony_ci        dataSerialIndex++;
478a3e0fd82Sopenharmony_ci    }
479a3e0fd82Sopenharmony_ci}
480a3e0fd82Sopenharmony_ci
481a3e0fd82Sopenharmony_civoid UIChartPolyline::RefreshChart()
482a3e0fd82Sopenharmony_ci{
483a3e0fd82Sopenharmony_ci    ListNode<UIChartDataSerial*>* iter = list_.Begin();
484a3e0fd82Sopenharmony_ci    for (; iter != list_.End(); iter = iter->next_) {
485a3e0fd82Sopenharmony_ci        UIChartDataSerial* data = iter->data_;
486a3e0fd82Sopenharmony_ci        uint16_t dataCount = data->GetDataCount();
487a3e0fd82Sopenharmony_ci        if (dataCount == 1) {
488a3e0fd82Sopenharmony_ci            break;
489a3e0fd82Sopenharmony_ci        }
490a3e0fd82Sopenharmony_ci        data->Refresh();
491a3e0fd82Sopenharmony_ci    }
492a3e0fd82Sopenharmony_ci}
493a3e0fd82Sopenharmony_ci
494a3e0fd82Sopenharmony_civoid UIChartPolyline::ReMeasure()
495a3e0fd82Sopenharmony_ci{
496a3e0fd82Sopenharmony_ci    if (!needRefresh_) {
497a3e0fd82Sopenharmony_ci        return;
498a3e0fd82Sopenharmony_ci    }
499a3e0fd82Sopenharmony_ci    needRefresh_ = false;
500a3e0fd82Sopenharmony_ci    int16_t height = GetHeight();
501a3e0fd82Sopenharmony_ci    if (mixData_ != nullptr) {
502a3e0fd82Sopenharmony_ci        UIFree(mixData_);
503a3e0fd82Sopenharmony_ci        mixData_ = nullptr;
504a3e0fd82Sopenharmony_ci    }
505a3e0fd82Sopenharmony_ci    if (height <= 0) {
506a3e0fd82Sopenharmony_ci        return;
507a3e0fd82Sopenharmony_ci    }
508a3e0fd82Sopenharmony_ci    if (height > COORD_MAX) {
509a3e0fd82Sopenharmony_ci        height = COORD_MAX;
510a3e0fd82Sopenharmony_ci    }
511a3e0fd82Sopenharmony_ci    mixData_ = static_cast<uint8_t*>(UIMalloc(height));
512a3e0fd82Sopenharmony_ci    if (mixData_ == nullptr) {
513a3e0fd82Sopenharmony_ci        return;
514a3e0fd82Sopenharmony_ci    }
515a3e0fd82Sopenharmony_ci    int16_t opa = maxOpa_ - minOpa_;
516a3e0fd82Sopenharmony_ci    for (int16_t y = 0; y < height; y++) {
517a3e0fd82Sopenharmony_ci        mixData_[y] = static_cast<uint8_t>(y * opa / height + minOpa_);
518a3e0fd82Sopenharmony_ci    }
519a3e0fd82Sopenharmony_ci}
520a3e0fd82Sopenharmony_ci
521a3e0fd82Sopenharmony_civoid UIChartPolyline::DrawDataSerials(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
522a3e0fd82Sopenharmony_ci{
523a3e0fd82Sopenharmony_ci    xAxis_.UpdateAxisPoints();
524a3e0fd82Sopenharmony_ci    yAxis_.UpdateAxisPoints();
525a3e0fd82Sopenharmony_ci    ListNode<UIChartDataSerial*>* iter = list_.Begin();
526a3e0fd82Sopenharmony_ci    for (; iter != list_.End(); iter = iter->next_) {
527a3e0fd82Sopenharmony_ci        UIChartDataSerial* data = iter->data_;
528a3e0fd82Sopenharmony_ci        uint16_t dataCount = data->GetDataCount();
529a3e0fd82Sopenharmony_ci        if (dataCount <= 1) {
530a3e0fd82Sopenharmony_ci            continue;
531a3e0fd82Sopenharmony_ci        }
532a3e0fd82Sopenharmony_ci        if (data->IsGradient()) {
533a3e0fd82Sopenharmony_ci            if (data->IsSmooth()) {
534a3e0fd82Sopenharmony_ci                Point* pointArrayBack = nullptr;
535a3e0fd82Sopenharmony_ci                data->PointArrayDup(&pointArrayBack);
536a3e0fd82Sopenharmony_ci                GetDataBySmooth(0, dataCount - 1, data);
537a3e0fd82Sopenharmony_ci                GradientColor(gfxDstBuffer, invalidatedArea, data);
538a3e0fd82Sopenharmony_ci                data->ClearData();
539a3e0fd82Sopenharmony_ci                data->AddPoints(pointArrayBack, dataCount);
540a3e0fd82Sopenharmony_ci                UIFree(pointArrayBack);
541a3e0fd82Sopenharmony_ci            } else {
542a3e0fd82Sopenharmony_ci                GradientColor(gfxDstBuffer, invalidatedArea, data);
543a3e0fd82Sopenharmony_ci            }
544a3e0fd82Sopenharmony_ci        }
545a3e0fd82Sopenharmony_ci        if (data->GetHideCount() != 0) {
546a3e0fd82Sopenharmony_ci            uint16_t hideIndex = data->GetHideIndex();
547a3e0fd82Sopenharmony_ci            DrawPolyLine(gfxDstBuffer, 0, hideIndex, invalidatedArea, data);
548a3e0fd82Sopenharmony_ci            DrawPolyLine(gfxDstBuffer, hideIndex + data->GetHideCount(), dataCount - 1, invalidatedArea, data);
549a3e0fd82Sopenharmony_ci        } else {
550a3e0fd82Sopenharmony_ci            DrawPolyLine(gfxDstBuffer, 0, dataCount - 1, invalidatedArea, data);
551a3e0fd82Sopenharmony_ci        }
552a3e0fd82Sopenharmony_ci
553a3e0fd82Sopenharmony_ci        data->DrawPoint(gfxDstBuffer, invalidatedArea);
554a3e0fd82Sopenharmony_ci    }
555a3e0fd82Sopenharmony_ci}
556a3e0fd82Sopenharmony_ci
557a3e0fd82Sopenharmony_cibool UIChartPolyline::Smooth(uint16_t startPos,
558a3e0fd82Sopenharmony_ci                             Point& start,
559a3e0fd82Sopenharmony_ci                             Point& end,
560a3e0fd82Sopenharmony_ci                             Point& current,
561a3e0fd82Sopenharmony_ci                             UIChartDataSerial* data,
562a3e0fd82Sopenharmony_ci                             uint16_t& slope,
563a3e0fd82Sopenharmony_ci                             uint16_t& preSlope)
564a3e0fd82Sopenharmony_ci{
565a3e0fd82Sopenharmony_ci    data->GetPoint(startPos + 1, current);
566a3e0fd82Sopenharmony_ci    if (((end.y - start.y <= 0) && (current.y - end.y <= 0)) || ((end.y - start.y >= 0) && (current.y - end.y >= 0))) {
567a3e0fd82Sopenharmony_ci        slope = (current.x == start.x) ? QUARTER_IN_DEGREE : FastAtan2(current.x - start.x, current.y - start.y);
568a3e0fd82Sopenharmony_ci        if (MATH_ABS(slope - preSlope) < SMOOTH_SLOPE_ANGLE) {
569a3e0fd82Sopenharmony_ci            end = current;
570a3e0fd82Sopenharmony_ci            return false;
571a3e0fd82Sopenharmony_ci        }
572a3e0fd82Sopenharmony_ci    }
573a3e0fd82Sopenharmony_ci    preSlope = (current.x == end.x) ? QUARTER_IN_DEGREE : FastAtan2(current.x - end.x, current.y - end.y);
574a3e0fd82Sopenharmony_ci    return true;
575a3e0fd82Sopenharmony_ci}
576a3e0fd82Sopenharmony_ci
577a3e0fd82Sopenharmony_civoid UIChartPolyline::GetDataBySmooth(uint16_t startIndex, uint16_t endIndex, UIChartDataSerial* data)
578a3e0fd82Sopenharmony_ci{
579a3e0fd82Sopenharmony_ci    if (data == nullptr) {
580a3e0fd82Sopenharmony_ci        return;
581a3e0fd82Sopenharmony_ci    }
582a3e0fd82Sopenharmony_ci    Point* pointArray = static_cast<Point*>(UIMalloc(sizeof(Point) * data->GetDataCount()));
583a3e0fd82Sopenharmony_ci    Point start;
584a3e0fd82Sopenharmony_ci    Point end;
585a3e0fd82Sopenharmony_ci
586a3e0fd82Sopenharmony_ci    uint16_t slope;
587a3e0fd82Sopenharmony_ci    data->GetPoint(startIndex, start);
588a3e0fd82Sopenharmony_ci    data->GetOriginalPoint(startIndex, pointArray[0]);
589a3e0fd82Sopenharmony_ci    int count = 1;
590a3e0fd82Sopenharmony_ci    data->GetPoint(startIndex + 1, end);
591a3e0fd82Sopenharmony_ci    uint16_t preSlope = (start.x == end.x) ? QUARTER_IN_DEGREE : FastAtan2(end.x - start.x, end.y - start.y);
592a3e0fd82Sopenharmony_ci    Point current;
593a3e0fd82Sopenharmony_ci    for (uint16_t i = startIndex; i < endIndex; i++) {
594a3e0fd82Sopenharmony_ci        if (!Smooth(i, start, end, current, data, slope, preSlope)) {
595a3e0fd82Sopenharmony_ci            continue;
596a3e0fd82Sopenharmony_ci        }
597a3e0fd82Sopenharmony_ci        data->GetOriginalPoint(i, pointArray[count++]);
598a3e0fd82Sopenharmony_ci        start = end;
599a3e0fd82Sopenharmony_ci        end = current;
600a3e0fd82Sopenharmony_ci    }
601a3e0fd82Sopenharmony_ci    data->GetOriginalPoint(endIndex, pointArray[count++]);
602a3e0fd82Sopenharmony_ci    data->ClearData();
603a3e0fd82Sopenharmony_ci    data->AddPoints(pointArray, count);
604a3e0fd82Sopenharmony_ci    UIFree(pointArray);
605a3e0fd82Sopenharmony_ci}
606a3e0fd82Sopenharmony_ci
607a3e0fd82Sopenharmony_civoid UIChartPolyline::DrawSmoothPolyLine(BufferInfo& gfxDstBuffer,
608a3e0fd82Sopenharmony_ci                                         uint16_t startIndex,
609a3e0fd82Sopenharmony_ci                                         uint16_t endIndex,
610a3e0fd82Sopenharmony_ci                                         const Rect& invalidatedArea,
611a3e0fd82Sopenharmony_ci                                         UIChartDataSerial* data)
612a3e0fd82Sopenharmony_ci{
613a3e0fd82Sopenharmony_ci    if (data == nullptr) {
614a3e0fd82Sopenharmony_ci        return;
615a3e0fd82Sopenharmony_ci    }
616a3e0fd82Sopenharmony_ci    Point start;
617a3e0fd82Sopenharmony_ci    Point end;
618a3e0fd82Sopenharmony_ci    ColorType color = data->GetLineColor();
619a3e0fd82Sopenharmony_ci    Style style = *style_;
620a3e0fd82Sopenharmony_ci    style.lineColor_ = color;
621a3e0fd82Sopenharmony_ci    style.lineOpa_ = OPA_OPAQUE;
622a3e0fd82Sopenharmony_ci    uint16_t slope;
623a3e0fd82Sopenharmony_ci    data->GetPoint(startIndex, start);
624a3e0fd82Sopenharmony_ci    data->GetPoint(startIndex + 1, end);
625a3e0fd82Sopenharmony_ci    uint16_t preSlope = (start.x == end.x) ? QUARTER_IN_DEGREE : FastAtan2(end.x - start.x, end.y - start.y);
626a3e0fd82Sopenharmony_ci    Point current;
627a3e0fd82Sopenharmony_ci    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
628a3e0fd82Sopenharmony_ci    for (uint16_t i = startIndex; i < endIndex; i++) {
629a3e0fd82Sopenharmony_ci        if (!Smooth(i, start, end, current, data, slope, preSlope)) {
630a3e0fd82Sopenharmony_ci            continue;
631a3e0fd82Sopenharmony_ci        }
632a3e0fd82Sopenharmony_ci        Rect rect;
633a3e0fd82Sopenharmony_ci        rect.SetLeft(MATH_MIN(start.x, end.x) - style_->lineWidth_);
634a3e0fd82Sopenharmony_ci        rect.SetRight(MATH_MAX(start.x, end.x) + style_->lineWidth_);
635a3e0fd82Sopenharmony_ci        rect.SetTop(MATH_MIN(start.y, end.y) - style_->lineWidth_);
636a3e0fd82Sopenharmony_ci        rect.SetBottom(MATH_MAX(start.y, end.y) + style_->lineWidth_);
637a3e0fd82Sopenharmony_ci        if (!invalidatedArea.IsIntersect(rect)) {
638a3e0fd82Sopenharmony_ci            start = end;
639a3e0fd82Sopenharmony_ci            end = current;
640a3e0fd82Sopenharmony_ci            continue;
641a3e0fd82Sopenharmony_ci        }
642a3e0fd82Sopenharmony_ci        baseGfxEngine->DrawLine(gfxDstBuffer, start, end, invalidatedArea, style_->lineWidth_, color, OPA_OPAQUE);
643a3e0fd82Sopenharmony_ci        ArcInfo arcinfo = {{0}};
644a3e0fd82Sopenharmony_ci        arcinfo.center = end;
645a3e0fd82Sopenharmony_ci        arcinfo.imgPos = Point{0, 0};
646a3e0fd82Sopenharmony_ci        arcinfo.radius = (style_->lineWidth_ + 1) >> 1;
647a3e0fd82Sopenharmony_ci        arcinfo.startAngle = 0;
648a3e0fd82Sopenharmony_ci        arcinfo.endAngle = CIRCLE_IN_DEGREE;
649a3e0fd82Sopenharmony_ci
650a3e0fd82Sopenharmony_ci        baseGfxEngine->DrawArc(gfxDstBuffer, arcinfo, invalidatedArea, style, OPA_OPAQUE, CapType::CAP_NONE);
651a3e0fd82Sopenharmony_ci        start = end;
652a3e0fd82Sopenharmony_ci        end = current;
653a3e0fd82Sopenharmony_ci    }
654a3e0fd82Sopenharmony_ci    baseGfxEngine->DrawLine(gfxDstBuffer, start, end, invalidatedArea, style_->lineWidth_, color, OPA_OPAQUE);
655a3e0fd82Sopenharmony_ci}
656a3e0fd82Sopenharmony_ci
657a3e0fd82Sopenharmony_civoid UIChartPolyline::DrawPolyLine(BufferInfo& gfxDstBuffer,
658a3e0fd82Sopenharmony_ci                                   uint16_t startIndex,
659a3e0fd82Sopenharmony_ci                                   uint16_t endIndex,
660a3e0fd82Sopenharmony_ci                                   const Rect& invalidatedArea,
661a3e0fd82Sopenharmony_ci                                   UIChartDataSerial* data)
662a3e0fd82Sopenharmony_ci{
663a3e0fd82Sopenharmony_ci    if ((startIndex >= endIndex) || (data == nullptr)) {
664a3e0fd82Sopenharmony_ci        return;
665a3e0fd82Sopenharmony_ci    }
666a3e0fd82Sopenharmony_ci
667a3e0fd82Sopenharmony_ci    if (data->IsSmooth()) {
668a3e0fd82Sopenharmony_ci        DrawSmoothPolyLine(gfxDstBuffer, startIndex, endIndex, invalidatedArea, data);
669a3e0fd82Sopenharmony_ci        return;
670a3e0fd82Sopenharmony_ci    }
671a3e0fd82Sopenharmony_ci    Point start;
672a3e0fd82Sopenharmony_ci    Point end;
673a3e0fd82Sopenharmony_ci    ColorType color = data->GetLineColor();
674a3e0fd82Sopenharmony_ci    Style style = *style_;
675a3e0fd82Sopenharmony_ci    style.lineColor_ = color;
676a3e0fd82Sopenharmony_ci    style.lineOpa_ = OPA_OPAQUE;
677a3e0fd82Sopenharmony_ci    ArcInfo arcinfo = {{0}};
678a3e0fd82Sopenharmony_ci    arcinfo.imgPos = Point{0, 0};
679a3e0fd82Sopenharmony_ci    arcinfo.radius = (style_->lineWidth_ + 1) >> 1;
680a3e0fd82Sopenharmony_ci    arcinfo.startAngle = 0;
681a3e0fd82Sopenharmony_ci    arcinfo.endAngle = CIRCLE_IN_DEGREE;
682a3e0fd82Sopenharmony_ci    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
683a3e0fd82Sopenharmony_ci    for (uint16_t i = startIndex; i < endIndex - 1; i++) {
684a3e0fd82Sopenharmony_ci        data->GetPoint(i, start);
685a3e0fd82Sopenharmony_ci        data->GetPoint(i + 1, end);
686a3e0fd82Sopenharmony_ci        Rect rect;
687a3e0fd82Sopenharmony_ci        rect.SetLeft(MATH_MIN(start.x, end.x) - style_->lineWidth_);
688a3e0fd82Sopenharmony_ci        rect.SetRight(MATH_MAX(start.x, end.x) + style_->lineWidth_);
689a3e0fd82Sopenharmony_ci        rect.SetTop(MATH_MIN(start.y, end.y) - style_->lineWidth_);
690a3e0fd82Sopenharmony_ci        rect.SetBottom(MATH_MAX(start.y, end.y) + style_->lineWidth_);
691a3e0fd82Sopenharmony_ci        if (!invalidatedArea.IsIntersect(rect)) {
692a3e0fd82Sopenharmony_ci            continue;
693a3e0fd82Sopenharmony_ci        }
694a3e0fd82Sopenharmony_ci
695a3e0fd82Sopenharmony_ci        baseGfxEngine->DrawLine(gfxDstBuffer, start, end, invalidatedArea, style_->lineWidth_, color, OPA_OPAQUE);
696a3e0fd82Sopenharmony_ci        if (style_->lineWidth_ >= LINE_JOIN_WIDTH) {
697a3e0fd82Sopenharmony_ci            arcinfo.center = end;
698a3e0fd82Sopenharmony_ci            baseGfxEngine->DrawArc(gfxDstBuffer, arcinfo, invalidatedArea, style, OPA_OPAQUE, CapType::CAP_NONE);
699a3e0fd82Sopenharmony_ci        }
700a3e0fd82Sopenharmony_ci    }
701a3e0fd82Sopenharmony_ci    data->GetPoint(endIndex - 1, start);
702a3e0fd82Sopenharmony_ci    data->GetPoint(endIndex, end);
703a3e0fd82Sopenharmony_ci    baseGfxEngine->DrawLine(gfxDstBuffer, start, end, invalidatedArea, style_->lineWidth_, color, OPA_OPAQUE);
704a3e0fd82Sopenharmony_ci}
705a3e0fd82Sopenharmony_ci
706a3e0fd82Sopenharmony_cibool UIChartPolyline::GetLineCrossPoint(const Point& p1,
707a3e0fd82Sopenharmony_ci                                        const Point& p2,
708a3e0fd82Sopenharmony_ci                                        const Point& p3,
709a3e0fd82Sopenharmony_ci                                        const Point& p4,
710a3e0fd82Sopenharmony_ci                                        Point& cross)
711a3e0fd82Sopenharmony_ci{
712a3e0fd82Sopenharmony_ci    /* Rectangular ranges of line segments must intersect. */
713a3e0fd82Sopenharmony_ci    if ((MATH_MIN(p1.x, p2.x) <= MATH_MAX(p3.x, p4.x)) && (MATH_MIN(p3.x, p4.x) <= MATH_MAX(p1.x, p2.x)) &&
714a3e0fd82Sopenharmony_ci        (MATH_MIN(p1.y, p2.y) <= MATH_MAX(p3.y, p4.y)) && (MATH_MIN(p3.y, p4.y) <= MATH_MAX(p1.y, p2.y))) {
715a3e0fd82Sopenharmony_ci        /* Check whether the lines are parallel. If the lines are collinear, there is no intersection point. */
716a3e0fd82Sopenharmony_ci        if ((p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y) != 0) {
717a3e0fd82Sopenharmony_ci            /*
718a3e0fd82Sopenharmony_ci             * (y1 - y2)x + (x2 - x1)y = x2y1 - x1y2  ->  ax + by = c
719a3e0fd82Sopenharmony_ci             * (y3 - y4)x + (x4 - x3)y = x4y3 - x3y4  ->  dx + ey = f
720a3e0fd82Sopenharmony_ci             */
721a3e0fd82Sopenharmony_ci            int64_t a = p1.y - p2.y;
722a3e0fd82Sopenharmony_ci            int64_t b = p2.x - p1.x;
723a3e0fd82Sopenharmony_ci            int64_t c = p2.x * p1.y - p1.x * p2.y;
724a3e0fd82Sopenharmony_ci            int64_t d = p3.y - p4.y;
725a3e0fd82Sopenharmony_ci            int64_t e = p4.x - p3.x;
726a3e0fd82Sopenharmony_ci            int64_t f = p4.x * p3.y - p3.x * p4.y;
727a3e0fd82Sopenharmony_ci            int64_t left = a * e - b * d;
728a3e0fd82Sopenharmony_ci            int64_t right = c * e - b * f;
729a3e0fd82Sopenharmony_ci            if (left == 0) {
730a3e0fd82Sopenharmony_ci                return false;
731a3e0fd82Sopenharmony_ci            }
732a3e0fd82Sopenharmony_ci            cross.x = static_cast<int16_t>(right / left);
733a3e0fd82Sopenharmony_ci            left = b * d - a * e;
734a3e0fd82Sopenharmony_ci            right = c * d - a * f;
735a3e0fd82Sopenharmony_ci            if (left == 0) {
736a3e0fd82Sopenharmony_ci                return false;
737a3e0fd82Sopenharmony_ci            }
738a3e0fd82Sopenharmony_ci            cross.y = static_cast<int16_t>(right / left);
739a3e0fd82Sopenharmony_ci            if ((cross.x >= MATH_MIN(p1.x, p2.x)) && (cross.x <= MATH_MAX(p1.x, p2.x)) &&
740a3e0fd82Sopenharmony_ci                (cross.x >= MATH_MIN(p3.x, p4.x)) && (cross.x <= MATH_MAX(p3.x, p4.x))) {
741a3e0fd82Sopenharmony_ci                return true;
742a3e0fd82Sopenharmony_ci            }
743a3e0fd82Sopenharmony_ci        }
744a3e0fd82Sopenharmony_ci    }
745a3e0fd82Sopenharmony_ci    if ((MATH_MIN(p1.x, p2.x) <= MATH_MAX(p3.x, p4.x)) && (MATH_MIN(p3.x, p4.x) <= MATH_MAX(p1.x, p2.x)) &&
746a3e0fd82Sopenharmony_ci        (MATH_MIN(p1.y, p2.y) >= MATH_MAX(p3.y, p4.y)) && (MATH_MIN(p3.y, p4.y) <= MATH_MAX(p1.y, p2.y))) {
747a3e0fd82Sopenharmony_ci        return enableReverse_ ? true : false;
748a3e0fd82Sopenharmony_ci    }
749a3e0fd82Sopenharmony_ci    return false;
750a3e0fd82Sopenharmony_ci}
751a3e0fd82Sopenharmony_ci
752a3e0fd82Sopenharmony_civoid UIChartPolyline::FindCrossPoints(const ChartLine& line, const ChartLine& polyLine, CrossPointSet& cross)
753a3e0fd82Sopenharmony_ci{
754a3e0fd82Sopenharmony_ci    if (GetLineCrossPoint(line.start, line.end, polyLine.start, polyLine.end, cross.nextFirst)) {
755a3e0fd82Sopenharmony_ci        if (enableReverse_ && (MATH_MIN(line.start.y, line.end.y) >= MATH_MAX(polyLine.start.y, polyLine.end.y))) {
756a3e0fd82Sopenharmony_ci            if (!cross.firstFind) {
757a3e0fd82Sopenharmony_ci                if (polyLine.start.y < polyLine.end.y) {
758a3e0fd82Sopenharmony_ci                    cross.first = cross.nextFirst;
759a3e0fd82Sopenharmony_ci                    cross.firstFind = false;
760a3e0fd82Sopenharmony_ci                }
761a3e0fd82Sopenharmony_ci            } else if (!cross.secondFind) {
762a3e0fd82Sopenharmony_ci                if ((cross.first.x != cross.nextFirst.x) || (cross.first.y != cross.nextFirst.y)) {
763a3e0fd82Sopenharmony_ci                    cross.second = cross.nextFirst;
764a3e0fd82Sopenharmony_ci                    cross.secondFind = true;
765a3e0fd82Sopenharmony_ci                    return;
766a3e0fd82Sopenharmony_ci                }
767a3e0fd82Sopenharmony_ci                if (polyLine.start.y > polyLine.end.y) {
768a3e0fd82Sopenharmony_ci                    cross.firstFind = true;
769a3e0fd82Sopenharmony_ci                }
770a3e0fd82Sopenharmony_ci            }
771a3e0fd82Sopenharmony_ci            return;
772a3e0fd82Sopenharmony_ci        }
773a3e0fd82Sopenharmony_ci        if (!cross.firstFind) {
774a3e0fd82Sopenharmony_ci            /* first corss must on the line like "/" */
775a3e0fd82Sopenharmony_ci            if (polyLine.start.y < polyLine.end.y) {
776a3e0fd82Sopenharmony_ci                cross.first = cross.nextFirst;
777a3e0fd82Sopenharmony_ci                cross.firstFind = true;
778a3e0fd82Sopenharmony_ci            }
779a3e0fd82Sopenharmony_ci        } else if (!cross.secondFind) {
780a3e0fd82Sopenharmony_ci            /* second corss can't be same with first cross. */
781a3e0fd82Sopenharmony_ci            if ((cross.first.x != cross.nextFirst.x) || (cross.first.y != cross.nextFirst.y)) {
782a3e0fd82Sopenharmony_ci                cross.second = cross.nextFirst;
783a3e0fd82Sopenharmony_ci                cross.secondFind = true;
784a3e0fd82Sopenharmony_ci                return;
785a3e0fd82Sopenharmony_ci            }
786a3e0fd82Sopenharmony_ci            /* second corss must on the line like "\", otherwise skip those crosss. */
787a3e0fd82Sopenharmony_ci            if (polyLine.start.y > polyLine.end.y) {
788a3e0fd82Sopenharmony_ci                cross.firstFind = false;
789a3e0fd82Sopenharmony_ci            }
790a3e0fd82Sopenharmony_ci        }
791a3e0fd82Sopenharmony_ci    }
792a3e0fd82Sopenharmony_ci}
793a3e0fd82Sopenharmony_ci
794a3e0fd82Sopenharmony_civoid UIChartPolyline::DrawGradientColor(BufferInfo& gfxDstBuffer,
795a3e0fd82Sopenharmony_ci                                        const Rect& invalidatedArea,
796a3e0fd82Sopenharmony_ci                                        UIChartDataSerial* data,
797a3e0fd82Sopenharmony_ci                                        const ChartLine& linePoints,
798a3e0fd82Sopenharmony_ci                                        const ChartLine& limitPoints,
799a3e0fd82Sopenharmony_ci                                        int16_t startY)
800a3e0fd82Sopenharmony_ci{
801a3e0fd82Sopenharmony_ci    if (data == nullptr) {
802a3e0fd82Sopenharmony_ci        return;
803a3e0fd82Sopenharmony_ci    }
804a3e0fd82Sopenharmony_ci    Rect currentRect = GetContentRect();
805a3e0fd82Sopenharmony_ci    CrossPointSet cross = {{0}};
806a3e0fd82Sopenharmony_ci    ChartLine polyLine = {{0}};
807a3e0fd82Sopenharmony_ci    uint16_t pointCount = data->GetDataCount() - 1;
808a3e0fd82Sopenharmony_ci    int16_t y = enableReverse_ ? (linePoints.start.y + startY) : (startY - linePoints.start.y);
809a3e0fd82Sopenharmony_ci    int16_t mixScale = !enableReverse_ ? (currentRect.GetBottom() - y) : (y - currentRect.GetTop());
810a3e0fd82Sopenharmony_ci    if ((mixScale < 0) || (mixScale >= currentRect.GetHeight())) {
811a3e0fd82Sopenharmony_ci        return;
812a3e0fd82Sopenharmony_ci    }
813a3e0fd82Sopenharmony_ci    bool onVerticalLine = enableReverse_ ? (y <= limitPoints.start.y) : (y >= limitPoints.start.y);
814a3e0fd82Sopenharmony_ci    if (onVerticalLine) {
815a3e0fd82Sopenharmony_ci        cross.first.x = limitPoints.start.x;
816a3e0fd82Sopenharmony_ci        cross.first.y = enableReverse_ ? (y - startY) : (startY - y);
817a3e0fd82Sopenharmony_ci        cross.firstFind = true;
818a3e0fd82Sopenharmony_ci    }
819a3e0fd82Sopenharmony_ci    Point start;
820a3e0fd82Sopenharmony_ci    Point end;
821a3e0fd82Sopenharmony_ci    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
822a3e0fd82Sopenharmony_ci    for (uint16_t i = 0; i < pointCount; i++) {
823a3e0fd82Sopenharmony_ci        data->GetPoint(i, start);
824a3e0fd82Sopenharmony_ci        data->GetPoint(i + 1, end);
825a3e0fd82Sopenharmony_ci        if (start.y == end.y) {
826a3e0fd82Sopenharmony_ci            int16_t tmpY = enableReverse_ ? (start.y + startY) : (startY - start.y);
827a3e0fd82Sopenharmony_ci            if (tmpY == linePoints.start.y) {
828a3e0fd82Sopenharmony_ci                cross.firstFind = false;
829a3e0fd82Sopenharmony_ci                cross.secondFind = false;
830a3e0fd82Sopenharmony_ci            }
831a3e0fd82Sopenharmony_ci            continue;
832a3e0fd82Sopenharmony_ci        }
833a3e0fd82Sopenharmony_ci        start.y = enableReverse_ ? (start.y - startY) : (startY - start.y);
834a3e0fd82Sopenharmony_ci        end.y = enableReverse_ ? (end.y - startY) : (startY - end.y);
835a3e0fd82Sopenharmony_ci        polyLine = {start, end};
836a3e0fd82Sopenharmony_ci        FindCrossPoints(linePoints, polyLine, cross);
837a3e0fd82Sopenharmony_ci        SetDrawLineCross(gfxDstBuffer, invalidatedArea, data, cross, baseGfxEngine, startY, mixScale);
838a3e0fd82Sopenharmony_ci    }
839a3e0fd82Sopenharmony_ci    if (cross.firstFind && !cross.secondFind) {
840a3e0fd82Sopenharmony_ci        cross.second = {limitPoints.end.x, y};
841a3e0fd82Sopenharmony_ci        cross.first.y = y;
842a3e0fd82Sopenharmony_ci        baseGfxEngine->DrawLine(gfxDstBuffer, cross.first, cross.second, invalidatedArea, 1, data->GetFillColor(),
843a3e0fd82Sopenharmony_ci                                mixData_[mixScale]);
844a3e0fd82Sopenharmony_ci    }
845a3e0fd82Sopenharmony_ci}
846a3e0fd82Sopenharmony_ci
847a3e0fd82Sopenharmony_civoid UIChartPolyline::SetDrawLineCross(BufferInfo& gfxDstBuffer,
848a3e0fd82Sopenharmony_ci                                       const Rect& invalidatedArea,
849a3e0fd82Sopenharmony_ci                                       UIChartDataSerial* data,
850a3e0fd82Sopenharmony_ci                                       CrossPointSet& cross,
851a3e0fd82Sopenharmony_ci                                       BaseGfxEngine* baseGfxEngine,
852a3e0fd82Sopenharmony_ci                                       int16_t startY,
853a3e0fd82Sopenharmony_ci                                       int16_t mixScale)
854a3e0fd82Sopenharmony_ci{
855a3e0fd82Sopenharmony_ci    if (cross.firstFind && cross.secondFind) {
856a3e0fd82Sopenharmony_ci        cross.first.y = enableReverse_ ? (cross.first.y + startY) : (startY - cross.first.y);
857a3e0fd82Sopenharmony_ci        cross.second.y = enableReverse_ ? (cross.second.y + startY) : (startY - cross.second.y);
858a3e0fd82Sopenharmony_ci        baseGfxEngine->DrawLine(gfxDstBuffer, cross.first, cross.second, invalidatedArea, 1, data->GetFillColor(),
859a3e0fd82Sopenharmony_ci                                mixData_[mixScale]);
860a3e0fd82Sopenharmony_ci        cross.firstFind = false;
861a3e0fd82Sopenharmony_ci        cross.secondFind = false;
862a3e0fd82Sopenharmony_ci    }
863a3e0fd82Sopenharmony_ci}
864a3e0fd82Sopenharmony_ci
865a3e0fd82Sopenharmony_civoid UIChartPolyline::CalcVerticalInfo(int16_t top,
866a3e0fd82Sopenharmony_ci                                       int16_t bottom,
867a3e0fd82Sopenharmony_ci                                       int16_t start,
868a3e0fd82Sopenharmony_ci                                       int16_t end,
869a3e0fd82Sopenharmony_ci                                       int16_t& y,
870a3e0fd82Sopenharmony_ci                                       int16_t& yHeight)
871a3e0fd82Sopenharmony_ci{
872a3e0fd82Sopenharmony_ci    if ((top < start) && (bottom > start)) {
873a3e0fd82Sopenharmony_ci        y = start;
874a3e0fd82Sopenharmony_ci        yHeight = top;
875a3e0fd82Sopenharmony_ci    } else if ((bottom <= start) && (top >= end)) {
876a3e0fd82Sopenharmony_ci        y = bottom;
877a3e0fd82Sopenharmony_ci        yHeight = top;
878a3e0fd82Sopenharmony_ci    } else if ((top < end) && (bottom > end)) {
879a3e0fd82Sopenharmony_ci        y = bottom;
880a3e0fd82Sopenharmony_ci        yHeight = end;
881a3e0fd82Sopenharmony_ci    }
882a3e0fd82Sopenharmony_ci}
883a3e0fd82Sopenharmony_ci
884a3e0fd82Sopenharmony_civoid UIChartPolyline::GradientColor(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea, UIChartDataSerial* data)
885a3e0fd82Sopenharmony_ci{
886a3e0fd82Sopenharmony_ci    if (data == nullptr) {
887a3e0fd82Sopenharmony_ci        return;
888a3e0fd82Sopenharmony_ci    }
889a3e0fd82Sopenharmony_ci    int16_t bottom = invalidatedArea.GetBottom();
890a3e0fd82Sopenharmony_ci    int16_t top = invalidatedArea.GetTop();
891a3e0fd82Sopenharmony_ci    Point yStart = yAxis_.GetStartPoint();
892a3e0fd82Sopenharmony_ci    yStart.y = enableReverse_ ? (yStart.y + gradientBottom_) : (yStart.y - gradientBottom_);
893a3e0fd82Sopenharmony_ci    int16_t topY = enableReverse_ ? data->GetValleyData() : data->GetPeakData();
894a3e0fd82Sopenharmony_ci    int16_t bottomY = enableReverse_ ? data->GetPeakData() : data->GetValleyData();
895a3e0fd82Sopenharmony_ci    yAxis_.TranslateToPixel(topY);
896a3e0fd82Sopenharmony_ci    yAxis_.TranslateToPixel(bottomY);
897a3e0fd82Sopenharmony_ci    int16_t valleyY = enableReverse_ ? topY : bottomY;
898a3e0fd82Sopenharmony_ci    int16_t startY = enableReverse_ ? topY : yStart.y;
899a3e0fd82Sopenharmony_ci    int16_t endY = enableReverse_ ? yStart.y : topY;
900a3e0fd82Sopenharmony_ci    if ((bottom < endY) || (top > startY)) {
901a3e0fd82Sopenharmony_ci        return;
902a3e0fd82Sopenharmony_ci    }
903a3e0fd82Sopenharmony_ci
904a3e0fd82Sopenharmony_ci    int16_t y = 0;
905a3e0fd82Sopenharmony_ci    int16_t yHeight = 0;
906a3e0fd82Sopenharmony_ci    CalcVerticalInfo(top, bottom, startY, endY, y, yHeight);
907a3e0fd82Sopenharmony_ci
908a3e0fd82Sopenharmony_ci    ChartLine limitPoints = {{0}};
909a3e0fd82Sopenharmony_ci    data->GetPoint(0, limitPoints.start);
910a3e0fd82Sopenharmony_ci    data->GetPoint(data->GetDataCount() - 1, limitPoints.end);
911a3e0fd82Sopenharmony_ci    ChartLine linePoints = {{0}};
912a3e0fd82Sopenharmony_ci    linePoints.start.x = limitPoints.start.x;
913a3e0fd82Sopenharmony_ci    linePoints.end.x = limitPoints.end.x;
914a3e0fd82Sopenharmony_ci    Rect currentRect = GetContentRect();
915a3e0fd82Sopenharmony_ci    BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
916a3e0fd82Sopenharmony_ci    while (y >= yHeight) {
917a3e0fd82Sopenharmony_ci        linePoints.start.y = enableReverse_ ? (y - endY) : (startY - y);
918a3e0fd82Sopenharmony_ci        linePoints.end.y = linePoints.start.y;
919a3e0fd82Sopenharmony_ci        if (y <= valleyY) {
920a3e0fd82Sopenharmony_ci            int16_t baseY = enableReverse_ ? endY : startY;
921a3e0fd82Sopenharmony_ci            DrawGradientColor(gfxDstBuffer, invalidatedArea, data, linePoints, limitPoints, baseY);
922a3e0fd82Sopenharmony_ci        } else {
923a3e0fd82Sopenharmony_ci            int16_t mixScale = enableReverse_ ? (linePoints.start.y + endY - currentRect.GetTop()) :
924a3e0fd82Sopenharmony_ci                                                (currentRect.GetBottom() - (startY - linePoints.start.y));
925a3e0fd82Sopenharmony_ci            if ((mixScale < 0) || (mixScale >= currentRect.GetHeight())) {
926a3e0fd82Sopenharmony_ci                y--;
927a3e0fd82Sopenharmony_ci                continue;
928a3e0fd82Sopenharmony_ci            }
929a3e0fd82Sopenharmony_ci            Point start = {limitPoints.start.x, y};
930a3e0fd82Sopenharmony_ci            Point end = {limitPoints.end.x, y};
931a3e0fd82Sopenharmony_ci            baseGfxEngine->DrawLine(gfxDstBuffer, start, end, invalidatedArea, 1, data->GetFillColor(),
932a3e0fd82Sopenharmony_ci                                    mixData_[mixScale]);
933a3e0fd82Sopenharmony_ci        }
934a3e0fd82Sopenharmony_ci        y--;
935a3e0fd82Sopenharmony_ci    }
936a3e0fd82Sopenharmony_ci}
937a3e0fd82Sopenharmony_ci} // namespace OHOS
938