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 #include <optional>
18 #include <utility>
19 
20 #include "base/memory/referenced.h"
21 #include "core/components/common/layout/constants.h"
22 #include "core/components/common/properties/color.h"
23 #include "core/components_ng/pattern/text_field/text_field_model.h"
24 #include "core/components_ng/render/paragraph.h"
25 
26 namespace OHOS::Ace {
27 // SpanBase
GetIntersectionInterval(std::pair<int32_t,int32_t> interval) const28 std::optional<std::pair<int32_t, int32_t>> SpanBase::GetIntersectionInterval(std::pair<int32_t, int32_t> interval) const
29 {
30     // 检查相交情况
31     if (end_ <= interval.first || interval.second <= start_) {
32         return std::nullopt;
33     }
34 
35     // 计算相交区间
36     int start = std::max(start_, interval.first);
37     int end = std::min(end_, interval.second);
38     return std::make_optional<std::pair<int32_t, int32_t>>(std::make_pair(start, end));
39 }
40 
GetStartIndex() const41 int32_t SpanBase::GetStartIndex() const
42 {
43     return start_;
44 }
45 
GetEndIndex() const46 int32_t SpanBase::GetEndIndex() const
47 {
48     return end_;
49 }
UpdateStartIndex(int32_t startIndex)50 void SpanBase::UpdateStartIndex(int32_t startIndex)
51 {
52     start_ = startIndex;
53 }
54 
UpdateEndIndex(int32_t endIndex)55 void SpanBase::UpdateEndIndex(int32_t endIndex)
56 {
57     end_ = endIndex;
58 }
59 
GetLength() const60 int32_t SpanBase::GetLength() const
61 {
62     return end_ - start_;
63 }
64 
65 // FontSpan
FontSpan(Font font)66 FontSpan::FontSpan(Font font) : SpanBase(0, 0), font_(std::move(font)) {}
67 
FontSpan(Font font,int32_t start,int32_t end)68 FontSpan::FontSpan(Font font, int32_t start, int32_t end) : SpanBase(start, end), font_(std::move(font)) {}
69 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const70 void FontSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
71 {
72     switch (operation) {
73         case SpanOperation::ADD:
74             AddSpanStyle(spanItem);
75             break;
76         case SpanOperation::REMOVE:
77             RemoveSpanStyle(spanItem);
78     }
79 }
80 
GetSubSpan(int32_t start,int32_t end)81 RefPtr<SpanBase> FontSpan::GetSubSpan(int32_t start, int32_t end)
82 {
83     RefPtr<SpanBase> spanBase = MakeRefPtr<FontSpan>(font_, start, end);
84     return spanBase;
85 }
86 
AddSpanStyle(const RefPtr<NG::SpanItem> & spanItem) const87 void FontSpan::AddSpanStyle(const RefPtr<NG::SpanItem>& spanItem) const
88 {
89     if (font_.fontColor.has_value()) {
90         spanItem->fontStyle->UpdateTextColor(font_.fontColor.value());
91     }
92 
93     if (font_.fontFamiliesNG.has_value()) {
94         spanItem->fontStyle->UpdateFontFamily(font_.fontFamiliesNG.value());
95     }
96 
97     if (font_.fontSize.has_value()) {
98         spanItem->fontStyle->UpdateFontSize(font_.fontSize.value());
99     }
100 
101     if (font_.fontStyle.has_value()) {
102         spanItem->fontStyle->UpdateItalicFontStyle(font_.fontStyle.value());
103     }
104 
105     if (font_.fontWeight.has_value()) {
106         spanItem->fontStyle->UpdateFontWeight(font_.fontWeight.value());
107     }
108 }
109 
RemoveSpanStyle(const RefPtr<NG::SpanItem> & spanItem)110 void FontSpan::RemoveSpanStyle(const RefPtr<NG::SpanItem>& spanItem)
111 {
112     spanItem->fontStyle->ResetTextColor();
113     spanItem->fontStyle->ResetFontFamily();
114     spanItem->fontStyle->ResetFontSize();
115     spanItem->fontStyle->ResetItalicFontStyle();
116     spanItem->fontStyle->ResetFontWeight();
117 }
118 
GetFont() const119 Font FontSpan::GetFont() const
120 {
121     return font_;
122 }
123 
GetSpanType() const124 SpanType FontSpan::GetSpanType() const
125 {
126     return SpanType::Font;
127 }
128 
ToString() const129 std::string FontSpan::ToString() const
130 {
131     std::stringstream str;
132     str << "FontSpan ( start:";
133     str << GetStartIndex();
134     str << " end:";
135     str << GetEndIndex();
136     str << "]";
137     std::string output = str.str();
138     return output;
139 }
140 
IsAttributesEqual(const RefPtr<SpanBase> & other) const141 bool FontSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
142 {
143     auto fontSpan = DynamicCast<FontSpan>(other);
144     if (!fontSpan) {
145         return false;
146     }
147     auto font = fontSpan->GetFont();
148     return font_.IsEqual(font);
149 }
150 
151 // DecorationSpan
DecorationSpan(TextDecoration type,std::optional<Color> color,std::optional<TextDecorationStyle> style)152 DecorationSpan::DecorationSpan(
153     TextDecoration type, std::optional<Color> color, std::optional<TextDecorationStyle> style)
154     : SpanBase(0, 0), type_(type), color_(color), style_(style)
155 {}
156 
DecorationSpan(TextDecoration type,std::optional<Color> color,std::optional<TextDecorationStyle> style,int32_t start,int32_t end)157 DecorationSpan::DecorationSpan(TextDecoration type, std::optional<Color> color,
158     std::optional<TextDecorationStyle> style, int32_t start, int32_t end)
159     : SpanBase(start, end), type_(type), color_(color), style_(style)
160 {}
161 
GetTextDecorationType() const162 TextDecoration DecorationSpan::GetTextDecorationType() const
163 {
164     return type_;
165 }
166 
GetColor() const167 std::optional<Color> DecorationSpan::GetColor() const
168 {
169     return color_;
170 }
171 
GetTextDecorationStyle() const172 std::optional<TextDecorationStyle> DecorationSpan::GetTextDecorationStyle() const
173 {
174     return style_;
175 }
176 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const177 void DecorationSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
178 {
179     switch (operation) {
180         case SpanOperation::ADD:
181             AddDecorationStyle(spanItem);
182             break;
183         case SpanOperation::REMOVE:
184             RemoveDecorationStyle(spanItem);
185     }
186 }
187 
GetSubSpan(int32_t start,int32_t end)188 RefPtr<SpanBase> DecorationSpan::GetSubSpan(int32_t start, int32_t end)
189 {
190     RefPtr<SpanBase> spanBase = MakeRefPtr<DecorationSpan>(type_, color_, style_, start, end);
191     return spanBase;
192 }
193 
AddDecorationStyle(const RefPtr<NG::SpanItem> & spanItem) const194 void DecorationSpan::AddDecorationStyle(const RefPtr<NG::SpanItem>& spanItem) const
195 {
196     spanItem->fontStyle->UpdateTextDecoration(type_);
197     if (color_.has_value()) {
198         spanItem->fontStyle->UpdateTextDecorationColor(color_.value());
199     }
200     if (style_.has_value()) {
201         spanItem->fontStyle->UpdateTextDecorationStyle(style_.value());
202     }
203 }
204 
RemoveDecorationStyle(const RefPtr<NG::SpanItem> & spanItem)205 void DecorationSpan::RemoveDecorationStyle(const RefPtr<NG::SpanItem>& spanItem)
206 {
207     spanItem->fontStyle->ResetTextDecoration();
208     spanItem->fontStyle->ResetTextDecorationColor();
209     spanItem->fontStyle->ResetTextDecorationStyle();
210 }
211 
GetSpanType() const212 SpanType DecorationSpan::GetSpanType() const
213 {
214     return SpanType::Decoration;
215 }
216 
ToString() const217 std::string DecorationSpan::ToString() const
218 {
219     std::stringstream str;
220     str << "DecorationSpan ( start:";
221     str << GetStartIndex();
222     str << " end:";
223     str << GetEndIndex();
224     str << "]";
225     std::string output = str.str();
226     return output;
227 }
228 
IsAttributesEqual(const RefPtr<SpanBase> & other) const229 bool DecorationSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
230 {
231     auto decorationSpan = DynamicCast<DecorationSpan>(other);
232     if (!decorationSpan) {
233         return false;
234     }
235     std::optional<Color> color = decorationSpan->GetColor();
236     std::optional<TextDecorationStyle> style = decorationSpan->GetTextDecorationStyle();
237     TextDecoration type = decorationSpan->GetTextDecorationType();
238     return color == color_ && style == style_ && type == type_;
239 }
240 
241 // BaselineOffsetSpan
BaselineOffsetSpan(Dimension baselineOffset)242 BaselineOffsetSpan::BaselineOffsetSpan(Dimension baselineOffset) : SpanBase(0, 0), baselineOffset_(baselineOffset) {}
243 
BaselineOffsetSpan(Dimension baselineOffset,int32_t start,int32_t end)244 BaselineOffsetSpan::BaselineOffsetSpan(Dimension baselineOffset, int32_t start, int32_t end)
245     : SpanBase(start, end), baselineOffset_(baselineOffset)
246 {}
247 
GetBaselineOffset() const248 Dimension BaselineOffsetSpan::GetBaselineOffset() const
249 {
250     return baselineOffset_;
251 }
252 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const253 void BaselineOffsetSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
254 {
255     switch (operation) {
256         case SpanOperation::ADD:
257             AddBaselineOffsetStyle(spanItem);
258             break;
259         case SpanOperation::REMOVE:
260             RemoveBaselineOffsetStyle(spanItem);
261     }
262 }
263 
GetSubSpan(int32_t start,int32_t end)264 RefPtr<SpanBase> BaselineOffsetSpan::GetSubSpan(int32_t start, int32_t end)
265 {
266     RefPtr<SpanBase> spanBase = MakeRefPtr<BaselineOffsetSpan>(baselineOffset_, start, end);
267     return spanBase;
268 }
269 
AddBaselineOffsetStyle(const RefPtr<NG::SpanItem> & spanItem) const270 void BaselineOffsetSpan::AddBaselineOffsetStyle(const RefPtr<NG::SpanItem>& spanItem) const
271 {
272     spanItem->textLineStyle->UpdateBaselineOffset(baselineOffset_);
273 }
274 
RemoveBaselineOffsetStyle(const RefPtr<NG::SpanItem> & spanItem)275 void BaselineOffsetSpan::RemoveBaselineOffsetStyle(const RefPtr<NG::SpanItem>& spanItem)
276 {
277     spanItem->textLineStyle->ResetBaselineOffset();
278 }
279 
GetSpanType() const280 SpanType BaselineOffsetSpan::GetSpanType() const
281 {
282     return SpanType::BaselineOffset;
283 }
284 
ToString() const285 std::string BaselineOffsetSpan::ToString() const
286 {
287     std::stringstream str;
288     str << "BaselineOffsetSpan ( start:";
289     str << GetStartIndex();
290     str << " end:";
291     str << GetEndIndex();
292     str << "]";
293     std::string output = str.str();
294     return output;
295 }
296 
IsAttributesEqual(const RefPtr<SpanBase> & other) const297 bool BaselineOffsetSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
298 {
299     auto baselineOffsetSpan = DynamicCast<BaselineOffsetSpan>(other);
300     if (!baselineOffsetSpan) {
301         return false;
302     }
303     auto baselineOffset = baselineOffsetSpan->GetBaselineOffset();
304     return baselineOffset == baselineOffset_;
305 }
306 
307 // LetterSpacingSpan
LetterSpacingSpan(Dimension letterSpacing)308 LetterSpacingSpan::LetterSpacingSpan(Dimension letterSpacing) : SpanBase(0, 0), letterSpacing_(letterSpacing) {}
309 
LetterSpacingSpan(Dimension letterSpacing,int32_t start,int32_t end)310 LetterSpacingSpan::LetterSpacingSpan(Dimension letterSpacing, int32_t start, int32_t end)
311     : SpanBase(start, end), letterSpacing_(letterSpacing)
312 {}
313 
GetLetterSpacing() const314 Dimension LetterSpacingSpan::GetLetterSpacing() const
315 {
316     return letterSpacing_;
317 }
318 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const319 void LetterSpacingSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
320 {
321     switch (operation) {
322         case SpanOperation::ADD:
323             AddLetterSpacingStyle(spanItem);
324             break;
325         case SpanOperation::REMOVE:
326             RemoveLetterSpacingStyle(spanItem);
327     }
328 }
329 
GetSubSpan(int32_t start,int32_t end)330 RefPtr<SpanBase> LetterSpacingSpan::GetSubSpan(int32_t start, int32_t end)
331 {
332     RefPtr<SpanBase> spanBase = MakeRefPtr<LetterSpacingSpan>(letterSpacing_, start, end);
333     return spanBase;
334 }
335 
AddLetterSpacingStyle(const RefPtr<NG::SpanItem> & spanItem) const336 void LetterSpacingSpan::AddLetterSpacingStyle(const RefPtr<NG::SpanItem>& spanItem) const
337 {
338     spanItem->fontStyle->UpdateLetterSpacing(letterSpacing_);
339 }
340 
RemoveLetterSpacingStyle(const RefPtr<NG::SpanItem> & spanItem)341 void LetterSpacingSpan::RemoveLetterSpacingStyle(const RefPtr<NG::SpanItem>& spanItem)
342 {
343     spanItem->fontStyle->ResetLetterSpacing();
344 }
345 
GetSpanType() const346 SpanType LetterSpacingSpan::GetSpanType() const
347 {
348     return SpanType::LetterSpacing;
349 }
350 
ToString() const351 std::string LetterSpacingSpan::ToString() const
352 {
353     std::stringstream str;
354     str << "LetterSpacingSpan ( start:";
355     str << GetStartIndex();
356     str << " end:";
357     str << GetEndIndex();
358     str << "]";
359     std::string output = str.str();
360     return output;
361 }
362 
IsAttributesEqual(const RefPtr<SpanBase> & other) const363 bool LetterSpacingSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
364 {
365     auto letterSpacingSpan = DynamicCast<LetterSpacingSpan>(other);
366     if (!letterSpacingSpan) {
367         return false;
368     }
369     auto letterSpacing = letterSpacingSpan->GetLetterSpacing();
370     return letterSpacing == letterSpacing_;
371 }
372 
373 // GestureSpan
GestureSpan(GestureStyle gestureInfo)374 GestureSpan::GestureSpan(GestureStyle gestureInfo) : SpanBase(0, 0), gestureInfo_(std::move(gestureInfo)) {}
375 
GestureSpan(GestureStyle gestureInfo,int32_t start,int32_t end)376 GestureSpan::GestureSpan(GestureStyle gestureInfo, int32_t start, int32_t end)
377     : SpanBase(start, end), gestureInfo_(std::move(gestureInfo))
378 {}
379 
GetGestureStyle() const380 GestureStyle GestureSpan::GetGestureStyle() const
381 {
382     return gestureInfo_;
383 }
384 
GetSubSpan(int32_t start,int32_t end)385 RefPtr<SpanBase> GestureSpan::GetSubSpan(int32_t start, int32_t end)
386 {
387     RefPtr<SpanBase> spanBase = MakeRefPtr<GestureSpan>(gestureInfo_, start, end);
388     return spanBase;
389 }
390 
IsAttributesEqual(const RefPtr<SpanBase> & other) const391 bool GestureSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
392 {
393     auto gestureSpan = DynamicCast<GestureSpan>(other);
394     if (!gestureSpan) {
395         return false;
396     }
397     auto gestureInfo = gestureSpan->GetGestureStyle();
398     return gestureInfo_.IsEqual(gestureInfo);
399 }
400 
GetSpanType() const401 SpanType GestureSpan::GetSpanType() const
402 {
403     return SpanType::Gesture;
404 }
405 
ToString() const406 std::string GestureSpan::ToString() const
407 {
408     std::stringstream str;
409     str << "GestureSpan [ start:";
410     str << GetStartIndex();
411     str << " end:";
412     str << GetEndIndex();
413     str << "]";
414     std::string output = str.str();
415     return output;
416 }
417 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const418 void GestureSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
419 {
420     switch (operation) {
421         case SpanOperation::ADD:
422             AddSpanStyle(spanItem);
423             break;
424         case SpanOperation::REMOVE:
425             RemoveSpanStyle(spanItem);
426     }
427 }
428 
AddSpanStyle(const RefPtr<NG::SpanItem> & spanItem) const429 void GestureSpan::AddSpanStyle(const RefPtr<NG::SpanItem>& spanItem) const
430 {
431     if (gestureInfo_.onClick.has_value()) {
432         spanItem->onClick = gestureInfo_.onClick.value();
433     } else {
434         spanItem->onClick = nullptr;
435     }
436 
437     if (gestureInfo_.onLongPress.has_value()) {
438         spanItem->onLongPress = gestureInfo_.onLongPress.value();
439     } else {
440         spanItem->onLongPress = nullptr;
441     }
442 }
RemoveSpanStyle(const RefPtr<NG::SpanItem> & spanItem)443 void GestureSpan::RemoveSpanStyle(const RefPtr<NG::SpanItem>& spanItem)
444 {
445     spanItem->onClick = nullptr;
446     spanItem->onLongPress = nullptr;
447 }
448 
449 // TextShadowSpan
TextShadowSpan(std::vector<Shadow> textShadow)450 TextShadowSpan::TextShadowSpan(std::vector<Shadow> textShadow) : SpanBase(0, 0), textShadow_(std::move(textShadow)) {}
451 
TextShadowSpan(std::vector<Shadow> textShadow,int32_t start,int32_t end)452 TextShadowSpan::TextShadowSpan(std::vector<Shadow> textShadow, int32_t start, int32_t end)
453     : SpanBase(start, end), textShadow_(std::move(textShadow))
454 {}
455 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const456 void TextShadowSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
457 {
458     switch (operation) {
459         case SpanOperation::ADD:
460             AddSpanStyle(spanItem);
461             break;
462         case SpanOperation::REMOVE:
463             RemoveSpanStyle(spanItem);
464     }
465 }
466 
GetSubSpan(int32_t start,int32_t end)467 RefPtr<SpanBase> TextShadowSpan::GetSubSpan(int32_t start, int32_t end)
468 {
469     RefPtr<SpanBase> spanBase = MakeRefPtr<TextShadowSpan>(GetTextShadow(), start, end);
470     return spanBase;
471 }
472 
AddSpanStyle(const RefPtr<NG::SpanItem> & spanItem) const473 void TextShadowSpan::AddSpanStyle(const RefPtr<NG::SpanItem>& spanItem) const
474 {
475     if (textShadow_.has_value()) {
476         spanItem->fontStyle->UpdateTextShadow(textShadow_.value());
477     }
478 }
479 
RemoveSpanStyle(const RefPtr<NG::SpanItem> & spanItem)480 void TextShadowSpan::RemoveSpanStyle(const RefPtr<NG::SpanItem>& spanItem)
481 {
482     spanItem->fontStyle->ResetTextShadow();
483 }
484 
GetTextShadow() const485 std::vector<Shadow> TextShadowSpan::GetTextShadow() const
486 {
487     return textShadow_.value_or(std::vector<Shadow>());
488 }
489 
GetSpanType() const490 SpanType TextShadowSpan::GetSpanType() const
491 {
492     return SpanType::TextShadow;
493 }
494 
ToString() const495 std::string TextShadowSpan::ToString() const
496 {
497     std::stringstream str;
498     str << "TextShadowSpan ( start:";
499     str << GetStartIndex();
500     str << " end:";
501     str << GetEndIndex();
502     str << "]";
503     std::string output = str.str();
504     return output;
505 }
506 
IsAttributesEqual(const RefPtr<SpanBase> & other) const507 bool TextShadowSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
508 {
509     auto textShadowSpan = DynamicCast<TextShadowSpan>(other);
510     if (!textShadowSpan) {
511         return false;
512     }
513     auto textShadow = textShadowSpan->GetTextShadow();
514     auto selfTextShadow = GetTextShadow();
515     if (textShadow.size() != selfTextShadow.size()) {
516         return false;
517     }
518     for (size_t i = 0; i < selfTextShadow.size(); ++i) {
519         if (selfTextShadow[i] != textShadow[i]) {
520             return false;
521         }
522     }
523     return true;
524 }
525 
526 // ImageSpan
ImageSpan(const ImageSpanOptions & options)527 ImageSpan::ImageSpan(const ImageSpanOptions& options) : SpanBase(0, 1), imageOptions_(options) {}
528 
ImageSpan(const ImageSpanOptions & options,int32_t position)529 ImageSpan::ImageSpan(const ImageSpanOptions& options, int32_t position)
530     : SpanBase(position, position + 1), imageOptions_(options)
531 {}
532 
IsAttributesEqual(const RefPtr<SpanBase> & other) const533 bool ImageSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
534 {
535     auto imageSpan = DynamicCast<ImageSpan>(other);
536     if (!imageSpan) {
537         return false;
538     }
539     if (imageOptions_.imageAttribute.has_value() && imageSpan->GetImageAttribute().has_value()) {
540         return imageOptions_.imageAttribute.value() == imageSpan->GetImageAttribute().value();
541     }
542     return false;
543 }
544 
GetSubSpan(int32_t start,int32_t end)545 RefPtr<SpanBase> ImageSpan::GetSubSpan(int32_t start, int32_t end)
546 {
547     if (end - start > 1) {
548         return nullptr;
549     }
550     auto spanBase = MakeRefPtr<ImageSpan>(imageOptions_);
551     spanBase->UpdateStartIndex(start);
552     spanBase->UpdateEndIndex(end);
553     return spanBase;
554 }
555 
GetSpanType() const556 SpanType ImageSpan::GetSpanType() const
557 {
558     return SpanType::Image;
559 }
560 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const561 void ImageSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
562 {
563     auto imageItem = DynamicCast<NG::ImageSpanItem>(spanItem);
564     if (!imageItem) {
565         return;
566     }
567 
568     switch (operation) {
569         case SpanOperation::ADD:
570             imageItem->SetImageSpanOptions(imageOptions_);
571             break;
572         case SpanOperation::REMOVE:
573             imageItem->ResetImageSpanOptions();
574     }
575 }
576 
ToString() const577 std::string ImageSpan::ToString() const
578 {
579     return "";
580 }
581 
GetImageSpanOptions()582 const ImageSpanOptions& ImageSpan::GetImageSpanOptions()
583 {
584     return imageOptions_;
585 }
586 
GetImageAttribute() const587 const std::optional<ImageSpanAttribute>& ImageSpan::GetImageAttribute() const
588 {
589     return imageOptions_.imageAttribute;
590 }
591 
592 // CustomSpan
CustomSpan()593 CustomSpan::CustomSpan() : SpanBase(0, 1) {}
594 
CustomSpan(std::optional<std::function<CustomSpanMetrics (CustomSpanMeasureInfo)>> onMeasure,std::optional<std::function<void (NG::DrawingContext &,CustomSpanOptions)>> onDraw)595 CustomSpan::CustomSpan(std::optional<std::function<CustomSpanMetrics(CustomSpanMeasureInfo)>> onMeasure,
596     std::optional<std::function<void(NG::DrawingContext&, CustomSpanOptions)>> onDraw)
597     : SpanBase(0, 1), onMeasure_(std::move(onMeasure)), onDraw_(std::move(onDraw))
598 {}
599 
CustomSpan(std::optional<std::function<CustomSpanMetrics (CustomSpanMeasureInfo)>> onMeasure,std::optional<std::function<void (NG::DrawingContext &,CustomSpanOptions)>> onDraw,int32_t start,int32_t end)600 CustomSpan::CustomSpan(std::optional<std::function<CustomSpanMetrics(CustomSpanMeasureInfo)>> onMeasure,
601     std::optional<std::function<void(NG::DrawingContext&, CustomSpanOptions)>> onDraw, int32_t start, int32_t end)
602     : SpanBase(start, end), onMeasure_(std::move(onMeasure)), onDraw_(std::move(onDraw))
603 {}
604 
SetOnMeasure(std::function<CustomSpanMetrics (CustomSpanMeasureInfo)> onMeasure)605 void CustomSpan::SetOnMeasure(std::function<CustomSpanMetrics(CustomSpanMeasureInfo)> onMeasure)
606 {
607     onMeasure_ = onMeasure;
608 }
609 
SetOnDraw(std::function<void (NG::DrawingContext &,CustomSpanOptions)> onDraw)610 void CustomSpan::SetOnDraw(std::function<void(NG::DrawingContext&, CustomSpanOptions)> onDraw)
611 {
612     onDraw_ = onDraw;
613 }
614 
GetOnMeasure()615 std::optional<std::function<CustomSpanMetrics(CustomSpanMeasureInfo)>> CustomSpan::GetOnMeasure()
616 {
617     return onMeasure_;
618 }
619 
GetOnDraw()620 std::optional<std::function<void(NG::DrawingContext&, CustomSpanOptions)>> CustomSpan::GetOnDraw()
621 {
622     return onDraw_;
623 }
624 
GetSubSpan(int32_t start,int32_t end)625 RefPtr<SpanBase> CustomSpan::GetSubSpan(int32_t start, int32_t end)
626 {
627     if (end - start > 1) {
628         return nullptr;
629     }
630     RefPtr<SpanBase> spanBase = MakeRefPtr<CustomSpan>(onMeasure_, onDraw_, start, end);
631     return spanBase;
632 }
633 
GetSpanType() const634 SpanType CustomSpan::GetSpanType() const
635 {
636     return SpanType::CustomSpan;
637 }
638 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const639 void CustomSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
640 {
641     auto imageItem = DynamicCast<NG::CustomSpanItem>(spanItem);
642     if (!imageItem) {
643         return;
644     }
645 
646     switch (operation) {
647         case SpanOperation::ADD:
648             imageItem->onMeasure = onMeasure_;
649             imageItem->onDraw = onDraw_;
650             break;
651         case SpanOperation::REMOVE:
652             imageItem->onMeasure = std::nullopt;
653             imageItem->onDraw = std::nullopt;
654     }
655 }
656 
ToString() const657 std::string CustomSpan::ToString() const
658 {
659     std::stringstream str;
660     str << "CustomSpan ( start:";
661     str << GetStartIndex();
662     str << " end:";
663     str << GetEndIndex();
664     str << "]";
665     std::string output = str.str();
666     return output;
667 }
668 
IsAttributesEqual(const RefPtr<SpanBase> & other) const669 bool CustomSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
670 {
671     return false;
672 }
673 
674 // ParagraphStyleSpan
ParagraphStyleSpan(SpanParagraphStyle paragraphStyle)675 ParagraphStyleSpan::ParagraphStyleSpan(SpanParagraphStyle paragraphStyle)
676     : SpanBase(0, 0), paragraphStyle_(std::move(paragraphStyle))
677 {}
678 
ParagraphStyleSpan(SpanParagraphStyle paragraphStyle,int32_t start,int32_t end)679 ParagraphStyleSpan::ParagraphStyleSpan(SpanParagraphStyle paragraphStyle, int32_t start, int32_t end)
680     : SpanBase(start, end), paragraphStyle_(std::move(paragraphStyle))
681 {}
682 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const683 void ParagraphStyleSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
684 {
685     switch (operation) {
686         case SpanOperation::ADD:
687             AddParagraphStyle(spanItem);
688             break;
689         case SpanOperation::REMOVE:
690             RemoveParagraphStyle(spanItem);
691     }
692 }
693 
AddParagraphStyle(const RefPtr<NG::SpanItem> & spanItem) const694 void ParagraphStyleSpan::AddParagraphStyle(const RefPtr<NG::SpanItem>& spanItem) const
695 {
696     if (paragraphStyle_.align.has_value()) {
697         spanItem->textLineStyle->UpdateTextAlign(paragraphStyle_.align.value());
698     }
699 
700     if (paragraphStyle_.maxLines.has_value()) {
701         spanItem->textLineStyle->UpdateMaxLines(static_cast<uint32_t>(paragraphStyle_.maxLines.value()));
702     }
703 
704     if (paragraphStyle_.textOverflow.has_value()) {
705         spanItem->textLineStyle->UpdateTextOverflow(paragraphStyle_.textOverflow.value());
706     }
707 
708     if (paragraphStyle_.leadingMargin.has_value()) {
709         spanItem->textLineStyle->UpdateLeadingMargin(paragraphStyle_.leadingMargin.value());
710     }
711 
712     if (paragraphStyle_.wordBreak.has_value()) {
713         spanItem->textLineStyle->UpdateWordBreak(paragraphStyle_.wordBreak.value());
714     }
715 
716     if (paragraphStyle_.textIndent.has_value()) {
717         spanItem->textLineStyle->UpdateTextIndent(paragraphStyle_.textIndent.value());
718     }
719 }
720 
RemoveParagraphStyle(const RefPtr<NG::SpanItem> & spanItem) const721 void ParagraphStyleSpan::RemoveParagraphStyle(const RefPtr<NG::SpanItem>& spanItem) const
722 {
723     spanItem->textLineStyle->ResetTextAlign();
724     spanItem->textLineStyle->ResetMaxLines();
725     spanItem->textLineStyle->ResetTextOverflow();
726     spanItem->textLineStyle->ResetLeadingMargin();
727     spanItem->textLineStyle->ResetWordBreak();
728     spanItem->textLineStyle->ResetTextIndent();
729 }
730 
IsAttributesEqual(const RefPtr<SpanBase> & other) const731 bool ParagraphStyleSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
732 {
733     auto paragraphSpan = DynamicCast<ParagraphStyleSpan>(other);
734     if (!paragraphSpan) {
735         return false;
736     }
737     auto paragraphStyle = paragraphSpan->GetParagraphStyle();
738     return paragraphStyle_.Equal(paragraphStyle);
739 }
740 
GetParagraphStyle() const741 SpanParagraphStyle ParagraphStyleSpan::GetParagraphStyle() const
742 {
743     return paragraphStyle_;
744 }
745 
GetSpanType() const746 SpanType ParagraphStyleSpan::GetSpanType() const
747 {
748     return SpanType::ParagraphStyle;
749 }
750 
ToString() const751 std::string ParagraphStyleSpan::ToString() const
752 {
753     return "";
754 }
755 
GetSubSpan(int32_t start,int32_t end)756 RefPtr<SpanBase> ParagraphStyleSpan::GetSubSpan(int32_t start, int32_t end)
757 {
758     RefPtr<SpanBase> spanBase = MakeRefPtr<ParagraphStyleSpan>(paragraphStyle_, start, end);
759     return spanBase;
760 }
761 
762 // LineHeightSpan
LineHeightSpan(Dimension lineHeight)763 LineHeightSpan::LineHeightSpan(Dimension lineHeight) : SpanBase(0, 0), lineHeight_(lineHeight) {}
764 
LineHeightSpan(Dimension lineHeight,int32_t start,int32_t end)765 LineHeightSpan::LineHeightSpan(Dimension lineHeight, int32_t start, int32_t end)
766     : SpanBase(start, end), lineHeight_(lineHeight)
767 {}
768 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const769 void LineHeightSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
770 {
771     switch (operation) {
772         case SpanOperation::ADD:
773             AddLineHeightStyle(spanItem);
774             break;
775         case SpanOperation::REMOVE:
776             RemoveLineHeightStyle(spanItem);
777     }
778 }
779 
GetSubSpan(int32_t start,int32_t end)780 RefPtr<SpanBase> LineHeightSpan::GetSubSpan(int32_t start, int32_t end)
781 {
782     RefPtr<SpanBase> spanBase = MakeRefPtr<LineHeightSpan>(GetLineHeight(), start, end);
783     return spanBase;
784 }
785 
AddLineHeightStyle(const RefPtr<NG::SpanItem> & spanItem) const786 void LineHeightSpan::AddLineHeightStyle(const RefPtr<NG::SpanItem>& spanItem) const
787 {
788     spanItem->textLineStyle->UpdateLineHeight(lineHeight_);
789 }
790 
RemoveLineHeightStyle(const RefPtr<NG::SpanItem> & spanItem) const791 void LineHeightSpan::RemoveLineHeightStyle(const RefPtr<NG::SpanItem>& spanItem) const
792 {
793     spanItem->textLineStyle->ResetLineHeight();
794 }
795 
GetLineHeight() const796 Dimension LineHeightSpan::GetLineHeight() const
797 {
798     return lineHeight_;
799 }
800 
GetSpanType() const801 SpanType LineHeightSpan::GetSpanType() const
802 {
803     return SpanType::LineHeight;
804 }
805 
ToString() const806 std::string LineHeightSpan::ToString() const
807 {
808     std::stringstream str;
809     str << "LineHeightSpan ( start:";
810     str << GetStartIndex();
811     str << " end:";
812     str << GetEndIndex();
813     str << "]";
814     std::string output = str.str();
815     return output;
816 }
817 
IsAttributesEqual(const RefPtr<SpanBase> & other) const818 bool LineHeightSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
819 {
820     auto lineHeightSpan = DynamicCast<LineHeightSpan>(other);
821     if (!lineHeightSpan) {
822         return false;
823     }
824     auto lineHeight = lineHeightSpan->GetLineHeight();
825     return lineHeight_ == lineHeight;
826 }
827 
828 // ExtSpan
ExtSpan(int32_t start,int32_t end)829 ExtSpan::ExtSpan(int32_t start, int32_t end) : SpanBase(start, end) {}
830 
GetSubSpan(int32_t start,int32_t end)831 RefPtr<SpanBase> ExtSpan::GetSubSpan(int32_t start, int32_t end)
832 {
833     RefPtr<SpanBase> spanBase = MakeRefPtr<ExtSpan>(start, end);
834     return spanBase;
835 }
836 
GetSpanType() const837 SpanType ExtSpan::GetSpanType() const
838 {
839     return SpanType::ExtSpan;
840 }
841 
ToString() const842 std::string ExtSpan::ToString() const
843 {
844     std::stringstream str;
845     str << "ExtSpan ( start:";
846     str << GetStartIndex();
847     str << " end:";
848     str << GetEndIndex();
849     str << "]";
850     std::string output = str.str();
851     return output;
852 }
853 
IsAttributesEqual(const RefPtr<SpanBase> & other) const854 bool ExtSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
855 {
856     return false;
857 }
858 
BackgroundColorSpan(std::optional<TextBackgroundStyle> textBackgroundStyle,int32_t start,int32_t end)859 BackgroundColorSpan::BackgroundColorSpan(
860     std::optional<TextBackgroundStyle> textBackgroundStyle, int32_t start, int32_t end)
861     : SpanBase(start, end), textBackgroundStyle_(std::move(textBackgroundStyle))
862 {}
863 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const864 void BackgroundColorSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
865 {
866     switch (operation) {
867         case SpanOperation::ADD:
868             AddSpanStyle(spanItem);
869             break;
870         case SpanOperation::REMOVE:
871             RemoveSpanStyle(spanItem);
872             break;
873     }
874 }
875 
BackgroundColorSpan(std::optional<TextBackgroundStyle> textBackgroundStyle)876 BackgroundColorSpan::BackgroundColorSpan(std::optional<TextBackgroundStyle> textBackgroundStyle)
877     : textBackgroundStyle_(textBackgroundStyle) {}
878 
GetSubSpan(int32_t start,int32_t end)879 RefPtr<SpanBase> BackgroundColorSpan::GetSubSpan(int32_t start, int32_t end)
880 {
881     RefPtr<SpanBase> spanBase = MakeRefPtr<BackgroundColorSpan>(GetBackgroundColor(), start, end);
882     return spanBase;
883 }
AddSpanStyle(const RefPtr<NG::SpanItem> & spanItem) const884 void BackgroundColorSpan::AddSpanStyle(const RefPtr<NG::SpanItem>& spanItem) const
885 {
886     if (textBackgroundStyle_.has_value()) {
887         TextBackgroundStyle tempVal = GetBackgroundColor();
888         spanItem->backgroundStyle = tempVal;
889     }
890 }
891 
RemoveSpanStyle(const RefPtr<NG::SpanItem> & spanItem)892 void BackgroundColorSpan::RemoveSpanStyle(const RefPtr<NG::SpanItem>& spanItem)
893 {
894     if (spanItem->backgroundStyle.has_value()) {
895         spanItem->backgroundStyle.reset();
896     }
897 }
898 
GetBackgroundColor() const899 TextBackgroundStyle BackgroundColorSpan::GetBackgroundColor() const
900 {
901     return textBackgroundStyle_.value();
902 }
903 
SetBackgroundColorGroupId(int32_t groupId)904 void BackgroundColorSpan::SetBackgroundColorGroupId(int32_t groupId)
905 {
906     textBackgroundStyle_->groupId = groupId;
907 }
908 
GetSpanType() const909 SpanType BackgroundColorSpan::GetSpanType() const
910 {
911     return SpanType::BackgroundColor;
912 }
913 
ToString() const914 std::string BackgroundColorSpan::ToString() const
915 {
916     std::stringstream str;
917     str << "BackgroundColorSpan ( start:";
918     str << GetStartIndex();
919     str << " end:";
920     str << GetEndIndex();
921     str << "]";
922     std::string output = str.str();
923     return output;
924 }
925 
IsAttributesEqual(const RefPtr<SpanBase> & other) const926 bool BackgroundColorSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
927 {
928     auto backgroundColorSpan = DynamicCast<BackgroundColorSpan>(other);
929         if (!backgroundColorSpan) {
930             return false;
931         }
932     auto backgroundColor = backgroundColorSpan->GetBackgroundColor();
933     return backgroundColor == textBackgroundStyle_;
934 }
935 
936 // UrlSpan
UrlSpan(const std::string & urlAddress)937 UrlSpan::UrlSpan(const std::string& urlAddress) : SpanBase(0, 0), urlAddress_(urlAddress) {}
938 
UrlSpan(const std::string & urlAddress,int32_t start,int32_t end)939 UrlSpan::UrlSpan(const std::string& urlAddress, int32_t start, int32_t end)
940     : SpanBase(start, end), urlAddress_(urlAddress)
941 {}
942 
GetUrlSpanAddress() const943 std::string UrlSpan::GetUrlSpanAddress() const
944 {
945     return urlAddress_;
946 }
947 
ApplyToSpanItem(const RefPtr<NG::SpanItem> & spanItem,SpanOperation operation) const948 void UrlSpan::ApplyToSpanItem(const RefPtr<NG::SpanItem>& spanItem, SpanOperation operation) const
949 {
950     switch (operation) {
951         case SpanOperation::ADD:
952             AddUrlStyle(spanItem);
953             break;
954         case SpanOperation::REMOVE:
955             RemoveUrlStyle(spanItem);
956             break;
957     }
958 }
959 
GetSubSpan(int32_t start,int32_t end)960 RefPtr<SpanBase> UrlSpan::GetSubSpan(int32_t start, int32_t end)
961 {
962     RefPtr<SpanBase> spanBase = MakeRefPtr<UrlSpan>(urlAddress_, start, end);
963     return spanBase;
964 }
965 
AddUrlStyle(const RefPtr<NG::SpanItem> & spanItem) const966 void UrlSpan::AddUrlStyle(const RefPtr<NG::SpanItem>& spanItem) const
967 {
968     auto address = urlAddress_;
969     auto urlOnRelease = [address]() {
970         auto pipelineContext = PipelineContext::GetCurrentContextSafely();
971         CHECK_NULL_VOID(pipelineContext);
972         pipelineContext->HyperlinkStartAbility(address);
973     };
974     spanItem->SetUrlOnReleaseEvent(std::move(urlOnRelease));
975 }
976 
RemoveUrlStyle(const RefPtr<NG::SpanItem> & spanItem)977 void UrlSpan::RemoveUrlStyle(const RefPtr<NG::SpanItem>& spanItem)
978 {
979     spanItem->urlOnRelease = nullptr;
980 }
981 
GetSpanType() const982 SpanType UrlSpan::GetSpanType() const
983 {
984     return SpanType::Url;
985 }
986 
ToString() const987 std::string UrlSpan::ToString() const
988 {
989     std::stringstream str;
990     str << "UrlSpan ( start:";
991     str << GetStartIndex();
992     str << " end:";
993     str << GetEndIndex();
994     str << "]";
995     std::string output = str.str();
996     return output;
997 }
998 
IsAttributesEqual(const RefPtr<SpanBase> & other) const999 bool UrlSpan::IsAttributesEqual(const RefPtr<SpanBase>& other) const
1000 {
1001     auto urlSpan = DynamicCast<UrlSpan>(other);
1002     if (!urlSpan) {
1003         return false;
1004     }
1005     auto urlAddress = urlSpan->GetUrlSpanAddress();
1006     return urlAddress == urlAddress_;
1007 }
1008 } // namespace OHOS::Ace