1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "components/ui_arc_label.h"
17 #include "common/typed_text.h"
18 #include "draw/draw_label.h"
19 #include "engines/gfx/gfx_engine_manager.h"
20 #include "font/ui_font.h"
21 #include "themes/theme_manager.h"
22
23 namespace OHOS {
UIArcLabel()24 UIArcLabel::UIArcLabel()
25 : arcLabelText_(nullptr),
26 needRefresh_(false),
27 textSize_({0, 0}),
28 radius_(0),
29 startAngle_(0),
30 endAngle_(0),
31 arcCenter_({0, 0}),
32 orientation_(TextOrientation::INSIDE),
33 arcTextInfo_{0}
34 {
35 Theme* theme = ThemeManager::GetInstance().GetCurrent();
36 style_ = (theme != nullptr) ? &(theme->GetLabelStyle()) : &(StyleDefault::GetLabelStyle());
37 }
38
~UIArcLabel()39 UIArcLabel::~UIArcLabel()
40 {
41 if (arcLabelText_ != nullptr) {
42 delete arcLabelText_;
43 arcLabelText_ = nullptr;
44 }
45 }
46
SetStyle(uint8_t key,int64_t value)47 void UIArcLabel::SetStyle(uint8_t key, int64_t value)
48 {
49 UIView::SetStyle(key, value);
50 RefreshArcLabel();
51 }
52
SetText(const char * text)53 void UIArcLabel::SetText(const char* text)
54 {
55 if (text == nullptr) {
56 return;
57 }
58 InitArcLabelText();
59 arcLabelText_->SetText(text);
60 if (arcLabelText_->IsNeedRefresh()) {
61 RefreshArcLabel();
62 }
63 }
64
GetText() const65 const char* UIArcLabel::GetText() const
66 {
67 return (arcLabelText_ == nullptr) ? nullptr : arcLabelText_->GetText();
68 }
69
SetAlign(UITextLanguageAlignment horizontalAlign)70 void UIArcLabel::SetAlign(UITextLanguageAlignment horizontalAlign)
71 {
72 InitArcLabelText();
73 arcLabelText_->SetAlign(horizontalAlign, TEXT_ALIGNMENT_TOP);
74 if (arcLabelText_->IsNeedRefresh()) {
75 RefreshArcLabel();
76 }
77 }
78
GetHorAlign()79 UITextLanguageAlignment UIArcLabel::GetHorAlign()
80 {
81 InitArcLabelText();
82 return arcLabelText_->GetHorAlign();
83 }
84
GetDirect()85 UITextLanguageDirect UIArcLabel::GetDirect()
86 {
87 InitArcLabelText();
88 return arcLabelText_->GetDirect();
89 }
90
SetFontId(uint8_t fontId)91 void UIArcLabel::SetFontId(uint8_t fontId)
92 {
93 InitArcLabelText();
94 arcLabelText_->SetFontId(fontId);
95 if (arcLabelText_->IsNeedRefresh()) {
96 RefreshArcLabel();
97 }
98 }
99
GetFontId()100 uint8_t UIArcLabel::GetFontId()
101 {
102 InitArcLabelText();
103 return arcLabelText_->GetFontId();
104 }
105
SetFont(const char * name,uint8_t size)106 void UIArcLabel::SetFont(const char* name, uint8_t size)
107 {
108 if (name == nullptr) {
109 return;
110 }
111 InitArcLabelText();
112 arcLabelText_->SetFont(name, size);
113 if (arcLabelText_->IsNeedRefresh()) {
114 RefreshArcLabel();
115 }
116 }
117
OnDraw(BufferInfo & gfxDstBuffer,const Rect & invalidatedArea)118 void UIArcLabel::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
119 {
120 InitArcLabelText();
121 const char* text = arcLabelText_->GetText();
122 if ((text == nullptr) || (radius_ == 0)) {
123 return;
124 }
125 Rect trunc = invalidatedArea;
126 OpacityType opa = GetMixOpaScale();
127 UIView::OnDraw(gfxDstBuffer, invalidatedArea);
128 DrawArcText(gfxDstBuffer, trunc, opa);
129 }
130
DrawArcText(BufferInfo & gfxDstBuffer,const Rect & mask,OpacityType opaScale)131 void UIArcLabel::DrawArcText(BufferInfo& gfxDstBuffer, const Rect& mask, OpacityType opaScale)
132 {
133 Point center;
134 center.x = arcTextInfo_.arcCenter.x + GetRect().GetX();
135 center.y = arcTextInfo_.arcCenter.y + GetRect().GetY();
136 InitArcLabelText();
137 UIFont::GetInstance()->SetCurrentFontId(arcLabelText_->GetFontId(), arcLabelText_->GetFontSize());
138 DrawLabel::DrawArcText(gfxDstBuffer, mask, arcLabelText_->GetText(), center, arcLabelText_->GetFontId(),
139 arcTextInfo_, orientation_, *style_, opaScale);
140 }
141
RefreshArcLabel()142 void UIArcLabel::RefreshArcLabel()
143 {
144 Invalidate();
145 if (!needRefresh_) {
146 needRefresh_ = true;
147 }
148 }
149
ReMeasure()150 void UIArcLabel::ReMeasure()
151 {
152 if (!needRefresh_) {
153 return;
154 }
155 needRefresh_ = false;
156 InitArcLabelText();
157 UIFont::GetInstance()->SetCurrentFontId(arcLabelText_->GetFontId(), arcLabelText_->GetFontSize());
158
159 MeasureArcTextInfo();
160 Rect textRect = TypedText::GetArcTextRect(arcLabelText_->GetText(), arcCenter_, style_->letterSpace_, orientation_,
161 arcTextInfo_);
162 int16_t arcTextWidth = textRect.GetWidth();
163 int16_t arcTextHeight = textRect.GetHeight();
164
165 SetPosition(textRect.GetX(), textRect.GetY());
166 Resize(arcTextWidth, arcTextHeight);
167 arcTextInfo_.arcCenter.x = arcCenter_.x - GetX() + style_->borderWidth_ + style_->paddingLeft_;
168 arcTextInfo_.arcCenter.y = arcCenter_.y - GetY() + style_->borderWidth_ + style_->paddingTop_;
169 textSize_.x = arcTextWidth;
170 textSize_.y = arcTextHeight;
171 Invalidate();
172 }
173
MeasureArcTextInfo()174 void UIArcLabel::MeasureArcTextInfo()
175 {
176 const char* text = arcLabelText_->GetText();
177 if (text == nullptr) {
178 return;
179 }
180 uint16_t letterHeight = UIFont::GetInstance()->GetHeight();
181 arcTextInfo_.radius = ((orientation_ == TextOrientation::INSIDE) ? radius_ : (radius_ - letterHeight));
182 if (arcTextInfo_.radius == 0) {
183 return;
184 }
185
186 uint16_t arcAngle;
187 if (startAngle_ < endAngle_) {
188 arcAngle = endAngle_ - startAngle_;
189 arcTextInfo_.direct = TEXT_DIRECT_LTR; // Clockwise
190 arcLabelText_->SetDirect(TEXT_DIRECT_LTR);
191 } else {
192 arcAngle = startAngle_ - endAngle_;
193 arcTextInfo_.direct = TEXT_DIRECT_RTL; // Counterclockwise
194 arcLabelText_->SetDirect(TEXT_DIRECT_RTL);
195 }
196 // calculate max arc length
197 float maxLength = static_cast<float>((UI_PI * radius_ * arcAngle) / SEMICIRCLE_IN_DEGREE);
198 arcTextInfo_.lineStart = 0;
199 arcTextInfo_.lineEnd =
200 TypedText::GetNextLine(&text[arcTextInfo_.lineStart], style_->letterSpace_, static_cast<int16_t>(maxLength));
201 arcTextInfo_.startAngle = startAngle_ % CIRCLE_IN_DEGREE;
202 int16_t actLength = TypedText::GetTextWidth(&text[arcTextInfo_.lineStart],
203 arcTextInfo_.lineEnd - arcTextInfo_.lineStart, style_->letterSpace_);
204 if ((arcLabelText_->GetHorAlign() != TEXT_ALIGNMENT_LEFT) && (actLength < maxLength)) {
205 float gapLength = maxLength - actLength;
206 if (arcLabelText_->GetHorAlign() == TEXT_ALIGNMENT_CENTER) {
207 gapLength = gapLength / 2; // 2: half
208 }
209 arcTextInfo_.startAngle += TypedText::GetAngleForArcLen(gapLength, letterHeight, arcTextInfo_.radius,
210 arcTextInfo_.direct, orientation_);
211 }
212 }
213 } // namespace OHOS