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