• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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