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