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