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
18 #include "common/typed_text.h"
19 #include "draw/draw_label.h"
20 #include "engines/gfx/gfx_engine_manager.h"
21 #include "font/ui_font.h"
22 #include "themes/theme_manager.h"
23
24 namespace OHOS {
UIArcLabel()25 UIArcLabel::UIArcLabel()
26 : arcLabelText_(nullptr),
27 compatibilityMode_(true),
28 needRefresh_(false),
29 arcTextInfo_{0},
30 textSize_({0, 0}),
31 radius_(0),
32 startAngle_(0),
33 endAngle_(0),
34 arcCenter_({0, 0}),
35 orientation_(TextOrientation::INSIDE)
36 {
37 Theme* theme = ThemeManager::GetInstance().GetCurrent();
38 style_ = (theme != nullptr) ? &(theme->GetLabelStyle()) : &(StyleDefault::GetLabelStyle());
39 }
40
~UIArcLabel()41 UIArcLabel::~UIArcLabel()
42 {
43 if (arcLabelText_ != nullptr) {
44 delete arcLabelText_;
45 arcLabelText_ = nullptr;
46 }
47 }
48
SetStyle(uint8_t key,int64_t value)49 void UIArcLabel::SetStyle(uint8_t key, int64_t value)
50 {
51 UIView::SetStyle(key, value);
52 RefreshArcLabel();
53 }
54
SetText(const char * text)55 void UIArcLabel::SetText(const char* text)
56 {
57 if (text == nullptr) {
58 return;
59 }
60 InitArcLabelText();
61 arcLabelText_->SetText(text);
62 if (arcLabelText_->IsNeedRefresh()) {
63 RefreshArcLabel();
64 }
65 }
66
GetText() const67 const char* UIArcLabel::GetText() const
68 {
69 return (arcLabelText_ == nullptr) ? nullptr : arcLabelText_->GetText();
70 }
71
SetAlign(UITextLanguageAlignment horizontalAlign)72 void UIArcLabel::SetAlign(UITextLanguageAlignment horizontalAlign)
73 {
74 InitArcLabelText();
75 arcLabelText_->SetAlign(horizontalAlign, TEXT_ALIGNMENT_TOP);
76 if (arcLabelText_->IsNeedRefresh()) {
77 RefreshArcLabel();
78 }
79 }
80
GetHorAlign()81 UITextLanguageAlignment UIArcLabel::GetHorAlign()
82 {
83 InitArcLabelText();
84 return arcLabelText_->GetHorAlign();
85 }
86
GetDirect()87 UITextLanguageDirect UIArcLabel::GetDirect()
88 {
89 InitArcLabelText();
90 return arcLabelText_->GetDirect();
91 }
92
SetFontId(uint16_t fontId)93 void UIArcLabel::SetFontId(uint16_t fontId)
94 {
95 InitArcLabelText();
96 arcLabelText_->SetFontId(fontId);
97 if (arcLabelText_->IsNeedRefresh()) {
98 RefreshArcLabel();
99 }
100 }
101
GetFontId()102 uint16_t UIArcLabel::GetFontId()
103 {
104 InitArcLabelText();
105 return arcLabelText_->GetFontId();
106 }
107
SetFont(const char * name,uint8_t size)108 void UIArcLabel::SetFont(const char* name, uint8_t size)
109 {
110 if (name == nullptr) {
111 return;
112 }
113 InitArcLabelText();
114 arcLabelText_->SetFont(name, size);
115 if (arcLabelText_->IsNeedRefresh()) {
116 RefreshArcLabel();
117 }
118 }
119
OnDraw(BufferInfo & gfxDstBuffer,const Rect & invalidatedArea)120 void UIArcLabel::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
121 {
122 InitArcLabelText();
123 const char* text = arcLabelText_->GetText();
124 if ((text == nullptr) || (radius_ == 0)) {
125 return;
126 }
127 OpacityType opa = GetMixOpaScale();
128 UIView::OnDraw(gfxDstBuffer, invalidatedArea);
129 DrawArcText(gfxDstBuffer, invalidatedArea, opa, arcTextInfo_, orientation_);
130 }
131
DrawArcText(BufferInfo & gfxDstBuffer,const Rect & mask,OpacityType opaScale,const ArcTextInfo arcTextInfo,TextOrientation orientation)132 void UIArcLabel::DrawArcText(BufferInfo& gfxDstBuffer,
133 const Rect& mask,
134 OpacityType opaScale,
135 const ArcTextInfo arcTextInfo,
136 TextOrientation orientation)
137 {
138 Point center;
139 center.x = arcTextInfo_.arcCenter.x + GetRect().GetX();
140 center.y = arcTextInfo_.arcCenter.y + GetRect().GetY();
141 DrawLabel::DrawArcText(gfxDstBuffer, mask, arcLabelText_->GetText(), center, arcLabelText_->GetFontId(),
142 arcLabelText_->GetFontSize(), arcTextInfo,
143 orientation, *style_, opaScale, compatibilityMode_);
144 }
145
GetArcTextRect(const char * text,uint16_t fontId,uint8_t fontSize,const Point & arcCenter,int16_t letterSpace,TextOrientation orientation,const ArcTextInfo & arcTextInfo)146 Rect UIArcLabel::GetArcTextRect(const char* text, uint16_t fontId, uint8_t fontSize, const Point& arcCenter,
147 int16_t letterSpace, TextOrientation orientation, const ArcTextInfo& arcTextInfo)
148 {
149 return TypedText::GetArcTextRect(text, fontId, fontSize, arcCenter, letterSpace, orientation, arcTextInfo);
150 }
151
RefreshArcLabel()152 void UIArcLabel::RefreshArcLabel()
153 {
154 Invalidate();
155 if (!needRefresh_) {
156 needRefresh_ = true;
157 }
158 }
159
ReMeasure()160 void UIArcLabel::ReMeasure()
161 {
162 if (!needRefresh_) {
163 return;
164 }
165 needRefresh_ = false;
166 InitArcLabelText();
167
168 MeasureArcTextInfo();
169 arcTextInfo_.shapingFontId = arcLabelText_->GetShapingFontId();
170 arcTextInfo_.codePoints = arcLabelText_->GetCodePoints();
171 arcTextInfo_.codePointsNum = arcLabelText_->GetCodePointNum();
172 Rect textRect =
173 GetArcTextRect(arcLabelText_->GetText(), arcLabelText_->GetFontId(), arcLabelText_->GetFontSize(),
174 arcCenter_, style_->letterSpace_, orientation_, arcTextInfo_);
175 int16_t arcTextWidth = textRect.GetWidth();
176 int16_t arcTextHeight = textRect.GetHeight();
177
178 if (compatibilityMode_) {
179 SetPosition(textRect.GetX(), textRect.GetY());
180 Resize(arcTextWidth, arcTextHeight);
181 }
182
183 arcTextInfo_.arcCenter.x = arcCenter_.x - GetX() + style_->borderWidth_ + style_->paddingLeft_;
184 arcTextInfo_.arcCenter.y = arcCenter_.y - GetY() + style_->borderWidth_ + style_->paddingTop_;
185 textSize_.x = arcTextWidth;
186 textSize_.y = arcTextHeight;
187 Invalidate();
188 }
189
GetLineEnd(int16_t maxLength)190 uint32_t UIArcLabel::GetLineEnd(int16_t maxLength)
191 {
192 const char* text = arcLabelText_->GetText();
193 if (text == nullptr) {
194 return 0;
195 }
196
197 return TypedText::GetNextLine(&text[arcTextInfo_.lineStart], arcLabelText_->GetFontId(),
198 arcLabelText_->GetFontSize(), style_->letterSpace_, maxLength);
199 }
200
MeasureArcTextInfo()201 void UIArcLabel::MeasureArcTextInfo()
202 {
203 const char* text = arcLabelText_->GetText();
204 if (text == nullptr) {
205 return;
206 }
207 uint16_t letterHeight = UIFont::GetInstance()->GetHeight(arcLabelText_->GetFontId(), arcLabelText_->GetFontSize());
208 if (compatibilityMode_) {
209 arcTextInfo_.radius = ((orientation_ == TextOrientation::INSIDE) ? radius_ : (radius_ - letterHeight));
210 } else {
211 arcTextInfo_.radius = radius_;
212 }
213 if (arcTextInfo_.radius == 0) {
214 return;
215 }
216
217 uint16_t arcAngle;
218 if (startAngle_ < endAngle_) {
219 arcAngle = endAngle_ - startAngle_;
220 arcTextInfo_.direct = TEXT_DIRECT_LTR; // Clockwise
221 arcLabelText_->SetDirect(TEXT_DIRECT_LTR);
222 } else {
223 arcAngle = startAngle_ - endAngle_;
224 arcTextInfo_.direct = TEXT_DIRECT_RTL; // Counterclockwise
225 arcLabelText_->SetDirect(TEXT_DIRECT_RTL);
226 }
227 // calculate max arc length
228 float maxLength = static_cast<float>((UI_PI * radius_ * arcAngle) / SEMICIRCLE_IN_DEGREE);
229 arcTextInfo_.lineStart = 0;
230
231 Rect rect;
232 rect.SetWidth(static_cast<int16_t>(maxLength));
233 arcLabelText_->ReMeasureTextSize(rect, *style_);
234
235 arcTextInfo_.lineEnd = GetLineEnd(static_cast<int16_t>(maxLength));
236
237 arcTextInfo_.startAngle = startAngle_ % CIRCLE_IN_DEGREE;
238 int16_t actLength =
239 TypedText::GetTextWidth(&text[arcTextInfo_.lineStart], arcLabelText_->GetFontId(), arcLabelText_->GetFontSize(),
240 arcTextInfo_.lineEnd - arcTextInfo_.lineStart, style_->letterSpace_);
241 if ((arcLabelText_->GetHorAlign() != TEXT_ALIGNMENT_LEFT) && (actLength < maxLength)) {
242 float gapLength = maxLength - actLength;
243 if (arcLabelText_->GetHorAlign() == TEXT_ALIGNMENT_CENTER) {
244 gapLength = gapLength / 2; // 2: half
245 }
246 arcTextInfo_.startAngle += TypedText::GetAngleForArcLen(gapLength, letterHeight, arcTextInfo_.radius,
247 arcTextInfo_.direct, orientation_);
248 }
249 }
250 } // namespace OHOS
251