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