• 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 #include "core/components_ng/pattern/text/span/span_object.h"
16 
17 namespace OHOS::Ace {
18 namespace {
19 static std::atomic<int32_t> gGestureSpanId = 0;
20 constexpr int32_t GESTURES_SPAN_DIVIDE_SIZE = 10000000;
21 }
22 
23 // SpanBase
GetIntersectionInterval(std::pair<int32_t,int32_t> interval) const24 std::optional<std::pair<int32_t, int32_t>> SpanBase::GetIntersectionInterval(std::pair<int32_t, int32_t> interval) const
25 {
26     // 检查相交情况
27     if (end_ <= interval.first || interval.second <= start_) {
28         return std::nullopt;
29     }
30 
31     // 计算相交区间
32     int start = std::max(start_, interval.first);
33     int end = std::min(end_, interval.second);
34     return std::make_optional<std::pair<int32_t, int32_t>>(std::make_pair(start, end));
35 }
36 
GetStartIndex() const37 int32_t SpanBase::GetStartIndex() const
38 {
39     return start_;
40 }
41 
GetEndIndex() const42 int32_t SpanBase::GetEndIndex() const
43 {
44     return end_;
45 }
UpdateStartIndex(int32_t startIndex)46 void SpanBase::UpdateStartIndex(int32_t startIndex)
47 {
48     start_ = startIndex;
49 }
50 
UpdateEndIndex(int32_t endIndex)51 void SpanBase::UpdateEndIndex(int32_t endIndex)
52 {
53     end_ = endIndex;
54 }
55 
GetLength() const56 int32_t SpanBase::GetLength() const
57 {
58     return end_ - start_;
59 }
60 
61 // FontSpan
FontSpan(Font font)62 FontSpan::FontSpan(Font font) : SpanBase(0, 0), font_(std::move(font)) {}
63 
FontSpan(Font font,int32_t start,int32_t end)64 FontSpan::FontSpan(Font font, int32_t start, int32_t end) : SpanBase(start, end), font_(std::move(font)) {}
65 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const66 void FontSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
67 {
68     switch (operation) {
69         case SpanOperation::ADD:
70             AddSpanStyle(spanItem);
71             break;
72         case SpanOperation::REMOVE:
73             RemoveSpanStyle(spanItem);
74     }
75 }
76 
GetSubSpan(int32_t start,int32_t end)77 RefPtr<SpanBase> FontSpan::GetSubSpan(int32_t start, int32_t end)
78 {
79     RefPtr<SpanBase> spanBase = MakeRefPtr<FontSpan>(font_, start, end);
80     return spanBase;
81 }
82 
AddSpanStyle(const RefPtr<NG::SpanItem> & spanItem) const83 void FontSpan::AddSpanStyle(const RefPtr<NG::SpanItem>& spanItem) const
84 {
85     if (!spanItem || !spanItem->fontStyle) {
86         return;
87     }
88     if (font_.fontColor.has_value()) {
89         spanItem->fontStyle->UpdateTextColor(font_.fontColor.value());
90     }
91 
92     if (font_.fontFamiliesNG.has_value()) {
93         spanItem->fontStyle->UpdateFontFamily(font_.fontFamiliesNG.value());
94     }
95 
96     if (font_.fontSize.has_value()) {
97         spanItem->fontStyle->UpdateFontSize(font_.fontSize.value());
98     }
99 
100     if (font_.fontStyle.has_value()) {
101         spanItem->fontStyle->UpdateItalicFontStyle(font_.fontStyle.value());
102     }
103 
104     if (font_.fontWeight.has_value()) {
105         spanItem->fontStyle->UpdateFontWeight(font_.fontWeight.value());
106     }
107 
108     if (font_.strokeWidth.has_value()) {
109         spanItem->fontStyle->UpdateStrokeWidth(font_.strokeWidth.value());
110     }
111 
112     if (font_.strokeColor.has_value()) {
113         spanItem->fontStyle->UpdateStrokeColor(font_.strokeColor.value());
114     }
115 
116     if (font_.superscript.has_value()) {
117         spanItem->fontStyle->UpdateSuperscript(font_.superscript.value());
118     }
119 }
120 
RemoveSpanStyle(const RefPtr<NG::SpanItem> & spanItem)121 void FontSpan::RemoveSpanStyle(const RefPtr<NG::SpanItem>& spanItem)
122 {
123     spanItem->fontStyle->ResetTextColor();
124     spanItem->fontStyle->ResetFontFamily();
125     spanItem->fontStyle->ResetFontSize();
126     spanItem->fontStyle->ResetItalicFontStyle();
127     spanItem->fontStyle->ResetFontWeight();
128     spanItem->fontStyle->ResetStrokeWidth();
129     spanItem->fontStyle->ResetStrokeColor();
130     spanItem->fontStyle->ResetSuperscript();
131 }
132 
GetFont() const133 Font FontSpan::GetFont() const
134 {
135     return font_;
136 }
137 
GetSpanType() const138 SpanType FontSpan::GetSpanType() const
139 {
140     return SpanType::Font;
141 }
142 
ToString() const143 std::string FontSpan::ToString() const
144 {
145     std::stringstream ss;
146     ss << "FontSpan [";
147     ss << GetStartIndex();
148     ss << ":";
149     ss << GetEndIndex();
150     ss << "]";
151     if (font_.fontColor.has_value()) {
152         ss << " FontColor:" << font_.fontColor.value().ColorToString();
153     }
154     if (font_.fontFamiliesNG.has_value()) {
155         ss << " FontFamily:";
156         for (auto& fontFam : font_.fontFamiliesNG.value()) {
157             ss << fontFam;
158         }
159     }
160     if (font_.fontSize.has_value()) {
161         ss << " FontSize:" << font_.fontSize.value().ToString();
162     }
163     if (font_.fontStyle.has_value()) {
164         ss << " FontStyle:" << static_cast<int32_t>(font_.fontStyle.value());
165     }
166     if (font_.fontWeight.has_value()) {
167         ss << " FontWeight:" << static_cast<int32_t>(font_.fontWeight.value());
168     }
169     if (font_.strokeWidth.has_value()) {
170         ss << " StrokeWidth:" << font_.strokeWidth.value().ToString();
171     }
172     if (font_.strokeColor.has_value()) {
173         ss << " StrokeColor:" << font_.strokeColor.value().ColorToString();
174     }
175     if (font_.superscript.has_value()) {
176         ss << " superscript:" << static_cast<int32_t>(font_.superscript.value());
177     }
178     std::string output = ss.str();
179     return output;
180 }
181 
IsAttributesEqual(const RefPtr<SpanBase> & other) const182 bool FontSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
183 {
184     auto fontSpan = DynamicCast<FontSpan>(other);
185     if (!fontSpan) {
186         return false;
187     }
188     auto font = fontSpan->GetFont();
189     return font_.IsEqual(font);
190 }
191 
192 // DecorationSpan
DecorationSpan(const std::vector<TextDecoration> & types,std::optional<Color> color,std::optional<TextDecorationStyle> style,std::optional<TextDecorationOptions> options)193 DecorationSpan::DecorationSpan(const std::vector<TextDecoration>& types, std::optional<Color> color,
194     std::optional<TextDecorationStyle> style, std::optional<TextDecorationOptions> options)
195     : SpanBase(0, 0), types_(types), color_(color), style_(style), options_(options)
196 {}
197 
DecorationSpan(const std::vector<TextDecoration> & types,std::optional<Color> color,std::optional<TextDecorationStyle> style,std::optional<TextDecorationOptions> options,int32_t start,int32_t end)198 DecorationSpan::DecorationSpan(const std::vector<TextDecoration>& types, std::optional<Color> color,
199     std::optional<TextDecorationStyle> style, std::optional<TextDecorationOptions> options,
200     int32_t start, int32_t end)
201     : SpanBase(start, end), types_(types), color_(color), style_(style), options_(options)
202 {}
203 
DecorationSpan(const std::vector<TextDecoration> & types,std::optional<Color> color,std::optional<TextDecorationStyle> style,std::optional<float> lineThicknessScale,std::optional<TextDecorationOptions> options)204 DecorationSpan::DecorationSpan(
205     const std::vector<TextDecoration>& types, std::optional<Color> color,
206     std::optional<TextDecorationStyle> style, std::optional<float> lineThicknessScale,
207     std::optional<TextDecorationOptions> options)
208     : SpanBase(0, 0), types_(types), color_(color), style_(style),
209     lineThicknessScale_(lineThicknessScale), options_(options)
210 {}
211 
DecorationSpan(const std::vector<TextDecoration> & types,std::optional<Color> color,std::optional<TextDecorationStyle> style,std::optional<float> lineThicknessScale,std::optional<TextDecorationOptions> options,int32_t start,int32_t end)212 DecorationSpan::DecorationSpan(const std::vector<TextDecoration>& types, std::optional<Color> color,
213     std::optional<TextDecorationStyle> style, std::optional<float> lineThicknessScale,
214     std::optional<TextDecorationOptions> options, int32_t start, int32_t end)
215     : SpanBase(start, end), types_(types), color_(color), style_(style),
216     lineThicknessScale_(lineThicknessScale), options_(options)
217 {}
218 
GetTextDecorationFirst() const219 TextDecoration DecorationSpan::GetTextDecorationFirst() const
220 {
221     return types_.size() > 0 ? types_[0] : TextDecoration::NONE;
222 }
223 
GetTextDecorationTypes() const224 std::vector<TextDecoration> DecorationSpan::GetTextDecorationTypes() const
225 {
226     return types_;
227 }
228 
SetTextDecorationTypes(const std::vector<TextDecoration> & types)229 void DecorationSpan::SetTextDecorationTypes(const std::vector<TextDecoration>& types)
230 {
231     types_ = types;
232 }
233 
RemoveTextDecorationType(TextDecoration type)234 void DecorationSpan::RemoveTextDecorationType(TextDecoration type)
235 {
236     if (!V2::HasTextDecoration(types_, type)) {
237         return;
238     }
239     auto iter = std::find(types_.begin(), types_.end(), type);
240     if (iter != types_.end()) {
241         types_.erase(iter);
242     }
243 }
244 
AddTextDecorationType(TextDecoration value)245 void DecorationSpan::AddTextDecorationType(TextDecoration value)
246 {
247     if (value == TextDecoration::NONE || V2::HasTextDecoration(types_, value)) {
248         return;
249     }
250     auto iter = std::find(types_.begin(), types_.end(), TextDecoration::NONE);
251     if (iter != types_.end()) {
252         types_.erase(iter);
253     }
254     types_.push_back(value);
255 }
256 
GetColor() const257 std::optional<Color> DecorationSpan::GetColor() const
258 {
259     return color_;
260 }
261 
GetTextDecorationStyle() const262 std::optional<TextDecorationStyle> DecorationSpan::GetTextDecorationStyle() const
263 {
264     return style_;
265 }
266 
GetTextDecorationLineThicknessScale() const267 std::optional<float> DecorationSpan::GetTextDecorationLineThicknessScale() const
268 {
269     return lineThicknessScale_;
270 }
271 
GetTextDecorationOptions() const272 std::optional<TextDecorationOptions> DecorationSpan::GetTextDecorationOptions() const
273 {
274     return options_;
275 }
276 
SetTextDecorationOptions(const TextDecorationOptions & options)277 void DecorationSpan::SetTextDecorationOptions(const TextDecorationOptions& options)
278 {
279     options_ = options;
280 }
281 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const282 void DecorationSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
283 {
284     switch (operation) {
285         case SpanOperation::ADD:
286             AddDecorationStyle(spanItem);
287             break;
288         case SpanOperation::REMOVE:
289             RemoveDecorationStyle(spanItem);
290     }
291 }
292 
GetLineThicknessScale() const293 std::optional<float> DecorationSpan::GetLineThicknessScale() const
294 {
295     return lineThicknessScale_;
296 }
297 
GetSubSpan(int32_t start,int32_t end)298 RefPtr<SpanBase> DecorationSpan::GetSubSpan(int32_t start, int32_t end)
299 {
300     RefPtr<SpanBase> spanBase = MakeRefPtr<DecorationSpan>(
301         types_, color_, style_, lineThicknessScale_, options_, start, end);
302     return spanBase;
303 }
304 
AddDecorationStyle(const RefPtr<NG::SpanItem> & spanItem) const305 void DecorationSpan::AddDecorationStyle(const RefPtr<NG::SpanItem>& spanItem) const
306 {
307     spanItem->fontStyle->UpdateTextDecoration(types_);
308     if (color_.has_value()) {
309         spanItem->fontStyle->UpdateTextDecorationColor(color_.value());
310     }
311     if (style_.has_value()) {
312         spanItem->fontStyle->UpdateTextDecorationStyle(style_.value());
313     }
314     if (lineThicknessScale_.has_value()) {
315         spanItem->fontStyle->UpdateLineThicknessScale(lineThicknessScale_.value());
316     }
317     if (options_.has_value()) {
318         spanItem->fontStyle->UpdateTextDecorationOptions(options_.value());
319     }
320 }
321 
RemoveDecorationStyle(const RefPtr<NG::SpanItem> & spanItem)322 void DecorationSpan::RemoveDecorationStyle(const RefPtr<NG::SpanItem>& spanItem)
323 {
324     spanItem->fontStyle->ResetTextDecoration();
325     spanItem->fontStyle->ResetTextDecorationColor();
326     spanItem->fontStyle->ResetTextDecorationStyle();
327     spanItem->fontStyle->ResetLineThicknessScale();
328 }
329 
GetSpanType() const330 SpanType DecorationSpan::GetSpanType() const
331 {
332     return SpanType::Decoration;
333 }
334 
DecorationTypesToString() const335 std::string DecorationSpan::DecorationTypesToString() const
336 {
337     std::string result = "";
338     for (TextDecoration type : types_) {
339         switch (type) {
340             case TextDecoration::UNDERLINE:
341                 result += "UNDERLINE,";
342                 break;
343             case TextDecoration::OVERLINE:
344                 result += "OVERLINE,";
345                 break;
346             case TextDecoration::LINE_THROUGH:
347                 result += "LINE_THROUGH,";
348                 break;
349             default:
350                 result += "NONE,";
351                 break;
352         }
353     }
354     result.pop_back();
355     return result;
356 }
357 
ToString() const358 std::string DecorationSpan::ToString() const
359 {
360     std::stringstream ss;
361     ss << "DecorationSpan [";
362     ss << GetStartIndex();
363     ss << ":";
364     ss << GetEndIndex();
365     ss << "]";
366     ss << " type:" << DecorationTypesToString() << " color:"
367         << (color_.has_value() ? color_.value().ColorToString(): "None")
368         << " style:" << (style_.has_value() ? static_cast<int32_t>(style_.value()): -1);
369     std::string output = ss.str();
370     return output;
371 }
372 
IsAttributesEqual(const RefPtr<SpanBase> & other) const373 bool DecorationSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
374 {
375     auto decorationSpan = DynamicCast<DecorationSpan>(other);
376     if (!decorationSpan) {
377         return false;
378     }
379     std::optional<Color> color = decorationSpan->GetColor();
380     std::optional<TextDecorationStyle> style = decorationSpan->GetTextDecorationStyle();
381     std::optional<float> lineThicknessScale = decorationSpan->GetTextDecorationLineThicknessScale();
382     std::optional<TextDecorationOptions> options = decorationSpan->GetTextDecorationOptions();
383     return color == color_ && style == style_ && lineThicknessScale_ == lineThicknessScale &&
384         V2::IsEqualTextDecorations(types_, decorationSpan->GetTextDecorationTypes()) &&
385         options_.value_or(TextDecorationOptions()) == options.value_or(TextDecorationOptions());
386 }
387 
388 // BaselineOffsetSpan
BaselineOffsetSpan(Dimension baselineOffset)389 BaselineOffsetSpan::BaselineOffsetSpan(Dimension baselineOffset) : SpanBase(0, 0), baselineOffset_(baselineOffset) {}
390 
BaselineOffsetSpan(Dimension baselineOffset,int32_t start,int32_t end)391 BaselineOffsetSpan::BaselineOffsetSpan(Dimension baselineOffset, int32_t start, int32_t end)
392     : SpanBase(start, end), baselineOffset_(baselineOffset)
393 {}
394 
GetBaselineOffset() const395 Dimension BaselineOffsetSpan::GetBaselineOffset() const
396 {
397     return baselineOffset_;
398 }
399 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const400 void BaselineOffsetSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
401 {
402     switch (operation) {
403         case SpanOperation::ADD:
404             AddBaselineOffsetStyle(spanItem);
405             break;
406         case SpanOperation::REMOVE:
407             RemoveBaselineOffsetStyle(spanItem);
408     }
409 }
410 
GetSubSpan(int32_t start,int32_t end)411 RefPtr<SpanBase> BaselineOffsetSpan::GetSubSpan(int32_t start, int32_t end)
412 {
413     RefPtr<SpanBase> spanBase = MakeRefPtr<BaselineOffsetSpan>(baselineOffset_, start, end);
414     return spanBase;
415 }
416 
AddBaselineOffsetStyle(const RefPtr<NG::SpanItem> & spanItem) const417 void BaselineOffsetSpan::AddBaselineOffsetStyle(const RefPtr<NG::SpanItem>& spanItem) const
418 {
419     CHECK_NULL_VOID(spanItem);
420     if (!spanItem->textLineStyle) {
421         spanItem->textLineStyle = std::make_unique<NG::TextLineStyle>();
422     }
423     spanItem->textLineStyle->UpdateBaselineOffset(baselineOffset_);
424 }
425 
RemoveBaselineOffsetStyle(const RefPtr<NG::SpanItem> & spanItem)426 void BaselineOffsetSpan::RemoveBaselineOffsetStyle(const RefPtr<NG::SpanItem>& spanItem)
427 {
428     CHECK_NULL_VOID(spanItem);
429     if (!spanItem->textLineStyle) {
430         spanItem->textLineStyle = std::make_unique<NG::TextLineStyle>();
431     }
432     spanItem->textLineStyle->ResetBaselineOffset();
433 }
434 
GetSpanType() const435 SpanType BaselineOffsetSpan::GetSpanType() const
436 {
437     return SpanType::BaselineOffset;
438 }
439 
ToString() const440 std::string BaselineOffsetSpan::ToString() const
441 {
442     std::stringstream ss;
443     ss << "BaselineOffsetSpan [";
444     ss << GetStartIndex();
445     ss << ":";
446     ss << GetEndIndex();
447     ss << "]";
448     ss << " baselineOffset:" << baselineOffset_.ToString();
449     std::string output = ss.str();
450     return output;
451 }
452 
IsAttributesEqual(const RefPtr<SpanBase> & other) const453 bool BaselineOffsetSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
454 {
455     auto baselineOffsetSpan = DynamicCast<BaselineOffsetSpan>(other);
456     if (!baselineOffsetSpan) {
457         return false;
458     }
459     auto baselineOffset = baselineOffsetSpan->GetBaselineOffset();
460     return baselineOffset == baselineOffset_;
461 }
462 
463 // LetterSpacingSpan
LetterSpacingSpan(Dimension letterSpacing)464 LetterSpacingSpan::LetterSpacingSpan(Dimension letterSpacing) : SpanBase(0, 0), letterSpacing_(letterSpacing) {}
465 
LetterSpacingSpan(Dimension letterSpacing,int32_t start,int32_t end)466 LetterSpacingSpan::LetterSpacingSpan(Dimension letterSpacing, int32_t start, int32_t end)
467     : SpanBase(start, end), letterSpacing_(letterSpacing)
468 {}
469 
GetLetterSpacing() const470 Dimension LetterSpacingSpan::GetLetterSpacing() const
471 {
472     return letterSpacing_;
473 }
474 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const475 void LetterSpacingSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
476 {
477     switch (operation) {
478         case SpanOperation::ADD:
479             AddLetterSpacingStyle(spanItem);
480             break;
481         case SpanOperation::REMOVE:
482             RemoveLetterSpacingStyle(spanItem);
483     }
484 }
485 
GetSubSpan(int32_t start,int32_t end)486 RefPtr<SpanBase> LetterSpacingSpan::GetSubSpan(int32_t start, int32_t end)
487 {
488     RefPtr<SpanBase> spanBase = MakeRefPtr<LetterSpacingSpan>(letterSpacing_, start, end);
489     return spanBase;
490 }
491 
AddLetterSpacingStyle(const RefPtr<NG::SpanItem> & spanItem) const492 void LetterSpacingSpan::AddLetterSpacingStyle(const RefPtr<NG::SpanItem>& spanItem) const
493 {
494     spanItem->fontStyle->UpdateLetterSpacing(letterSpacing_);
495 }
496 
RemoveLetterSpacingStyle(const RefPtr<NG::SpanItem> & spanItem)497 void LetterSpacingSpan::RemoveLetterSpacingStyle(const RefPtr<NG::SpanItem>& spanItem)
498 {
499     spanItem->fontStyle->ResetLetterSpacing();
500 }
501 
GetSpanType() const502 SpanType LetterSpacingSpan::GetSpanType() const
503 {
504     return SpanType::LetterSpacing;
505 }
506 
ToString() const507 std::string LetterSpacingSpan::ToString() const
508 {
509     std::stringstream ss;
510     ss << "LetterSpacingSpan [";
511     ss << GetStartIndex();
512     ss << ":";
513     ss << GetEndIndex();
514     ss << "]";
515     ss << " letterSpacing:" << letterSpacing_.ToString();
516     std::string output = ss.str();
517     return output;
518 }
519 
IsAttributesEqual(const RefPtr<SpanBase> & other) const520 bool LetterSpacingSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
521 {
522     auto letterSpacingSpan = DynamicCast<LetterSpacingSpan>(other);
523     if (!letterSpacingSpan) {
524         return false;
525     }
526     auto letterSpacing = letterSpacingSpan->GetLetterSpacing();
527     return letterSpacing == letterSpacing_;
528 }
529 
530 // GestureSpan
GestureSpan(GestureStyle gestureInfo)531 GestureSpan::GestureSpan(GestureStyle gestureInfo) : SpanBase(0, 0), gestureInfo_(std::move(gestureInfo)) {}
532 
GestureSpan(GestureStyle gestureInfo,int32_t start,int32_t end)533 GestureSpan::GestureSpan(GestureStyle gestureInfo, int32_t start, int32_t end)
534     : SpanBase(start, end), gestureInfo_(std::move(gestureInfo))
535 {}
536 
GetGestureStyle() const537 GestureStyle GestureSpan::GetGestureStyle() const
538 {
539     return gestureInfo_;
540 }
541 
GetSubSpan(int32_t start,int32_t end)542 RefPtr<SpanBase> GestureSpan::GetSubSpan(int32_t start, int32_t end)
543 {
544     RefPtr<SpanBase> spanBase = MakeRefPtr<GestureSpan>(gestureInfo_, start, end);
545     auto gestureSpan = DynamicCast<GestureSpan>(spanBase);
546     CHECK_NULL_RETURN(gestureSpan, spanBase);
547     if (gestureSpanId_ == -1) {
548         gestureSpanId_ = gGestureSpanId.fetch_add(1) % GESTURES_SPAN_DIVIDE_SIZE;
549     }
550     gestureSpan->SetGestureSpanId(gestureSpanId_);
551     return spanBase;
552 }
553 
IsAttributesEqual(const RefPtr<SpanBase> & other) const554 bool GestureSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
555 {
556     auto gestureSpan = DynamicCast<GestureSpan>(other);
557     if (!gestureSpan) {
558         return false;
559     }
560     if (gestureSpanId_ != -1 && gestureSpanId_ == gestureSpan->GetGestureSpanId()) {
561         return true;
562     }
563     auto gestureInfo = gestureSpan->GetGestureStyle();
564     return gestureInfo_.IsEqual(gestureInfo);
565 }
566 
GetSpanType() const567 SpanType GestureSpan::GetSpanType() const
568 {
569     return SpanType::Gesture;
570 }
571 
ToString() const572 std::string GestureSpan::ToString() const
573 {
574     std::stringstream ss;
575     ss << "GestureSpan [";
576     ss << GetStartIndex();
577     ss << ":";
578     ss << GetEndIndex();
579     ss << "]";
580     std::string output = ss.str();
581     return output;
582 }
583 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const584 void GestureSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
585 {
586     switch (operation) {
587         case SpanOperation::ADD:
588             AddSpanStyle(spanItem);
589             break;
590         case SpanOperation::REMOVE:
591             RemoveSpanStyle(spanItem);
592     }
593 }
594 
AddSpanStyle(const RefPtr<NG::SpanItem> & spanItem) const595 void GestureSpan::AddSpanStyle(const RefPtr<NG::SpanItem>& spanItem) const
596 {
597     spanItem->onClick = gestureInfo_.onClick.value_or(nullptr);
598     spanItem->onLongPress = gestureInfo_.onLongPress.value_or(nullptr);
599     spanItem->onTouch = gestureInfo_.onTouch.value_or(nullptr);
600 }
601 
RemoveSpanStyle(const RefPtr<NG::SpanItem> & spanItem)602 void GestureSpan::RemoveSpanStyle(const RefPtr<NG::SpanItem>& spanItem)
603 {
604     spanItem->onClick = nullptr;
605     spanItem->onLongPress = nullptr;
606     spanItem->onTouch = nullptr;
607 }
608 
609 // TextShadowSpan
TextShadowSpan(std::vector<Shadow> textShadow)610 TextShadowSpan::TextShadowSpan(std::vector<Shadow> textShadow) : SpanBase(0, 0), textShadow_(std::move(textShadow)) {}
611 
TextShadowSpan(std::vector<Shadow> textShadow,int32_t start,int32_t end)612 TextShadowSpan::TextShadowSpan(std::vector<Shadow> textShadow, int32_t start, int32_t end)
613     : SpanBase(start, end), textShadow_(std::move(textShadow))
614 {}
615 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const616 void TextShadowSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
617 {
618     switch (operation) {
619         case SpanOperation::ADD:
620             AddSpanStyle(spanItem);
621             break;
622         case SpanOperation::REMOVE:
623             RemoveSpanStyle(spanItem);
624     }
625 }
626 
GetSubSpan(int32_t start,int32_t end)627 RefPtr<SpanBase> TextShadowSpan::GetSubSpan(int32_t start, int32_t end)
628 {
629     RefPtr<SpanBase> spanBase = MakeRefPtr<TextShadowSpan>(GetTextShadow(), start, end);
630     return spanBase;
631 }
632 
AddSpanStyle(const RefPtr<NG::SpanItem> & spanItem) const633 void TextShadowSpan::AddSpanStyle(const RefPtr<NG::SpanItem>& spanItem) const
634 {
635     if (textShadow_.has_value()) {
636         spanItem->fontStyle->UpdateTextShadow(textShadow_.value());
637     }
638 }
639 
RemoveSpanStyle(const RefPtr<NG::SpanItem> & spanItem)640 void TextShadowSpan::RemoveSpanStyle(const RefPtr<NG::SpanItem>& spanItem)
641 {
642     spanItem->fontStyle->ResetTextShadow();
643 }
644 
GetTextShadow() const645 std::vector<Shadow> TextShadowSpan::GetTextShadow() const
646 {
647     return textShadow_.value_or(std::vector<Shadow>());
648 }
649 
GetSpanType() const650 SpanType TextShadowSpan::GetSpanType() const
651 {
652     return SpanType::TextShadow;
653 }
654 
ToString() const655 std::string TextShadowSpan::ToString() const
656 {
657     std::stringstream ss;
658     ss << "TextShadowSpan [";
659     ss << GetStartIndex();
660     ss << ":";
661     ss << GetEndIndex();
662     ss << "]";
663     std::string output = ss.str();
664     return output;
665 }
666 
IsAttributesEqual(const RefPtr<SpanBase> & other) const667 bool TextShadowSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
668 {
669     auto textShadowSpan = DynamicCast<TextShadowSpan>(other);
670     if (!textShadowSpan) {
671         return false;
672     }
673     auto textShadow = textShadowSpan->GetTextShadow();
674     auto selfTextShadow = GetTextShadow();
675     if (textShadow.size() != selfTextShadow.size()) {
676         return false;
677     }
678     for (size_t i = 0; i < selfTextShadow.size(); ++i) {
679         if (selfTextShadow[i] != textShadow[i]) {
680             return false;
681         }
682     }
683     return true;
684 }
685 
686 // ImageSpan
ImageSpan(const ImageSpanOptions & options)687 ImageSpan::ImageSpan(const ImageSpanOptions& options) : SpanBase(0, 1), imageOptions_(options) {}
688 
ImageSpan(const ImageSpanOptions & options,int32_t position)689 ImageSpan::ImageSpan(const ImageSpanOptions& options, int32_t position)
690     : SpanBase(position, position + 1), imageOptions_(options)
691 {}
692 
IsAttributesEqual(const RefPtr<SpanBase> & other) const693 bool ImageSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
694 {
695     auto imageSpan = DynamicCast<ImageSpan>(other);
696     if (!imageSpan) {
697         return false;
698     }
699     if (imageOptions_.imageAttribute.has_value() && imageSpan->GetImageAttribute().has_value()) {
700         return imageOptions_.imageAttribute.value() == imageSpan->GetImageAttribute().value();
701     }
702     return false;
703 }
704 
GetSubSpan(int32_t start,int32_t end)705 RefPtr<SpanBase> ImageSpan::GetSubSpan(int32_t start, int32_t end)
706 {
707     if (end - start > 1) {
708         return nullptr;
709     }
710     auto spanBase = MakeRefPtr<ImageSpan>(imageOptions_);
711     spanBase->UpdateStartIndex(start);
712     spanBase->UpdateEndIndex(end);
713     return spanBase;
714 }
715 
GetSpanType() const716 SpanType ImageSpan::GetSpanType() const
717 {
718     return SpanType::Image;
719 }
720 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const721 void ImageSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
722 {
723     auto imageItem = DynamicCast<NG::ImageSpanItem>(spanItem);
724     if (!imageItem) {
725         return;
726     }
727 
728     switch (operation) {
729         case SpanOperation::ADD:
730             imageItem->SetImageSpanOptions(imageOptions_);
731             break;
732         case SpanOperation::REMOVE:
733             imageItem->ResetImageSpanOptions();
734     }
735 }
736 
ToString() const737 std::string ImageSpan::ToString() const
738 {
739     std::stringstream ss;
740     ss << "ImageSpan [";
741     ss << GetStartIndex();
742     ss << ":";
743     ss << GetEndIndex();
744     ss << "]";
745     std::string output = ss.str();
746     return output;
747 }
748 
GetImageSpanOptions()749 const ImageSpanOptions& ImageSpan::GetImageSpanOptions()
750 {
751     return imageOptions_;
752 }
753 
GetImageAttribute() const754 const std::optional<ImageSpanAttribute>& ImageSpan::GetImageAttribute() const
755 {
756     return imageOptions_.imageAttribute;
757 }
758 
759 // CustomSpan
CustomSpan()760 CustomSpan::CustomSpan() : SpanBase(0, 1) {}
761 
CustomSpan(std::optional<std::function<CustomSpanMetrics (CustomSpanMeasureInfo)>> onMeasure,std::optional<std::function<void (NG::DrawingContext &,CustomSpanOptions)>> onDraw)762 CustomSpan::CustomSpan(std::optional<std::function<CustomSpanMetrics(CustomSpanMeasureInfo)>> onMeasure,
763     std::optional<std::function<void(NG::DrawingContext&, CustomSpanOptions)>> onDraw)
764     : SpanBase(0, 1), onMeasure_(std::move(onMeasure)), onDraw_(std::move(onDraw))
765 {}
766 
CustomSpan(std::optional<std::function<CustomSpanMetrics (CustomSpanMeasureInfo)>> onMeasure,std::optional<std::function<void (NG::DrawingContext &,CustomSpanOptions)>> onDraw,int32_t start,int32_t end)767 CustomSpan::CustomSpan(std::optional<std::function<CustomSpanMetrics(CustomSpanMeasureInfo)>> onMeasure,
768     std::optional<std::function<void(NG::DrawingContext&, CustomSpanOptions)>> onDraw, int32_t start, int32_t end)
769     : SpanBase(start, end), onMeasure_(std::move(onMeasure)), onDraw_(std::move(onDraw))
770 {}
771 
SetOnMeasure(std::function<CustomSpanMetrics (CustomSpanMeasureInfo)> onMeasure)772 void CustomSpan::SetOnMeasure(std::function<CustomSpanMetrics(CustomSpanMeasureInfo)> onMeasure)
773 {
774     onMeasure_ = onMeasure;
775 }
776 
SetOnDraw(std::function<void (NG::DrawingContext &,CustomSpanOptions)> onDraw)777 void CustomSpan::SetOnDraw(std::function<void(NG::DrawingContext&, CustomSpanOptions)> onDraw)
778 {
779     onDraw_ = onDraw;
780 }
781 
GetOnMeasure()782 std::optional<std::function<CustomSpanMetrics(CustomSpanMeasureInfo)>> CustomSpan::GetOnMeasure()
783 {
784     return onMeasure_;
785 }
786 
GetOnDraw()787 std::optional<std::function<void(NG::DrawingContext&, CustomSpanOptions)>> CustomSpan::GetOnDraw()
788 {
789     return onDraw_;
790 }
791 
GetSubSpan(int32_t start,int32_t end)792 RefPtr<SpanBase> CustomSpan::GetSubSpan(int32_t start, int32_t end)
793 {
794     if (end - start > 1) {
795         return nullptr;
796     }
797     RefPtr<SpanBase> spanBase = MakeRefPtr<CustomSpan>(onMeasure_, onDraw_, start, end);
798     return spanBase;
799 }
800 
GetSpanType() const801 SpanType CustomSpan::GetSpanType() const
802 {
803     return SpanType::CustomSpan;
804 }
805 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const806 void CustomSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
807 {
808     auto imageItem = DynamicCast<NG::CustomSpanItem>(spanItem);
809     if (!imageItem) {
810         return;
811     }
812 
813     switch (operation) {
814         case SpanOperation::ADD:
815             imageItem->onMeasure = onMeasure_;
816             imageItem->onDraw = onDraw_;
817             break;
818         case SpanOperation::REMOVE:
819             imageItem->onMeasure = std::nullopt;
820             imageItem->onDraw = std::nullopt;
821     }
822 }
823 
ToString() const824 std::string CustomSpan::ToString() const
825 {
826     std::stringstream ss;
827     ss << "CustomSpan [";
828     ss << GetStartIndex();
829     ss << ":";
830     ss << GetEndIndex();
831     ss << "]";
832     std::string output = ss.str();
833     return output;
834 }
835 
IsAttributesEqual(const RefPtr<SpanBase> & other) const836 bool CustomSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
837 {
838     return false;
839 }
840 
841 // ParagraphStyleSpan
ParagraphStyleSpan(SpanParagraphStyle paragraphStyle)842 ParagraphStyleSpan::ParagraphStyleSpan(SpanParagraphStyle paragraphStyle)
843     : SpanBase(0, 0), paragraphStyle_(std::move(paragraphStyle))
844 {}
845 
ParagraphStyleSpan(SpanParagraphStyle paragraphStyle,int32_t start,int32_t end)846 ParagraphStyleSpan::ParagraphStyleSpan(SpanParagraphStyle paragraphStyle, int32_t start, int32_t end)
847     : SpanBase(start, end), paragraphStyle_(std::move(paragraphStyle))
848 {}
849 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const850 void ParagraphStyleSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
851 {
852     switch (operation) {
853         case SpanOperation::ADD:
854             AddParagraphStyle(spanItem);
855             break;
856         case SpanOperation::REMOVE:
857             RemoveParagraphStyle(spanItem);
858     }
859 }
860 
AddParagraphStyle(const RefPtr<NG::SpanItem> & spanItem) const861 void ParagraphStyleSpan::AddParagraphStyle(const RefPtr<NG::SpanItem>& spanItem) const
862 {
863     if (paragraphStyle_.align.has_value()) {
864         spanItem->textLineStyle->UpdateTextAlign(paragraphStyle_.align.value());
865     }
866 
867     if (paragraphStyle_.textVerticalAlign.has_value()) {
868         spanItem->textLineStyle->UpdateTextVerticalAlign(paragraphStyle_.textVerticalAlign.value());
869     }
870 
871     if (paragraphStyle_.maxLines.has_value()) {
872         spanItem->textLineStyle->UpdateMaxLines(static_cast<uint32_t>(paragraphStyle_.maxLines.value()));
873     }
874 
875     if (paragraphStyle_.textOverflow.has_value()) {
876         spanItem->textLineStyle->UpdateTextOverflow(paragraphStyle_.textOverflow.value());
877     }
878 
879     if (paragraphStyle_.leadingMargin.has_value()) {
880         spanItem->textLineStyle->UpdateLeadingMargin(paragraphStyle_.leadingMargin.value());
881     }
882 
883     if (paragraphStyle_.wordBreak.has_value()) {
884         spanItem->textLineStyle->UpdateWordBreak(paragraphStyle_.wordBreak.value());
885     }
886 
887     if (paragraphStyle_.textIndent.has_value()) {
888         spanItem->textLineStyle->UpdateTextIndent(paragraphStyle_.textIndent.value());
889     }
890 
891     if (paragraphStyle_.paragraphSpacing.has_value()) {
892         spanItem->textLineStyle->UpdateParagraphSpacing(paragraphStyle_.paragraphSpacing.value());
893     }
894 }
895 
RemoveParagraphStyle(const RefPtr<NG::SpanItem> & spanItem) const896 void ParagraphStyleSpan::RemoveParagraphStyle(const RefPtr<NG::SpanItem>& spanItem) const
897 {
898     spanItem->textLineStyle->ResetTextAlign();
899     spanItem->textLineStyle->ResetTextVerticalAlign();
900     spanItem->textLineStyle->ResetMaxLines();
901     spanItem->textLineStyle->ResetTextOverflow();
902     spanItem->textLineStyle->ResetLeadingMargin();
903     spanItem->textLineStyle->ResetWordBreak();
904     spanItem->textLineStyle->ResetTextIndent();
905     spanItem->textLineStyle->ResetParagraphSpacing();
906 }
907 
IsAttributesEqual(const RefPtr<SpanBase> & other) const908 bool ParagraphStyleSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
909 {
910     auto paragraphSpan = DynamicCast<ParagraphStyleSpan>(other);
911     if (!paragraphSpan) {
912         return false;
913     }
914     auto paragraphStyle = paragraphSpan->GetParagraphStyle();
915     return paragraphStyle_.Equal(paragraphStyle);
916 }
917 
GetParagraphStyle() const918 SpanParagraphStyle ParagraphStyleSpan::GetParagraphStyle() const
919 {
920     return paragraphStyle_;
921 }
922 
GetSpanType() const923 SpanType ParagraphStyleSpan::GetSpanType() const
924 {
925     return SpanType::ParagraphStyle;
926 }
927 
ToString() const928 std::string ParagraphStyleSpan::ToString() const
929 {
930     std::stringstream ss;
931     ss << "ParagraphStyleSpan [";
932     ss << GetStartIndex();
933     ss << ":";
934     ss << GetEndIndex();
935     ss << "]";
936     std::string output = ss.str();
937     return output;
938 }
939 
GetSubSpan(int32_t start,int32_t end)940 RefPtr<SpanBase> ParagraphStyleSpan::GetSubSpan(int32_t start, int32_t end)
941 {
942     RefPtr<SpanBase> spanBase = MakeRefPtr<ParagraphStyleSpan>(paragraphStyle_, start, end);
943     return spanBase;
944 }
945 
946 // LineHeightSpan
LineHeightSpan(Dimension lineHeight)947 LineHeightSpan::LineHeightSpan(Dimension lineHeight) : SpanBase(0, 0), lineHeight_(lineHeight) {}
948 
LineHeightSpan(Dimension lineHeight,int32_t start,int32_t end)949 LineHeightSpan::LineHeightSpan(Dimension lineHeight, int32_t start, int32_t end)
950     : SpanBase(start, end), lineHeight_(lineHeight)
951 {}
952 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const953 void LineHeightSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
954 {
955     switch (operation) {
956         case SpanOperation::ADD:
957             AddLineHeightStyle(spanItem);
958             break;
959         case SpanOperation::REMOVE:
960             RemoveLineHeightStyle(spanItem);
961     }
962 }
963 
GetSubSpan(int32_t start,int32_t end)964 RefPtr<SpanBase> LineHeightSpan::GetSubSpan(int32_t start, int32_t end)
965 {
966     RefPtr<SpanBase> spanBase = MakeRefPtr<LineHeightSpan>(GetLineHeight(), start, end);
967     return spanBase;
968 }
969 
AddLineHeightStyle(const RefPtr<NG::SpanItem> & spanItem) const970 void LineHeightSpan::AddLineHeightStyle(const RefPtr<NG::SpanItem>& spanItem) const
971 {
972     spanItem->textLineStyle->UpdateLineHeight(lineHeight_);
973 }
974 
RemoveLineHeightStyle(const RefPtr<NG::SpanItem> & spanItem) const975 void LineHeightSpan::RemoveLineHeightStyle(const RefPtr<NG::SpanItem>& spanItem) const
976 {
977     spanItem->textLineStyle->ResetLineHeight();
978 }
979 
GetLineHeight() const980 Dimension LineHeightSpan::GetLineHeight() const
981 {
982     return lineHeight_;
983 }
984 
GetSpanType() const985 SpanType LineHeightSpan::GetSpanType() const
986 {
987     return SpanType::LineHeight;
988 }
989 
ToString() const990 std::string LineHeightSpan::ToString() const
991 {
992     std::stringstream ss;
993     ss << "LineHeightSpan [";
994     ss << GetStartIndex();
995     ss << ":";
996     ss << GetEndIndex();
997     ss << "]";
998     ss << " baselineOffset:" << lineHeight_.ToString();
999     std::string output = ss.str();
1000     return output;
1001 }
1002 
IsAttributesEqual(const RefPtr<SpanBase> & other) const1003 bool LineHeightSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
1004 {
1005     auto lineHeightSpan = DynamicCast<LineHeightSpan>(other);
1006     if (!lineHeightSpan) {
1007         return false;
1008     }
1009     auto lineHeight = lineHeightSpan->GetLineHeight();
1010     return lineHeight_ == lineHeight;
1011 }
1012 
1013 // HalfLeadingSpan
HalfLeadingSpan(bool halfLeading)1014 HalfLeadingSpan::HalfLeadingSpan(bool halfLeading) : SpanBase(0, 0), halfLeading_(halfLeading) {}
1015 
HalfLeadingSpan(bool halfLeading,int32_t start,int32_t end)1016 HalfLeadingSpan::HalfLeadingSpan(bool halfLeading, int32_t start, int32_t end)
1017     : SpanBase(start, end), halfLeading_(halfLeading)
1018 {}
1019 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const1020 void HalfLeadingSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
1021 {
1022     switch (operation) {
1023         case SpanOperation::ADD:
1024             AddHalfLeadingStyle(spanItem);
1025             break;
1026         case SpanOperation::REMOVE:
1027             RemoveHalfLeadingStyle(spanItem);
1028     }
1029 }
1030 
GetSubSpan(int32_t start,int32_t end)1031 RefPtr<SpanBase> HalfLeadingSpan::GetSubSpan(int32_t start, int32_t end)
1032 {
1033     return MakeRefPtr<HalfLeadingSpan>(halfLeading_, start, end);
1034 }
1035 
AddHalfLeadingStyle(const RefPtr<NG::SpanItem> & spanItem) const1036 void HalfLeadingSpan::AddHalfLeadingStyle(const RefPtr<NG::SpanItem>& spanItem) const
1037 {
1038     spanItem->textLineStyle->UpdateHalfLeading(halfLeading_);
1039 }
1040 
RemoveHalfLeadingStyle(const RefPtr<NG::SpanItem> & spanItem) const1041 void HalfLeadingSpan::RemoveHalfLeadingStyle(const RefPtr<NG::SpanItem>& spanItem) const
1042 {
1043     spanItem->textLineStyle->ResetHalfLeading();
1044 }
1045 
GetHalfLeading() const1046 bool HalfLeadingSpan::GetHalfLeading() const
1047 {
1048     return halfLeading_;
1049 }
1050 
GetSpanType() const1051 SpanType HalfLeadingSpan::GetSpanType() const
1052 {
1053     return SpanType::HalfLeading;
1054 }
1055 
ToString() const1056 std::string HalfLeadingSpan::ToString() const
1057 {
1058     std::stringstream str;
1059     str << "HalfLeadingSpan ( start:";
1060     str << GetStartIndex();
1061     str << " end:";
1062     str << GetEndIndex();
1063     str << "]";
1064     return str.str();
1065 }
1066 
IsAttributesEqual(const RefPtr<SpanBase> & other) const1067 bool HalfLeadingSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
1068 {
1069     auto halfLeadingSpan = DynamicCast<HalfLeadingSpan>(other);
1070     CHECK_NULL_RETURN(halfLeadingSpan, false);
1071     return halfLeading_ == halfLeadingSpan->GetHalfLeading();
1072 }
1073 
1074 // ExtSpan
ExtSpan(int32_t start,int32_t end)1075 ExtSpan::ExtSpan(int32_t start, int32_t end) : SpanBase(start, end) {}
1076 
GetSubSpan(int32_t start,int32_t end)1077 RefPtr<SpanBase> ExtSpan::GetSubSpan(int32_t start, int32_t end)
1078 {
1079     RefPtr<SpanBase> spanBase = MakeRefPtr<ExtSpan>(start, end);
1080     return spanBase;
1081 }
1082 
GetSpanType() const1083 SpanType ExtSpan::GetSpanType() const
1084 {
1085     return SpanType::ExtSpan;
1086 }
1087 
ToString() const1088 std::string ExtSpan::ToString() const
1089 {
1090     std::stringstream ss;
1091     ss << "ExtSpan [";
1092     ss << GetStartIndex();
1093     ss << ":";
1094     ss << GetEndIndex();
1095     ss << "]";
1096     std::string output = ss.str();
1097     return output;
1098 }
1099 
IsAttributesEqual(const RefPtr<SpanBase> & other) const1100 bool ExtSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
1101 {
1102     return false;
1103 }
1104 
BackgroundColorSpan(std::optional<TextBackgroundStyle> textBackgroundStyle,int32_t start,int32_t end)1105 BackgroundColorSpan::BackgroundColorSpan(
1106     std::optional<TextBackgroundStyle> textBackgroundStyle, int32_t start, int32_t end)
1107     : SpanBase(start, end), textBackgroundStyle_(std::move(textBackgroundStyle))
1108 {}
1109 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const1110 void BackgroundColorSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
1111 {
1112     switch (operation) {
1113         case SpanOperation::ADD:
1114             AddSpanStyle(spanItem);
1115             break;
1116         case SpanOperation::REMOVE:
1117             RemoveSpanStyle(spanItem);
1118             break;
1119     }
1120 }
1121 
BackgroundColorSpan(std::optional<TextBackgroundStyle> textBackgroundStyle)1122 BackgroundColorSpan::BackgroundColorSpan(std::optional<TextBackgroundStyle> textBackgroundStyle)
1123     : textBackgroundStyle_(textBackgroundStyle) {}
1124 
GetSubSpan(int32_t start,int32_t end)1125 RefPtr<SpanBase> BackgroundColorSpan::GetSubSpan(int32_t start, int32_t end)
1126 {
1127     RefPtr<SpanBase> spanBase = MakeRefPtr<BackgroundColorSpan>(GetBackgroundColor(), start, end);
1128     return spanBase;
1129 }
AddSpanStyle(const RefPtr<NG::SpanItem> & spanItem) const1130 void BackgroundColorSpan::AddSpanStyle(const RefPtr<NG::SpanItem>& spanItem) const
1131 {
1132     if (textBackgroundStyle_.has_value()) {
1133         TextBackgroundStyle tempVal = GetBackgroundColor();
1134         spanItem->backgroundStyle = tempVal;
1135     }
1136 }
1137 
RemoveSpanStyle(const RefPtr<NG::SpanItem> & spanItem)1138 void BackgroundColorSpan::RemoveSpanStyle(const RefPtr<NG::SpanItem>& spanItem)
1139 {
1140     if (spanItem->backgroundStyle.has_value()) {
1141         spanItem->backgroundStyle.reset();
1142     }
1143 }
1144 
GetBackgroundColor() const1145 TextBackgroundStyle BackgroundColorSpan::GetBackgroundColor() const
1146 {
1147     return textBackgroundStyle_.value_or(TextBackgroundStyle());
1148 }
1149 
SetBackgroundColorGroupId(int32_t groupId)1150 void BackgroundColorSpan::SetBackgroundColorGroupId(int32_t groupId)
1151 {
1152     textBackgroundStyle_->groupId = groupId;
1153 }
1154 
GetSpanType() const1155 SpanType BackgroundColorSpan::GetSpanType() const
1156 {
1157     return SpanType::BackgroundColor;
1158 }
1159 
ToString() const1160 std::string BackgroundColorSpan::ToString() const
1161 {
1162     std::stringstream ss;
1163     ss << "BackgroundColorSpan [";
1164     ss << GetStartIndex();
1165     ss << ":";
1166     ss << GetEndIndex();
1167     ss << "]";
1168     std::string output = ss.str();
1169     return output;
1170 }
1171 
IsAttributesEqual(const RefPtr<SpanBase> & other) const1172 bool BackgroundColorSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
1173 {
1174     auto backgroundColorSpan = DynamicCast<BackgroundColorSpan>(other);
1175         if (!backgroundColorSpan) {
1176             return false;
1177         }
1178     auto backgroundColor = backgroundColorSpan->GetBackgroundColor();
1179     return backgroundColor == textBackgroundStyle_;
1180 }
1181 
1182 // UrlSpan
UrlSpan(const std::string & urlAddress)1183 UrlSpan::UrlSpan(const std::string& urlAddress) : SpanBase(0, 0), urlAddress_(urlAddress) {}
1184 
UrlSpan(const std::string & urlAddress,int32_t start,int32_t end)1185 UrlSpan::UrlSpan(const std::string& urlAddress, int32_t start, int32_t end)
1186     : SpanBase(start, end), urlAddress_(urlAddress)
1187 {}
1188 
GetUrlSpanAddress() const1189 std::string UrlSpan::GetUrlSpanAddress() const
1190 {
1191     return urlAddress_;
1192 }
1193 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const1194 void UrlSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
1195 {
1196     switch (operation) {
1197         case SpanOperation::ADD:
1198             AddUrlStyle(spanItem);
1199             break;
1200         case SpanOperation::REMOVE:
1201             RemoveUrlStyle(spanItem);
1202             break;
1203     }
1204 }
1205 
GetSubSpan(int32_t start,int32_t end)1206 RefPtr<SpanBase> UrlSpan::GetSubSpan(int32_t start, int32_t end)
1207 {
1208     RefPtr<SpanBase> spanBase = MakeRefPtr<UrlSpan>(urlAddress_, start, end);
1209     return spanBase;
1210 }
1211 
AddUrlStyle(const RefPtr<NG::SpanItem> & spanItem) const1212 void UrlSpan::AddUrlStyle(const RefPtr<NG::SpanItem>& spanItem) const
1213 {
1214     auto address = urlAddress_;
1215     spanItem->urlAddress = UtfUtils::Str8DebugToStr16(address);
1216     auto urlOnRelease = [address]() {
1217         auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
1218         CHECK_NULL_VOID(pipelineContext);
1219         pipelineContext->HyperlinkStartAbility(address);
1220     };
1221     spanItem->SetUrlOnReleaseEvent(std::move(urlOnRelease));
1222     spanItem->urlAddress = std::u16string(address.begin(), address.end());
1223 }
1224 
RemoveUrlStyle(const RefPtr<NG::SpanItem> & spanItem)1225 void UrlSpan::RemoveUrlStyle(const RefPtr<NG::SpanItem>& spanItem)
1226 {
1227     spanItem->urlAddress = std::nullopt;
1228     spanItem->urlOnRelease = nullptr;
1229 }
1230 
GetSpanType() const1231 SpanType UrlSpan::GetSpanType() const
1232 {
1233     return SpanType::Url;
1234 }
1235 
ToString() const1236 std::string UrlSpan::ToString() const
1237 {
1238     std::stringstream ss;
1239     ss << "UrlSpan [";
1240     ss << GetStartIndex();
1241     ss << ":";
1242     ss << GetEndIndex();
1243     ss << "]";
1244     std::string output = ss.str();
1245     return output;
1246 }
1247 
IsAttributesEqual(const RefPtr<SpanBase> & other) const1248 bool UrlSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
1249 {
1250     auto urlSpan = DynamicCast<UrlSpan>(other);
1251     if (!urlSpan) {
1252         return false;
1253     }
1254     auto urlAddress = urlSpan->GetUrlSpanAddress();
1255     return urlAddress == urlAddress_;
1256 }
1257 } // namespace OHOS::Ace