1 /* 2 * Copyright (c) 2024 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 "core/components_ng/pattern/text/span/span_string.h" 17 18 #include <cstdint> 19 #include <iterator> 20 #include <utility> 21 22 #include "base/utils/string_utils.h" 23 #include "base/utils/utils.h" 24 #include "core/components/common/properties/color.h" 25 #include "core/components_ng/pattern/text/span/span_object.h" 26 #include "core/components_ng/pattern/text/span_node.h" 27 #include "core/text/text_emoji_processor.h" 28 29 namespace OHOS::Ace { 30 31 const std::unordered_set<SpanType> specailTypes = { SpanType::Image, SpanType::CustomSpan }; 32 GetWideStringSubstr(const std::wstring & content,int32_t start,int32_t length)33 std::wstring SpanString::GetWideStringSubstr(const std::wstring& content, int32_t start, int32_t length) 34 { 35 if (start >= static_cast<int32_t>(content.length())) { 36 return StringUtils::ToWstring(""); 37 } 38 return content.substr(start, length); 39 } 40 GetWideStringSubstr(const std::wstring & content,int32_t start)41 std::wstring SpanString::GetWideStringSubstr(const std::wstring& content, int32_t start) 42 { 43 if (start >= static_cast<int32_t>(content.length())) { 44 return StringUtils::ToWstring(""); 45 } 46 return content.substr(start); 47 } 48 SpanString(const std::string & text)49 SpanString::SpanString(const std::string& text) 50 { 51 auto spanItem = MakeRefPtr<NG::SpanItem>(); 52 std::wstring wideText = StringUtils::ToWstring(text); 53 if (wideText.length() == 0 && text.length() != 0) { 54 text_ = TextEmojiProcessor::ConvertU8stringUnpairedSurrogates(text); 55 wideText = StringUtils::ToWstring(text_); 56 } else { 57 text_ = text; 58 } 59 spanItem->content = text_; 60 spanItem->interval = { 0, wideText.length() }; 61 spans_.emplace_back(spanItem); 62 auto it = spans_.begin(); 63 SplitSpansAndForward(it); 64 } 65 SpanString(const ImageSpanOptions & options)66 SpanString::SpanString(const ImageSpanOptions& options) : text_(" ") 67 { 68 auto spanItem = MakeRefPtr<NG::ImageSpanItem>(); 69 spanItem->options = options; 70 spanItem->content = " "; 71 spanItem->interval = { 0, 1 }; 72 spans_.emplace_back(spanItem); 73 spansMap_[SpanType::Image].emplace_back(MakeRefPtr<ImageSpan>(options)); 74 } 75 SpanString(RefPtr<CustomSpan> & span)76 SpanString::SpanString(RefPtr<CustomSpan>& span) : text_(" ") 77 { 78 auto spanItem = MakeRefPtr<NG::CustomSpanItem>(); 79 spanItem->content = " "; 80 spanItem->interval = { 0, 1 }; 81 spanItem->onMeasure = span->GetOnMeasure(); 82 spanItem->onDraw = span->GetOnDraw(); 83 spans_.emplace_back(spanItem); 84 spansMap_[SpanType::CustomSpan].emplace_back(span); 85 } 86 AddCustomSpan()87 void SpanString::AddCustomSpan() 88 { 89 auto spanBases = GetSpans(0, GetLength(), SpanType::CustomSpan); 90 for (const auto& spanBase : spanBases) { 91 if (spanBase->GetSpanType() != SpanType::CustomSpan) { 92 continue; 93 } 94 auto customSpan = DynamicCast<CustomSpan>(spanBase); 95 if (!customSpan) { 96 continue; 97 } 98 customSpan->AddStyledString(Referenced::WeakClaim(this)); 99 } 100 } 101 RemoveCustomSpan()102 void SpanString::RemoveCustomSpan() 103 { 104 auto spanBases = GetSpans(0, GetLength(), SpanType::CustomSpan); 105 for (const auto& spanBase : spanBases) { 106 if (spanBase->GetSpanType() != SpanType::CustomSpan) { 107 continue; 108 } 109 auto customSpan = DynamicCast<CustomSpan>(spanBase); 110 if (!customSpan) { 111 continue; 112 } 113 customSpan->RemoveStyledString(Referenced::WeakClaim(this)); 114 } 115 } SetFramNode(const WeakPtr<NG::FrameNode> & frameNode)116 void SpanString::SetFramNode(const WeakPtr<NG::FrameNode>& frameNode) 117 { 118 framNode_ = frameNode; 119 } 120 MarkDirtyFrameNode()121 void SpanString::MarkDirtyFrameNode() 122 { 123 auto frameNode = framNode_.Upgrade(); 124 CHECK_NULL_VOID(frameNode); 125 frameNode->MarkDirtyNode(NG::PROPERTY_UPDATE_RENDER); 126 } 127 ~SpanString()128 SpanString::~SpanString() 129 { 130 spansMap_.clear(); 131 spans_.clear(); 132 } 133 SplitSpansAndForward(std::list<RefPtr<NG::SpanItem>>::iterator & it)134 std::list<RefPtr<NG::SpanItem>>::iterator SpanString::SplitSpansAndForward( 135 std::list<RefPtr<NG::SpanItem>>::iterator& it) 136 { 137 auto wString = StringUtils::ToWstring((*it)->content); 138 auto newlineIndex = static_cast<int32_t>(wString.find(L'\n')); 139 int32_t offset = (*it)->interval.first; 140 while (newlineIndex != -1 && newlineIndex != static_cast<int32_t>(wString.size()) - 1) { 141 auto newSpan = (*it)->GetSameStyleSpanItem(); 142 newSpan->interval = { offset + newlineIndex + 1, (*it)->interval.second }; 143 (*it)->interval = { offset, offset + newlineIndex + 1 }; 144 (*it)->content = StringUtils::ToString(GetWideStringSubstr(wString, 0, newlineIndex + 1)); 145 wString = GetWideStringSubstr(wString, newlineIndex + 1); 146 newSpan->content = StringUtils::ToString(wString); 147 newlineIndex = static_cast<int32_t>(wString.find(L'\n')); 148 149 offset = newSpan->interval.first; 150 ++it; 151 it = spans_.insert(it, newSpan); 152 } 153 154 return std::next(it); 155 } 156 ApplyToSpans(const RefPtr<SpanBase> & span,std::pair<int32_t,int32_t> interval,SpanOperation operation)157 void SpanString::ApplyToSpans( 158 const RefPtr<SpanBase>& span, std::pair<int32_t, int32_t> interval, SpanOperation operation) 159 { 160 SetGroupId(span); 161 for (auto it = spans_.begin(); it != spans_.end(); ++it) { 162 auto intersection = (*it)->GetIntersectionInterval(interval); 163 if (!intersection) { 164 continue; 165 } 166 auto oldStart = (*it)->interval.first; 167 auto oldEnd = (*it)->interval.second; 168 if (oldStart == intersection->first && intersection->second == oldEnd) { 169 span->ApplyToSpanItem(*it, operation); 170 continue; 171 } 172 173 auto wContent = StringUtils::ToWstring((*it)->content); 174 auto newSpan = (*it)->GetSameStyleSpanItem(); 175 if (oldStart < intersection->first && intersection->second < oldEnd) { 176 (*it)->interval = { oldStart, intersection->first }; 177 (*it)->content = StringUtils::ToString(wContent.substr(0, intersection->first - oldStart)); 178 179 newSpan->interval = { intersection->first, intersection->second }; 180 newSpan->content = StringUtils::ToString( 181 wContent.substr(intersection->first - oldStart, intersection->second - intersection->first)); 182 span->ApplyToSpanItem(newSpan, operation); 183 184 auto newSpan2 = (*it)->GetSameStyleSpanItem(); 185 newSpan2->interval = { intersection->second, oldEnd }; 186 newSpan2->content = StringUtils::ToString(wContent.substr(intersection->second - oldStart)); 187 it = spans_.insert(std::next(it), newSpan); 188 it = spans_.insert(std::next(it), newSpan2); 189 continue; 190 } 191 192 if (oldEnd > intersection->second) { 193 (*it)->content = StringUtils::ToString(wContent.substr(0, intersection->second - oldStart)); 194 (*it)->interval = { oldStart, intersection->second }; 195 span->ApplyToSpanItem(*it, operation); 196 newSpan->interval = { intersection->second, oldEnd }; 197 newSpan->content = StringUtils::ToString(wContent.substr(intersection->second - oldStart)); 198 it = spans_.insert(std::next(it), newSpan); 199 continue; 200 } 201 202 if (intersection->first > oldStart) { 203 (*it)->content = StringUtils::ToString(wContent.substr(0, intersection->first - oldStart)); 204 (*it)->interval = { oldStart, intersection->first }; 205 newSpan->interval = { intersection->first, oldEnd }; 206 newSpan->content = StringUtils::ToString(wContent.substr(intersection->first - oldStart)); 207 span->ApplyToSpanItem(newSpan, operation); 208 it = spans_.insert(std::next(it), newSpan); 209 } 210 } 211 } 212 SplitInterval(std::list<RefPtr<SpanBase>> & spans,std::pair<int32_t,int32_t> interval)213 void SpanString::SplitInterval(std::list<RefPtr<SpanBase>>& spans, std::pair<int32_t, int32_t> interval) 214 { 215 std::list<RefPtr<SpanBase>> newSpans; 216 for (auto it = spans.begin(); it != spans.end();) { 217 auto intersection = (*it)->GetIntersectionInterval(interval); 218 if (!intersection) { 219 ++it; 220 continue; 221 } 222 auto oldStart = (*it)->GetStartIndex(); 223 auto oldEnd = (*it)->GetEndIndex(); 224 if (intersection->first == oldStart && intersection->second == oldEnd) { 225 it = spans.erase(it); 226 continue; 227 } 228 if (oldStart < intersection->first && intersection->second < oldEnd) { 229 newSpans.emplace_back((*it)->GetSubSpan(oldStart, intersection->first)); 230 newSpans.emplace_back((*it)->GetSubSpan(intersection->second, oldEnd)); 231 it = spans.erase(it); 232 continue; 233 } 234 if (oldEnd > intersection->second) { 235 (*it)->UpdateStartIndex(intersection->second); 236 ++it; 237 continue; 238 } 239 if (intersection->first > oldStart) { 240 (*it)->UpdateEndIndex(intersection->first); 241 ++it; 242 } 243 } 244 spans.merge(newSpans); 245 } 246 SortSpans(std::list<RefPtr<SpanBase>> & spans)247 void SpanString::SortSpans(std::list<RefPtr<SpanBase>>& spans) 248 { 249 spans.sort( 250 [](const RefPtr<SpanBase>& a, const RefPtr<SpanBase>& b) { return a->GetStartIndex() < b->GetStartIndex(); }); 251 } 252 CanMerge(const RefPtr<SpanBase> & a,const RefPtr<SpanBase> & b)253 bool SpanString::CanMerge(const RefPtr<SpanBase>& a, const RefPtr<SpanBase>& b) 254 { 255 return a->GetEndIndex() >= b->GetStartIndex() && a->IsAttributesEqual(b); 256 } 257 MergeIntervals(std::list<RefPtr<SpanBase>> & spans)258 void SpanString::MergeIntervals(std::list<RefPtr<SpanBase>>& spans) 259 { 260 auto it = spans.begin(); 261 while (it != spans.end()) { 262 auto spanType = (*it)->GetSpanType(); 263 if (spanType == SpanType::Image || spanType == SpanType::CustomSpan) { 264 return; 265 } 266 auto current = it++; 267 if (it != spans.end() && CanMerge(*current, *it)) { 268 (*current)->UpdateStartIndex(std::min((*current)->GetStartIndex(), (*it)->GetStartIndex())); 269 (*current)->UpdateEndIndex(std::max((*current)->GetEndIndex(), (*it)->GetEndIndex())); 270 spans.erase(it++); 271 if (it == spans.end()) { 272 break; 273 } 274 it = current; 275 } 276 } 277 } 278 GetStepsByPosition(int32_t pos)279 int32_t SpanString::GetStepsByPosition(int32_t pos) 280 { 281 if (pos == 0) { 282 return 0; 283 } 284 int32_t step = 0; 285 for (auto iter = spans_.begin(); iter != spans_.end(); ++iter) { 286 if ((*iter)->interval.first == pos) { 287 return step; 288 } 289 if ((*iter)->interval.first < pos && pos < (*iter)->interval.second) { 290 auto spanItem = (*iter)->GetSameStyleSpanItem(); 291 spanItem->interval.first = pos; 292 spanItem->interval.second = (*iter)->interval.second; 293 auto wStr = StringUtils::ToWstring(spanItem->content); 294 auto start = (*iter)->interval.first; 295 spanItem->content = StringUtils::ToString(wStr.substr(pos - start)); 296 spans_.insert(std::next(iter), spanItem); 297 (*iter)->interval.second = pos; 298 (*iter)->content = StringUtils::ToString(wStr.substr(0, pos - start)); 299 return step; 300 } 301 step++; 302 } 303 return step; 304 } 305 AddSpecialSpan(const RefPtr<SpanBase> & span,SpanType type,int32_t start)306 void SpanString::AddSpecialSpan(const RefPtr<SpanBase>& span, SpanType type, int32_t start) 307 { 308 auto wStr = GetWideString(); 309 text_ = StringUtils::ToString( 310 wStr.substr(0, start) + StringUtils::ToWstring(" ") + wStr.substr(start)); 311 auto iter = spans_.begin(); 312 auto step = GetStepsByPosition(start); 313 std::advance(iter, step); 314 RefPtr<NG::SpanItem> spanItem; 315 if (type == SpanType::Image) { 316 auto imageSpan = DynamicCast<ImageSpan>(span); 317 CHECK_NULL_VOID(imageSpan); 318 spanItem = MakeImageSpanItem(imageSpan); 319 } else if (type == SpanType::CustomSpan) { 320 auto customSpan = AceType::DynamicCast<CustomSpan>(span); 321 CHECK_NULL_VOID(customSpan); 322 spanItem = MakeCustomSpanItem(customSpan); 323 } 324 iter = spans_.insert(iter, spanItem); 325 for (++iter; iter != spans_.end(); ++iter) { 326 ++(*iter)->interval.first; 327 ++(*iter)->interval.second; 328 } 329 330 UpdateSpanMapWithOffset(start - 1, 1); 331 if (spansMap_.find(type) == spansMap_.end()) { 332 spansMap_[type].emplace_back(span); 333 } else { 334 auto specialList = spansMap_[type]; 335 int32_t step = 0; 336 for (const auto& specialSpan : specialList) { 337 if (specialSpan->GetStartIndex() >= start) { 338 break; 339 } 340 ++step; 341 } 342 auto iter = specialList.begin(); 343 std::advance(iter, step); 344 specialList.insert(iter, span); 345 spansMap_[type] = specialList; 346 } 347 } 348 MakeImageSpanItem(const RefPtr<ImageSpan> & imageSpan)349 RefPtr<NG::ImageSpanItem> SpanString::MakeImageSpanItem(const RefPtr<ImageSpan>& imageSpan) 350 { 351 auto spanItem = MakeRefPtr<NG::ImageSpanItem>(); 352 spanItem->content = " "; 353 spanItem->interval.first = imageSpan->GetStartIndex(); 354 spanItem->interval.second = imageSpan->GetEndIndex(); 355 spanItem->SetImageSpanOptions(imageSpan->GetImageSpanOptions()); 356 return spanItem; 357 } 358 MakeCustomSpanItem(const RefPtr<CustomSpan> & customSpan)359 RefPtr<NG::CustomSpanItem> SpanString::MakeCustomSpanItem(const RefPtr<CustomSpan>& customSpan) 360 { 361 auto spanItem = MakeRefPtr<NG::CustomSpanItem>(); 362 spanItem->content = " "; 363 spanItem->interval.first = customSpan->GetStartIndex(); 364 spanItem->interval.second = customSpan->GetEndIndex(); 365 spanItem->onDraw = customSpan->GetOnDraw(); 366 spanItem->onMeasure = customSpan->GetOnMeasure(); 367 return spanItem; 368 } 369 ChangeStartAndEndToCorrectNum(int32_t & start,int32_t & end)370 void SpanString::ChangeStartAndEndToCorrectNum(int32_t& start, int32_t& end) 371 { 372 auto text = GetWideString(); 373 TextEmojiSubStringRange range = TextEmojiProcessor::CalSubWstringRange( 374 start, end-start, text, true); 375 int startIndex = range.startIndex; 376 int endIndex = range.endIndex; 377 378 if (start == startIndex) { 379 ChangeStartToCorrectNum(start); 380 } else { 381 LOGI("SpanString: Get Emoji, Change Start %{public}d to %{public}d", 382 start, startIndex); 383 start = startIndex; 384 } 385 386 if (end == endIndex) { 387 ChangeEndToCorrectNum(end); 388 } else { 389 LOGI("SpanString: Get Emoji, Change End %{public}d to %{public}d", 390 end, endIndex); 391 end = endIndex; 392 } 393 394 if (end < start) { 395 std::swap(start, end); 396 } 397 } 398 ChangeStartToCorrectNum(int32_t & start)399 void SpanString::ChangeStartToCorrectNum(int32_t& start) 400 { 401 if (start == 0) { 402 return; 403 } 404 auto text = GetWideString(); 405 auto textLen = static_cast<int32_t>(text.length()); 406 if (textLen == 0) { 407 return; 408 } 409 auto tmpStart = start; 410 auto substr = StringUtils::ToString(GetWideStringSubstr(text, 0, tmpStart)); 411 while (substr.length() == 0) { 412 if (tmpStart == textLen) { 413 break; 414 } 415 tmpStart --; 416 if (tmpStart <= 0) { 417 break; 418 } 419 substr = StringUtils::ToString(GetWideStringSubstr(text, 0, tmpStart)); 420 } 421 if (tmpStart != start) { 422 LOGI("SpanString: Get Complex Char, Change Start %{public}d to %{public}d", start, tmpStart); 423 start = tmpStart; 424 } 425 } 426 ChangeEndToCorrectNum(int32_t & end)427 void SpanString::ChangeEndToCorrectNum(int32_t& end) 428 { 429 auto text = GetWideString(); 430 auto textLen = static_cast<int32_t>(text.length()); 431 if (textLen == 0) { 432 return; 433 } 434 auto tmpEnd = end; 435 auto substr = StringUtils::ToString(GetWideStringSubstr(text, end)); 436 while (substr.length() == 0) { 437 if (tmpEnd == textLen) { 438 break; 439 } 440 tmpEnd ++; 441 if (tmpEnd >= textLen) { 442 break; 443 } 444 substr = StringUtils::ToString(GetWideStringSubstr(text, tmpEnd)); 445 } 446 if (tmpEnd != end) { 447 LOGI("SpanString: Get Complex Char, Change End %{public}d to %{public}d", end, tmpEnd); 448 end = tmpEnd; 449 } 450 } 451 AddSpan(const RefPtr<SpanBase> & span)452 void SpanString::AddSpan(const RefPtr<SpanBase>& span) 453 { 454 if (!span || !CheckRange(span)) { 455 return; 456 } 457 auto start = span->GetStartIndex(); 458 auto end = span->GetEndIndex(); 459 ChangeStartAndEndToCorrectNum(start, end); 460 if (span->GetSpanType() == SpanType::Image || span->GetSpanType() == SpanType::CustomSpan) { 461 AddSpecialSpan(span, span->GetSpanType(), start); 462 return; 463 } 464 if (spansMap_.find(span->GetSpanType()) == spansMap_.end()) { 465 spansMap_[span->GetSpanType()].emplace_back(span); 466 ApplyToSpans(span, { start, end }, SpanOperation::ADD); 467 return; 468 } 469 RemoveSpan(start, end - start, span->GetSpanType()); 470 auto spans = spansMap_[span->GetSpanType()]; 471 ApplyToSpans(span, { start, end }, SpanOperation::ADD); 472 SplitInterval(spans, { start, end }); 473 spans.emplace_back(span); 474 SortSpans(spans); 475 MergeIntervals(spans); 476 spansMap_[span->GetSpanType()] = spans; 477 } 478 RemoveSpan(int32_t start,int32_t length,SpanType key)479 void SpanString::RemoveSpan(int32_t start, int32_t length, SpanType key) 480 { 481 if (!CheckRange(start, length)) { 482 return; 483 } 484 auto end = start + length; 485 ChangeStartAndEndToCorrectNum(start, end); 486 length = end - start; 487 auto it = spansMap_.find(key); 488 if (it == spansMap_.end()) { 489 return; 490 } 491 auto spans = spansMap_[key]; 492 if (key == SpanType::Image) { 493 RemoveSpecialSpan(start, end, key); 494 return; 495 } 496 if (key == SpanType::CustomSpan) { 497 RemoveSpecialSpan(start, end, key); 498 return; 499 } 500 auto defaultSpan = GetDefaultSpan(key); 501 CHECK_NULL_VOID(defaultSpan); 502 defaultSpan->UpdateStartIndex(start); 503 defaultSpan->UpdateEndIndex(end); 504 ApplyToSpans(defaultSpan, { start, end }, SpanOperation::REMOVE); 505 SplitInterval(spans, { start, end }); 506 SortSpans(spans); 507 MergeIntervals(spans); 508 if (spans.empty()) { 509 spansMap_.erase(key); 510 } else { 511 spansMap_[key] = spans; 512 } 513 } 514 GetDefaultSpan(SpanType type)515 RefPtr<SpanBase> SpanString::GetDefaultSpan(SpanType type) 516 { 517 switch (type) { 518 case SpanType::Font: 519 return MakeRefPtr<FontSpan>(); 520 case SpanType::TextShadow: 521 return MakeRefPtr<TextShadowSpan>(); 522 case SpanType::Gesture: 523 return MakeRefPtr<GestureSpan>(); 524 case SpanType::Decoration: 525 return MakeRefPtr<DecorationSpan>(); 526 case SpanType::BaselineOffset: 527 return MakeRefPtr<BaselineOffsetSpan>(); 528 case SpanType::LetterSpacing: 529 return MakeRefPtr<LetterSpacingSpan>(); 530 case SpanType::ParagraphStyle: 531 return MakeRefPtr<ParagraphStyleSpan>(); 532 case SpanType::LineHeight: 533 return MakeRefPtr<LineHeightSpan>(); 534 case SpanType::ExtSpan: 535 return MakeRefPtr<ExtSpan>(); 536 case SpanType::BackgroundColor: 537 return MakeRefPtr<BackgroundColorSpan>(); 538 case SpanType::Url: 539 return MakeRefPtr<UrlSpan>(); 540 default: 541 return nullptr; 542 } 543 } 544 CheckRange(const RefPtr<SpanBase> & spanBase) const545 bool SpanString::CheckRange(const RefPtr<SpanBase>& spanBase) const 546 { 547 auto start = spanBase->GetStartIndex(); 548 auto length = spanBase->GetLength(); 549 if (length <= 0) { 550 return false; 551 } 552 auto spanType = spanBase->GetSpanType(); 553 auto len = spanType == SpanType::Image || spanType == SpanType::CustomSpan ? GetLength() + 1 : GetLength(); 554 auto end = start + length; 555 556 if (start > len || end > len) { 557 return false; 558 } 559 560 if (start < 0) { 561 return false; 562 } 563 564 return true; 565 } 566 CheckRange(int32_t start,int32_t length,bool allowLengthZero) const567 bool SpanString::CheckRange(int32_t start, int32_t length, bool allowLengthZero) const 568 { 569 if (length < 0 || (length == 0 && !allowLengthZero)) { 570 return false; 571 } 572 573 auto len = GetLength(); 574 auto end = start + length; 575 576 if (start > len || end > len) { 577 return false; 578 } 579 580 if (start < 0) { 581 return false; 582 } 583 584 return true; 585 } 586 GetDefaultSpanItem(const std::string & text)587 RefPtr<NG::SpanItem> SpanString::GetDefaultSpanItem(const std::string& text) 588 { 589 auto spanItem = MakeRefPtr<NG::SpanItem>(); 590 spanItem->content = text; 591 spanItem->interval = { 0, StringUtils::ToWstring(text).length() }; 592 return spanItem; 593 } 594 SetString(const std::string & text)595 void SpanString::SetString(const std::string& text) 596 { 597 text_ = text; 598 } 599 SetGroupId(const RefPtr<SpanBase> & span)600 void SpanString::SetGroupId(const RefPtr<SpanBase>& span) 601 { 602 if (span->GetSpanType() == SpanType::BackgroundColor) { 603 auto backgroundColorSpan = DynamicCast<BackgroundColorSpan>(span); 604 CHECK_NULL_VOID(backgroundColorSpan); 605 backgroundColorSpan->SetBackgroundColorGroupId(groupId_++); 606 } 607 } SetSpanItems(const std::list<RefPtr<NG::SpanItem>> && spanItems)608 void SpanString::SetSpanItems(const std::list<RefPtr<NG::SpanItem>>&& spanItems) 609 { 610 spans_ = spanItems; 611 } 612 SetSpanMap(std::unordered_map<SpanType,std::list<RefPtr<SpanBase>>> && spansMap)613 void SpanString::SetSpanMap(std::unordered_map<SpanType, std::list<RefPtr<SpanBase>>>&& spansMap) 614 { 615 spansMap_ = spansMap; 616 } 617 GetString() const618 const std::string& SpanString::GetString() const 619 { 620 return text_; 621 } 622 GetWideString()623 std::wstring SpanString::GetWideString() 624 { 625 return StringUtils::ToWstring(text_); 626 } 627 GetLength() const628 int32_t SpanString::GetLength() const 629 { 630 return StringUtils::ToWstring(text_).length(); 631 } 632 IsEqualToSpanString(const RefPtr<SpanString> & other) const633 bool SpanString::IsEqualToSpanString(const RefPtr<SpanString>& other) const 634 { 635 return *this == *other; 636 } 637 GetSubSpanString(int32_t start,int32_t length) const638 RefPtr<SpanString> SpanString::GetSubSpanString(int32_t start, int32_t length) const 639 { 640 if (!CheckRange(start, length)) { 641 RefPtr<SpanString> span = AceType::MakeRefPtr<SpanString>(""); 642 return span; 643 } 644 int32_t end = start + length; 645 RefPtr<SpanString> span = 646 AceType::MakeRefPtr<SpanString>(StringUtils::ToString(StringUtils::ToWstring(text_).substr(start, length))); 647 std::unordered_map<SpanType, std::list<RefPtr<SpanBase>>> subMap; 648 for (const auto& map : spansMap_) { 649 auto subList = GetSubSpanList(start, length, map.second); 650 if (!subList.empty()) { 651 subMap.insert({ map.first, subList }); 652 } 653 } 654 span->spansMap_ = subMap; 655 656 std::list<RefPtr<NG::SpanItem>> subSpans_; 657 for (const auto& spanItem : spans_) { 658 auto intersection = spanItem->GetIntersectionInterval({start, start+length}); 659 if (intersection) { 660 int32_t oldStart = spanItem->interval.first; 661 int32_t oldEnd = spanItem->interval.second; 662 auto spanStart = oldStart <= start ? 0 : oldStart - start; 663 auto spanEnd = oldEnd < end ? oldEnd - start : end - start; 664 auto newSpanItem = spanItem->GetSameStyleSpanItem(); 665 newSpanItem->interval = { spanStart, spanEnd }; 666 newSpanItem->content = StringUtils::ToString( 667 StringUtils::ToWstring(spanItem->content) 668 .substr(std::max(start - oldStart, 0), std::min(end, oldEnd) - std::max(start, oldStart))); 669 subSpans_.emplace_back(newSpanItem); 670 } 671 } 672 span->spans_ = subSpans_; 673 return span; 674 } 675 GetSubSpanList(int32_t start,int32_t length,const std::list<RefPtr<SpanBase>> & spans) const676 std::list<RefPtr<SpanBase>> SpanString::GetSubSpanList( 677 int32_t start, int32_t length, const std::list<RefPtr<SpanBase>>& spans) const 678 { 679 std::list<RefPtr<SpanBase>> res; 680 int32_t end = start + length; 681 for (auto& span : spans) { 682 auto intersection = span->GetIntersectionInterval({ start, end }); 683 if (intersection) { 684 int32_t spanStart = span->GetStartIndex(); 685 int32_t spanEnd = span->GetEndIndex(); 686 spanStart = spanStart <= start ? 0 : spanStart - start; 687 spanEnd = spanEnd < end ? spanEnd - start : end - start; 688 if (spanStart == spanEnd) { 689 continue; 690 } 691 res.emplace_back(span->GetSubSpan(spanStart, spanEnd)); 692 } 693 } 694 return res; 695 } 696 GetSpansMap() const697 const std::unordered_map<SpanType, std::list<RefPtr<SpanBase>>>& SpanString::GetSpansMap() const 698 { 699 return spansMap_; 700 } 701 GetSpans(int32_t start,int32_t length) const702 std::vector<RefPtr<SpanBase>> SpanString::GetSpans(int32_t start, int32_t length) const 703 { 704 std::vector<RefPtr<SpanBase>> res; 705 if (!CheckRange(start, length)) { 706 return res; 707 } 708 709 for (const auto& map : spansMap_) { 710 auto spans = GetSpans(start, length, map.first); 711 res.insert(res.begin(), spans.begin(), spans.end()); 712 } 713 return res; 714 } 715 GetSpans(int32_t start,int32_t length,SpanType spanType) const716 std::vector<RefPtr<SpanBase>> SpanString::GetSpans(int32_t start, int32_t length, SpanType spanType) const 717 { 718 std::vector<RefPtr<SpanBase>> res; 719 if (!CheckRange(start, length)) { 720 return res; 721 } 722 int32_t end = start + length; 723 RefPtr<SpanBase> span; 724 while ((span = GetSpan(start, length, spanType)) != nullptr) { 725 res.emplace_back(span); 726 start = span->GetEndIndex(); 727 length = end - start; 728 } 729 return res; 730 } 731 GetSpan(int32_t start,int32_t length,SpanType spanType) const732 RefPtr<SpanBase> SpanString::GetSpan(int32_t start, int32_t length, SpanType spanType) const 733 { 734 if (!CheckRange(start, length) || spansMap_.find(spanType) == spansMap_.end()) { 735 return nullptr; 736 } 737 int32_t end = start + length; 738 auto spanBaseList = spansMap_.find(spanType)->second; 739 for (auto& spanBase : spanBaseList) { 740 auto intersection = spanBase->GetIntersectionInterval({ start, end }); 741 if (intersection) { 742 int32_t newStart = intersection->first; 743 int32_t newEnd = intersection->second; 744 if (newStart == newEnd) { 745 continue; 746 } 747 return spanBase->GetSubSpan(newStart, newEnd); 748 } 749 } 750 return nullptr; 751 } 752 operator ==(const SpanString & other) const753 bool SpanString::operator==(const SpanString& other) const 754 { 755 if (text_ != other.text_) { 756 return false; 757 } 758 auto size = 759 !spansMap_.empty() 760 ? (static_cast<int32_t>(spansMap_.size()) - (spansMap_.find(SpanType::Gesture) == spansMap_.end() ? 0 : 1)) 761 : 0; 762 auto sizeOther = !other.spansMap_.empty() 763 ? (static_cast<int32_t>(other.spansMap_.size()) - 764 (other.spansMap_.find(SpanType::Gesture) == other.spansMap_.end() ? 0 : 1)) 765 : 0; 766 if (size != sizeOther) { 767 return false; 768 } 769 770 for (const auto& map : spansMap_) { 771 if (map.first == SpanType::Gesture) { 772 continue; 773 } 774 auto spansOtherMap = other.spansMap_.find(map.first); 775 if (spansOtherMap == other.spansMap_.end()) { 776 return false; 777 } 778 auto spans = map.second; 779 auto spansOther = spansOtherMap->second; 780 if (spans.size() != spansOther.size()) { 781 return false; 782 } 783 for (auto spansItr = spans.begin(), spansOtherItr = spansOther.begin(); 784 spansItr != spans.end() && spansOtherItr != spansOther.end(); ++spansItr, ++spansOtherItr) { 785 if (!(*spansItr)->IsAttributesEqual(*spansOtherItr) || 786 (*spansItr)->GetEndIndex() != (*spansOtherItr)->GetEndIndex() || 787 (*spansItr)->GetStartIndex() != (*spansOtherItr)->GetStartIndex()) { 788 return false; 789 } 790 } 791 } 792 return true; 793 } 794 GetSpanItems() const795 std::list<RefPtr<NG::SpanItem>> SpanString::GetSpanItems() const 796 { 797 return spans_; 798 } 799 BindWithSpans(const std::vector<RefPtr<SpanBase>> & spans)800 void SpanString::BindWithSpans(const std::vector<RefPtr<SpanBase>>& spans) 801 { 802 for (auto& span : spans) { 803 AddSpan(span); 804 } 805 } 806 UpdateSpansWithOffset(int32_t start,int32_t offset)807 void SpanString::UpdateSpansWithOffset(int32_t start, int32_t offset) 808 { 809 for (auto& span : spans_) { 810 if (span->interval.second > start && span->interval.first != start) { 811 span->interval.second += offset; 812 } 813 if (span->interval.first > start) { 814 span->interval.first += offset; 815 } 816 } 817 } 818 UpdateSpanMapWithOffset(int32_t start,int32_t offset)819 void SpanString::UpdateSpanMapWithOffset(int32_t start, int32_t offset) 820 { 821 for (auto& iter : spansMap_) { 822 if (spansMap_.find(iter.first) == spansMap_.end()) { 823 continue; 824 } 825 auto spans = spansMap_[iter.first]; 826 for (auto& it : spans) { 827 UpdateSpanBaseWithOffset(it, start, offset); 828 } 829 spansMap_[iter.first] = spans; 830 } 831 } 832 UpdateSpanBaseWithOffset(RefPtr<SpanBase> & span,int32_t start,int32_t offset)833 void SpanString::UpdateSpanBaseWithOffset(RefPtr<SpanBase>& span, int32_t start, int32_t offset) 834 { 835 if (span->GetEndIndex() > start && span->GetStartIndex() != start) { 836 span->UpdateEndIndex(span->GetEndIndex() + offset); 837 } 838 if (span->GetStartIndex() > start) { 839 span->UpdateStartIndex(span->GetStartIndex() + offset); 840 } 841 } 842 RemoveSpecialSpan(int32_t start,int32_t end,SpanType type)843 void SpanString::RemoveSpecialSpan(int32_t start, int32_t end, SpanType type) 844 { 845 auto spans = spansMap_[type]; 846 int32_t count = 0; 847 for (auto iter = spans.begin(); iter != spans.end();) { 848 if ((*iter)->GetStartIndex() >= start && (*iter)->GetStartIndex() < end - count) { 849 auto wStr = GetWideString(); 850 wStr.erase((*iter)->GetStartIndex(), 1); 851 text_ = StringUtils::ToString(wStr); 852 UpdateSpanMapWithOffset((*iter)->GetStartIndex(), -1); 853 iter = spans.erase(iter); 854 ++count; 855 continue; 856 } 857 ++iter; 858 } 859 if (spans.empty()) { 860 spansMap_.erase(type); 861 } else { 862 spansMap_[type] = spans; 863 } 864 count = 0; 865 for (auto iter = spans_.begin(); iter != spans_.end();) { 866 if ((*iter)->interval.first >= start && (*iter)->interval.first < end - count 867 && ((type == SpanType::Image && (*iter)->spanItemType == NG::SpanItemType::IMAGE) 868 || (type == SpanType::CustomSpan && (*iter)->spanItemType == NG::SpanItemType::CustomSpan))) { 869 UpdateSpansWithOffset((*iter)->interval.first, -1); 870 iter = spans_.erase(iter); 871 ++count; 872 continue; 873 } 874 ++iter; 875 } 876 } 877 GetSpecialTypesVector(std::list<int32_t> & indexList,int32_t start,int32_t length)878 void SpanString::GetSpecialTypesVector(std::list<int32_t>& indexList, int32_t start, int32_t length) 879 { 880 int32_t end = start + length; 881 auto iter = indexList.begin(); 882 for (const auto& type : specailTypes) { 883 auto spans = spansMap_[type]; 884 for (const auto& span : spans) { 885 auto intersection = span->GetIntersectionInterval({ start, end }); 886 if (!intersection) { 887 continue; 888 } 889 iter = indexList.insert(iter, span->GetStartIndex()); 890 } 891 } 892 indexList.sort([](const int32_t& a, const int32_t& b) { return a < b; }); 893 } 894 GetNormalTypesVector(std::list<std::pair<int32_t,int32_t>> & indexList,int32_t start,int32_t length)895 void SpanString::GetNormalTypesVector(std::list<std::pair<int32_t, int32_t>>& indexList, int32_t start, int32_t length) 896 { 897 std::list<int32_t> specialList; 898 GetSpecialTypesVector(specialList, start, length); 899 auto next = start; 900 auto iter = indexList.begin(); 901 for (const auto& index : specialList) { 902 if (index > next) { 903 iter = indexList.insert(iter, { next, index - next }); 904 } 905 next = index + 1; 906 } 907 if (next < start + length) { 908 indexList.insert(iter, { next, start + length - next }); 909 } 910 } 911 ContainSpecialNode(int32_t start,int32_t length)912 bool SpanString::ContainSpecialNode(int32_t start, int32_t length) 913 { 914 int32_t end = start + length; 915 for (const auto& type : specailTypes) { 916 auto spans = spansMap_[type]; 917 for (const auto& span : spans) { 918 auto intersection = span->GetIntersectionInterval({ start, end }); 919 if (intersection) { 920 return true; 921 } 922 if (span->GetStartIndex() >= end) { 923 break; 924 } 925 } 926 } 927 return false; 928 } 929 IsSpecialNode(RefPtr<SpanBase> span)930 bool SpanString::IsSpecialNode(RefPtr<SpanBase> span) 931 { 932 auto type = span->GetSpanType(); 933 if (specailTypes.find(type) == specailTypes.end()) { 934 return false; 935 } 936 return true; 937 } 938 ClearSpans()939 void SpanString::ClearSpans() 940 { 941 spans_.clear(); 942 } 943 AppendSpanItem(const RefPtr<NG::SpanItem> & spanItem)944 void SpanString::AppendSpanItem(const RefPtr<NG::SpanItem>& spanItem) 945 { 946 spans_.emplace_back(spanItem); 947 } 948 EncodeTlv(std::vector<uint8_t> & buff)949 bool SpanString::EncodeTlv(std::vector<uint8_t>& buff) 950 { 951 TLVUtil::WriteUint8(buff, TLV_SPAN_STRING_SPANS); 952 TLVUtil::WriteInt32(buff, spans_.size()); 953 for (auto it = spans_.begin(); it != spans_.end(); ++it) { 954 auto spanItem = (*it); 955 if (spanItem->spanItemType == NG::SpanItemType::CustomSpan) { 956 TLVUtil::WriteInt32(buff, static_cast<int32_t>(NG::SpanItemType::NORMAL)); 957 auto placeHolderSpan = AceType::MakeRefPtr<NG::SpanItem>(); 958 placeHolderSpan->content = " "; 959 placeHolderSpan->interval = spanItem->interval; 960 placeHolderSpan->EncodeTlv(buff); 961 continue; 962 } 963 TLVUtil::WriteInt32(buff, static_cast<int32_t>(spanItem->spanItemType)); 964 spanItem->EncodeTlv(buff); 965 } 966 TLVUtil::WriteUint8(buff, TLV_SPAN_STRING_CONTENT); 967 TLVUtil::WriteString(buff, text_); 968 TLVUtil::WriteUint8(buff, TLV_END); 969 return true; 970 } 971 DecodeTlv(std::vector<uint8_t> & buff)972 RefPtr<SpanString> SpanString::DecodeTlv(std::vector<uint8_t>& buff) 973 { 974 RefPtr<SpanString> spanStr = MakeRefPtr<SpanString>(""); 975 SpanString* spanString = spanStr.GetRawPtr(); 976 DecodeTlvExt(buff, spanString); 977 return spanStr; 978 } 979 DecodeTlvExt(std::vector<uint8_t> & buff,SpanString * spanString)980 void SpanString::DecodeTlvExt(std::vector<uint8_t>& buff, SpanString* spanString) 981 { 982 CHECK_NULL_VOID(spanString); 983 spanString->ClearSpans(); 984 int32_t cursor = 0; 985 for (uint8_t tag = TLVUtil::ReadUint8(buff, cursor); tag != TLV_END; tag = TLVUtil::ReadUint8(buff, cursor)) { 986 switch (tag) { 987 case TLV_SPAN_STRING_CONTENT: { 988 auto str = TLVUtil::ReadString(buff, cursor); 989 spanString->SetString(str); 990 break; 991 } 992 case TLV_SPAN_STRING_SPANS: { 993 DecodeSpanItemListExt(buff, cursor, spanString); 994 break; 995 } 996 default: 997 break; 998 } 999 } 1000 } 1001 DecodeSpanItemListExt(std::vector<uint8_t> & buff,int32_t & cursor,SpanString * spanStr)1002 void SpanString::DecodeSpanItemListExt(std::vector<uint8_t>& buff, int32_t& cursor, SpanString* spanStr) 1003 { 1004 CHECK_NULL_VOID(spanStr); 1005 int32_t spanLength = TLVUtil::ReadInt32(buff, cursor); 1006 for (auto i = 0; i < spanLength; i++) { 1007 auto spanItemType = TLVUtil::ReadInt32(buff, cursor); 1008 if (spanItemType == static_cast<int32_t>(NG::SpanItemType::IMAGE)) { 1009 auto imageSpanItem = NG::ImageSpanItem::DecodeTlv(buff, cursor); 1010 spanStr->AppendSpanItem(imageSpanItem); 1011 } else { 1012 auto spanItem = NG::SpanItem::DecodeTlv(buff, cursor); 1013 spanStr->AppendSpanItem(spanItem); 1014 } 1015 } 1016 spanStr->UpdateSpansMap(); 1017 } 1018 DecodeSpanItemList(std::vector<uint8_t> & buff,int32_t & cursor,RefPtr<SpanString> & spanStr)1019 void SpanString::DecodeSpanItemList(std::vector<uint8_t>& buff, int32_t& cursor, RefPtr<SpanString>& spanStr) 1020 { 1021 CHECK_NULL_VOID(spanStr); 1022 DecodeSpanItemListExt(buff, cursor, spanStr.GetRawPtr()); 1023 } 1024 UpdateSpansMap()1025 void SpanString::UpdateSpansMap() 1026 { 1027 spansMap_.clear(); 1028 for (auto& spanItem : spans_) { 1029 if (!spanItem) { 1030 continue; 1031 } 1032 auto start = spanItem->interval.first; 1033 auto end = spanItem->interval.second; 1034 std::list<RefPtr<SpanBase>> spanBases; 1035 if (spanItem->spanItemType == NG::SpanItemType::IMAGE) { 1036 spanBases = { ToImageSpan(spanItem, start, end) }; 1037 } else if (spanItem->spanItemType == NG::SpanItemType::NORMAL) 1038 spanBases = { ToFontSpan(spanItem, start, end), 1039 ToDecorationSpan(spanItem, start, end), 1040 ToBaselineOffsetSpan(spanItem, start, end), 1041 ToLetterSpacingSpan(spanItem, start, end), 1042 ToGestureSpan(spanItem, start, end), 1043 ToParagraphStyleSpan(spanItem, start, end), 1044 ToLineHeightSpan(spanItem, start, end) }; 1045 for (auto& spanBase : spanBases) { 1046 if (!spanBase) { 1047 continue; 1048 } 1049 auto it = spansMap_.find(spanBase->GetSpanType()); 1050 if (it == spansMap_.end()) { 1051 spansMap_.insert({ spanBase->GetSpanType(), { spanBase } }); 1052 } else { 1053 it->second.emplace_back(std::move(spanBase)); 1054 } 1055 } 1056 } 1057 } 1058 ToFontSpan(const RefPtr<NG::SpanItem> & spanItem,int32_t start,int32_t end)1059 RefPtr<FontSpan> SpanString::ToFontSpan(const RefPtr<NG::SpanItem>& spanItem, int32_t start, int32_t end) 1060 { 1061 CHECK_NULL_RETURN(spanItem && spanItem->fontStyle, nullptr); 1062 Font font; 1063 font.fontColor = spanItem->fontStyle->GetTextColor(); 1064 font.fontFamiliesNG = spanItem->fontStyle->GetFontFamily(); 1065 font.fontSize = spanItem->fontStyle->GetFontSize(); 1066 font.fontStyle = spanItem->fontStyle->GetItalicFontStyle(); 1067 font.fontWeight = spanItem->fontStyle->GetFontWeight(); 1068 return AceType::MakeRefPtr<FontSpan>(font, start, end); 1069 } 1070 ToDecorationSpan(const RefPtr<NG::SpanItem> & spanItem,int32_t start,int32_t end)1071 RefPtr<DecorationSpan> SpanString::ToDecorationSpan( 1072 const RefPtr<NG::SpanItem>& spanItem, int32_t start, int32_t end) 1073 { 1074 CHECK_NULL_RETURN(spanItem && spanItem->fontStyle, nullptr); 1075 TextDecoration type = spanItem->fontStyle->GetTextDecoration().value_or(TextDecoration::NONE); 1076 std::optional<Color> color = spanItem->fontStyle->GetTextDecorationColor(); 1077 std::optional<TextDecorationStyle> style = spanItem->fontStyle->GetTextDecorationStyle(); 1078 return AceType::MakeRefPtr<DecorationSpan>(type, color, style, start, end); 1079 } 1080 ToBaselineOffsetSpan(const RefPtr<NG::SpanItem> & spanItem,int32_t start,int32_t end)1081 RefPtr<BaselineOffsetSpan> SpanString::ToBaselineOffsetSpan( 1082 const RefPtr<NG::SpanItem>& spanItem, int32_t start, int32_t end) 1083 { 1084 CHECK_NULL_RETURN(spanItem && spanItem->textLineStyle, nullptr); 1085 Dimension baselineOffset; 1086 if (spanItem->textLineStyle->GetBaselineOffset().has_value()) { 1087 baselineOffset.SetValue(spanItem->textLineStyle->GetBaselineOffsetValue().ConvertToVp()); 1088 } 1089 return AceType::MakeRefPtr<BaselineOffsetSpan>(baselineOffset, start, end); 1090 } 1091 ToLetterSpacingSpan(const RefPtr<NG::SpanItem> & spanItem,int32_t start,int32_t end)1092 RefPtr<LetterSpacingSpan> SpanString::ToLetterSpacingSpan( 1093 const RefPtr<NG::SpanItem>& spanItem, int32_t start, int32_t end) 1094 { 1095 CHECK_NULL_RETURN(spanItem && spanItem->fontStyle, nullptr); 1096 Dimension letterSpacing; 1097 if (spanItem->fontStyle->GetLetterSpacing().has_value()) { 1098 letterSpacing.SetValue(spanItem->fontStyle->GetLetterSpacingValue().ConvertToVp()); 1099 } 1100 return AceType::MakeRefPtr<LetterSpacingSpan>(letterSpacing, start, end); 1101 } 1102 ToGestureSpan(const RefPtr<NG::SpanItem> & spanItem,int32_t start,int32_t end)1103 RefPtr<GestureSpan> SpanString::ToGestureSpan(const RefPtr<NG::SpanItem>& spanItem, int32_t start, int32_t end) 1104 { 1105 GestureStyle gestureInfo; 1106 if (spanItem->onClick) { 1107 gestureInfo.onClick = spanItem->onClick; 1108 } 1109 if (spanItem->onLongPress) { 1110 gestureInfo.onLongPress = spanItem->onLongPress; 1111 } 1112 return AceType::MakeRefPtr<GestureSpan>(gestureInfo, start, end); 1113 } 1114 ToTextShadowSpan(const RefPtr<NG::SpanItem> & spanItem,int32_t start,int32_t end)1115 RefPtr<TextShadowSpan> SpanString::ToTextShadowSpan( 1116 const RefPtr<NG::SpanItem>& spanItem, int32_t start, int32_t end) 1117 { 1118 CHECK_NULL_RETURN(spanItem && spanItem->fontStyle, nullptr); 1119 std::vector<Shadow> textShadow = spanItem->fontStyle->GetTextShadow().value_or(std::vector<Shadow> { Shadow() }); 1120 return AceType::MakeRefPtr<TextShadowSpan>(textShadow, start, end); 1121 } 1122 ToImageSpan(const RefPtr<NG::SpanItem> & spanItem,int32_t start,int32_t end)1123 RefPtr<ImageSpan> SpanString::ToImageSpan(const RefPtr<NG::SpanItem>& spanItem, int32_t start, int32_t end) 1124 { 1125 auto imageItem = DynamicCast<NG::ImageSpanItem>(spanItem); 1126 CHECK_NULL_RETURN(imageItem && start + 1 == end, nullptr); 1127 return AceType::MakeRefPtr<ImageSpan>(imageItem->options, start); 1128 } 1129 ToParagraphStyleSpan(const RefPtr<NG::SpanItem> & spanItem,int32_t start,int32_t end)1130 RefPtr<ParagraphStyleSpan> SpanString::ToParagraphStyleSpan( 1131 const RefPtr<NG::SpanItem>& spanItem, int32_t start, int32_t end) 1132 { 1133 CHECK_NULL_RETURN(spanItem && spanItem->textLineStyle, nullptr); 1134 SpanParagraphStyle paragraphStyle; 1135 paragraphStyle.align = spanItem->textLineStyle->GetTextAlign(); 1136 paragraphStyle.maxLines = spanItem->textLineStyle->GetMaxLines(); 1137 paragraphStyle.textOverflow = spanItem->textLineStyle->GetTextOverflow(); 1138 paragraphStyle.leadingMargin = spanItem->textLineStyle->GetLeadingMargin(); 1139 paragraphStyle.wordBreak = spanItem->textLineStyle->GetWordBreak(); 1140 paragraphStyle.textIndent = spanItem->textLineStyle->GetTextIndent(); 1141 return AceType::MakeRefPtr<ParagraphStyleSpan>(paragraphStyle, start, end); 1142 } 1143 ToLineHeightSpan(const RefPtr<NG::SpanItem> & spanItem,int32_t start,int32_t end)1144 RefPtr<LineHeightSpan> SpanString::ToLineHeightSpan(const RefPtr<NG::SpanItem>& spanItem, int32_t start, int32_t end) 1145 { 1146 CHECK_NULL_RETURN(spanItem && spanItem->textLineStyle, nullptr); 1147 Dimension lineHeight; 1148 if (spanItem->textLineStyle->GetLineHeight().has_value()) { 1149 lineHeight.SetValue(spanItem->textLineStyle->GetLineHeightValue().ConvertToVp()); 1150 } 1151 return AceType::MakeRefPtr<LineHeightSpan>(lineHeight, start, end); 1152 } 1153 } // namespace OHOS::Ace 1154