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