1 /*
2 * Copyright (c) 2020-2022 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 "text_component.h"
17 #include <stdlib.h>
18 #include <string.h>
19 #include "ace_log.h"
20 #include "font/ui_font_header.h"
21 #include "js_app_context.h"
22 #include "key_parser.h"
23 #include "keys.h"
24 #include "product_adapter.h"
25
26 using namespace OHOS;
27
28 namespace OHOS {
29 namespace ACELite {
TextComponent(jerry_value_t options,jerry_value_t children,AppStyleManager * styleManager)30 TextComponent::TextComponent(jerry_value_t options, jerry_value_t children, AppStyleManager *styleManager)
31 : Component(options, children, styleManager),
32 fontSize_(DEFAULT_FONT_SIZE),
33 fontFamily_(nullptr),
34 textValue_(nullptr),
35 overflowMode_(UILabel::LINE_BREAK_CLIP),
36 horizontalAlign_(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT)
37 {
38 SetComponentName(K_TEXT);
39 fontSize_ = ProductAdapter::GetDefaultFontSize();
40 #if FEATURE_COMPONENT_TEXT_SPANNABLE
41 backgroundColorSpan_.start = -1;
42 backgroundColorSpan_.end = -1;
43 foregroundColorSpan_.start = -1;
44 foregroundColorSpan_.end = -1;
45 lineBackgroundColorSpan_.start = -1;
46 lineBackgroundColorSpan_.end = -1;
47 #endif // FEATURE_COMPONENT_TEXT_SPANNABLE
48 }
49
CreateNativeViews()50 bool TextComponent::CreateNativeViews()
51 {
52 /* set default text OverFlow clip */
53 uiLabel_.SetLineBreakMode(overflowMode_);
54 const int32_t supportBaseLineApiVersion = 5;
55 if (JsAppContext::GetInstance()->GetTargetApi() < supportBaseLineApiVersion) {
56 uiLabel_.SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT, UITextLanguageAlignment::TEXT_ALIGNMENT_TOP);
57 uiLabel_.SetSupportBaseLine(false);
58 } else {
59 uiLabel_.SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT, UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);
60 uiLabel_.SetSupportBaseLine(true);
61 }
62 return CopyFontFamily(fontFamily_, ProductAdapter::GetDefaultFontFamilyName());
63 }
64
ReleaseNativeViews()65 void TextComponent::ReleaseNativeViews()
66 {
67 ACE_FREE(textValue_);
68 ACE_FREE(fontFamily_);
69 }
70
GetComponentRootView() const71 inline UIView *TextComponent::GetComponentRootView() const
72 {
73 return const_cast<UI_LABEL_TYPE_WRAPPER *>(&uiLabel_);
74 }
75
GetUILabelView() const76 UI_LABEL_TYPE_WRAPPER *TextComponent::GetUILabelView() const
77 {
78 return const_cast<UI_LABEL_TYPE_WRAPPER *>(&uiLabel_);
79 }
80
SetPrivateAttribute(uint16_t attrKeyId,jerry_value_t attrValue)81 bool TextComponent::SetPrivateAttribute(uint16_t attrKeyId, jerry_value_t attrValue)
82 {
83 switch (attrKeyId) {
84 case K_VALUE: {
85 ACE_FREE(textValue_);
86 textValue_ = MallocStringOf(attrValue);
87 break;
88 }
89 default: {
90 return false;
91 }
92 }
93
94 return true;
95 }
96
ApplyPrivateStyle(const AppStyleItem * styleItem)97 bool TextComponent::ApplyPrivateStyle(const AppStyleItem *styleItem)
98 {
99 switch (GetStylePropNameId(styleItem)) {
100 case K_COLOR:
101 SetTextColor(uiLabel_, styleItem);
102 break;
103 case K_LETTER_SPACING:
104 SetTextLetterSpace(uiLabel_, styleItem);
105 break;
106 case K_TEXT_ALIGN:
107 SetTextAlign(uiLabel_, styleItem);
108 break;
109 case K_FONT_SIZE:
110 SetTextSize(styleItem);
111 break;
112 case K_FONT_FAMILY:
113 if (!IsStyleValueTypeString(styleItem)) {
114 HILOG_ERROR(HILOG_MODULE_ACE, "text Family style value type is invalid!");
115 return false;
116 }
117 CopyFontFamily(fontFamily_, GetStyleStrValue(styleItem));
118 break;
119 case K_TEXT_OVERFLOW:
120 SetTextOverflow(uiLabel_, styleItem);
121 break;
122 case K_LINE_HEIGHT:
123 SetTextLineHeight(uiLabel_, styleItem);
124 break;
125 #if FEATURE_COMPONENT_TEXT_SPANNABLE
126 case K_BACKGROUNDCOLORSPANCOLOR: {
127 uint32_t color = 0;
128 uint8_t alpha = OPA_OPAQUE;
129 if (GetStyleColorValue(styleItem, color, alpha)) {
130 backgroundColorSpan_.backgroundColor = GetRGBColor(color);
131 }
132 break;
133 }
134 case K_BACKGROUNDCOLORSPANSTART: {
135 backgroundColorSpan_.start = styleItem->GetNumValue();
136 break;
137 }
138 case K_BACKGROUNDCOLORSPANEND: {
139 backgroundColorSpan_.end = styleItem->GetNumValue();
140 break;
141 }
142 case K_FOREGROUNDCOLORSPANCOLOR: {
143 uint32_t color = 0;
144 uint8_t alpha = OPA_OPAQUE;
145 if (GetStyleColorValue(styleItem, color, alpha)) {
146 foregroundColorSpan_.fontColor = GetRGBColor(color);
147 }
148 break;
149 }
150 case K_FOREGROUNDCOLORSPANSTART: {
151 foregroundColorSpan_.start = styleItem->GetNumValue();
152 break;
153 }
154 case K_FOREGROUNDCOLORSPANEND: {
155 foregroundColorSpan_.end = styleItem->GetNumValue();
156 break;
157 }
158 case K_LINEBACKGROUNDCOLORSPANCOLOR: {
159 uint32_t color = 0;
160 uint8_t alpha = OPA_OPAQUE;
161 if (GetStyleColorValue(styleItem, color, alpha)) {
162 lineBackgroundColorSpan_.linebackgroundColor = GetRGBColor(color);
163 }
164 break;
165 }
166 case K_LINEBACKGROUNDCOLORSPANSTART: {
167 lineBackgroundColorSpan_.start = styleItem->GetNumValue();
168 break;
169 }
170 case K_LINEBACKGROUNDCOLORSPANEND: {
171 lineBackgroundColorSpan_.end = styleItem->GetNumValue();
172 break;
173 }
174 case K_ABSOLUTESIZESPANSTART: {
175 absoluteSizeSpan_.start = styleItem->GetNumValue();
176 break;
177 }
178 case K_ABSOLUTESIZESPANEND: {
179 absoluteSizeSpan_.end = styleItem->GetNumValue();
180 break;
181 }
182 case K_ABSOLUTESIZESPANSIZE: {
183 absoluteSizeSpan_.size = GetStylePixelValue(styleItem);
184 break;
185 }
186 case K_RELATIVESIZESPANSTART: {
187 relativeSizeSpan_.start = styleItem->GetNumValue();
188 break;
189 }
190 case K_RELATIVESIZESPANEND: {
191 relativeSizeSpan_.end = styleItem->GetNumValue();
192 break;
193 }
194 case K_RELATIVESIZESPANSIZE: {
195 relativeSizeSpan_.size = styleItem->GetFloatingValue();
196 break;
197 }
198 case K_SPANNABLESTYLE: {
199 TextStyle style = TextStyle::TEXT_STYLE_NORMAL;
200 const char* styleStr = styleItem->GetStrValue();
201 if (!strcmp(styleStr, "bold")) {
202 style = TextStyle::TEXT_STYLE_BOLD;
203 } else if (!strcmp(styleStr, "bold-italic")) {
204 style = TextStyle::TEXT_STYLE_BOLD_ITALIC;
205 } else if (!strcmp(styleStr, "italic")) {
206 style = TextStyle::TEXT_STYLE_ITALIC;
207 }
208 stringStyleSpan_.style = style;
209 break;
210 }
211 case K_SPANNABLESTART: {
212 stringStyleSpan_.start = styleItem->GetNumValue();
213 break;
214 }
215 case K_SPANNABLEEND: {
216 stringStyleSpan_.end = styleItem->GetNumValue();
217 break;
218 }
219 #endif // FEATURE_COMPONENT_TEXT_SPANNABLE
220 default:
221 return false;
222 }
223
224 return true;
225 }
226
SetTextLetterSpace(UI_LABEL_TYPE_WRAPPER & label,const AppStyleItem * styleItem) const227 void TextComponent::SetTextLetterSpace(UI_LABEL_TYPE_WRAPPER &label, const AppStyleItem *styleItem) const
228 {
229 label.SetStyle(STYLE_LETTER_SPACE, (int16_t)GetStylePixelValue(styleItem));
230 }
231
SetTextLineHeight(UI_LABEL_TYPE_WRAPPER & label,const AppStyleItem * styleItem) const232 void TextComponent::SetTextLineHeight(UI_LABEL_TYPE_WRAPPER &label, const AppStyleItem *styleItem) const
233 {
234 label.SetStyle(STYLE_LINE_HEIGHT, (int16_t)GetStylePixelValue(styleItem));
235 }
236
SetTextOverflow(UI_LABEL_TYPE_WRAPPER & label,const AppStyleItem * styleItem)237 void TextComponent::SetTextOverflow(UI_LABEL_TYPE_WRAPPER &label, const AppStyleItem *styleItem)
238 {
239 if (!IsStyleValueTypeString(styleItem)) {
240 HILOG_ERROR(HILOG_MODULE_ACE, "text overflow style value is invalid!");
241 return;
242 }
243 // set ui label text OverFlow, LINE_BREAK_CLIP, TEXT_OVERFLOW_ELLIPSIS and TEXT_OVERFLOW_EXPAND are support
244 uint16_t propNameId = KeyParser::ParseKeyId(GetStyleStrValue(styleItem), GetStyleStrValueLen(styleItem));
245
246 switch (propNameId) {
247 case K_CLIP:
248 overflowMode_ = UILabel::LINE_BREAK_CLIP;
249 break;
250 case K_ELLIPSIS:
251 overflowMode_ = UILabel::LINE_BREAK_ELLIPSIS;
252 break;
253 case K_EXPAND:
254 overflowMode_ = UILabel::LINE_BREAK_ADAPT;
255 break;
256 case K_BREAK:
257 overflowMode_ = UILabel::LINE_BREAK_WRAP;
258 break;
259 default:
260 HILOG_WARN(HILOG_MODULE_ACE, "TextOverFlow id=%{public}d is invalid, using default instead", propNameId);
261 break;
262 }
263 label.SetLineBreakMode(overflowMode_);
264 }
265
SetTextColor(UI_LABEL_TYPE_WRAPPER & label,const AppStyleItem * styleItem) const266 void TextComponent::SetTextColor(UI_LABEL_TYPE_WRAPPER &label, const AppStyleItem *styleItem) const
267 {
268 uint32_t color = 0;
269 uint8_t alpha = OPA_OPAQUE;
270 if (GetStyleColorValue(styleItem, color, alpha)) {
271 label.SetStyle(STYLE_TEXT_COLOR, GetRGBColor(color).full);
272 label.SetStyle(STYLE_TEXT_OPA, alpha);
273 }
274 }
275
SetTextSize(const AppStyleItem * styleItem)276 void TextComponent::SetTextSize(const AppStyleItem *styleItem)
277 {
278 fontSize_ = GetStylePixelValue(styleItem);
279 }
280
OnViewAttached()281 void TextComponent::OnViewAttached()
282 {
283 if (GetHeight() < 0 && GetWidth() < 0) {
284 /* component height & width adjust text context when not set text height & text width */
285 uiLabel_.SetLineBreakMode(UILabel::LINE_BREAK_ADAPT);
286 } else if (GetHeight() < 0 && GetWidth() >= 0) {
287 /* component height adjust text context when set width not set text height */
288 uiLabel_.SetLineBreakMode(UILabel::LINE_BREAK_WRAP);
289 } else if (GetHeight() >= 0 && GetWidth() < 0) {
290 /* component width adjust text context when not set text width */
291 uiLabel_.SetLineBreakMode(UILabel::LINE_BREAK_STRETCH);
292 }
293 if (textValue_ != nullptr && fontFamily_ != nullptr) {
294 uiLabel_.SetFont(fontFamily_, fontSize_);
295 uiLabel_.SetText(textValue_);
296 UpdateTextAlignToLabel(uiLabel_);
297 #if FEATURE_COMPONENT_TEXT_SPANNABLE
298 SetRichTextSpan();
299 #endif // FEATURE_COMPONENT_TEXT_SPANNABLE
300 }
301 }
302
303 /* watchcallback update text context */
PostUpdate(uint16_t attrKeyId)304 void TextComponent::PostUpdate(uint16_t attrKeyId)
305 {
306 if (!KeyParser::IsKeyValid(attrKeyId)) {
307 HILOG_ERROR(HILOG_MODULE_ACE, "text component post update check args failed");
308 return;
309 }
310 switch (attrKeyId) {
311 case K_VALUE:
312 if (textValue_ != nullptr) {
313 uiLabel_.SetText(textValue_);
314 UpdateTextAlignToLabel(uiLabel_);
315 #if FEATURE_COMPONENT_TEXT_SPANNABLE
316 SetRichTextSpan();
317 #endif // FEATURE_COMPONENT_TEXT_SPANNABLE
318 }
319 break;
320 case K_FONT_SIZE:
321 case K_FONT_FAMILY:
322 if (fontFamily_ != nullptr) {
323 uiLabel_.SetFont(fontFamily_, fontSize_);
324 }
325 break;
326 default:
327 break;
328 }
329 UIView *parent = uiLabel_.GetParent();
330 if (parent != nullptr) {
331 parent->LayoutChildren(true);
332 }
333 }
334
SetTextAlign(UI_LABEL_TYPE_WRAPPER & label,const AppStyleItem * styleItem)335 void TextComponent::SetTextAlign(UI_LABEL_TYPE_WRAPPER &label, const AppStyleItem *styleItem)
336 {
337 if (!IsStyleValueTypeString(styleItem)) {
338 HILOG_ERROR(HILOG_MODULE_ACE, "text text align style value is invalid!");
339 return;
340 }
341 // set ui label text align, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER are support.
342 const char * const stylePropValue = GetStyleStrValue(styleItem);
343 uint16_t alignId = KeyParser::ParseKeyId(stylePropValue, GetStyleStrValueLen(styleItem));
344 switch (alignId) {
345 case K_LEFT:
346 horizontalAlign_ = UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT;
347 break;
348 case K_RIGHT:
349 horizontalAlign_ = UITextLanguageAlignment::TEXT_ALIGNMENT_RIGHT;
350 break;
351 case K_CENTER:
352 horizontalAlign_ = UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER;
353 break;
354 default:
355 HILOG_WARN(HILOG_MODULE_ACE, "text textAlign style value =%{public}s is invalid, using default instead",
356 stylePropValue);
357 break;
358 }
359 UpdateTextAlignToLabel(label);
360 }
361
UpdateTextAlignToLabel(UI_LABEL_TYPE_WRAPPER & label)362 void TextComponent::UpdateTextAlignToLabel(UI_LABEL_TYPE_WRAPPER& label)
363 {
364 const int32_t defaultVerticalAlignCenterApiVersion = 5;
365 if (JsAppContext::GetInstance()->GetTargetApi() < defaultVerticalAlignCenterApiVersion) {
366 label.SetAlign(horizontalAlign_, UITextLanguageAlignment::TEXT_ALIGNMENT_TOP);
367 } else {
368 label.SetAlign(horizontalAlign_, UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);
369 }
370 }
371
372 #if FEATURE_COMPONENT_TEXT_SPANNABLE
SetRichTextSpan()373 void TextComponent::SetRichTextSpan()
374 {
375 if (backgroundColorSpan_.start != -1 && backgroundColorSpan_.end != -1) {
376 uiLabel_.SetBackgroundColorSpan(backgroundColorSpan_.backgroundColor,
377 backgroundColorSpan_.start,
378 backgroundColorSpan_.end);
379 }
380 if (foregroundColorSpan_.start != -1 && foregroundColorSpan_.end != -1) {
381 uiLabel_.SetForegroundColorSpan(foregroundColorSpan_.fontColor,
382 foregroundColorSpan_.start,
383 foregroundColorSpan_.end);
384 }
385 if (lineBackgroundColorSpan_.start != -1 && lineBackgroundColorSpan_.end != -1) {
386 uiLabel_.SetLineBackgroundSpan(lineBackgroundColorSpan_.linebackgroundColor,
387 lineBackgroundColorSpan_.start,
388 lineBackgroundColorSpan_.end);
389 }
390 if (absoluteSizeSpan_.start != -1 && absoluteSizeSpan_.end != -1) {
391 uiLabel_.SetAbsoluteSizeSpan(absoluteSizeSpan_.start,
392 absoluteSizeSpan_.end,
393 absoluteSizeSpan_.size);
394 }
395 if (relativeSizeSpan_.start != -1 && relativeSizeSpan_.end != -1) {
396 uiLabel_.SetRelativeSizeSpan(relativeSizeSpan_.start,
397 relativeSizeSpan_.end,
398 relativeSizeSpan_.size);
399 }
400 #if defined(ENABLE_TEXT_STYLE) && ENABLE_TEXT_STYLE
401 if (stringStyleSpan_.start != -1 && stringStyleSpan_.end != -1) {
402 SpannableString spanString(textValue_);
403 spanString.SetTextStyle(stringStyleSpan_.style,
404 stringStyleSpan_.start,
405 stringStyleSpan_.end);
406 uiLabel_.SetText(&spanString);
407 }
408 #endif
409 }
410 #endif // FEATURE_COMPONENT_TEXT_SPANNABLE
411 } // namespace ACELite
412 } // namespace OHOS
413