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_arc_label.h" 17a3e0fd82Sopenharmony_ci 18a3e0fd82Sopenharmony_ci#include "common/typed_text.h" 19a3e0fd82Sopenharmony_ci#include "draw/draw_label.h" 20a3e0fd82Sopenharmony_ci#include "engines/gfx/gfx_engine_manager.h" 21a3e0fd82Sopenharmony_ci#include "font/ui_font.h" 22a3e0fd82Sopenharmony_ci#include "themes/theme_manager.h" 23a3e0fd82Sopenharmony_ci 24a3e0fd82Sopenharmony_cinamespace OHOS { 25a3e0fd82Sopenharmony_cistatic constexpr uint16_t DEFAULT_ARC_LABEL_ROLL_COUNT = 1; 26a3e0fd82Sopenharmony_cistatic constexpr uint16_t DEFAULT_ARC_LABEL_ANIMATOR_SPEED = 10; 27a3e0fd82Sopenharmony_ci 28a3e0fd82Sopenharmony_ciclass ArcLabelAnimator : public Animator, public AnimatorCallback { 29a3e0fd82Sopenharmony_cipublic: 30a3e0fd82Sopenharmony_ci ArcLabelAnimator(uint16_t rollCount, UIView* view) 31a3e0fd82Sopenharmony_ci : Animator(this, view, 0, true), 32a3e0fd82Sopenharmony_ci waitCount_(ANIM_WAIT_COUNT), 33a3e0fd82Sopenharmony_ci speed_(0), 34a3e0fd82Sopenharmony_ci preRunTime_(0), 35a3e0fd82Sopenharmony_ci decimal_(0), 36a3e0fd82Sopenharmony_ci rollCount_(rollCount) 37a3e0fd82Sopenharmony_ci { 38a3e0fd82Sopenharmony_ci } 39a3e0fd82Sopenharmony_ci 40a3e0fd82Sopenharmony_ci virtual ~ArcLabelAnimator() {} 41a3e0fd82Sopenharmony_ci 42a3e0fd82Sopenharmony_ci void Callback(UIView* view) override 43a3e0fd82Sopenharmony_ci { 44a3e0fd82Sopenharmony_ci if (view == nullptr || rollCount_ == 0) { 45a3e0fd82Sopenharmony_ci return; 46a3e0fd82Sopenharmony_ci } 47a3e0fd82Sopenharmony_ci 48a3e0fd82Sopenharmony_ci uint32_t curTime = GetRunTime(); 49a3e0fd82Sopenharmony_ci if (waitCount_ > 0) { 50a3e0fd82Sopenharmony_ci waitCount_--; 51a3e0fd82Sopenharmony_ci preRunTime_ = curTime; 52a3e0fd82Sopenharmony_ci return; 53a3e0fd82Sopenharmony_ci } 54a3e0fd82Sopenharmony_ci if (curTime == preRunTime_) { 55a3e0fd82Sopenharmony_ci return; 56a3e0fd82Sopenharmony_ci } 57a3e0fd82Sopenharmony_ci uint32_t time = (curTime > preRunTime_) ? (curTime - preRunTime_) : (UINT32_MAX - preRunTime_ + curTime); 58a3e0fd82Sopenharmony_ci // 1000: 1000 milliseconds is 1 second 59a3e0fd82Sopenharmony_ci float floatStep = (static_cast<float>(time * speed_) / 1000) + decimal_; 60a3e0fd82Sopenharmony_ci uint16_t integerStep = static_cast<uint16_t>(floatStep); 61a3e0fd82Sopenharmony_ci decimal_ = floatStep - integerStep; 62a3e0fd82Sopenharmony_ci preRunTime_ = curTime; 63a3e0fd82Sopenharmony_ci 64a3e0fd82Sopenharmony_ci if (integerStep == 0) { 65a3e0fd82Sopenharmony_ci return; 66a3e0fd82Sopenharmony_ci } 67a3e0fd82Sopenharmony_ci 68a3e0fd82Sopenharmony_ci CalculatedOffsetAngle(view); 69a3e0fd82Sopenharmony_ci } 70a3e0fd82Sopenharmony_ci 71a3e0fd82Sopenharmony_ci void SetRollSpeed(uint16_t speed) 72a3e0fd82Sopenharmony_ci { 73a3e0fd82Sopenharmony_ci speed_ = speed; 74a3e0fd82Sopenharmony_ci } 75a3e0fd82Sopenharmony_ci 76a3e0fd82Sopenharmony_ci int16_t GetRollSpeed() const 77a3e0fd82Sopenharmony_ci { 78a3e0fd82Sopenharmony_ci return speed_; 79a3e0fd82Sopenharmony_ci } 80a3e0fd82Sopenharmony_ci 81a3e0fd82Sopenharmony_ci void SetRollCount(uint16_t rollCount) 82a3e0fd82Sopenharmony_ci { 83a3e0fd82Sopenharmony_ci rollCount_ = rollCount; 84a3e0fd82Sopenharmony_ci } 85a3e0fd82Sopenharmony_ci 86a3e0fd82Sopenharmony_ci void RegisterScrollListener(ArcLabelScrollListener* scrollListener) 87a3e0fd82Sopenharmony_ci { 88a3e0fd82Sopenharmony_ci scrollListener_ = scrollListener; 89a3e0fd82Sopenharmony_ci } 90a3e0fd82Sopenharmony_ci 91a3e0fd82Sopenharmony_ciprivate: 92a3e0fd82Sopenharmony_ci void CalculatedOffsetAngle(UIView* view) 93a3e0fd82Sopenharmony_ci { 94a3e0fd82Sopenharmony_ci if (view == nullptr) { 95a3e0fd82Sopenharmony_ci return; 96a3e0fd82Sopenharmony_ci } 97a3e0fd82Sopenharmony_ci UIArcLabel* arcLabel = static_cast<UIArcLabel*>(view); 98a3e0fd82Sopenharmony_ci if (arcLabel == nullptr) { 99a3e0fd82Sopenharmony_ci return; 100a3e0fd82Sopenharmony_ci } 101a3e0fd82Sopenharmony_ci 102a3e0fd82Sopenharmony_ci int16_t startAngle = arcLabel->GetArcTextStartAngle(); 103a3e0fd82Sopenharmony_ci int16_t endAngle = arcLabel->GetArcTextEndAngle(); 104a3e0fd82Sopenharmony_ci uint16_t arcAngle = (startAngle < endAngle) ? (endAngle - startAngle) : 105a3e0fd82Sopenharmony_ci (startAngle - endAngle); 106a3e0fd82Sopenharmony_ci 107a3e0fd82Sopenharmony_ci if (arcLabel->offsetAngle_ < arcAngle) { 108a3e0fd82Sopenharmony_ci arcLabel->offsetAngle_ += DEFAULT_CHANGE_ANGLE; 109a3e0fd82Sopenharmony_ci } else { 110a3e0fd82Sopenharmony_ci rollCount_--; 111a3e0fd82Sopenharmony_ci if (rollCount_ > 0) { 112a3e0fd82Sopenharmony_ci arcLabel->offsetAngle_ = arcLabel->animator_.secondLapOffsetAngle_; 113a3e0fd82Sopenharmony_ci } 114a3e0fd82Sopenharmony_ci } 115a3e0fd82Sopenharmony_ci 116a3e0fd82Sopenharmony_ci if (rollCount_ == 0) { 117a3e0fd82Sopenharmony_ci if (scrollListener_) { 118a3e0fd82Sopenharmony_ci scrollListener_->Finish(); 119a3e0fd82Sopenharmony_ci } 120a3e0fd82Sopenharmony_ci Stop(); 121a3e0fd82Sopenharmony_ci } 122a3e0fd82Sopenharmony_ci view->Invalidate(); 123a3e0fd82Sopenharmony_ci } 124a3e0fd82Sopenharmony_ci 125a3e0fd82Sopenharmony_ciprivate: 126a3e0fd82Sopenharmony_ci static constexpr uint8_t ANIM_WAIT_COUNT = 50; 127a3e0fd82Sopenharmony_ci static constexpr float DEFAULT_CHANGE_ANGLE = 1.0f; 128a3e0fd82Sopenharmony_ci uint16_t waitCount_; 129a3e0fd82Sopenharmony_ci uint16_t speed_; 130a3e0fd82Sopenharmony_ci uint32_t preRunTime_; 131a3e0fd82Sopenharmony_ci float decimal_; 132a3e0fd82Sopenharmony_ci 133a3e0fd82Sopenharmony_ci uint16_t rollCount_; 134a3e0fd82Sopenharmony_ci ArcLabelScrollListener* scrollListener_; 135a3e0fd82Sopenharmony_ci}; 136a3e0fd82Sopenharmony_ci 137a3e0fd82Sopenharmony_ciUIArcLabel::UIArcLabel() 138a3e0fd82Sopenharmony_ci : arcLabelText_(nullptr), 139a3e0fd82Sopenharmony_ci compatibilityMode_(true), 140a3e0fd82Sopenharmony_ci offsetAngle_(0.0f), 141a3e0fd82Sopenharmony_ci arcTextInfo_{0}, 142a3e0fd82Sopenharmony_ci needRefresh_(false), 143a3e0fd82Sopenharmony_ci hasAnimator_(false), 144a3e0fd82Sopenharmony_ci textSize_({0, 0}), 145a3e0fd82Sopenharmony_ci radius_(0), 146a3e0fd82Sopenharmony_ci startAngle_(0), 147a3e0fd82Sopenharmony_ci endAngle_(0), 148a3e0fd82Sopenharmony_ci arcCenter_({0, 0}), 149a3e0fd82Sopenharmony_ci orientation_(TextOrientation::INSIDE) 150a3e0fd82Sopenharmony_ci{ 151a3e0fd82Sopenharmony_ci Theme* theme = ThemeManager::GetInstance().GetCurrent(); 152a3e0fd82Sopenharmony_ci style_ = (theme != nullptr) ? &(theme->GetLabelStyle()) : &(StyleDefault::GetLabelStyle()); 153a3e0fd82Sopenharmony_ci 154a3e0fd82Sopenharmony_ci animator_.animator = nullptr; 155a3e0fd82Sopenharmony_ci animator_.scrollListener = nullptr; 156a3e0fd82Sopenharmony_ci animator_.speed = DEFAULT_ARC_LABEL_ANIMATOR_SPEED; 157a3e0fd82Sopenharmony_ci animator_.rollCount = DEFAULT_ARC_LABEL_ROLL_COUNT; 158a3e0fd82Sopenharmony_ci animator_.secondLapOffsetAngle_ = 0.0f; 159a3e0fd82Sopenharmony_ci} 160a3e0fd82Sopenharmony_ci 161a3e0fd82Sopenharmony_ciUIArcLabel::~UIArcLabel() 162a3e0fd82Sopenharmony_ci{ 163a3e0fd82Sopenharmony_ci if (arcLabelText_ != nullptr) { 164a3e0fd82Sopenharmony_ci delete arcLabelText_; 165a3e0fd82Sopenharmony_ci arcLabelText_ = nullptr; 166a3e0fd82Sopenharmony_ci } 167a3e0fd82Sopenharmony_ci 168a3e0fd82Sopenharmony_ci if (hasAnimator_) { 169a3e0fd82Sopenharmony_ci delete animator_.animator; 170a3e0fd82Sopenharmony_ci animator_.animator = nullptr; 171a3e0fd82Sopenharmony_ci hasAnimator_ = false; 172a3e0fd82Sopenharmony_ci } 173a3e0fd82Sopenharmony_ci} 174a3e0fd82Sopenharmony_ci 175a3e0fd82Sopenharmony_civoid UIArcLabel::SetStyle(uint8_t key, int64_t value) 176a3e0fd82Sopenharmony_ci{ 177a3e0fd82Sopenharmony_ci UIView::SetStyle(key, value); 178a3e0fd82Sopenharmony_ci RefreshArcLabel(); 179a3e0fd82Sopenharmony_ci} 180a3e0fd82Sopenharmony_ci 181a3e0fd82Sopenharmony_civoid UIArcLabel::SetText(const char* text) 182a3e0fd82Sopenharmony_ci{ 183a3e0fd82Sopenharmony_ci if (text == nullptr) { 184a3e0fd82Sopenharmony_ci return; 185a3e0fd82Sopenharmony_ci } 186a3e0fd82Sopenharmony_ci InitArcLabelText(); 187a3e0fd82Sopenharmony_ci arcLabelText_->SetText(text); 188a3e0fd82Sopenharmony_ci if (arcLabelText_->IsNeedRefresh()) { 189a3e0fd82Sopenharmony_ci RefreshArcLabel(); 190a3e0fd82Sopenharmony_ci } 191a3e0fd82Sopenharmony_ci} 192a3e0fd82Sopenharmony_ci 193a3e0fd82Sopenharmony_ciconst char* UIArcLabel::GetText() const 194a3e0fd82Sopenharmony_ci{ 195a3e0fd82Sopenharmony_ci return (arcLabelText_ == nullptr) ? nullptr : arcLabelText_->GetText(); 196a3e0fd82Sopenharmony_ci} 197a3e0fd82Sopenharmony_ci 198a3e0fd82Sopenharmony_civoid UIArcLabel::SetAlign(UITextLanguageAlignment horizontalAlign) 199a3e0fd82Sopenharmony_ci{ 200a3e0fd82Sopenharmony_ci InitArcLabelText(); 201a3e0fd82Sopenharmony_ci arcLabelText_->SetAlign(horizontalAlign, TEXT_ALIGNMENT_TOP); 202a3e0fd82Sopenharmony_ci if (arcLabelText_->IsNeedRefresh()) { 203a3e0fd82Sopenharmony_ci RefreshArcLabel(); 204a3e0fd82Sopenharmony_ci } 205a3e0fd82Sopenharmony_ci} 206a3e0fd82Sopenharmony_ci 207a3e0fd82Sopenharmony_ciUITextLanguageAlignment UIArcLabel::GetHorAlign() 208a3e0fd82Sopenharmony_ci{ 209a3e0fd82Sopenharmony_ci InitArcLabelText(); 210a3e0fd82Sopenharmony_ci return arcLabelText_->GetHorAlign(); 211a3e0fd82Sopenharmony_ci} 212a3e0fd82Sopenharmony_ci 213a3e0fd82Sopenharmony_ciUITextLanguageDirect UIArcLabel::GetDirect() 214a3e0fd82Sopenharmony_ci{ 215a3e0fd82Sopenharmony_ci InitArcLabelText(); 216a3e0fd82Sopenharmony_ci return arcLabelText_->GetDirect(); 217a3e0fd82Sopenharmony_ci} 218a3e0fd82Sopenharmony_ci 219a3e0fd82Sopenharmony_civoid UIArcLabel::SetFontId(uint16_t fontId) 220a3e0fd82Sopenharmony_ci{ 221a3e0fd82Sopenharmony_ci InitArcLabelText(); 222a3e0fd82Sopenharmony_ci arcLabelText_->SetFontId(fontId); 223a3e0fd82Sopenharmony_ci if (arcLabelText_->IsNeedRefresh()) { 224a3e0fd82Sopenharmony_ci RefreshArcLabel(); 225a3e0fd82Sopenharmony_ci } 226a3e0fd82Sopenharmony_ci} 227a3e0fd82Sopenharmony_ci 228a3e0fd82Sopenharmony_ciuint16_t UIArcLabel::GetFontId() 229a3e0fd82Sopenharmony_ci{ 230a3e0fd82Sopenharmony_ci InitArcLabelText(); 231a3e0fd82Sopenharmony_ci return arcLabelText_->GetFontId(); 232a3e0fd82Sopenharmony_ci} 233a3e0fd82Sopenharmony_ci 234a3e0fd82Sopenharmony_civoid UIArcLabel::SetFont(const char* name, uint8_t size) 235a3e0fd82Sopenharmony_ci{ 236a3e0fd82Sopenharmony_ci if (name == nullptr) { 237a3e0fd82Sopenharmony_ci return; 238a3e0fd82Sopenharmony_ci } 239a3e0fd82Sopenharmony_ci InitArcLabelText(); 240a3e0fd82Sopenharmony_ci arcLabelText_->SetFont(name, size); 241a3e0fd82Sopenharmony_ci if (arcLabelText_->IsNeedRefresh()) { 242a3e0fd82Sopenharmony_ci RefreshArcLabel(); 243a3e0fd82Sopenharmony_ci } 244a3e0fd82Sopenharmony_ci} 245a3e0fd82Sopenharmony_ci 246a3e0fd82Sopenharmony_civoid UIArcLabel::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea) 247a3e0fd82Sopenharmony_ci{ 248a3e0fd82Sopenharmony_ci InitArcLabelText(); 249a3e0fd82Sopenharmony_ci const char* text = arcLabelText_->GetText(); 250a3e0fd82Sopenharmony_ci if ((text == nullptr) || (radius_ == 0)) { 251a3e0fd82Sopenharmony_ci return; 252a3e0fd82Sopenharmony_ci } 253a3e0fd82Sopenharmony_ci OpacityType opa = GetMixOpaScale(); 254a3e0fd82Sopenharmony_ci UIView::OnDraw(gfxDstBuffer, invalidatedArea); 255a3e0fd82Sopenharmony_ci DrawArcText(gfxDstBuffer, invalidatedArea, opa, arcTextInfo_, orientation_); 256a3e0fd82Sopenharmony_ci} 257a3e0fd82Sopenharmony_ci 258a3e0fd82Sopenharmony_civoid UIArcLabel::DrawArcText(BufferInfo& gfxDstBuffer, 259a3e0fd82Sopenharmony_ci const Rect& mask, 260a3e0fd82Sopenharmony_ci OpacityType opaScale, 261a3e0fd82Sopenharmony_ci ArcTextInfo arcTextInfo, 262a3e0fd82Sopenharmony_ci TextOrientation orientation) 263a3e0fd82Sopenharmony_ci{ 264a3e0fd82Sopenharmony_ci Point center; 265a3e0fd82Sopenharmony_ci center.x = arcTextInfo_.arcCenter.x + GetRect().GetX(); 266a3e0fd82Sopenharmony_ci center.y = arcTextInfo_.arcCenter.y + GetRect().GetY(); 267a3e0fd82Sopenharmony_ci Rect temp = mask; 268a3e0fd82Sopenharmony_ci if (compatibilityMode_ && hasAnimator_) { 269a3e0fd82Sopenharmony_ci temp.SetLeft(center.x - radius_); 270a3e0fd82Sopenharmony_ci temp.SetTop(center.y - radius_); 271a3e0fd82Sopenharmony_ci temp.SetWidth(radius_ * 2); // 2 mean diameter 272a3e0fd82Sopenharmony_ci temp.SetHeight(radius_ * 2); 273a3e0fd82Sopenharmony_ci } 274a3e0fd82Sopenharmony_ci arcTextInfo.hasAnimator = hasAnimator_; 275a3e0fd82Sopenharmony_ci 276a3e0fd82Sopenharmony_ci DrawLabel::DrawArcText(gfxDstBuffer, temp, arcLabelText_->GetText(), center, arcLabelText_->GetFontId(), 277a3e0fd82Sopenharmony_ci arcLabelText_->GetFontSize(), arcTextInfo, offsetAngle_, 278a3e0fd82Sopenharmony_ci orientation, *style_, opaScale, compatibilityMode_); 279a3e0fd82Sopenharmony_ci} 280a3e0fd82Sopenharmony_ci 281a3e0fd82Sopenharmony_ciRect UIArcLabel::GetArcTextRect(const char* text, uint16_t fontId, uint8_t fontSize, const Point& arcCenter, 282a3e0fd82Sopenharmony_ci int16_t letterSpace, TextOrientation orientation, const ArcTextInfo& arcTextInfo) 283a3e0fd82Sopenharmony_ci{ 284a3e0fd82Sopenharmony_ci return TypedText::GetArcTextRect(text, fontId, fontSize, arcCenter, letterSpace, orientation, arcTextInfo); 285a3e0fd82Sopenharmony_ci} 286a3e0fd82Sopenharmony_ci 287a3e0fd82Sopenharmony_civoid UIArcLabel::RefreshArcLabel() 288a3e0fd82Sopenharmony_ci{ 289a3e0fd82Sopenharmony_ci Invalidate(); 290a3e0fd82Sopenharmony_ci if (!needRefresh_) { 291a3e0fd82Sopenharmony_ci needRefresh_ = true; 292a3e0fd82Sopenharmony_ci } 293a3e0fd82Sopenharmony_ci} 294a3e0fd82Sopenharmony_ci 295a3e0fd82Sopenharmony_civoid UIArcLabel::ReMeasure() 296a3e0fd82Sopenharmony_ci{ 297a3e0fd82Sopenharmony_ci if (!needRefresh_) { 298a3e0fd82Sopenharmony_ci return; 299a3e0fd82Sopenharmony_ci } 300a3e0fd82Sopenharmony_ci needRefresh_ = false; 301a3e0fd82Sopenharmony_ci InitArcLabelText(); 302a3e0fd82Sopenharmony_ci 303a3e0fd82Sopenharmony_ci MeasureArcTextInfo(); 304a3e0fd82Sopenharmony_ci arcTextInfo_.shapingFontId = arcLabelText_->GetShapingFontId(); 305a3e0fd82Sopenharmony_ci arcTextInfo_.codePoints = arcLabelText_->GetCodePoints(); 306a3e0fd82Sopenharmony_ci arcTextInfo_.codePointsNum = arcLabelText_->GetCodePointNum(); 307a3e0fd82Sopenharmony_ci Rect textRect = 308a3e0fd82Sopenharmony_ci GetArcTextRect(arcLabelText_->GetText(), arcLabelText_->GetFontId(), arcLabelText_->GetFontSize(), 309a3e0fd82Sopenharmony_ci arcCenter_, style_->letterSpace_, orientation_, arcTextInfo_); 310a3e0fd82Sopenharmony_ci int16_t arcTextWidth = textRect.GetWidth(); 311a3e0fd82Sopenharmony_ci int16_t arcTextHeight = textRect.GetHeight(); 312a3e0fd82Sopenharmony_ci 313a3e0fd82Sopenharmony_ci if (compatibilityMode_) { 314a3e0fd82Sopenharmony_ci SetPosition(textRect.GetX(), textRect.GetY()); 315a3e0fd82Sopenharmony_ci Resize(arcTextWidth, arcTextHeight); 316a3e0fd82Sopenharmony_ci } 317a3e0fd82Sopenharmony_ci 318a3e0fd82Sopenharmony_ci arcTextInfo_.arcCenter.x = arcCenter_.x - GetX() + style_->borderWidth_ + style_->paddingLeft_; 319a3e0fd82Sopenharmony_ci arcTextInfo_.arcCenter.y = arcCenter_.y - GetY() + style_->borderWidth_ + style_->paddingTop_; 320a3e0fd82Sopenharmony_ci textSize_.x = arcTextWidth; 321a3e0fd82Sopenharmony_ci textSize_.y = arcTextHeight; 322a3e0fd82Sopenharmony_ci Invalidate(); 323a3e0fd82Sopenharmony_ci} 324a3e0fd82Sopenharmony_ci 325a3e0fd82Sopenharmony_ciuint32_t UIArcLabel::GetLineEnd(int16_t maxLength) 326a3e0fd82Sopenharmony_ci{ 327a3e0fd82Sopenharmony_ci const char* text = arcLabelText_->GetText(); 328a3e0fd82Sopenharmony_ci if (text == nullptr) { 329a3e0fd82Sopenharmony_ci return 0; 330a3e0fd82Sopenharmony_ci } 331a3e0fd82Sopenharmony_ci 332a3e0fd82Sopenharmony_ci return TypedText::GetNextLine(&text[arcTextInfo_.lineStart], arcLabelText_->GetFontId(), 333a3e0fd82Sopenharmony_ci arcLabelText_->GetFontSize(), style_->letterSpace_, maxLength); 334a3e0fd82Sopenharmony_ci} 335a3e0fd82Sopenharmony_ci 336a3e0fd82Sopenharmony_civoid UIArcLabel::MeasureArcTextInfo() 337a3e0fd82Sopenharmony_ci{ 338a3e0fd82Sopenharmony_ci const char* text = arcLabelText_->GetText(); 339a3e0fd82Sopenharmony_ci if (text == nullptr) { 340a3e0fd82Sopenharmony_ci return; 341a3e0fd82Sopenharmony_ci } 342a3e0fd82Sopenharmony_ci uint16_t letterHeight = UIFont::GetInstance()->GetHeight(arcLabelText_->GetFontId(), arcLabelText_->GetFontSize()); 343a3e0fd82Sopenharmony_ci if (compatibilityMode_) { 344a3e0fd82Sopenharmony_ci arcTextInfo_.radius = ((orientation_ == TextOrientation::INSIDE) ? radius_ : (radius_ - letterHeight)); 345a3e0fd82Sopenharmony_ci } else { 346a3e0fd82Sopenharmony_ci arcTextInfo_.radius = radius_; 347a3e0fd82Sopenharmony_ci } 348a3e0fd82Sopenharmony_ci if (arcTextInfo_.radius == 0) { 349a3e0fd82Sopenharmony_ci return; 350a3e0fd82Sopenharmony_ci } 351a3e0fd82Sopenharmony_ci 352a3e0fd82Sopenharmony_ci uint16_t arcAngle; 353a3e0fd82Sopenharmony_ci if (startAngle_ < endAngle_) { 354a3e0fd82Sopenharmony_ci arcAngle = endAngle_ - startAngle_; 355a3e0fd82Sopenharmony_ci arcTextInfo_.direct = TEXT_DIRECT_LTR; // Clockwise 356a3e0fd82Sopenharmony_ci arcLabelText_->SetDirect(TEXT_DIRECT_LTR); 357a3e0fd82Sopenharmony_ci } else { 358a3e0fd82Sopenharmony_ci arcAngle = startAngle_ - endAngle_; 359a3e0fd82Sopenharmony_ci arcTextInfo_.direct = TEXT_DIRECT_RTL; // Counterclockwise 360a3e0fd82Sopenharmony_ci arcLabelText_->SetDirect(TEXT_DIRECT_RTL); 361a3e0fd82Sopenharmony_ci } 362a3e0fd82Sopenharmony_ci 363a3e0fd82Sopenharmony_ci OnMeasureArcTextInfo(arcAngle, letterHeight); 364a3e0fd82Sopenharmony_ci} 365a3e0fd82Sopenharmony_ci 366a3e0fd82Sopenharmony_civoid UIArcLabel::OnMeasureArcTextInfo(const uint16_t arcAngle, const uint16_t letterHeight) 367a3e0fd82Sopenharmony_ci{ 368a3e0fd82Sopenharmony_ci const char* text = arcLabelText_->GetText(); 369a3e0fd82Sopenharmony_ci if (text == nullptr) { 370a3e0fd82Sopenharmony_ci return; 371a3e0fd82Sopenharmony_ci } 372a3e0fd82Sopenharmony_ci 373a3e0fd82Sopenharmony_ci // calculate max arc length 374a3e0fd82Sopenharmony_ci float maxLength = static_cast<float>((UI_PI * radius_ * arcAngle) / SEMICIRCLE_IN_DEGREE); 375a3e0fd82Sopenharmony_ci arcTextInfo_.lineStart = 0; 376a3e0fd82Sopenharmony_ci 377a3e0fd82Sopenharmony_ci Rect rect; 378a3e0fd82Sopenharmony_ci rect.SetWidth(static_cast<int16_t>(maxLength)); 379a3e0fd82Sopenharmony_ci arcLabelText_->ReMeasureTextSize(rect, *style_); 380a3e0fd82Sopenharmony_ci 381a3e0fd82Sopenharmony_ci arcTextInfo_.lineEnd = GetLineEnd(static_cast<int16_t>(maxLength)); 382a3e0fd82Sopenharmony_ci arcTextInfo_.startAngle = startAngle_ > CIRCLE_IN_DEGREE ? startAngle_ % CIRCLE_IN_DEGREE : startAngle_; 383a3e0fd82Sopenharmony_ci arcTextInfo_.endAngle = endAngle_ > CIRCLE_IN_DEGREE ? endAngle_ % CIRCLE_IN_DEGREE : endAngle_; 384a3e0fd82Sopenharmony_ci 385a3e0fd82Sopenharmony_ci int16_t actLength = GetArcLength(); 386a3e0fd82Sopenharmony_ci if ((arcLabelText_->GetHorAlign() != TEXT_ALIGNMENT_LEFT) && (actLength < maxLength)) { 387a3e0fd82Sopenharmony_ci float gapLength = maxLength - actLength; 388a3e0fd82Sopenharmony_ci if (arcLabelText_->GetHorAlign() == TEXT_ALIGNMENT_CENTER) { 389a3e0fd82Sopenharmony_ci gapLength = gapLength / 2; // 2: half 390a3e0fd82Sopenharmony_ci } 391a3e0fd82Sopenharmony_ci arcTextInfo_.startAngle += TypedText::GetAngleForArcLen(gapLength, letterHeight, arcTextInfo_.radius, 392a3e0fd82Sopenharmony_ci arcTextInfo_.direct, orientation_); 393a3e0fd82Sopenharmony_ci } 394a3e0fd82Sopenharmony_ci 395a3e0fd82Sopenharmony_ci int16_t maxTextLength = arcLabelText_->GetMetaTextWidth(*style_); 396a3e0fd82Sopenharmony_ci 397a3e0fd82Sopenharmony_ci float maxTextAngle = 0.0f; 398a3e0fd82Sopenharmony_ci if (compatibilityMode_) { 399a3e0fd82Sopenharmony_ci maxTextAngle = TypedText::GetAngleForArcLen(maxTextLength, letterHeight, arcTextInfo_.radius, 400a3e0fd82Sopenharmony_ci arcTextInfo_.direct, orientation_); 401a3e0fd82Sopenharmony_ci } else { 402a3e0fd82Sopenharmony_ci maxTextAngle = TypedText::GetAngleForArcLen(maxTextLength, style_->letterSpace_, arcTextInfo_.radius); 403a3e0fd82Sopenharmony_ci maxTextAngle = arcLabelText_->GetDirect() == TEXT_DIRECT_RTL ? -maxTextAngle : maxTextAngle; 404a3e0fd82Sopenharmony_ci } 405a3e0fd82Sopenharmony_ci 406a3e0fd82Sopenharmony_ci if (arcLabelText_->GetDirect() == TEXT_DIRECT_LTR) { 407a3e0fd82Sopenharmony_ci animator_.secondLapOffsetAngle_ = -maxTextAngle; 408a3e0fd82Sopenharmony_ci } else if (arcLabelText_->GetDirect() == TEXT_DIRECT_RTL) { 409a3e0fd82Sopenharmony_ci animator_.secondLapOffsetAngle_ = maxTextAngle; 410a3e0fd82Sopenharmony_ci } 411a3e0fd82Sopenharmony_ci} 412a3e0fd82Sopenharmony_ci 413a3e0fd82Sopenharmony_ciuint16_t UIArcLabel::GetArcLength() 414a3e0fd82Sopenharmony_ci{ 415a3e0fd82Sopenharmony_ci const char* text = arcLabelText_->GetText(); 416a3e0fd82Sopenharmony_ci if (text == nullptr) { 417a3e0fd82Sopenharmony_ci return 0; 418a3e0fd82Sopenharmony_ci } 419a3e0fd82Sopenharmony_ci 420a3e0fd82Sopenharmony_ci return TypedText::GetTextWidth(&text[arcTextInfo_.lineStart], arcLabelText_->GetFontId(), 421a3e0fd82Sopenharmony_ci arcLabelText_->GetFontSize(), (arcTextInfo_.lineEnd - arcTextInfo_.lineStart), 422a3e0fd82Sopenharmony_ci style_->letterSpace_); 423a3e0fd82Sopenharmony_ci} 424a3e0fd82Sopenharmony_ci 425a3e0fd82Sopenharmony_civoid UIArcLabel::Start() 426a3e0fd82Sopenharmony_ci{ 427a3e0fd82Sopenharmony_ci if (arcLabelText_->GetDirect() == TEXT_DIRECT_RTL) { 428a3e0fd82Sopenharmony_ci arcLabelText_->SetAlign(TEXT_ALIGNMENT_RIGHT, TEXT_ALIGNMENT_CENTER); 429a3e0fd82Sopenharmony_ci } else { 430a3e0fd82Sopenharmony_ci arcLabelText_->SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_CENTER); 431a3e0fd82Sopenharmony_ci } 432a3e0fd82Sopenharmony_ci if (hasAnimator_) { 433a3e0fd82Sopenharmony_ci static_cast<ArcLabelAnimator*>(animator_.animator)->SetRollCount(animator_.rollCount); 434a3e0fd82Sopenharmony_ci } else { 435a3e0fd82Sopenharmony_ci ArcLabelAnimator* animator = new ArcLabelAnimator(animator_.rollCount, this); 436a3e0fd82Sopenharmony_ci if (animator == nullptr) { 437a3e0fd82Sopenharmony_ci GRAPHIC_LOGE("new ArcLabelAnimator fail"); 438a3e0fd82Sopenharmony_ci return; 439a3e0fd82Sopenharmony_ci } 440a3e0fd82Sopenharmony_ci animator->SetRollSpeed(animator_.speed); 441a3e0fd82Sopenharmony_ci animator->RegisterScrollListener(animator_.scrollListener); 442a3e0fd82Sopenharmony_ci animator_.animator = animator; 443a3e0fd82Sopenharmony_ci hasAnimator_ = true; 444a3e0fd82Sopenharmony_ci } 445a3e0fd82Sopenharmony_ci animator_.animator->Start(); 446a3e0fd82Sopenharmony_ci} 447a3e0fd82Sopenharmony_ci 448a3e0fd82Sopenharmony_civoid UIArcLabel::Stop() 449a3e0fd82Sopenharmony_ci{ 450a3e0fd82Sopenharmony_ci if (hasAnimator_) { 451a3e0fd82Sopenharmony_ci static_cast<ArcLabelAnimator*>(animator_.animator)->Stop(); 452a3e0fd82Sopenharmony_ci } 453a3e0fd82Sopenharmony_ci} 454a3e0fd82Sopenharmony_ci 455a3e0fd82Sopenharmony_civoid UIArcLabel::SetRollCount(const uint16_t rollCount) 456a3e0fd82Sopenharmony_ci{ 457a3e0fd82Sopenharmony_ci if (hasAnimator_) { 458a3e0fd82Sopenharmony_ci static_cast<ArcLabelAnimator*>(animator_.animator)->SetRollCount(rollCount); 459a3e0fd82Sopenharmony_ci } else { 460a3e0fd82Sopenharmony_ci animator_.rollCount = rollCount; 461a3e0fd82Sopenharmony_ci } 462a3e0fd82Sopenharmony_ci} 463a3e0fd82Sopenharmony_ci 464a3e0fd82Sopenharmony_civoid UIArcLabel::RegisterScrollListener(ArcLabelScrollListener* scrollListener) 465a3e0fd82Sopenharmony_ci{ 466a3e0fd82Sopenharmony_ci if (hasAnimator_) { 467a3e0fd82Sopenharmony_ci static_cast<ArcLabelAnimator*>(animator_.animator)->RegisterScrollListener(scrollListener); 468a3e0fd82Sopenharmony_ci } else { 469a3e0fd82Sopenharmony_ci animator_.scrollListener = scrollListener; 470a3e0fd82Sopenharmony_ci } 471a3e0fd82Sopenharmony_ci} 472a3e0fd82Sopenharmony_ci 473a3e0fd82Sopenharmony_civoid UIArcLabel::SetRollSpeed(const uint16_t speed) 474a3e0fd82Sopenharmony_ci{ 475a3e0fd82Sopenharmony_ci if (hasAnimator_) { 476a3e0fd82Sopenharmony_ci static_cast<ArcLabelAnimator*>(animator_.animator)->SetRollSpeed(speed); 477a3e0fd82Sopenharmony_ci } else { 478a3e0fd82Sopenharmony_ci animator_.speed = speed; 479a3e0fd82Sopenharmony_ci } 480a3e0fd82Sopenharmony_ci} 481a3e0fd82Sopenharmony_ci 482a3e0fd82Sopenharmony_ciuint16_t UIArcLabel::GetRollSpeed() const 483a3e0fd82Sopenharmony_ci{ 484a3e0fd82Sopenharmony_ci if (hasAnimator_) { 485a3e0fd82Sopenharmony_ci return static_cast<ArcLabelAnimator*>(animator_.animator)->GetRollSpeed(); 486a3e0fd82Sopenharmony_ci } 487a3e0fd82Sopenharmony_ci 488a3e0fd82Sopenharmony_ci return animator_.speed; 489a3e0fd82Sopenharmony_ci} 490a3e0fd82Sopenharmony_ci} // namespace OHOS 491