• 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