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