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