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 "common/text.h"
17 #include "common/typed_text.h"
18 #include "draw/draw_label.h"
19 #include "font/ui_font.h"
20 #include "font/ui_font_adaptor.h"
21 #include "font/ui_font_builder.h"
22 #include "gfx_utils/graphic_log.h"
23 #include "securec.h"
24
25 namespace OHOS {
26 Text::TextLine Text::textLine_[MAX_LINE_COUNT] = {{0}};
27
Text()28 Text::Text()
29 : text_(nullptr),
30 fontId_(0),
31 fontSize_(0),
32 textSize_({0, 0}),
33 needRefresh_(false),
34 expandWidth_(false),
35 expandHeight_(false),
36 baseLine_(true),
37 direct_(TEXT_DIRECT_LTR),
38 sizeSpans_(nullptr),
39 characterSize_(0),
40 horizontalAlign_(TEXT_ALIGNMENT_LEFT),
41 verticalAlign_(TEXT_ALIGNMENT_TOP),
42 eliminateTrailingSpaces_(false)
43
44 {
45 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
46 textStyles_ = nullptr;
47 #endif
48 SetFont(DEFAULT_VECTOR_FONT_FILENAME, DEFAULT_VECTOR_FONT_SIZE);
49 }
50
~Text()51 Text::~Text()
52 {
53 if (text_ != nullptr) {
54 UIFree(text_);
55 text_ = nullptr;
56 }
57 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
58 if (textStyles_ != nullptr) {
59 UIFree(textStyles_);
60 textStyles_ = nullptr;
61 }
62 #endif
63 if (backgroundColor_.Size() > 0) {
64 backgroundColor_.Clear();
65 }
66 if (linebackgroundColor_.Size() > 0) {
67 linebackgroundColor_.Clear();
68 }
69 if (foregroundColor_.Size() > 0) {
70 foregroundColor_.Clear();
71 }
72 if (sizeSpans_ != nullptr) {
73 UIFree(sizeSpans_);
74 sizeSpans_ = nullptr;
75 }
76 }
77
78 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
SetSpannableString(const SpannableString * spannableString)79 void Text::SetSpannableString(const SpannableString* spannableString)
80 {
81 SetText(spannableString->text_);
82 if (textStyles_ != nullptr) {
83 UIFree(textStyles_);
84 textStyles_ = nullptr;
85 }
86 if (spannableString->spanList_.IsEmpty()) {
87 return;
88 }
89 uint32_t textLen = TypedText::GetUTF8CharacterSize(text_, GetTextStrLen());
90 if (textLen == 0 || textLen > MAX_TEXT_LENGTH) {
91 return;
92 }
93 textStyles_ = static_cast<TextStyle*>(UIMalloc(textLen));
94 if (textStyles_ == nullptr) {
95 GRAPHIC_LOGE("Text::SetSpannableString invalid parameter");
96 return;
97 }
98 ListNode<StyleSpan*>* node = spannableString->spanList_.Begin();
99 while (node != spannableString->spanList_.End()) {
100 for (uint32_t i = node->data_->start_; i < node->data_->end_; i++) {
101 if (textLen > i) {
102 textStyles_[i] = node->data_->textStyle_;
103 }
104 }
105 node = node->next_;
106 }
107 needRefresh_ = true;
108 }
109 #endif
SetText(const char * text)110 void Text::SetText(const char* text)
111 {
112 if (text == nullptr) {
113 return;
114 }
115 uint32_t textLen = static_cast<uint32_t>(strlen(text));
116 if (textLen > MAX_TEXT_LENGTH) {
117 textLen = MAX_TEXT_LENGTH;
118 }
119 if (text_ != nullptr) {
120 if (strcmp(text, text_) == 0) {
121 return;
122 }
123 UIFree(text_);
124 text_ = nullptr;
125 }
126 text_ = static_cast<char*>(UIMalloc(textLen + 1));
127 if (text_ == nullptr) {
128 return;
129 }
130 if (strncpy_s(text_, textLen + 1, text, textLen) != EOK) {
131 UIFree(text_);
132 text_ = nullptr;
133 return;
134 }
135 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
136 if (textStyles_ != nullptr) {
137 UIFree(textStyles_);
138 textStyles_ = nullptr;
139 }
140 #endif
141 needRefresh_ = true;
142 if (sizeSpans_ != nullptr) {
143 UIFree(sizeSpans_);
144 sizeSpans_ = nullptr;
145 }
146 }
147
SetFont(const char * name,uint8_t size)148 void Text::SetFont(const char* name, uint8_t size)
149 {
150 if (name == nullptr) {
151 return;
152 }
153 UIFont* font = UIFont::GetInstance();
154 if (font->IsVectorFont()) {
155 uint16_t fontId = font->GetFontId(name);
156 if ((fontId != UIFontBuilder::GetInstance()->GetTotalFontId()) &&
157 ((fontId_ != fontId) || (fontSize_ != size))) {
158 fontId_ = fontId;
159 fontSize_ = size;
160 needRefresh_ = true;
161 }
162 } else {
163 uint16_t fontId = font->GetFontId(name, size);
164 SetFontId(fontId);
165 }
166 }
167
SetFont(const char * name,uint8_t size,char * & destName,uint8_t & destSize)168 void Text::SetFont(const char* name, uint8_t size, char*& destName, uint8_t& destSize)
169 {
170 if (name == nullptr) {
171 return;
172 }
173 uint32_t nameLen = static_cast<uint32_t>(strlen(name));
174 if (nameLen > MAX_TEXT_LENGTH) {
175 return;
176 }
177 if (destName != nullptr) {
178 if (strcmp(destName, name) == 0) {
179 destSize = size;
180 return;
181 }
182 UIFree(destName);
183 destName = nullptr;
184 }
185 if (nameLen != 0) {
186 /* one more to store '\0' */
187 destName = static_cast<char*>(UIMalloc(++nameLen));
188 if (destName == nullptr) {
189 return;
190 }
191 if (memcpy_s(destName, nameLen, name, nameLen) != EOK) {
192 UIFree(destName);
193 destName = nullptr;
194 return;
195 }
196 destSize = size;
197 }
198 }
199
SetFontId(uint16_t fontId)200 void Text::SetFontId(uint16_t fontId)
201 {
202 UIFontBuilder* fontBuilder = UIFontBuilder::GetInstance();
203 if (fontId >= fontBuilder->GetTotalFontId()) {
204 GRAPHIC_LOGE("Text::SetFontId invalid fontId(%hhd)", fontId);
205 return;
206 }
207 UIFont* font = UIFont::GetInstance();
208 if ((fontId_ == fontId) && (fontSize_ != 0) && !font->IsVectorFont()) {
209 GRAPHIC_LOGD("Text::SetFontId same font has already set");
210 return;
211 }
212
213 UITextLanguageFontParam* fontParam = fontBuilder->GetTextLangFontsTable(fontId);
214 if (fontParam == nullptr) {
215 return;
216 }
217 if (font->IsVectorFont()) {
218 uint16_t fontId = font->GetFontId(fontParam->ttfName);
219 if ((fontId != fontBuilder->GetTotalFontId()) && ((fontId_ != fontId) ||
220 (fontSize_ != fontParam->size))) {
221 fontId_ = fontId;
222 fontSize_ = fontParam->size;
223 needRefresh_ = true;
224 }
225 } else {
226 fontId_ = fontId;
227 fontSize_ = fontParam->size;
228 needRefresh_ = true;
229 }
230 }
231
ReMeasureTextSize(const Rect & textRect,const Style & style)232 void Text::ReMeasureTextSize(const Rect& textRect, const Style& style)
233 {
234 if (fontSize_ == 0) {
235 return;
236 }
237 int16_t maxWidth = (expandWidth_ ? COORD_MAX : textRect.GetWidth());
238 if (maxWidth > 0) {
239 textSize_ = TypedText::GetTextSize(text_, fontId_, fontSize_, style.letterSpace_, style.lineHeight_, maxWidth,
240 style.lineSpace_, sizeSpans_, IsEliminateTrailingSpaces());
241 if (baseLine_) {
242 FontHeader head;
243 if (UIFont::GetInstance()->GetFontHeader(head, fontId_, fontSize_) != 0) {
244 return;
245 }
246 textSize_.y += fontSize_ - head.ascender;
247 }
248 }
249 }
250
ReMeasureTextWidthInEllipsisMode(const Rect & textRect,const Style & style,uint16_t ellipsisIndex)251 void Text::ReMeasureTextWidthInEllipsisMode(const Rect& textRect, const Style& style, uint16_t ellipsisIndex)
252 {
253 if (ellipsisIndex != TEXT_ELLIPSIS_END_INV) {
254 int16_t lineMaxWidth = expandWidth_ ? textSize_.x : textRect.GetWidth();
255 uint32_t maxLineBytes = 0;
256 uint16_t lineCount = GetLine(lineMaxWidth, style.letterSpace_, ellipsisIndex, maxLineBytes);
257 if ((lineCount > 0) && (textSize_.x < textLine_[lineCount - 1].linePixelWidth)) {
258 textSize_.x = textLine_[lineCount - 1].linePixelWidth;
259 }
260 }
261 }
262
DrawEllipsis(BufferInfo & gfxDstBuffer,LabelLineInfo & labelLine,uint16_t & letterIndex)263 void Text::DrawEllipsis(BufferInfo& gfxDstBuffer, LabelLineInfo& labelLine, uint16_t& letterIndex)
264 {
265 labelLine.offset.x = 0;
266 labelLine.text = TEXT_ELLIPSIS;
267 labelLine.lineLength = 1;
268 labelLine.length = 1;
269 DrawLabel::DrawTextOneLine(gfxDstBuffer, labelLine, letterIndex);
270 }
271
OnDraw(BufferInfo & gfxDstBuffer,const Rect & invalidatedArea,const Rect & viewOrigRect,const Rect & textRect,int16_t offsetX,const Style & style,uint16_t ellipsisIndex,OpacityType opaScale)272 void Text::OnDraw(BufferInfo& gfxDstBuffer,
273 const Rect& invalidatedArea,
274 const Rect& viewOrigRect,
275 const Rect& textRect,
276 int16_t offsetX,
277 const Style& style,
278 uint16_t ellipsisIndex,
279 OpacityType opaScale)
280 {
281 if ((text_ == nullptr) || (strlen(text_) == 0) || (fontSize_ == 0)) {
282 return;
283 }
284 Rect mask = invalidatedArea;
285
286 if (mask.Intersect(mask, textRect)) {
287 Draw(gfxDstBuffer, mask, textRect, style, offsetX, ellipsisIndex, opaScale);
288 }
289 }
290
Draw(BufferInfo & gfxDstBuffer,const Rect & mask,const Rect & coords,const Style & style,int16_t offsetX,uint16_t ellipsisIndex,OpacityType opaScale)291 void Text::Draw(BufferInfo& gfxDstBuffer,
292 const Rect& mask,
293 const Rect& coords,
294 const Style& style,
295 int16_t offsetX,
296 uint16_t ellipsisIndex,
297 OpacityType opaScale)
298 {
299 Point offset = {offsetX, 0};
300 int16_t lineMaxWidth = expandWidth_ ? textSize_.x : coords.GetWidth();
301 uint16_t lineBegin = 0;
302 uint32_t maxLineBytes = 0;
303 uint16_t lineCount = GetLine(lineMaxWidth, style.letterSpace_, ellipsisIndex, maxLineBytes);
304 int16_t lineHeight = style.lineHeight_;
305 int16_t curLineHeight;
306 UIFont* font = UIFont::GetInstance();
307 if (lineHeight <= 0) {
308 lineHeight = font->GetHeight(fontId_, fontSize_);
309 lineHeight += style.lineSpace_;
310 }
311 if ((style.lineSpace_ == 0) && (sizeSpans_ != nullptr)) {
312 uint16_t letterIndex = 0;
313 curLineHeight = font->GetLineMaxHeight(text_, textLine_[0].lineBytes, fontId_, fontSize_,
314 letterIndex, sizeSpans_);
315 curLineHeight += style.lineSpace_;
316 } else {
317 curLineHeight = lineHeight;
318 }
319 Point pos;
320 if (lineHeight == style.lineHeight_) {
321 pos.y = TextPositionY(coords, (lineCount * lineHeight));
322 } else {
323 pos.y = TextPositionY(coords, (lineCount * lineHeight - style.lineSpace_));
324 }
325 OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.textOpa_);
326 uint16_t letterIndex = 0;
327 for (uint16_t i = 0; i < lineCount; i++) {
328 if (pos.y > mask.GetBottom()) {
329 return;
330 }
331 int16_t nextLine = pos.y + curLineHeight;
332 if (lineHeight != style.lineHeight_) {
333 nextLine -= style.lineSpace_;
334 }
335 int16_t tempLetterIndex = letterIndex;
336 uint16_t lineBytes = textLine_[i].lineBytes;
337 #if defined(ENABLE_ICU) && ENABLE_ICU
338 if (this->IsEliminateTrailingSpaces()) {
339 int j = lineBytes - 1;
340 while (j >= 0 && text_[lineBegin + j] == ' ') {
341 --j;
342 }
343 lineBytes = j + 1;
344 }
345 #endif
346 if (nextLine >= mask.GetTop()) {
347 pos.x = LineStartPos(coords, textLine_[i].linePixelWidth);
348 LabelLineInfo labelLine {pos, offset, mask, curLineHeight, lineBytes,
349 0, opa, style, &text_[lineBegin], lineBytes,
350 lineBegin, fontId_, fontSize_, 0, static_cast<UITextLanguageDirect>(direct_),
351 nullptr, baseLine_,
352 #if defined(ENABLE_SPANNABLE_STRING) && ENABLE_SPANNABLE_STRING
353 textStyles_,
354 #endif
355 &backgroundColor_, &foregroundColor_, &linebackgroundColor_, sizeSpans_, 0};
356
357 uint16_t ellipsisOssetY = DrawLabel::DrawTextOneLine(gfxDstBuffer, labelLine, letterIndex);
358 if ((i == (lineCount - 1)) && (ellipsisIndex != TEXT_ELLIPSIS_END_INV)) {
359 labelLine.ellipsisOssetY = ellipsisOssetY;
360 DrawEllipsis(gfxDstBuffer, labelLine, letterIndex);
361 }
362 } else {
363 letterIndex = TypedText::GetUTF8CharacterSize(text_, lineBegin + lineBytes);
364 }
365 if ((style.lineSpace_ == 0) && (sizeSpans_ != nullptr)) {
366 curLineHeight = font->GetLineMaxHeight(&text_[lineBegin], textLine_[i].lineBytes, fontId_,
367 fontSize_, tempLetterIndex, sizeSpans_);
368 curLineHeight += style.lineSpace_;
369 } else {
370 curLineHeight = lineHeight;
371 }
372 lineBegin += textLine_[i].lineBytes;
373 pos.y += curLineHeight;
374 }
375 }
376
TextPositionY(const Rect & textRect,int16_t textHeight)377 int16_t Text::TextPositionY(const Rect& textRect, int16_t textHeight)
378 {
379 int16_t yOffset = 0;
380 if (!expandHeight_ && (verticalAlign_ != TEXT_ALIGNMENT_TOP) && (textRect.GetHeight() > textHeight)) {
381 if (verticalAlign_ == TEXT_ALIGNMENT_CENTER) {
382 yOffset = (textRect.GetHeight() - textHeight) >> 1;
383 } else if (verticalAlign_ == TEXT_ALIGNMENT_BOTTOM) {
384 yOffset = textRect.GetHeight() - textHeight;
385 }
386 }
387 return textRect.GetY() + yOffset;
388 }
389
LineStartPos(const Rect & textRect,uint16_t lineWidth)390 int16_t Text::LineStartPos(const Rect& textRect, uint16_t lineWidth)
391 {
392 int16_t xOffset = 0;
393 int16_t rectWidth = textRect.GetWidth();
394 if (horizontalAlign_ == TEXT_ALIGNMENT_CENTER) {
395 xOffset = (direct_ == TEXT_DIRECT_RTL) ? ((rectWidth + lineWidth + 1) >> 1) : ((rectWidth - lineWidth) >> 1);
396 } else if (horizontalAlign_ == TEXT_ALIGNMENT_RIGHT) {
397 xOffset = (direct_ == TEXT_DIRECT_RTL) ? rectWidth : (rectWidth - lineWidth);
398 } else {
399 xOffset = (direct_ == TEXT_DIRECT_RTL) ? rectWidth : 0;
400 }
401 return textRect.GetX() + xOffset;
402 }
403
GetLine(int16_t width,uint8_t letterSpace,uint16_t ellipsisIndex,uint32_t & maxLineBytes)404 uint16_t Text::GetLine(int16_t width, uint8_t letterSpace, uint16_t ellipsisIndex, uint32_t& maxLineBytes)
405 {
406 if (text_ == nullptr) {
407 return 0;
408 }
409 uint16_t lineNum = 0;
410 uint32_t textLen = GetTextStrLen();
411 if ((ellipsisIndex != TEXT_ELLIPSIS_END_INV) && (ellipsisIndex < textLen)) {
412 textLen = ellipsisIndex;
413 }
414 uint32_t begin = 0;
415 uint16_t letterIndex = 0;
416 while ((begin < textLen) && (text_[begin] != '\0') && (lineNum < MAX_LINE_COUNT)) {
417 begin += GetTextLine(begin, textLen, width, lineNum, letterSpace, letterIndex, sizeSpans_, textLine_[lineNum]);
418 if (maxLineBytes < textLine_[lineNum].lineBytes) {
419 maxLineBytes = textLine_[lineNum].lineBytes;
420 }
421 lineNum++;
422 }
423 if ((lineNum != 0) && (ellipsisIndex != TEXT_ELLIPSIS_END_INV)) {
424 uint16_t ellipsisWidth =
425 UIFont::GetInstance()->GetWidth(TEXT_ELLIPSIS_UNICODE, fontId_, fontSize_, 0) + letterSpace;
426 textLine_[lineNum - 1].linePixelWidth += ellipsisWidth;
427 if (textLine_[lineNum - 1].linePixelWidth > width) {
428 int16_t newWidth = width - ellipsisWidth;
429 maxLineBytes = CalculateLineWithEllipsis(begin, textLen, newWidth, letterSpace, lineNum, letterIndex,
430 sizeSpans_);
431 textLine_[lineNum - 1].linePixelWidth += ellipsisWidth;
432 }
433 }
434 return lineNum;
435 }
436
CalculateLineWithEllipsis(uint32_t begin,uint32_t textLen,int16_t width,uint8_t letterSpace,uint16_t & lineNum,uint16_t & letterIndex,SizeSpan * sizeSpans)437 uint32_t Text::CalculateLineWithEllipsis(uint32_t begin, uint32_t textLen, int16_t width,
438 uint8_t letterSpace, uint16_t& lineNum,
439 uint16_t& letterIndex,
440 SizeSpan* sizeSpans)
441 {
442 begin -= textLine_[lineNum - 1].lineBytes;
443 lineNum--;
444 while ((begin < textLen) && (text_[begin] != '\0') && (lineNum < MAX_LINE_COUNT)) {
445 begin += GetTextLine(begin, textLen, width, lineNum, letterSpace, letterIndex, sizeSpans,
446 textLine_[lineNum]);
447 lineNum++;
448 }
449 uint32_t maxLineBytes = 0;
450 for (uint16_t i = 0; i < lineNum; i++) {
451 if (maxLineBytes < textLine_[i].lineBytes) {
452 maxLineBytes = textLine_[i].lineBytes;
453 }
454 }
455 return maxLineBytes;
456 }
457
GetTextStrLen()458 uint32_t Text::GetTextStrLen()
459 {
460 return (text_ != nullptr) ? (strlen(text_)) : 0;
461 }
462
GetTextLine(uint32_t begin,uint32_t textLen,int16_t width,uint16_t lineNum,uint8_t letterSpace,uint16_t & letterIndex,SizeSpan * sizeSpans,TextLine & textLine)463 uint32_t Text::GetTextLine(uint32_t begin, uint32_t textLen, int16_t width, uint16_t lineNum, uint8_t letterSpace,
464 uint16_t& letterIndex, SizeSpan* sizeSpans, TextLine& textLine)
465 {
466 int16_t lineWidth = width;
467 int16_t lineHeight = 0;
468 uint16_t nextLineBytes = UIFontAdaptor::GetNextLineAndWidth(&text_[begin], fontId_, fontSize_, letterSpace,
469 lineWidth, lineHeight, letterIndex, sizeSpans, false,
470 textLen - begin, IsEliminateTrailingSpaces());
471 if (nextLineBytes + begin > textLen) {
472 nextLineBytes = textLen - begin;
473 }
474 textLine.lineBytes = nextLineBytes;
475 textLine.linePixelWidth = lineWidth;
476 return nextLineBytes;
477 }
478
GetEllipsisIndex(const Rect & textRect,const Style & style)479 uint16_t Text::GetEllipsisIndex(const Rect& textRect, const Style& style)
480 {
481 if (textSize_.y <= textRect.GetHeight()) {
482 return TEXT_ELLIPSIS_END_INV;
483 }
484 UIFont* fontEngine = UIFont::GetInstance();
485 int16_t letterWidth = fontEngine->GetWidth(TEXT_ELLIPSIS_UNICODE, fontId_, fontSize_, 0) + style.letterSpace_;
486 Point p;
487 p.x = textRect.GetWidth() - letterWidth;
488 p.y = textRect.GetHeight();
489 int16_t height = style.lineHeight_;
490 if (height == 0) {
491 height = fontEngine->GetHeight(fontId_, fontSize_) + style.lineSpace_;
492 }
493 if (height) {
494 p.y -= p.y % height;
495 }
496 if (height != style.lineHeight_) {
497 p.y -= style.lineSpace_;
498 }
499 return GetLetterIndexByPosition(textRect, style, p);
500 }
501
GetLetterIndexByLinePosition(const Style & style,int16_t contentWidth,const int16_t & posX,int16_t offsetX)502 uint16_t Text::GetLetterIndexByLinePosition(const Style& style, int16_t contentWidth,
503 const int16_t& posX, int16_t offsetX)
504 {
505 uint16_t letterIndex = 0;
506 int16_t width = 0;
507 if (direct_ == UITextLanguageDirect::TEXT_DIRECT_LTR) {
508 width = posX - offsetX;
509 }
510
511 int16_t lineHeight = style.lineHeight_;
512 UIFontAdaptor::GetNextLineAndWidth(text_, fontId_, fontSize_, style.letterSpace_,
513 width, lineHeight, letterIndex, sizeSpans_,
514 false, 0xFFFF, IsEliminateTrailingSpaces());
515 return letterIndex;
516 }
517
GetPosXByLetterIndex(const Rect & textRect,const Style & style,uint16_t beginIndex,uint16_t count)518 uint16_t Text::GetPosXByLetterIndex(const Rect &textRect, const Style &style,
519 uint16_t beginIndex, uint16_t count)
520 {
521 if (count == 0) {
522 return 0;
523 }
524
525 int16_t maxWidth = (expandWidth_ ? COORD_MAX : textRect.GetWidth());
526
527 int16_t textWidth = TypedText::GetTextWidth(text_, fontId_, fontSize_, GetTextStrLen(),
528 style.letterSpace_, beginIndex, count);
529
530 return static_cast<uint16_t>(textWidth > maxWidth ? maxWidth : textWidth);
531 }
532
GetLetterIndexByPosition(const Rect & textRect,const Style & style,const Point & pos)533 uint16_t Text::GetLetterIndexByPosition(const Rect& textRect, const Style& style, const Point& pos)
534 {
535 if (text_ == nullptr) {
536 return 0;
537 }
538 uint32_t lineStart = 0;
539 uint32_t nextLineStart = 0;
540 int16_t lineHeight = style.lineHeight_;
541 uint16_t letterHeight = UIFont::GetInstance()->GetHeight(fontId_, fontSize_);
542 if (lineHeight == 0) {
543 lineHeight = letterHeight + style.lineSpace_;
544 }
545 uint16_t height = 0;
546 if (lineHeight != style.lineHeight_) {
547 height = letterHeight;
548 } else {
549 height = lineHeight;
550 }
551 int16_t y = 0;
552 uint32_t textLen = static_cast<uint32_t>(strlen(text_));
553 int16_t width = 0;
554 uint16_t letterIndex = 0;
555 while ((lineStart < textLen) && (text_[lineStart] != '\0')) {
556 width = textRect.GetWidth();
557 nextLineStart += UIFontAdaptor::GetNextLineAndWidth(&text_[lineStart], fontId_, fontSize_, style.letterSpace_,
558 width, lineHeight, letterIndex, sizeSpans_,
559 false, 0xFFFF, IsEliminateTrailingSpaces());
560 if (nextLineStart == 0) {
561 break;
562 }
563 if (pos.y <= y + height) {
564 break;
565 }
566 y += lineHeight;
567 lineStart = nextLineStart;
568 }
569 if (nextLineStart == textLen) {
570 return TEXT_ELLIPSIS_END_INV;
571 }
572 /* Calculate the x coordinate */
573 width = pos.x;
574 lineStart +=
575 UIFontAdaptor::GetNextLineAndWidth(&text_[lineStart], fontId_, fontSize_, style.letterSpace_, width, lineHeight,
576 letterIndex, sizeSpans_, true, 0xFFFF, IsEliminateTrailingSpaces());
577 return (lineStart < textLen) ? lineStart : TEXT_ELLIPSIS_END_INV;
578 }
579
SetAbsoluteSizeSpan(uint16_t start,uint16_t end,uint8_t size)580 void Text::SetAbsoluteSizeSpan(uint16_t start, uint16_t end, uint8_t size)
581 {
582 #if defined(ENABLE_VECTOR_FONT) && ENABLE_VECTOR_FONT
583 if (fontId_ == FONT_ID_MAX) {
584 return;
585 }
586 #else
587 if (fontId_ == UIFontBuilder::GetInstance()->GetBitmapFontIdMax()) {
588 return;
589 }
590 #endif
591 uint16_t fontId = GetSpanFontIdBySize(size);
592 #if defined(ENABLE_VECTOR_FONT) && !ENABLE_VECTOR_FONT
593 if (fontId == fontId_) {
594 return;
595 }
596 #endif
597 if (text_ != nullptr && sizeSpans_ == nullptr) {
598 characterSize_ = TypedText::GetUTF8CharacterSize(text_, GetTextStrLen());
599 sizeSpans_ = static_cast<SizeSpan*>(UIMalloc(characterSize_ * sizeof(SizeSpan)));
600 if (sizeSpans_ == nullptr) {
601 GRAPHIC_LOGE("Text::SetAbsoluteSizeSpan invalid parameter");
602 return;
603 }
604 InitSizeSpans();
605 }
606
607 if (sizeSpans_ != nullptr && start <= characterSize_) {
608 for (uint16_t i = start; i < end && i < characterSize_; i++) {
609 sizeSpans_[i].fontId = fontId;
610 sizeSpans_[i].size = size;
611 sizeSpans_[i].isSizeSpan = true;
612 }
613 }
614 }
615
SetRelativeSizeSpan(uint16_t start,uint16_t end,float size)616 void Text::SetRelativeSizeSpan(uint16_t start, uint16_t end, float size)
617 {
618 uint8_t absoluteSize = 0;
619 #if defined(ENABLE_VECTOR_FONT) && ENABLE_VECTOR_FONT
620 absoluteSize = static_cast<uint8_t>(size * fontSize_);
621 #else
622 UITextLanguageFontParam* fontParam = UIFontBuilder::GetInstance()->GetTextLangFontsTable(fontId_);
623 if (fontParam == nullptr) {
624 GRAPHIC_LOGE("Text::SetRelativeSizeSpan invalid parameter");
625 return;
626 }
627 absoluteSize = static_cast<uint8_t>(size * fontParam->size);
628 #endif
629 SetAbsoluteSizeSpan(start, end, absoluteSize);
630 }
631
GetSpanFontIdBySize(uint8_t size)632 uint16_t Text::GetSpanFontIdBySize(uint8_t size)
633 {
634 #if defined(ENABLE_VECTOR_FONT) && ENABLE_VECTOR_FONT
635 return fontId_;
636 #else
637 UIFontBuilder* fontBuilder = UIFontBuilder::GetInstance();
638 UITextLanguageFontParam* fontParam = fontBuilder->GetTextLangFontsTable(fontId_);
639 if (fontParam == nullptr) {
640 return fontId_;
641 }
642
643 uint8_t ttfId = fontParam->ttfId;
644 for (uint16_t fontId = 0; fontId < fontBuilder->GetTotalFontId(); fontId++) {
645 UITextLanguageFontParam* tempFontParam = fontBuilder->GetTextLangFontsTable(fontId);
646 if (tempFontParam == nullptr) {
647 continue;
648 }
649 if (ttfId == tempFontParam->ttfId && size == tempFontParam->size) {
650 return fontId;
651 }
652 }
653 return fontId_;
654 #endif
655 }
656
InitSizeSpans()657 void Text::InitSizeSpans()
658 {
659 if (sizeSpans_ != nullptr) {
660 for (uint32_t i = 0 ; i < TypedText::GetUTF8CharacterSize(text_, GetTextStrLen()); i++) {
661 sizeSpans_[i].isSizeSpan = false;
662 sizeSpans_[i].height = 0;
663 }
664 }
665 }
666
GetNextCharacterFullDispalyOffset(const Rect & textRect,const Style & style,uint16_t beginIndex,uint16_t num)667 uint16_t Text::GetNextCharacterFullDispalyOffset(const Rect& textRect,
668 const Style& style, uint16_t beginIndex, uint16_t num)
669 {
670 return GetPosXByLetterIndex(textRect, style, beginIndex, num);
671 }
672 } // namespace OHOS
673