1 /*
2  * Copyright (c) 2022-2023 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_node.h"
17 
18 #include <cstdint>
19 #include <optional>
20 #include <string>
21 
22 #include "base/geometry/dimension.h"
23 #include "base/utils/utils.h"
24 #include "core/common/font_manager.h"
25 #include "core/components/common/layout/constants.h"
26 #include "core/components/common/properties/text_style.h"
27 #include "core/components/hyperlink/hyperlink_theme.h"
28 #include "core/components/text/text_theme.h"
29 #include "core/components_ng/base/frame_node.h"
30 #include "core/components_ng/base/inspector_filter.h"
31 #include "core/components_ng/pattern/text/text_pattern.h"
32 #include "core/components_ng/pattern/text/text_styles.h"
33 #include "core/components_ng/property/property.h"
34 #include "core/components_ng/render/drawing_prop_convertor.h"
35 #include "core/components_ng/render/paragraph.h"
36 #include "core/pipeline/pipeline_context.h"
37 #include "core/pipeline_ng/pipeline_context.h"
38 
39 namespace OHOS::Ace::NG {
40 namespace {
GetDeclaration(const std::optional<Color> & color,const std::optional<TextDecoration> & textDecoration,const std::optional<TextDecorationStyle> & textDecorationStyle)41 std::string GetDeclaration(const std::optional<Color>& color, const std::optional<TextDecoration>& textDecoration,
42     const std::optional<TextDecorationStyle>& textDecorationStyle)
43 {
44     auto jsonSpanDeclaration = JsonUtil::Create(true);
45     jsonSpanDeclaration->Put(
46         "type", V2::ConvertWrapTextDecorationToStirng(textDecoration.value_or(TextDecoration::NONE)).c_str());
47     jsonSpanDeclaration->Put("color", (color.value_or(Color::BLACK).ColorToString()).c_str());
48     jsonSpanDeclaration->Put("style",
49         V2::ConvertWrapTextDecorationStyleToString(textDecorationStyle.value_or(TextDecorationStyle::SOLID))
50             .c_str());
51     return jsonSpanDeclaration->ToString();
52 }
ConvertShadowToJson(const Shadow & shadow)53 inline std::unique_ptr<JsonValue> ConvertShadowToJson(const Shadow& shadow)
54 {
55     auto jsonShadow = JsonUtil::Create(true);
56     jsonShadow->Put("radius", std::to_string(shadow.GetBlurRadius()).c_str());
57     jsonShadow->Put("color", shadow.GetColor().ColorToString().c_str());
58     jsonShadow->Put("offsetX", std::to_string(shadow.GetOffset().GetX()).c_str());
59     jsonShadow->Put("offsetY", std::to_string(shadow.GetOffset().GetY()).c_str());
60     jsonShadow->Put("type", std::to_string(static_cast<int32_t>(shadow.GetShadowType())).c_str());
61     return jsonShadow;
62 }
ConvertShadowsToJson(const std::vector<Shadow> & shadows)63 std::unique_ptr<JsonValue> ConvertShadowsToJson(const std::vector<Shadow>& shadows)
64 {
65     auto jsonShadows = JsonUtil::CreateArray(true);
66     for (const auto& shadow : shadows) {
67         jsonShadows->Put(ConvertShadowToJson(shadow));
68     }
69     return jsonShadows;
70 }
71 } // namespace
72 
GetFont() const73 std::string SpanItem::GetFont() const
74 {
75     auto jsonValue = JsonUtil::Create(true);
76     jsonValue->Put("style", GetFontStyleInJson(fontStyle->GetItalicFontStyle()).c_str());
77     jsonValue->Put("size", GetFontSizeInJson(fontStyle->GetFontSize()).c_str());
78     jsonValue->Put("weight", GetFontWeightInJson(fontStyle->GetFontWeight()).c_str());
79     jsonValue->Put("family", GetFontFamilyInJson(fontStyle->GetFontFamily()).c_str());
80     return jsonValue->ToString();
81 }
82 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const83 void SpanItem::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
84 {
85     json->PutFixedAttr("content", content.c_str(), filter, FIXED_ATTR_CONTENT);
86     /* no fixed attr below, just return */
87     if (filter.IsFastFilter()) {
88         TextBackgroundStyle::ToJsonValue(json, backgroundStyle, filter);
89         return;
90     }
91     if (fontStyle) {
92         json->PutExtAttr("font", GetFont().c_str(), filter);
93         json->PutExtAttr("fontSize", GetFontSizeInJson(fontStyle->GetFontSize()).c_str(), filter);
94         json->PutExtAttr("decoration", GetDeclaration(fontStyle->GetTextDecorationColor(),
95             fontStyle->GetTextDecoration(), fontStyle->GetTextDecorationStyle()).c_str(), filter);
96         json->PutExtAttr("letterSpacing",
97             fontStyle->GetLetterSpacing().value_or(Dimension()).ToString().c_str(), filter);
98         json->PutExtAttr("textCase",
99             V2::ConvertWrapTextCaseToStirng(fontStyle->GetTextCase().value_or(TextCase::NORMAL)).c_str(), filter);
100         json->PutExtAttr("fontColor", fontStyle->GetForegroundColor().value_or(fontStyle->GetTextColor()
101             .value_or(Color::BLACK)).ColorToString().c_str(), filter);
102         json->PutExtAttr("fontStyle", GetFontStyleInJson(fontStyle->GetItalicFontStyle()).c_str(), filter);
103         json->PutExtAttr("fontWeight", GetFontWeightInJson(fontStyle->GetFontWeight()).c_str(), filter);
104         json->PutExtAttr("fontFamily", GetFontFamilyInJson(fontStyle->GetFontFamily()).c_str(), filter);
105         json->PutExtAttr("renderingStrategy",
106             GetSymbolRenderingStrategyInJson(fontStyle->GetSymbolRenderingStrategy()).c_str(), filter);
107         json->PutExtAttr(
108             "effectStrategy", GetSymbolEffectStrategyInJson(fontStyle->GetSymbolEffectStrategy()).c_str(), filter);
109         json->Put("symbolEffect",
110             GetSymbolEffectOptionsInJson(fontStyle->GetSymbolEffectOptions().value_or(SymbolEffectOptions())).c_str());
111 
112         auto shadow = fontStyle->GetTextShadow().value_or(std::vector<Shadow> { Shadow() });
113         // Determines if there are multiple textShadows
114         auto jsonShadow = (shadow.size() == 1) ? ConvertShadowToJson(shadow.front()) : ConvertShadowsToJson(shadow);
115         json->PutExtAttr("textShadow", jsonShadow, filter);
116     }
117     if (textLineStyle) {
118         json->PutExtAttr("lineHeight",
119             textLineStyle->GetLineHeight().value_or(Dimension()).ToString().c_str(), filter);
120         json->PutExtAttr("lineSpacing",
121             textLineStyle->GetLineSpacing().value_or(Dimension()).ToString().c_str(), filter);
122         json->PutExtAttr("baselineOffset",
123             textLineStyle->GetBaselineOffset().value_or(Dimension()).ToString().c_str(), filter);
124     }
125     TextBackgroundStyle::ToJsonValue(json, backgroundStyle, filter);
126 }
127 
GetOrCreateSpanNode(int32_t nodeId)128 RefPtr<SpanNode> SpanNode::GetOrCreateSpanNode(int32_t nodeId)
129 {
130     auto spanNode = ElementRegister::GetInstance()->GetSpecificItemById<SpanNode>(nodeId);
131     if (spanNode) {
132         return spanNode;
133     }
134     spanNode = MakeRefPtr<SpanNode>(nodeId);
135     ElementRegister::GetInstance()->AddUINode(spanNode);
136     return spanNode;
137 }
138 
CreateSpanNode(int32_t nodeId)139 RefPtr<SpanNode> SpanNode::CreateSpanNode(int32_t nodeId)
140 {
141     auto spanNode = MakeRefPtr<SpanNode>(nodeId);
142     ElementRegister::GetInstance()->AddUINode(spanNode);
143     return spanNode;
144 }
145 
GetOrCreateSpanNode(const std::string & tag,int32_t nodeId)146 RefPtr<SpanNode> SpanNode::GetOrCreateSpanNode(const std::string& tag, int32_t nodeId)
147 {
148     auto spanNode = ElementRegister::GetInstance()->GetSpecificItemById<SpanNode>(nodeId);
149     if (spanNode) {
150         return spanNode;
151     }
152     spanNode = MakeRefPtr<SpanNode>(tag, nodeId);
153     ElementRegister::GetInstance()->AddUINode(spanNode);
154     return spanNode;
155 }
156 
MountToParagraph()157 void SpanNode::MountToParagraph()
158 {
159     auto parent = GetParent();
160     while (parent) {
161         auto spanNode = DynamicCast<SpanNode>(parent);
162         if (spanNode) {
163             spanNode->AddChildSpanItem(Claim(this));
164             return;
165         }
166         auto textNode = DynamicCast<FrameNode>(parent);
167         if (textNode) {
168             auto textPattern = textNode->GetPattern<TextPattern>();
169             if (textPattern) {
170                 textPattern->AddChildSpanItem(Claim(this));
171                 return;
172             }
173         }
174         parent = parent->GetParent();
175     }
176 }
177 
RequestTextFlushDirty()178 void SpanNode::RequestTextFlushDirty()
179 {
180     RequestTextFlushDirty(Claim<UINode>(this));
181 }
182 
RequestTextFlushDirty(const RefPtr<UINode> & node)183 void SpanNode::RequestTextFlushDirty(const RefPtr<UINode>& node)
184 {
185     CHECK_NULL_VOID(node);
186     auto parent = node->GetParent();
187     while (parent) {
188         auto textNode = DynamicCast<FrameNode>(parent);
189         if (textNode) {
190             textNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
191             auto textPattern = textNode->GetPattern<TextPattern>();
192             if (textPattern) {
193                 textPattern->OnModifyDone();
194                 return;
195             }
196         }
197         parent = parent->GetParent();
198     }
199 }
200 
SetTextBackgroundStyle(const TextBackgroundStyle & style)201 void SpanNode::SetTextBackgroundStyle(const TextBackgroundStyle& style)
202 {
203     BaseSpan::SetTextBackgroundStyle(style);
204     spanItem_->backgroundStyle = GetTextBackgroundStyle();
205 }
206 
UpdateTextBackgroundFromParent(const std::optional<TextBackgroundStyle> & style)207 void SpanNode::UpdateTextBackgroundFromParent(const std::optional<TextBackgroundStyle>& style)
208 {
209     BaseSpan::UpdateTextBackgroundFromParent(style);
210     spanItem_->backgroundStyle = GetTextBackgroundStyle();
211 }
212 
DumpInfo()213 void SpanNode::DumpInfo()
214 {
215     auto& dumpLog = DumpLog::GetInstance();
216     dumpLog.AddDesc(std::string("Content: ").append("\"").append(spanItem_->content).append("\""));
217     auto textStyle = spanItem_->GetTextStyle();
218     if (!textStyle) {
219         return;
220     }
221     dumpLog.AddDesc(std::string("FontSize: ").append(textStyle->GetFontSize().ToString()));
222     dumpLog.AddDesc(std::string("LineHeight: ").append(textStyle->GetLineHeight().ToString()));
223     dumpLog.AddDesc(std::string("LineSpacing: ").append(textStyle->GetLineSpacing().ToString()));
224     dumpLog.AddDesc(std::string("BaselineOffset: ").append(textStyle->GetBaselineOffset().ToString()));
225     dumpLog.AddDesc(std::string("WordSpacing: ").append(textStyle->GetWordSpacing().ToString()));
226     dumpLog.AddDesc(std::string("TextIndent: ").append(textStyle->GetTextIndent().ToString()));
227     dumpLog.AddDesc(std::string("LetterSpacing: ").append(textStyle->GetLetterSpacing().ToString()));
228     dumpLog.AddDesc(std::string("TextColor: ").append(textStyle->GetTextColor().ColorToString()));
229     if (spanItem_ && spanItem_->fontStyle) {
230         dumpLog.AddDesc(std::string("SpanTextColor: ")
231                             .append(spanItem_->fontStyle->GetTextColor().value_or(Color::FOREGROUND).ColorToString()));
232     }
233     dumpLog.AddDesc(std::string("FontWeight: ").append(StringUtils::ToString(textStyle->GetFontWeight())));
234     dumpLog.AddDesc(std::string("FontStyle: ").append(StringUtils::ToString(textStyle->GetFontStyle())));
235     dumpLog.AddDesc(std::string("TextBaseline: ").append(StringUtils::ToString(textStyle->GetTextBaseline())));
236     dumpLog.AddDesc(std::string("TextOverflow: ").append(StringUtils::ToString(textStyle->GetTextOverflow())));
237     dumpLog.AddDesc(std::string("VerticalAlign: ").append(StringUtils::ToString(textStyle->GetTextVerticalAlign())));
238     dumpLog.AddDesc(std::string("TextAlign: ").append(StringUtils::ToString(textStyle->GetTextAlign())));
239     dumpLog.AddDesc(std::string("WordBreak: ").append(StringUtils::ToString(textStyle->GetWordBreak())));
240     dumpLog.AddDesc(std::string("TextCase: ").append(StringUtils::ToString(textStyle->GetTextCase())));
241     dumpLog.AddDesc(std::string("EllipsisMode: ").append(StringUtils::ToString(textStyle->GetEllipsisMode())));
242     dumpLog.AddDesc(std::string("HalfLeading: ").append(std::to_string(textStyle->GetHalfLeading())));
243     if (GetTag() == V2::SYMBOL_SPAN_ETS_TAG) {
244         dumpLog.AddDesc(std::string("SymbolColor:").append(spanItem_->SymbolColorToString()));
245         dumpLog.AddDesc(std::string("RenderStrategy: ").append(std::to_string(textStyle->GetRenderStrategy())));
246         dumpLog.AddDesc(std::string("EffectStrategy: ").append(std::to_string(textStyle->GetEffectStrategy())));
247         dumpLog.AddDesc(std::string("SymbolEffect:").append(
248             spanItem_->fontStyle->GetSymbolEffectOptions().value_or(NG::SymbolEffectOptions()).ToString()));
249     }
250 }
251 
UpdateParagraph(const RefPtr<FrameNode> & frameNode,const RefPtr<Paragraph> & builder,bool isSpanStringMode,PlaceholderStyle,bool isMarquee)252 int32_t SpanItem::UpdateParagraph(const RefPtr<FrameNode>& frameNode, const RefPtr<Paragraph>& builder,
253     bool isSpanStringMode, PlaceholderStyle /*placeholderStyle*/, bool isMarquee)
254 {
255     CHECK_NULL_RETURN(builder, -1);
256     CHECK_NULL_RETURN(frameNode, -1);
257     auto pipelineContext = frameNode->GetContext();
258     CHECK_NULL_RETURN(pipelineContext, -1);
259     auto theme = pipelineContext->GetTheme<TextTheme>();
260     CHECK_NULL_RETURN(theme, -1);
261     auto textStyle = InheritParentProperties(frameNode, isSpanStringMode);
262     UseSelfStyle(fontStyle, textLineStyle, textStyle);
263     auto fontManager = pipelineContext->GetFontManager();
264     if (fontManager && !(fontManager->GetAppCustomFont().empty()) && (textStyle.GetFontFamilies().empty())) {
265         textStyle.SetFontFamilies(Framework::ConvertStrToFontFamilies(fontManager->GetAppCustomFont()));
266     }
267     FontRegisterCallback(frameNode, textStyle);
268     if (NearZero(textStyle.GetFontSize().Value())) {
269         return -1;
270     }
271     CHECK_NULL_RETURN(frameNode, -1);
272     auto textLayoutProp = frameNode->GetLayoutProperty<TextLayoutProperty>();
273     if (textLayoutProp && textLayoutProp->HasHalfLeading()) {
274         textStyle.SetHalfLeading(textLayoutProp->GetHalfLeadingValue(false));
275     } else {
276         textStyle.SetHalfLeading(pipelineContext->GetHalfLeading());
277     }
278 
279     auto spanContent = GetSpanContent(content, isMarquee);
280     auto pattern = frameNode->GetPattern<TextPattern>();
281     CHECK_NULL_RETURN(pattern, -1);
282     textStyle.SetTextBackgroundStyle(backgroundStyle);
283     if (!fontStyle->HasTextColor() && urlOnRelease) {
284         auto urlSpanColor = pattern->GetUrlSpanColor();
285         textStyle.SetTextColor(urlSpanColor);
286         UpdateTextStyle(spanContent, builder, textStyle, selectedStart, selectedEnd);
287     } else if (pattern->NeedShowAIDetect() && !aiSpanMap.empty()) {
288         TextStyle aiSpanStyle = textStyle;
289         pattern->ModifyAISpanStyle(aiSpanStyle);
290         UpdateTextStyleForAISpan(spanContent, builder, textStyle, aiSpanStyle);
291     } else {
292         UpdateTextStyle(spanContent, builder, textStyle, selectedStart, selectedEnd);
293     }
294     textStyle_ = textStyle;
295     return -1;
296 }
297 
UpdateSymbolSpanParagraph(const RefPtr<FrameNode> & frameNode,const RefPtr<Paragraph> & builder)298 void SpanItem::UpdateSymbolSpanParagraph(const RefPtr<FrameNode>& frameNode, const RefPtr<Paragraph>& builder)
299 {
300     CHECK_NULL_VOID(builder);
301     CHECK_NULL_VOID(frameNode);
302     std::optional<TextStyle> textStyle;
303     auto symbolUnicode = GetSymbolUnicode();
304     if (fontStyle || textLineStyle) {
305         auto pipelineContext = frameNode->GetContext();
306         CHECK_NULL_VOID(pipelineContext);
307         TextStyle themeTextStyle =
308             CreateTextStyleUsingTheme(fontStyle, textLineStyle, pipelineContext->GetTheme<TextTheme>());
309         if (frameNode) {
310             FontRegisterCallback(frameNode, themeTextStyle);
311         }
312         if (NearZero(themeTextStyle.GetFontSize().Value())) {
313             return;
314         }
315         auto textLayoutProp = frameNode->GetLayoutProperty<TextLayoutProperty>();
316         if (textLayoutProp && textLayoutProp->HasHalfLeading()) {
317             themeTextStyle.SetHalfLeading(textLayoutProp->GetHalfLeadingValue(false));
318         } else {
319             themeTextStyle.SetHalfLeading(pipelineContext->GetHalfLeading());
320         }
321         textStyle = themeTextStyle;
322         if (symbolUnicode != 0) {
323             UpdateSymbolSpanColor(frameNode, themeTextStyle);
324         }
325         themeTextStyle.SetFontFamilies({"HM Symbol"});
326         builder->PushStyle(themeTextStyle);
327     }
328     textStyle_ = textStyle;
329 
330     if (symbolUnicode != 0) {
331         textStyle_->isSymbolGlyph_ = true;
332         builder->AddSymbol(symbolUnicode);
333     }
334 
335     if (fontStyle || textLineStyle) {
336         builder->PopStyle();
337     }
338 }
339 
UpdateSymbolSpanColor(const RefPtr<FrameNode> & frameNode,TextStyle & symbolSpanStyle)340 void SpanItem::UpdateSymbolSpanColor(const RefPtr<FrameNode>& frameNode, TextStyle& symbolSpanStyle)
341 {
342     symbolSpanStyle.isSymbolGlyph_ = true;
343     CHECK_NULL_VOID(frameNode);
344     if (GetIsParentText() && symbolSpanStyle.GetSymbolColorList().empty()) {
345         RefPtr<LayoutProperty> layoutProperty = frameNode->GetLayoutProperty();
346         CHECK_NULL_VOID(layoutProperty);
347         RefPtr<TextLayoutProperty> textLayoutProperty = DynamicCast<TextLayoutProperty>(layoutProperty);
348         CHECK_NULL_VOID(textLayoutProperty);
349         if (textLayoutProperty->GetTextColor().has_value()) {
350             std::vector<Color> symbolColor;
351             symbolColor.emplace_back(textLayoutProperty->GetTextColor().value());
352             symbolSpanStyle.SetSymbolColorList(symbolColor);
353         }
354     }
355 }
356 
UpdateTextStyleForAISpan(const std::string & spanContent,const RefPtr<Paragraph> & builder,const TextStyle & textStyle,const TextStyle & aiSpanStyle)357 void SpanItem::UpdateTextStyleForAISpan(const std::string& spanContent, const RefPtr<Paragraph>& builder,
358     const TextStyle& textStyle, const TextStyle& aiSpanStyle)
359 {
360     auto wSpanContent = StringUtils::ToWstring(spanContent);
361     int32_t wSpanContentLength = static_cast<int32_t>(wSpanContent.length());
362     int32_t spanStart = position - wSpanContentLength;
363     if (needRemoveNewLine) {
364         spanStart -= 1;
365     }
366     int32_t preEnd = spanStart;
367     while (!aiSpanMap.empty()) {
368         auto aiSpan = aiSpanMap.begin()->second;
369         if (aiSpan.start >= position || preEnd >= position) {
370             break;
371         }
372         int32_t aiSpanStartInSpan = std::max(spanStart, aiSpan.start);
373         int32_t aiSpanEndInSpan = std::min(position, aiSpan.end);
374         if (aiSpan.end <= spanStart || aiSpanStartInSpan < preEnd) {
375             TAG_LOGI(AceLogTag::ACE_TEXT, "Error prediction");
376             aiSpanMap.erase(aiSpanMap.begin());
377             continue;
378         }
379         int32_t contentStart = preEnd - spanStart;
380         if (preEnd < aiSpanStartInSpan) {
381             auto beforeContent =
382                 StringUtils::ToString(wSpanContent.substr(preEnd - spanStart, aiSpanStartInSpan - preEnd));
383             UpdateTextStyle(
384                 beforeContent, builder, textStyle, selectedStart - contentStart, selectedEnd - contentStart);
385             contentStart = contentStart + aiSpanStartInSpan - preEnd;
386         }
387         auto displayContent = StringUtils::ToWstring(aiSpan.content)
388             .substr(aiSpanStartInSpan - aiSpan.start, aiSpanEndInSpan - aiSpanStartInSpan);
389         UpdateTextStyle(StringUtils::ToString(displayContent), builder, aiSpanStyle,
390             selectedStart - contentStart, selectedEnd - contentStart);
391         preEnd = aiSpanEndInSpan;
392         if (aiSpan.end > position) {
393             return;
394         } else {
395             aiSpanMap.erase(aiSpanMap.begin());
396         }
397     }
398     if (preEnd < position) {
399         int32_t contentStart = preEnd - spanStart;
400         auto afterContent = StringUtils::ToString(wSpanContent.substr(preEnd - spanStart, position - preEnd));
401         UpdateTextStyle(afterContent, builder, textStyle, selectedStart - contentStart, selectedEnd - contentStart);
402     }
403 }
404 
FontRegisterCallback(const RefPtr<FrameNode> & frameNode,const TextStyle & textStyle)405 void SpanItem::FontRegisterCallback(const RefPtr<FrameNode>& frameNode, const TextStyle& textStyle)
406 {
407     auto callback = [weakNode = WeakPtr<FrameNode>(frameNode)] {
408         auto frameNode = weakNode.Upgrade();
409         CHECK_NULL_VOID(frameNode);
410         frameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
411         auto pattern = frameNode->GetPattern<TextPattern>();
412         CHECK_NULL_VOID(pattern);
413         auto modifier = DynamicCast<TextContentModifier>(pattern->GetContentModifier());
414         CHECK_NULL_VOID(modifier);
415         modifier->SetFontReady(true);
416     };
417     auto pipeline = frameNode->GetContext();
418     CHECK_NULL_VOID(pipeline);
419     auto fontManager = pipeline->GetFontManager();
420     if (fontManager) {
421         bool isCustomFont = false;
422         for (const auto& familyName : textStyle.GetFontFamilies()) {
423             bool customFont = fontManager->RegisterCallbackNG(frameNode, familyName, callback);
424             if (customFont) {
425                 isCustomFont = true;
426             }
427         }
428         if (isCustomFont) {
429             auto pattern = frameNode->GetPattern<TextPattern>();
430             CHECK_NULL_VOID(pattern);
431             pattern->SetIsCustomFont(true);
432             auto modifier = DynamicCast<TextContentModifier>(pattern->GetContentModifier());
433             CHECK_NULL_VOID(modifier);
434             modifier->SetIsCustomFont(true);
435         }
436     }
437 }
438 
UpdateTextStyle(const std::string & content,const RefPtr<Paragraph> & builder,const TextStyle & textStyle,const int32_t selStart,const int32_t selEnd)439 void SpanItem::UpdateTextStyle(const std::string& content, const RefPtr<Paragraph>& builder, const TextStyle& textStyle,
440     const int32_t selStart, const int32_t selEnd)
441 {
442     if (!IsDragging()) {
443         UpdateContentTextStyle(content, builder, textStyle);
444     } else {
445         if (content.empty()) {
446             builder->PushStyle(textStyle);
447             builder->PopStyle();
448             return;
449         }
450         auto displayContent = StringUtils::Str8ToStr16(content);
451         auto contentLength = static_cast<int32_t>(displayContent.length());
452         if (selStart > 0) {
453             auto beforeSelectedText = displayContent.substr(0, selStart);
454             UpdateContentTextStyle(StringUtils::Str16ToStr8(beforeSelectedText), builder, textStyle);
455         }
456         auto finalSelStart = selStart;
457         if (finalSelStart < 0) {
458             finalSelStart = 0;
459         }
460         auto finalSelEnd = selEnd;
461         if (finalSelEnd < 0) {
462             finalSelEnd = 0;
463         }
464         if (finalSelEnd > 0 && finalSelEnd > contentLength) {
465             finalSelEnd = contentLength;
466         }
467         if (finalSelStart < contentLength) {
468             auto pipelineContext = PipelineContext::GetCurrentContextSafely();
469             TextStyle selectedTextStyle = textStyle;
470             Color color = selectedTextStyle.GetTextColor().ChangeAlpha(DRAGGED_TEXT_OPACITY);
471             selectedTextStyle.SetTextColor(color);
472             Color textDecorationColor = selectedTextStyle.GetTextDecorationColor().ChangeAlpha(DRAGGED_TEXT_OPACITY);
473             selectedTextStyle.SetTextDecorationColor(textDecorationColor);
474             auto selectedText = displayContent.substr(finalSelStart, finalSelEnd - finalSelStart);
475             UpdateContentTextStyle(StringUtils::Str16ToStr8(selectedText), builder, selectedTextStyle);
476         }
477 
478         if (finalSelEnd < contentLength) {
479             auto afterSelectedText = displayContent.substr(finalSelEnd);
480             UpdateContentTextStyle(StringUtils::Str16ToStr8(afterSelectedText), builder, textStyle);
481         }
482     }
483 }
484 
UpdateContentTextStyle(const std::string & content,const RefPtr<Paragraph> & builder,const TextStyle & textStyle)485 void SpanItem::UpdateContentTextStyle(
486     const std::string& content, const RefPtr<Paragraph>& builder, const TextStyle& textStyle)
487 {
488     builder->PushStyle(textStyle);
489     if (!content.empty()) {
490         auto displayText = content;
491         auto textCase = textStyle.GetTextCase();
492         StringUtils::TransformStrCase(displayText, static_cast<int32_t>(textCase));
493         builder->AddText(StringUtils::Str8ToStr16(displayText));
494     }
495     builder->PopStyle();
496 }
497 
GetSpanContent(const std::string & rawContent,bool isMarquee)498 std::string SpanItem::GetSpanContent(const std::string& rawContent, bool isMarquee)
499 {
500     std::string data;
501     if (needRemoveNewLine && !rawContent.empty()) {
502         data = rawContent.substr(0, static_cast<int32_t>(rawContent.length()) - 1);
503     } else {
504         data = rawContent;
505     }
506     if (isMarquee) {
507         std::replace(data.begin(), data.end(), '\n', ' ');
508     }
509     return data;
510 }
511 
GetSpanContent()512 std::string SpanItem::GetSpanContent()
513 {
514     return content;
515 }
516 
GetSymbolUnicode()517 uint32_t SpanItem::GetSymbolUnicode()
518 {
519     return unicode;
520 }
521 
StartDrag(int32_t start,int32_t end)522 void SpanItem::StartDrag(int32_t start, int32_t end)
523 {
524     selectedStart = std::max(0, start);
525     auto contentLen = static_cast<int32_t>(content.size());
526     selectedEnd = std::min(contentLen, end);
527 }
528 
EndDrag()529 void SpanItem::EndDrag()
530 {
531     selectedStart = -1;
532     selectedEnd = -1;
533 }
534 
IsDragging()535 bool SpanItem::IsDragging()
536 {
537     return selectedStart >= 0 && selectedEnd >= 0;
538 }
539 
GetSpanResultObject(int32_t start,int32_t end)540 ResultObject SpanItem::GetSpanResultObject(int32_t start, int32_t end)
541 {
542     bool selectFlag = true;
543     ResultObject resultObject;
544     int32_t endPosition = interval.second;
545     int32_t startPosition = interval.first;
546     int32_t itemLength = endPosition - startPosition;
547 
548     if (startPosition >= start && endPosition <= end) {
549         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
550         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
551     } else if (startPosition < start && endPosition <= end && endPosition > start) {
552         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = start - startPosition;
553         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
554     } else if (startPosition >= start && startPosition < end && endPosition >= end) {
555         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
556         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = end - startPosition;
557     } else if (startPosition <= start && endPosition >= end) {
558         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = start - startPosition;
559         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = end - startPosition;
560     } else {
561         selectFlag = false;
562     }
563     if (selectFlag) {
564         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGESTART] = startPosition;
565         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGEEND] = endPosition;
566         resultObject.type = SelectSpanType::TYPESPAN;
567         resultObject.valueString = content;
568         resultObject.span = WeakClaim(this);
569         resultObject.isInit = true;
570     }
571     return resultObject;
572 }
573 
574 #define INHERIT_TEXT_STYLE(group, name, func)                    \
575     do {                                                         \
576         if ((textLayoutProp)->Has##name()) {                     \
577             textStyle.func(textLayoutProp->Get##name().value()); \
578         }                                                        \
579     } while (false)
580 
InheritParentProperties(const RefPtr<FrameNode> & frameNode,bool isSpanStringMode)581 TextStyle SpanItem::InheritParentProperties(const RefPtr<FrameNode>& frameNode, bool isSpanStringMode)
582 {
583     TextStyle textStyle;
584     auto context = PipelineContext::GetCurrentContextSafely();
585     CHECK_NULL_RETURN(context, textStyle);
586     auto theme = context->GetTheme<TextTheme>();
587     CHECK_NULL_RETURN(theme, textStyle);
588     textStyle = theme->GetTextStyle();
589     CHECK_NULL_RETURN(isSpanStringMode, textStyle);
590     auto textLayoutProp = frameNode->GetLayoutProperty<TextLayoutProperty>();
591     CHECK_NULL_RETURN(textLayoutProp, textStyle);
592     INHERIT_TEXT_STYLE(fontStyle, FontSize, SetFontSize);
593     INHERIT_TEXT_STYLE(fontStyle, TextColor, SetTextColor);
594     INHERIT_TEXT_STYLE(fontStyle, ItalicFontStyle, SetFontStyle);
595     INHERIT_TEXT_STYLE(fontStyle, FontWeight, SetFontWeight);
596     INHERIT_TEXT_STYLE(fontStyle, FontFamily, SetFontFamilies);
597     INHERIT_TEXT_STYLE(fontStyle, TextShadow, SetTextShadows);
598     INHERIT_TEXT_STYLE(fontStyle, TextCase, SetTextCase);
599     INHERIT_TEXT_STYLE(fontStyle, TextDecoration, SetTextDecoration);
600     INHERIT_TEXT_STYLE(fontStyle, TextDecorationColor, SetTextDecorationColor);
601     INHERIT_TEXT_STYLE(fontStyle, TextDecorationStyle, SetTextDecorationStyle);
602     INHERIT_TEXT_STYLE(fontStyle, LetterSpacing, SetLetterSpacing);
603     INHERIT_TEXT_STYLE(fontStyle, FontFeature, SetFontFeatures);
604     INHERIT_TEXT_STYLE(fontStyle, MinFontScale, SetMinFontScale);
605     INHERIT_TEXT_STYLE(fontStyle, MaxFontScale, SetMaxFontScale);
606     if (!GetHasUserFontWeight()) {
607         INHERIT_TEXT_STYLE(fontStyle, VariableFontWeight, SetVariableFontWeight);
608         INHERIT_TEXT_STYLE(fontStyle, EnableVariableFontWeight, SetEnableVariableFontWeight);
609     }
610     INHERIT_TEXT_STYLE(textLineStyle, LineHeight, SetLineHeight);
611     INHERIT_TEXT_STYLE(textLineStyle, LineSpacing, SetLineSpacing);
612     INHERIT_TEXT_STYLE(textLineStyle, HalfLeading, SetHalfLeading);
613     return textStyle;
614 }
615 
616 #define COPY_TEXT_STYLE(group, name, func)                      \
617     do {                                                        \
618         if ((group)->Has##name()) {                             \
619             sameSpan->group->func((group)->prop##name.value()); \
620         }                                                       \
621     } while (false)
622 
GetSameStyleSpanItem() const623 RefPtr<SpanItem> SpanItem::GetSameStyleSpanItem() const
624 {
625     auto sameSpan = MakeRefPtr<SpanItem>();
626     COPY_TEXT_STYLE(fontStyle, FontSize, UpdateFontSize);
627     COPY_TEXT_STYLE(fontStyle, TextColor, UpdateTextColor);
628     COPY_TEXT_STYLE(fontStyle, TextShadow, UpdateTextShadow);
629     COPY_TEXT_STYLE(fontStyle, ItalicFontStyle, UpdateItalicFontStyle);
630     COPY_TEXT_STYLE(fontStyle, FontWeight, UpdateFontWeight);
631     COPY_TEXT_STYLE(fontStyle, FontFamily, UpdateFontFamily);
632     COPY_TEXT_STYLE(fontStyle, FontFeature, UpdateFontFeature);
633     COPY_TEXT_STYLE(fontStyle, TextDecoration, UpdateTextDecoration);
634     COPY_TEXT_STYLE(fontStyle, TextDecorationColor, UpdateTextDecorationColor);
635     COPY_TEXT_STYLE(fontStyle, TextDecorationStyle, UpdateTextDecorationStyle);
636     COPY_TEXT_STYLE(fontStyle, TextCase, UpdateTextCase);
637     COPY_TEXT_STYLE(fontStyle, AdaptMinFontSize, UpdateAdaptMinFontSize);
638     COPY_TEXT_STYLE(fontStyle, AdaptMaxFontSize, UpdateAdaptMaxFontSize);
639     COPY_TEXT_STYLE(fontStyle, LetterSpacing, UpdateLetterSpacing);
640     COPY_TEXT_STYLE(fontStyle, MinFontScale, UpdateMinFontScale);
641     COPY_TEXT_STYLE(fontStyle, MaxFontScale, UpdateMaxFontScale);
642 
643     COPY_TEXT_STYLE(textLineStyle, LineHeight, UpdateLineHeight);
644     COPY_TEXT_STYLE(textLineStyle, LineSpacing, UpdateLineSpacing);
645     COPY_TEXT_STYLE(textLineStyle, TextBaseline, UpdateTextBaseline);
646     COPY_TEXT_STYLE(textLineStyle, BaselineOffset, UpdateBaselineOffset);
647     COPY_TEXT_STYLE(textLineStyle, TextOverflow, UpdateTextOverflow);
648     COPY_TEXT_STYLE(textLineStyle, TextAlign, UpdateTextAlign);
649     COPY_TEXT_STYLE(textLineStyle, MaxLength, UpdateMaxLength);
650     COPY_TEXT_STYLE(textLineStyle, MaxLines, UpdateMaxLines);
651     COPY_TEXT_STYLE(textLineStyle, HeightAdaptivePolicy, UpdateHeightAdaptivePolicy);
652     COPY_TEXT_STYLE(textLineStyle, TextIndent, UpdateTextIndent);
653     COPY_TEXT_STYLE(textLineStyle, LeadingMargin, UpdateLeadingMargin);
654     COPY_TEXT_STYLE(textLineStyle, WordBreak, UpdateWordBreak);
655     COPY_TEXT_STYLE(textLineStyle, LineBreakStrategy, UpdateLineBreakStrategy);
656     COPY_TEXT_STYLE(textLineStyle, EllipsisMode, UpdateEllipsisMode);
657     COPY_TEXT_STYLE(textLineStyle, HalfLeading, UpdateHalfLeading);
658 
659     if (backgroundStyle.has_value()) {
660         sameSpan->backgroundStyle = backgroundStyle;
661     }
662 
663     sameSpan->urlOnRelease = urlOnRelease;
664     sameSpan->onClick = onClick;
665     sameSpan->onLongPress = onLongPress;
666     return sameSpan;
667 }
668 
669 #define WRITE_TEXT_STYLE_TLV(group, name, tag, type)                   \
670     do {                                                               \
671         if ((group)->Has##name()) {                                    \
672             TLVUtil::WriteUint8(buff, (tag));                          \
673             TLVUtil::Write##type(buff, (group)->prop##name.value());   \
674         }                                                              \
675     } while (false)
676 
677 #define READ_TEXT_STYLE_TLV(group, func, tag, type)                         \
678     case tag: {                                                             \
679         sameSpan->group->func(TLVUtil::Read##type(buff, cursor));           \
680         break;                                                              \
681     }
682 
EncodeTlv(std::vector<uint8_t> & buff)683 bool SpanItem::EncodeTlv(std::vector<uint8_t>& buff)
684 {
685     TLVUtil::WriteUint8(buff, TLV_SPANITEM_TAG);
686     TLVUtil::WriteInt32(buff, interval.first);
687     TLVUtil::WriteInt32(buff, interval.second);
688     TLVUtil::WriteString(buff, content);
689     // encode fontStyle
690     WRITE_TEXT_STYLE_TLV(fontStyle, FontSize, TLV_SPAN_FONT_STYLE_FONTSIZE, Dimension);
691     WRITE_TEXT_STYLE_TLV(fontStyle, TextColor, TLV_SPAN_FONT_STYLE_TEXTCOLOR, Color);
692     WRITE_TEXT_STYLE_TLV(fontStyle, TextShadow, TLV_SPAN_FONT_STYLE_TEXTSHADOW, TextShadows);
693     WRITE_TEXT_STYLE_TLV(fontStyle, ItalicFontStyle, TLV_SPAN_FONT_STYLE_ITALICFONTSTYLE, FontStyle);
694     WRITE_TEXT_STYLE_TLV(fontStyle, FontWeight, TLV_SPAN_FONT_STYLE_FONTWEIGHT, FontWeight);
695     WRITE_TEXT_STYLE_TLV(fontStyle, FontFamily, TLV_SPAN_FONT_STYLE_FONTFAMILY, FontFamily);
696     WRITE_TEXT_STYLE_TLV(fontStyle, FontFeature, TLV_SPAN_FONT_STYLE_FONTFEATURE, FontFeature);
697     WRITE_TEXT_STYLE_TLV(fontStyle, TextDecoration, TLV_SPAN_FONT_STYLE_TEXTDECORATION, TextDecoration);
698     WRITE_TEXT_STYLE_TLV(fontStyle, TextDecorationColor, TLV_SPAN_FONT_STYLE_TEXTDECORATIONCOLOR, Color);
699     WRITE_TEXT_STYLE_TLV(fontStyle, TextDecorationStyle, TLV_SPAN_FONT_STYLE_TEXTDECORATIONSTYLE, TextDecorationStyle);
700     WRITE_TEXT_STYLE_TLV(fontStyle, TextCase, TLV_SPAN_FONT_STYLE_TEXTCASE, TextCase);
701     WRITE_TEXT_STYLE_TLV(fontStyle, AdaptMinFontSize, TLV_SPAN_FONT_STYLE_ADPATMINFONTSIZE, Dimension);
702     WRITE_TEXT_STYLE_TLV(fontStyle, AdaptMaxFontSize, TLV_SPAN_FONT_STYLE_ADPATMAXFONTSIZE, Dimension);
703     WRITE_TEXT_STYLE_TLV(fontStyle, LetterSpacing, TLV_SPAN_FONT_STYLE_LETTERSPACING, Dimension);
704 
705     WRITE_TEXT_STYLE_TLV(textLineStyle, LineHeight, TLV_SPAN_TEXT_LINE_STYLE_LINEHEIGHT, Dimension);
706     WRITE_TEXT_STYLE_TLV(textLineStyle, LineSpacing, TLV_SPAN_TEXT_LINE_STYLE_LINESPACING, Dimension);
707     WRITE_TEXT_STYLE_TLV(textLineStyle, TextBaseline, TLV_SPAN_TEXT_LINE_STYLE_TEXTBASELINE, TextBaseline);
708     WRITE_TEXT_STYLE_TLV(textLineStyle, BaselineOffset, TLV_SPAN_TEXT_LINE_STYLE_BASELINEOFFSET, Dimension);
709     WRITE_TEXT_STYLE_TLV(textLineStyle, TextOverflow, TLV_SPAN_TEXT_LINE_STYLE_TEXTOVERFLOW, TextOverflow);
710     WRITE_TEXT_STYLE_TLV(textLineStyle, TextAlign, TLV_SPAN_TEXT_LINE_STYLE_TEXTALIGN, TextAlign);
711     WRITE_TEXT_STYLE_TLV(textLineStyle, MaxLength, TLV_SPAN_TEXT_LINE_STYLE_MAXLENGTH, Int32);
712     WRITE_TEXT_STYLE_TLV(textLineStyle, MaxLines, TLV_SPAN_TEXT_LINE_STYLE_MAXLINES, Int32);
713     WRITE_TEXT_STYLE_TLV(textLineStyle, HeightAdaptivePolicy,
714         TLV_SPAN_TEXT_LINE_STYLE_HEIGHTADAPTIVEPOLICY, TextHeightAdaptivePolicy);
715     WRITE_TEXT_STYLE_TLV(textLineStyle, TextIndent, TLV_SPAN_TEXT_LINE_STYLE_TEXTINDENT, Dimension);
716     WRITE_TEXT_STYLE_TLV(textLineStyle, LeadingMargin, TLV_SPAN_TEXT_LINE_STYLE_LEADINGMARGIN, LeadingMargin);
717     WRITE_TEXT_STYLE_TLV(textLineStyle, WordBreak, TLV_SPAN_TEXT_LINE_STYLE_WORDBREAK, WordBreak);
718     WRITE_TEXT_STYLE_TLV(textLineStyle, LineBreakStrategy,
719         TLV_SPAN_TEXT_LINE_STYLE_LINEBREAKSTRATEGY, LineBreakStrategy);
720     WRITE_TEXT_STYLE_TLV(textLineStyle, EllipsisMode, TLV_SPAN_TEXT_LINE_STYLE_ELLIPSISMODE, EllipsisMode);
721     if (backgroundStyle.has_value()) {
722         if (backgroundStyle->backgroundColor.has_value()) {
723             TLVUtil::WriteUint8(buff, TLV_SPAN_BACKGROUND_BACKGROUNDCOLOR);
724             TLVUtil::WriteColor(buff, backgroundStyle->backgroundColor.value());
725         }
726         if (backgroundStyle->backgroundRadius.has_value()) {
727             TLVUtil::WriteUint8(buff, TLV_SPAN_BACKGROUND_BACKGROUNDRADIUS);
728             TLVUtil::WriteBorderRadiusProperty(buff, backgroundStyle->backgroundRadius.value());
729         }
730         TLVUtil::WriteUint8(buff, TLV_SPAN_BACKGROUND_GROUPID);
731         TLVUtil::WriteInt32(buff, backgroundStyle->groupId);
732     }
733     TLVUtil::WriteUint8(buff, TLV_SPANITEM_END_TAG);
734     return true;
735 };
736 
DecodeTlv(std::vector<uint8_t> & buff,int32_t & cursor)737 RefPtr<SpanItem> SpanItem::DecodeTlv(std::vector<uint8_t>& buff, int32_t& cursor)
738 {
739     auto sameSpan = MakeRefPtr<SpanItem>();
740     if (TLVUtil::ReadUint8(buff, cursor) != TLV_SPANITEM_TAG) {
741         return sameSpan;
742     }
743 
744     int32_t start = TLVUtil::ReadInt32(buff, cursor);
745     int32_t end = TLVUtil::ReadInt32(buff, cursor);
746     sameSpan->interval = {start, end};
747     sameSpan->content = TLVUtil::ReadString(buff, cursor);
748 
749     for (uint8_t tag = TLVUtil::ReadUint8(buff, cursor);
750         tag != TLV_SPANITEM_END_TAG; tag = TLVUtil::ReadUint8(buff, cursor)) {
751         switch (tag) {
752             READ_TEXT_STYLE_TLV(fontStyle, UpdateFontSize, TLV_SPAN_FONT_STYLE_FONTSIZE, Dimension);
753             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextColor, TLV_SPAN_FONT_STYLE_TEXTCOLOR, Color);
754             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextShadow, TLV_SPAN_FONT_STYLE_TEXTSHADOW, TextShadows);
755             READ_TEXT_STYLE_TLV(fontStyle, UpdateItalicFontStyle, TLV_SPAN_FONT_STYLE_ITALICFONTSTYLE, FontStyle);
756             READ_TEXT_STYLE_TLV(fontStyle, UpdateFontWeight, TLV_SPAN_FONT_STYLE_FONTWEIGHT, FontWeight);
757             READ_TEXT_STYLE_TLV(fontStyle, UpdateFontFamily, TLV_SPAN_FONT_STYLE_FONTFAMILY, FontFamily);
758             READ_TEXT_STYLE_TLV(fontStyle, UpdateFontFeature, TLV_SPAN_FONT_STYLE_FONTFEATURE, FontFeature);
759             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextDecoration, TLV_SPAN_FONT_STYLE_TEXTDECORATION, TextDecoration);
760             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextDecorationColor, TLV_SPAN_FONT_STYLE_TEXTDECORATIONCOLOR, Color);
761             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextDecorationStyle,
762                 TLV_SPAN_FONT_STYLE_TEXTDECORATIONSTYLE, TextDecorationStyle);
763             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextCase, TLV_SPAN_FONT_STYLE_TEXTCASE, TextCase);
764             READ_TEXT_STYLE_TLV(fontStyle, UpdateAdaptMinFontSize, TLV_SPAN_FONT_STYLE_ADPATMINFONTSIZE, Dimension);
765             READ_TEXT_STYLE_TLV(fontStyle, UpdateAdaptMaxFontSize, TLV_SPAN_FONT_STYLE_ADPATMAXFONTSIZE, Dimension);
766             READ_TEXT_STYLE_TLV(fontStyle, UpdateLetterSpacing, TLV_SPAN_FONT_STYLE_LETTERSPACING, Dimension);
767 
768             READ_TEXT_STYLE_TLV(textLineStyle, UpdateLineHeight, TLV_SPAN_TEXT_LINE_STYLE_LINEHEIGHT, Dimension);
769             READ_TEXT_STYLE_TLV(textLineStyle, UpdateLineSpacing, TLV_SPAN_TEXT_LINE_STYLE_LINESPACING, Dimension);
770             READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextBaseline, TLV_SPAN_TEXT_LINE_STYLE_TEXTBASELINE, TextBaseline);
771             READ_TEXT_STYLE_TLV(textLineStyle, UpdateBaselineOffset,
772                 TLV_SPAN_TEXT_LINE_STYLE_BASELINEOFFSET, Dimension);
773             READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextOverflow, TLV_SPAN_TEXT_LINE_STYLE_TEXTOVERFLOW, TextOverflow);
774             READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextAlign, TLV_SPAN_TEXT_LINE_STYLE_TEXTALIGN, TextAlign);
775             READ_TEXT_STYLE_TLV(textLineStyle, UpdateMaxLength, TLV_SPAN_TEXT_LINE_STYLE_MAXLENGTH, Int32);
776             READ_TEXT_STYLE_TLV(textLineStyle, UpdateMaxLines, TLV_SPAN_TEXT_LINE_STYLE_MAXLINES, Int32);
777             READ_TEXT_STYLE_TLV(textLineStyle, UpdateHeightAdaptivePolicy,
778                 TLV_SPAN_TEXT_LINE_STYLE_HEIGHTADAPTIVEPOLICY, TextHeightAdaptivePolicy);
779             READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextIndent, TLV_SPAN_TEXT_LINE_STYLE_TEXTINDENT, Dimension);
780             READ_TEXT_STYLE_TLV(textLineStyle, UpdateLeadingMargin,
781                 TLV_SPAN_TEXT_LINE_STYLE_LEADINGMARGIN, LeadingMargin);
782             READ_TEXT_STYLE_TLV(textLineStyle, UpdateWordBreak, TLV_SPAN_TEXT_LINE_STYLE_WORDBREAK, WordBreak);
783             READ_TEXT_STYLE_TLV(textLineStyle, UpdateLineBreakStrategy,
784                 TLV_SPAN_TEXT_LINE_STYLE_LINEBREAKSTRATEGY, LineBreakStrategy);
785             READ_TEXT_STYLE_TLV(textLineStyle, UpdateEllipsisMode, TLV_SPAN_TEXT_LINE_STYLE_ELLIPSISMODE, EllipsisMode);
786 
787             case TLV_SPAN_BACKGROUND_BACKGROUNDCOLOR: {
788                 sameSpan->backgroundStyle->backgroundColor = TLVUtil::ReadColor(buff, cursor);
789                 break;
790             }
791             case TLV_SPAN_BACKGROUND_BACKGROUNDRADIUS: {
792                 sameSpan->backgroundStyle->backgroundRadius = TLVUtil::ReadBorderRadiusProperty(buff, cursor);
793                 break;
794             }
795             case TLV_SPAN_BACKGROUND_GROUPID: {
796                 sameSpan->backgroundStyle->groupId = TLVUtil::ReadInt32(buff, cursor);
797                 break;
798             }
799             default:
800                 break;
801         }
802     }
803 
804     return sameSpan;
805 }
806 
SymbolColorToString()807 std::string SpanItem::SymbolColorToString()
808 {
809     auto colors = fontStyle->GetSymbolColorList();
810     auto colorStr = std::string("[");
811     if (colors.has_value()) {
812         for (const auto& color : colors.value()) {
813             colorStr.append(color.ColorToString());
814             colorStr.append(",");
815         }
816     }
817     colorStr.append("]");
818     return colorStr;
819 }
820 
GetIntersectionInterval(std::pair<int32_t,int32_t> interval) const821 std::optional<std::pair<int32_t, int32_t>> SpanItem::GetIntersectionInterval(std::pair<int32_t, int32_t> interval) const
822 {
823     // Check the intersection
824     if (this->interval.second <= interval.first || interval.second <= this->interval.first) {
825         return std::nullopt;
826     }
827 
828     // Calculate the intersection interval
829     int32_t start = std::max(this->interval.first, interval.first);
830     int32_t end = std::min(this->interval.second, interval.second);
831     return std::make_optional<std::pair<int32_t, int32_t>>(std::make_pair(start, end));
832 }
833 
EncodeTlv(std::vector<uint8_t> & buff)834 bool ImageSpanItem::EncodeTlv(std::vector<uint8_t>& buff)
835 {
836     TLVUtil::WriteUint8(buff, TLV_IMAGESPANITEM_TAG);
837     TLVUtil::WriteInt32(buff, interval.first);
838     TLVUtil::WriteInt32(buff, interval.second);
839     TLVUtil::WriteString(buff, content);
840     if (options.offset.has_value()) {
841         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_OFFSET_TAG);
842         TLVUtil::WriteInt32(buff, options.offset.value());
843     }
844     if (options.image.has_value()) {
845         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_IMAGE_TAG);
846         TLVUtil::WriteString(buff, options.image.value());
847     }
848     if (options.bundleName.has_value()) {
849         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_BUNDLENAME_TAG);
850         TLVUtil::WriteString(buff, options.bundleName.value());
851     }
852     if (options.bundleName.has_value()) {
853         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_MODULENAME_TAG);
854         TLVUtil::WriteString(buff, options.moduleName.value());
855     }
856     if (options.imagePixelMap.has_value()) {
857         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_IMAGEPIXELMAP_TAG);
858         TLVUtil::WritePixelMap(buff, options.imagePixelMap.value());
859     }
860     if (options.imageAttribute.has_value()) {
861         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_IMAGEATTRIBUTE_TAG);
862         TLVUtil::WriteImageSpanAttribute(buff, options.imageAttribute.value());
863     }
864     TLVUtil::WriteUint8(buff, TLV_SPANITEM_END_TAG);
865     return true;
866 }
867 
DecodeTlv(std::vector<uint8_t> & buff,int32_t & cursor)868 RefPtr<ImageSpanItem> ImageSpanItem::DecodeTlv(std::vector<uint8_t>& buff, int32_t& cursor)
869 {
870     auto sameSpan = MakeRefPtr<ImageSpanItem>();
871 
872     if (TLVUtil::ReadUint8(buff, cursor) != TLV_IMAGESPANITEM_TAG) {
873         return sameSpan;
874     }
875 
876     int32_t start = TLVUtil::ReadInt32(buff, cursor);
877     int32_t end = TLVUtil::ReadInt32(buff, cursor);
878     sameSpan->interval = {start, end};
879     sameSpan->content = TLVUtil::ReadString(buff, cursor);
880 
881     for (uint8_t tag = TLVUtil::ReadUint8(buff, cursor);
882         tag != TLV_SPANITEM_END_TAG; tag = TLVUtil::ReadUint8(buff, cursor)) {
883         switch (tag) {
884             case TLV_IMAGESPANOPTION_OFFSET_TAG: {
885                 sameSpan->options.offset = TLVUtil::ReadInt32(buff, cursor);
886                 break;
887             }
888             case TLV_IMAGESPANOPTION_IMAGE_TAG: {
889                 sameSpan->options.image = TLVUtil::ReadString(buff, cursor);
890                 break;
891             }
892             case TLV_IMAGESPANOPTION_BUNDLENAME_TAG: {
893                 sameSpan->options.bundleName = TLVUtil::ReadString(buff, cursor);
894                 break;
895             }
896             case TLV_IMAGESPANOPTION_MODULENAME_TAG: {
897                 sameSpan->options.moduleName = TLVUtil::ReadString(buff, cursor);
898                 break;
899             }
900             case TLV_IMAGESPANOPTION_IMAGEPIXELMAP_TAG: {
901                 sameSpan->options.imagePixelMap = TLVUtil::ReadPixelMap(buff, cursor);
902                 break;
903             }
904             case TLV_IMAGESPANOPTION_IMAGEATTRIBUTE_TAG: {
905                 sameSpan->options.imageAttribute = TLVUtil::ReadImageSpanAttribute(buff, cursor);
906                 break;
907             }
908             default:
909                 break;
910         }
911     }
912     return sameSpan;
913 }
914 
UpdateParagraph(const RefPtr<FrameNode> &,const RefPtr<Paragraph> & builder,bool,PlaceholderStyle placeholderStyle,bool)915 int32_t ImageSpanItem::UpdateParagraph(const RefPtr<FrameNode>& /* frameNode */, const RefPtr<Paragraph>& builder,
916     bool /* isSpanStringMode */, PlaceholderStyle placeholderStyle, bool /* isMarquee*/)
917 {
918     CHECK_NULL_RETURN(builder, -1);
919     PlaceholderRun run;
920     run.width = placeholderStyle.width;
921     run.height = placeholderStyle.height;
922     if (!NearZero(placeholderStyle.baselineOffset)) {
923         run.baseline_offset = placeholderStyle.baselineOffset;
924         run.alignment = PlaceholderAlignment::BASELINE;
925     } else {
926         switch (placeholderStyle.verticalAlign) {
927             case VerticalAlign::TOP:
928                 run.alignment = PlaceholderAlignment::TOP;
929                 break;
930             case VerticalAlign::CENTER:
931                 run.alignment = PlaceholderAlignment::MIDDLE;
932                 break;
933             case VerticalAlign::BOTTOM:
934             case VerticalAlign::NONE:
935                 run.alignment = PlaceholderAlignment::BOTTOM;
936                 break;
937             case VerticalAlign::BASELINE:
938                 run.alignment = PlaceholderAlignment::ABOVEBASELINE;
939                 break;
940             default:
941                 run.alignment = PlaceholderAlignment::BOTTOM;
942         }
943     }
944 
945     // ImageSpan should ignore decoration styles
946     textStyle.SetTextDecoration(TextDecoration::NONE);
947     textStyle.SetTextBackgroundStyle(backgroundStyle);
948     textStyle.SetFontSize(placeholderStyle.paragraphFontSize);
949     textStyle.SetTextColor(placeholderStyle.paragraphTextColor);
950     builder->PushStyle(textStyle);
951     int32_t index = builder->AddPlaceholder(run);
952     run_ = run;
953     builder->PopStyle();
954     return index;
955 }
956 
UpdatePlaceholderBackgroundStyle(const RefPtr<FrameNode> & imageNode)957 void ImageSpanItem::UpdatePlaceholderBackgroundStyle(const RefPtr<FrameNode>& imageNode)
958 {
959     CHECK_NULL_VOID(imageNode);
960     auto property = imageNode->GetLayoutProperty<ImageLayoutProperty>();
961     CHECK_NULL_VOID(property);
962     backgroundStyle = property->GetPlaceHolderStyle();
963 }
964 
SetImageSpanOptions(const ImageSpanOptions & options)965 void ImageSpanItem::SetImageSpanOptions(const ImageSpanOptions& options)
966 {
967     this->options = options;
968 }
969 
ResetImageSpanOptions()970 void ImageSpanItem::ResetImageSpanOptions()
971 {
972     options.imageAttribute.reset();
973 }
974 
GetSameStyleSpanItem() const975 RefPtr<SpanItem> ImageSpanItem::GetSameStyleSpanItem() const
976 {
977     auto sameSpan = MakeRefPtr<ImageSpanItem>();
978     sameSpan->SetImageSpanOptions(options);
979     sameSpan->urlOnRelease = urlOnRelease;
980     sameSpan->onClick = onClick;
981     sameSpan->onLongPress = onLongPress;
982     if (backgroundStyle.has_value()) {
983         sameSpan->backgroundStyle = backgroundStyle;
984     }
985     return sameSpan;
986 }
987 
GetSpanResultObject(int32_t start,int32_t end)988 ResultObject ImageSpanItem::GetSpanResultObject(int32_t start, int32_t end)
989 {
990     int32_t itemLength = 1;
991     ResultObject resultObject;
992 
993     int32_t endPosition = interval.second;
994     int32_t startPosition = interval.first;
995     resultObject.type = SelectSpanType::TYPEIMAGE;
996     if ((start <= startPosition) && (end >= endPosition)) {
997         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGESTART] = startPosition;
998         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGEEND] = endPosition;
999         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
1000         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
1001         if (options.image.has_value()) {
1002             resultObject.valueString = options.image.value();
1003         }
1004         if (options.imagePixelMap.has_value()) {
1005             resultObject.valuePixelMap = options.imagePixelMap.value();
1006         }
1007         resultObject.isInit = true;
1008     }
1009     return resultObject;
1010 }
1011 
GetSpanResultObject(int32_t start,int32_t end)1012 ResultObject CustomSpanItem::GetSpanResultObject(int32_t start, int32_t end)
1013 {
1014     int32_t itemLength = 1;
1015     ResultObject resultObject;
1016 
1017     int32_t endPosition = interval.second;
1018     int32_t startPosition = interval.first;
1019     resultObject.type = SelectSpanType::TYPEBUILDERSPAN;
1020     if ((start <= startPosition) && (end >= endPosition)) {
1021         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGESTART] = startPosition;
1022         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGEEND] = endPosition;
1023         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
1024         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
1025         resultObject.valueString = " ";
1026         resultObject.isInit = true;
1027     }
1028     return resultObject;
1029 }
1030 
UpdateSpanTextColor(Color color)1031 bool SpanItem::UpdateSpanTextColor(Color color)
1032 {
1033     auto pattern = pattern_.Upgrade();
1034     CHECK_NULL_RETURN(pattern, false);
1035     auto textPattern = DynamicCast<TextPattern>(pattern);
1036     CHECK_NULL_RETURN(textPattern, false);
1037     auto paragraphManager = textPattern->GetParagraphManager();
1038     CHECK_NULL_RETURN(paragraphManager, false);
1039     auto paragraphInfos = paragraphManager->GetParagraphs();
1040     if (paragraphIndex != 0 || paragraphInfos.size() != 1) {
1041         return false;
1042     }
1043     auto iter = paragraphInfos.begin();
1044     auto paragraphInfo = *iter;
1045     auto paragraph = paragraphInfo.paragraph;
1046     CHECK_NULL_RETURN(paragraph, false);
1047     paragraph->UpdateColor(position - length, position, color);
1048     textPattern->MarkDirtyNodeRender();
1049     return true;
1050 }
1051 
GetIndex(int32_t & start,int32_t & end) const1052 void SpanItem::GetIndex(int32_t& start, int32_t& end) const
1053 {
1054     auto contentLen = StringUtils::ToWstring(content).length();
1055     start = position - contentLen;
1056     end = position;
1057 }
1058 
UpdateParagraph(const RefPtr<FrameNode> &,const RefPtr<Paragraph> & builder,bool,PlaceholderStyle placeholderStyle,bool)1059 int32_t PlaceholderSpanItem::UpdateParagraph(const RefPtr<FrameNode>& /* frameNode */, const RefPtr<Paragraph>& builder,
1060     bool /* isSpanStringMode */, PlaceholderStyle placeholderStyle, bool /* isMarquee*/)
1061 {
1062     CHECK_NULL_RETURN(builder, -1);
1063     PlaceholderRun run;
1064     run.width = placeholderStyle.width;
1065     run.height = placeholderStyle.height;
1066     textStyle.SetTextDecoration(TextDecoration::NONE);
1067     textStyle.SetTextBackgroundStyle(backgroundStyle);
1068     builder->PushStyle(textStyle);
1069     int32_t index = builder->AddPlaceholder(run);
1070     run_ = run;
1071     builder->PopStyle();
1072     return index;
1073 }
1074 
GetSameStyleSpanItem() const1075 RefPtr<SpanItem> CustomSpanItem::GetSameStyleSpanItem() const
1076 {
1077     auto sameSpan = MakeRefPtr<CustomSpanItem>();
1078     sameSpan->onMeasure = onMeasure;
1079     sameSpan->onDraw = onDraw;
1080     sameSpan->urlOnRelease = urlOnRelease;
1081     sameSpan->onClick = onClick;
1082     sameSpan->onLongPress = onLongPress;
1083     if (backgroundStyle.has_value()) {
1084         sameSpan->backgroundStyle = backgroundStyle;
1085     }
1086     return sameSpan;
1087 }
1088 
SetTextBackgroundStyle(const TextBackgroundStyle & style)1089 void BaseSpan::SetTextBackgroundStyle(const TextBackgroundStyle& style)
1090 {
1091     textBackgroundStyle_ = style;
1092     textBackgroundStyle_->groupId = groupId_;
1093     SetHasTextBackgroundStyle(style.backgroundColor.has_value() || style.backgroundRadius.has_value());
1094     MarkTextDirty();
1095 }
1096 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1097 void ContainerSpanNode::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1098 {
1099     TextBackgroundStyle::ToJsonValue(json, GetTextBackgroundStyle(), filter);
1100 }
1101 
CalculateInheritPropertyInfo()1102 std::set<PropertyInfo> SpanNode::CalculateInheritPropertyInfo()
1103 {
1104     std::set<PropertyInfo> inheritPropertyInfo;
1105     static const std::set<PropertyInfo> propertyInfoContainer = { PropertyInfo::FONTSIZE, PropertyInfo::FONTCOLOR,
1106         PropertyInfo::FONTSTYLE, PropertyInfo::FONTWEIGHT, PropertyInfo::FONTFAMILY, PropertyInfo::TEXTDECORATION,
1107         PropertyInfo::TEXTCASE, PropertyInfo::LETTERSPACE, PropertyInfo::BASELINE_OFFSET, PropertyInfo::LINEHEIGHT,
1108         PropertyInfo::TEXT_ALIGN, PropertyInfo::LEADING_MARGIN, PropertyInfo::TEXTSHADOW, PropertyInfo::SYMBOL_COLOR,
1109         PropertyInfo::MIN_FONT_SCALE, PropertyInfo::MAX_FONT_SCALE,
1110         PropertyInfo::SYMBOL_RENDERING_STRATEGY, PropertyInfo::SYMBOL_EFFECT_STRATEGY, PropertyInfo::WORD_BREAK,
1111         PropertyInfo::LINE_BREAK_STRATEGY, PropertyInfo::FONTFEATURE, PropertyInfo::LINESPACING,
1112         PropertyInfo::SYMBOL_EFFECT_OPTIONS, PropertyInfo::HALFLEADING, PropertyInfo::VARIABLE_FONT_WEIGHT,
1113         PropertyInfo::ENABLE_VARIABLE_FONT_WEIGHT };
1114     set_difference(propertyInfoContainer.begin(), propertyInfoContainer.end(), propertyInfo_.begin(),
1115         propertyInfo_.end(), inserter(inheritPropertyInfo, inheritPropertyInfo.begin()));
1116     return inheritPropertyInfo;
1117 }
1118 } // namespace OHOS::Ace::NG
1119