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