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