• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 textStyle = InheritParentProperties(frameNode, isSpanStringMode);
260     UseSelfStyle(fontStyle, textLineStyle, textStyle);
261     auto fontManager = pipelineContext->GetFontManager();
262     if (fontManager && !(fontManager->GetAppCustomFont().empty()) && (textStyle.GetFontFamilies().empty())) {
263         textStyle.SetFontFamilies(Framework::ConvertStrToFontFamilies(fontManager->GetAppCustomFont()));
264     }
265     FontRegisterCallback(frameNode, textStyle);
266     if (NearZero(textStyle.GetFontSize().Value())) {
267         return -1;
268     }
269     auto textLayoutProp = frameNode->GetLayoutProperty<TextLayoutProperty>();
270     if (textLayoutProp && textLayoutProp->HasHalfLeading()) {
271         textStyle.SetHalfLeading(textLayoutProp->GetHalfLeadingValue(false));
272     } else {
273         textStyle.SetHalfLeading(pipelineContext->GetHalfLeading());
274     }
275 
276     auto spanContent = GetSpanContent(content, isMarquee);
277     auto pattern = frameNode->GetPattern<TextPattern>();
278     CHECK_NULL_RETURN(pattern, -1);
279     textStyle.SetTextBackgroundStyle(backgroundStyle);
280     if (pattern->NeedShowAIDetect() && !aiSpanMap.empty()) {
281         TextStyle aiSpanStyle = textStyle;
282         pattern->ModifyAISpanStyle(aiSpanStyle);
283         UpdateTextStyleForAISpan(spanContent, builder, textStyle, aiSpanStyle);
284     } else {
285         UpdateTextStyle(spanContent, builder, textStyle, selectedStart, selectedEnd);
286     }
287     textStyle_ = textStyle;
288     return -1;
289 }
290 
UpdateSymbolSpanParagraph(const RefPtr<FrameNode> & frameNode,const RefPtr<Paragraph> & builder)291 void SpanItem::UpdateSymbolSpanParagraph(const RefPtr<FrameNode>& frameNode, const RefPtr<Paragraph>& builder)
292 {
293     CHECK_NULL_VOID(builder);
294     CHECK_NULL_VOID(frameNode);
295     std::optional<TextStyle> textStyle;
296     auto symbolUnicode = GetSymbolUnicode();
297     if (fontStyle || textLineStyle) {
298         auto pipelineContext = frameNode->GetContext();
299         CHECK_NULL_VOID(pipelineContext);
300         TextStyle themeTextStyle =
301             CreateTextStyleUsingTheme(fontStyle, textLineStyle, pipelineContext->GetTheme<TextTheme>());
302         if (frameNode) {
303             FontRegisterCallback(frameNode, themeTextStyle);
304         }
305         if (NearZero(themeTextStyle.GetFontSize().Value())) {
306             return;
307         }
308         auto textLayoutProp = frameNode->GetLayoutProperty<TextLayoutProperty>();
309         if (textLayoutProp && textLayoutProp->HasHalfLeading()) {
310             themeTextStyle.SetHalfLeading(textLayoutProp->GetHalfLeadingValue(false));
311         } else {
312             themeTextStyle.SetHalfLeading(pipelineContext->GetHalfLeading());
313         }
314         textStyle = themeTextStyle;
315         if (symbolUnicode != 0) {
316             UpdateSymbolSpanColor(frameNode, themeTextStyle);
317         }
318         themeTextStyle.SetFontFamilies({"HM Symbol"});
319         builder->PushStyle(themeTextStyle);
320     }
321     textStyle_ = textStyle;
322 
323     if (symbolUnicode != 0) {
324         textStyle_->isSymbolGlyph_ = true;
325         builder->AddSymbol(symbolUnicode);
326     }
327 
328     if (fontStyle || textLineStyle) {
329         builder->PopStyle();
330     }
331 }
332 
UpdateSymbolSpanColor(const RefPtr<FrameNode> & frameNode,TextStyle & symbolSpanStyle)333 void SpanItem::UpdateSymbolSpanColor(const RefPtr<FrameNode>& frameNode, TextStyle& symbolSpanStyle)
334 {
335     symbolSpanStyle.isSymbolGlyph_ = true;
336     CHECK_NULL_VOID(frameNode);
337     if (GetIsParentText() && symbolSpanStyle.GetSymbolColorList().empty()) {
338         RefPtr<LayoutProperty> layoutProperty = frameNode->GetLayoutProperty();
339         CHECK_NULL_VOID(layoutProperty);
340         RefPtr<TextLayoutProperty> textLayoutProperty = DynamicCast<TextLayoutProperty>(layoutProperty);
341         CHECK_NULL_VOID(textLayoutProperty);
342         if (textLayoutProperty->GetTextColor().has_value()) {
343             std::vector<Color> symbolColor;
344             symbolColor.emplace_back(textLayoutProperty->GetTextColor().value());
345             symbolSpanStyle.SetSymbolColorList(symbolColor);
346         }
347     }
348 }
349 
UpdateTextStyleForAISpan(const std::string & spanContent,const RefPtr<Paragraph> & builder,const TextStyle & textStyle,const TextStyle & aiSpanStyle)350 void SpanItem::UpdateTextStyleForAISpan(const std::string& spanContent, const RefPtr<Paragraph>& builder,
351     const TextStyle& textStyle, const TextStyle& aiSpanStyle)
352 {
353     auto wSpanContent = StringUtils::ToWstring(spanContent);
354     int32_t wSpanContentLength = static_cast<int32_t>(wSpanContent.length());
355     int32_t spanStart = position - wSpanContentLength;
356     if (needRemoveNewLine) {
357         spanStart -= 1;
358     }
359     int32_t preEnd = spanStart;
360     while (!aiSpanMap.empty()) {
361         auto aiSpan = aiSpanMap.begin()->second;
362         if (aiSpan.start >= position || preEnd >= position) {
363             break;
364         }
365         int32_t aiSpanStartInSpan = std::max(spanStart, aiSpan.start);
366         int32_t aiSpanEndInSpan = std::min(position, aiSpan.end);
367         if (aiSpan.end <= spanStart || aiSpanStartInSpan < preEnd) {
368             TAG_LOGI(AceLogTag::ACE_TEXT, "Error prediction");
369             aiSpanMap.erase(aiSpanMap.begin());
370             continue;
371         }
372         int32_t contentStart = preEnd - spanStart;
373         if (preEnd < aiSpanStartInSpan) {
374             auto beforeContent =
375                 StringUtils::ToString(wSpanContent.substr(preEnd - spanStart, aiSpanStartInSpan - preEnd));
376             UpdateTextStyle(
377                 beforeContent, builder, textStyle, selectedStart - contentStart, selectedEnd - contentStart);
378             contentStart = contentStart + aiSpanStartInSpan - preEnd;
379         }
380         auto displayContent = StringUtils::ToWstring(aiSpan.content)
381             .substr(aiSpanStartInSpan - aiSpan.start, aiSpanEndInSpan - aiSpanStartInSpan);
382         UpdateTextStyle(StringUtils::ToString(displayContent), builder, aiSpanStyle,
383             selectedStart - contentStart, selectedEnd - contentStart);
384         preEnd = aiSpanEndInSpan;
385         if (aiSpan.end > position) {
386             return;
387         } else {
388             aiSpanMap.erase(aiSpanMap.begin());
389         }
390     }
391     if (preEnd < position) {
392         int32_t contentStart = preEnd - spanStart;
393         auto afterContent = StringUtils::ToString(wSpanContent.substr(preEnd - spanStart, position - preEnd));
394         UpdateTextStyle(afterContent, builder, textStyle, selectedStart - contentStart, selectedEnd - contentStart);
395     }
396 }
397 
FontRegisterCallback(const RefPtr<FrameNode> & frameNode,const TextStyle & textStyle)398 void SpanItem::FontRegisterCallback(const RefPtr<FrameNode>& frameNode, const TextStyle& textStyle)
399 {
400     auto callback = [weakNode = WeakPtr<FrameNode>(frameNode)] {
401         auto frameNode = weakNode.Upgrade();
402         CHECK_NULL_VOID(frameNode);
403         frameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
404         auto pattern = frameNode->GetPattern<TextPattern>();
405         CHECK_NULL_VOID(pattern);
406         auto modifier = DynamicCast<TextContentModifier>(pattern->GetContentModifier());
407         CHECK_NULL_VOID(modifier);
408         modifier->SetFontReady(true);
409     };
410     auto pipeline = frameNode->GetContext();
411     CHECK_NULL_VOID(pipeline);
412     auto fontManager = pipeline->GetFontManager();
413     if (fontManager) {
414         bool isCustomFont = false;
415         for (const auto& familyName : textStyle.GetFontFamilies()) {
416             bool customFont = fontManager->RegisterCallbackNG(frameNode, familyName, callback);
417             if (customFont) {
418                 isCustomFont = true;
419             }
420         }
421         if (isCustomFont) {
422             auto pattern = frameNode->GetPattern<TextPattern>();
423             CHECK_NULL_VOID(pattern);
424             pattern->SetIsCustomFont(true);
425             auto modifier = DynamicCast<TextContentModifier>(pattern->GetContentModifier());
426             CHECK_NULL_VOID(modifier);
427             modifier->SetIsCustomFont(true);
428         }
429     }
430 }
431 
UpdateTextStyle(const std::string & content,const RefPtr<Paragraph> & builder,const TextStyle & textStyle,const int32_t selStart,const int32_t selEnd)432 void SpanItem::UpdateTextStyle(const std::string& content, const RefPtr<Paragraph>& builder, const TextStyle& textStyle,
433     const int32_t selStart, const int32_t selEnd)
434 {
435     if (!IsDragging()) {
436         UpdateContentTextStyle(content, builder, textStyle);
437     } else {
438         if (content.empty()) {
439             builder->PushStyle(textStyle);
440             builder->PopStyle();
441             return;
442         }
443         auto displayContent = StringUtils::Str8ToStr16(content);
444         auto contentLength = static_cast<int32_t>(displayContent.length());
445         if (selStart > 0) {
446             auto beforeSelectedText = displayContent.substr(0, selStart);
447             UpdateContentTextStyle(StringUtils::Str16ToStr8(beforeSelectedText), builder, textStyle);
448         }
449         auto finalSelStart = selStart;
450         if (finalSelStart < 0) {
451             finalSelStart = 0;
452         }
453         auto finalSelEnd = selEnd;
454         if (finalSelEnd < 0) {
455             finalSelEnd = 0;
456         }
457         if (finalSelEnd > 0 && finalSelEnd > contentLength) {
458             finalSelEnd = contentLength;
459         }
460         if (finalSelStart < contentLength) {
461             auto pipelineContext = PipelineContext::GetCurrentContextSafely();
462             TextStyle selectedTextStyle = textStyle;
463             Color color = selectedTextStyle.GetTextColor().ChangeAlpha(DRAGGED_TEXT_OPACITY);
464             selectedTextStyle.SetTextColor(color);
465             Color textDecorationColor = selectedTextStyle.GetTextDecorationColor().ChangeAlpha(DRAGGED_TEXT_OPACITY);
466             selectedTextStyle.SetTextDecorationColor(textDecorationColor);
467             auto selectedText = displayContent.substr(finalSelStart, finalSelEnd - finalSelStart);
468             UpdateContentTextStyle(StringUtils::Str16ToStr8(selectedText), builder, selectedTextStyle);
469         }
470 
471         if (finalSelEnd < contentLength) {
472             auto afterSelectedText = displayContent.substr(finalSelEnd);
473             UpdateContentTextStyle(StringUtils::Str16ToStr8(afterSelectedText), builder, textStyle);
474         }
475     }
476 }
477 
UpdateContentTextStyle(const std::string & content,const RefPtr<Paragraph> & builder,const TextStyle & textStyle)478 void SpanItem::UpdateContentTextStyle(
479     const std::string& content, const RefPtr<Paragraph>& builder, const TextStyle& textStyle)
480 {
481     builder->PushStyle(textStyle);
482     if (!content.empty()) {
483         auto displayText = content;
484         auto textCase = textStyle.GetTextCase();
485         StringUtils::TransformStrCase(displayText, static_cast<int32_t>(textCase));
486         builder->AddText(StringUtils::Str8ToStr16(displayText));
487     }
488     builder->PopStyle();
489 }
490 
GetSpanContent(const std::string & rawContent,bool isMarquee)491 std::string SpanItem::GetSpanContent(const std::string& rawContent, bool isMarquee)
492 {
493     std::string data;
494     if (needRemoveNewLine && !rawContent.empty()) {
495         data = rawContent.substr(0, static_cast<int32_t>(rawContent.length()) - 1);
496     } else {
497         data = rawContent;
498     }
499     if (isMarquee) {
500         std::replace(data.begin(), data.end(), '\n', ' ');
501     }
502     return data;
503 }
504 
GetSpanContent()505 std::string SpanItem::GetSpanContent()
506 {
507     return content;
508 }
509 
GetSymbolUnicode()510 uint32_t SpanItem::GetSymbolUnicode()
511 {
512     return unicode;
513 }
514 
StartDrag(int32_t start,int32_t end)515 void SpanItem::StartDrag(int32_t start, int32_t end)
516 {
517     selectedStart = std::max(0, start);
518     auto contentLen = static_cast<int32_t>(content.size());
519     selectedEnd = std::min(contentLen, end);
520 }
521 
EndDrag()522 void SpanItem::EndDrag()
523 {
524     selectedStart = -1;
525     selectedEnd = -1;
526 }
527 
IsDragging()528 bool SpanItem::IsDragging()
529 {
530     return selectedStart >= 0 && selectedEnd >= 0;
531 }
532 
GetSpanResultObject(int32_t start,int32_t end)533 ResultObject SpanItem::GetSpanResultObject(int32_t start, int32_t end)
534 {
535     bool selectFlag = true;
536     ResultObject resultObject;
537     int32_t endPosition = interval.second;
538     int32_t startPosition = interval.first;
539     int32_t itemLength = endPosition - startPosition;
540 
541     if (startPosition >= start && endPosition <= end) {
542         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
543         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
544     } else if (startPosition < start && endPosition <= end && endPosition > start) {
545         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = start - startPosition;
546         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
547     } else if (startPosition >= start && startPosition < end && endPosition >= end) {
548         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
549         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = end - startPosition;
550     } else if (startPosition <= start && endPosition >= end) {
551         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = start - startPosition;
552         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = end - startPosition;
553     } else {
554         selectFlag = false;
555     }
556     if (selectFlag) {
557         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGESTART] = startPosition;
558         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGEEND] = endPosition;
559         resultObject.type = SelectSpanType::TYPESPAN;
560         resultObject.valueString = content;
561         resultObject.span = WeakClaim(this);
562         resultObject.isInit = true;
563     }
564     return resultObject;
565 }
566 
567 #define INHERIT_TEXT_STYLE(group, name, func)                    \
568     do {                                                         \
569         if ((textLayoutProp)->Has##name()) {                     \
570             textStyle.func(textLayoutProp->Get##name().value()); \
571         }                                                        \
572     } while (false)
573 
InheritParentProperties(const RefPtr<FrameNode> & frameNode,bool isSpanStringMode)574 TextStyle SpanItem::InheritParentProperties(const RefPtr<FrameNode>& frameNode, bool isSpanStringMode)
575 {
576     TextStyle textStyle;
577     auto context = PipelineContext::GetCurrentContextSafely();
578     CHECK_NULL_RETURN(context, textStyle);
579     auto theme = context->GetTheme<TextTheme>();
580     CHECK_NULL_RETURN(theme, textStyle);
581     textStyle = theme->GetTextStyle();
582     CHECK_NULL_RETURN(isSpanStringMode, textStyle);
583     auto textLayoutProp = frameNode->GetLayoutProperty<TextLayoutProperty>();
584     CHECK_NULL_RETURN(textLayoutProp, textStyle);
585     INHERIT_TEXT_STYLE(fontStyle, FontSize, SetFontSize);
586     INHERIT_TEXT_STYLE(fontStyle, TextColor, SetTextColor);
587     INHERIT_TEXT_STYLE(fontStyle, ItalicFontStyle, SetFontStyle);
588     INHERIT_TEXT_STYLE(fontStyle, FontWeight, SetFontWeight);
589     INHERIT_TEXT_STYLE(fontStyle, FontFamily, SetFontFamilies);
590     INHERIT_TEXT_STYLE(fontStyle, TextShadow, SetTextShadows);
591     INHERIT_TEXT_STYLE(fontStyle, TextCase, SetTextCase);
592     INHERIT_TEXT_STYLE(fontStyle, TextDecoration, SetTextDecoration);
593     INHERIT_TEXT_STYLE(fontStyle, TextDecorationColor, SetTextDecorationColor);
594     INHERIT_TEXT_STYLE(fontStyle, TextDecorationStyle, SetTextDecorationStyle);
595     INHERIT_TEXT_STYLE(fontStyle, LetterSpacing, SetLetterSpacing);
596     INHERIT_TEXT_STYLE(fontStyle, FontFeature, SetFontFeatures);
597     INHERIT_TEXT_STYLE(fontStyle, MinFontScale, SetMinFontScale);
598     INHERIT_TEXT_STYLE(fontStyle, MaxFontScale, SetMaxFontScale);
599     if (!GetHasUserFontWeight()) {
600         INHERIT_TEXT_STYLE(fontStyle, VariableFontWeight, SetVariableFontWeight);
601         INHERIT_TEXT_STYLE(fontStyle, EnableVariableFontWeight, SetEnableVariableFontWeight);
602     }
603     INHERIT_TEXT_STYLE(textLineStyle, LineHeight, SetLineHeight);
604     INHERIT_TEXT_STYLE(textLineStyle, LineSpacing, SetLineSpacing);
605     INHERIT_TEXT_STYLE(textLineStyle, HalfLeading, SetHalfLeading);
606     return textStyle;
607 }
608 
609 #define COPY_TEXT_STYLE(group, name, func)                      \
610     do {                                                        \
611         if ((group)->Has##name()) {                             \
612             sameSpan->group->func((group)->prop##name.value()); \
613         }                                                       \
614     } while (false)
615 
GetSameStyleSpanItem() const616 RefPtr<SpanItem> SpanItem::GetSameStyleSpanItem() const
617 {
618     auto sameSpan = MakeRefPtr<SpanItem>();
619     COPY_TEXT_STYLE(fontStyle, FontSize, UpdateFontSize);
620     COPY_TEXT_STYLE(fontStyle, TextColor, UpdateTextColor);
621     COPY_TEXT_STYLE(fontStyle, TextShadow, UpdateTextShadow);
622     COPY_TEXT_STYLE(fontStyle, ItalicFontStyle, UpdateItalicFontStyle);
623     COPY_TEXT_STYLE(fontStyle, FontWeight, UpdateFontWeight);
624     COPY_TEXT_STYLE(fontStyle, FontFamily, UpdateFontFamily);
625     COPY_TEXT_STYLE(fontStyle, FontFeature, UpdateFontFeature);
626     COPY_TEXT_STYLE(fontStyle, TextDecoration, UpdateTextDecoration);
627     COPY_TEXT_STYLE(fontStyle, TextDecorationColor, UpdateTextDecorationColor);
628     COPY_TEXT_STYLE(fontStyle, TextDecorationStyle, UpdateTextDecorationStyle);
629     COPY_TEXT_STYLE(fontStyle, TextCase, UpdateTextCase);
630     COPY_TEXT_STYLE(fontStyle, AdaptMinFontSize, UpdateAdaptMinFontSize);
631     COPY_TEXT_STYLE(fontStyle, AdaptMaxFontSize, UpdateAdaptMaxFontSize);
632     COPY_TEXT_STYLE(fontStyle, LetterSpacing, UpdateLetterSpacing);
633     COPY_TEXT_STYLE(fontStyle, MinFontScale, UpdateMinFontScale);
634     COPY_TEXT_STYLE(fontStyle, MaxFontScale, UpdateMaxFontScale);
635 
636     COPY_TEXT_STYLE(textLineStyle, LineHeight, UpdateLineHeight);
637     COPY_TEXT_STYLE(textLineStyle, LineSpacing, UpdateLineSpacing);
638     COPY_TEXT_STYLE(textLineStyle, TextBaseline, UpdateTextBaseline);
639     COPY_TEXT_STYLE(textLineStyle, BaselineOffset, UpdateBaselineOffset);
640     COPY_TEXT_STYLE(textLineStyle, TextOverflow, UpdateTextOverflow);
641     COPY_TEXT_STYLE(textLineStyle, TextAlign, UpdateTextAlign);
642     COPY_TEXT_STYLE(textLineStyle, MaxLength, UpdateMaxLength);
643     COPY_TEXT_STYLE(textLineStyle, MaxLines, UpdateMaxLines);
644     COPY_TEXT_STYLE(textLineStyle, HeightAdaptivePolicy, UpdateHeightAdaptivePolicy);
645     COPY_TEXT_STYLE(textLineStyle, TextIndent, UpdateTextIndent);
646     COPY_TEXT_STYLE(textLineStyle, LeadingMargin, UpdateLeadingMargin);
647     COPY_TEXT_STYLE(textLineStyle, WordBreak, UpdateWordBreak);
648     COPY_TEXT_STYLE(textLineStyle, LineBreakStrategy, UpdateLineBreakStrategy);
649     COPY_TEXT_STYLE(textLineStyle, EllipsisMode, UpdateEllipsisMode);
650     COPY_TEXT_STYLE(textLineStyle, HalfLeading, UpdateHalfLeading);
651 
652     if (backgroundStyle.has_value()) {
653         sameSpan->backgroundStyle->backgroundColor = backgroundStyle->backgroundColor;
654         sameSpan->backgroundStyle->backgroundRadius = backgroundStyle->backgroundRadius;
655         sameSpan->backgroundStyle->groupId = backgroundStyle->groupId;
656     }
657 
658     sameSpan->onClick = onClick;
659     sameSpan->onLongPress = onLongPress;
660     return sameSpan;
661 }
662 
663 
664 #define WRITE_TEXT_STYLE_TLV(group, name, tag, type)                   \
665     do {                                                               \
666         if ((group)->Has##name()) {                                    \
667             TLVUtil::WriteUint8(buff, (tag));                          \
668             TLVUtil::Write##type(buff, (group)->prop##name.value());   \
669         }                                                              \
670     } while (false)
671 
672 #define READ_TEXT_STYLE_TLV(group, func, tag, type)                         \
673     case tag: {                                                             \
674         sameSpan->group->func(TLVUtil::Read##type(buff, cursor));           \
675         break;                                                              \
676     }
677 
EncodeTlv(std::vector<uint8_t> & buff)678 bool SpanItem::EncodeTlv(std::vector<uint8_t>& buff)
679 {
680     TLVUtil::WriteUint8(buff, TLV_SPANITEM_TAG);
681     TLVUtil::WriteInt32(buff, interval.first);
682     TLVUtil::WriteInt32(buff, interval.second);
683     TLVUtil::WriteString(buff, content);
684     // encode fontStyle
685     WRITE_TEXT_STYLE_TLV(fontStyle, FontSize, TLV_SPAN_FONT_STYLE_FONTSIZE, Dimension);
686     WRITE_TEXT_STYLE_TLV(fontStyle, TextColor, TLV_SPAN_FONT_STYLE_TEXTCOLOR, Color);
687     WRITE_TEXT_STYLE_TLV(fontStyle, TextShadow, TLV_SPAN_FONT_STYLE_TEXTSHADOW, TextShadows);
688     WRITE_TEXT_STYLE_TLV(fontStyle, ItalicFontStyle, TLV_SPAN_FONT_STYLE_ITALICFONTSTYLE, FontStyle);
689     WRITE_TEXT_STYLE_TLV(fontStyle, FontWeight, TLV_SPAN_FONT_STYLE_FONTWEIGHT, FontWeight);
690     WRITE_TEXT_STYLE_TLV(fontStyle, FontFamily, TLV_SPAN_FONT_STYLE_FONTFAMILY, FontFamily);
691     WRITE_TEXT_STYLE_TLV(fontStyle, FontFeature, TLV_SPAN_FONT_STYLE_FONTFEATURE, FontFeature);
692     WRITE_TEXT_STYLE_TLV(fontStyle, TextDecoration, TLV_SPAN_FONT_STYLE_TEXTDECORATION, TextDecoration);
693     WRITE_TEXT_STYLE_TLV(fontStyle, TextDecorationColor, TLV_SPAN_FONT_STYLE_TEXTDECORATIONCOLOR, Color);
694     WRITE_TEXT_STYLE_TLV(fontStyle, TextDecorationStyle, TLV_SPAN_FONT_STYLE_TEXTDECORATIONSTYLE, TextDecorationStyle);
695     WRITE_TEXT_STYLE_TLV(fontStyle, TextCase, TLV_SPAN_FONT_STYLE_TEXTCASE, TextCase);
696     WRITE_TEXT_STYLE_TLV(fontStyle, AdaptMinFontSize, TLV_SPAN_FONT_STYLE_ADPATMINFONTSIZE, Dimension);
697     WRITE_TEXT_STYLE_TLV(fontStyle, AdaptMaxFontSize, TLV_SPAN_FONT_STYLE_ADPATMAXFONTSIZE, Dimension);
698     WRITE_TEXT_STYLE_TLV(fontStyle, LetterSpacing, TLV_SPAN_FONT_STYLE_LETTERSPACING, Dimension);
699 
700     WRITE_TEXT_STYLE_TLV(textLineStyle, LineHeight, TLV_SPAN_TEXT_LINE_STYLE_LINEHEIGHT, Dimension);
701     WRITE_TEXT_STYLE_TLV(textLineStyle, LineSpacing, TLV_SPAN_TEXT_LINE_STYLE_LINESPACING, Dimension);
702     WRITE_TEXT_STYLE_TLV(textLineStyle, TextBaseline, TLV_SPAN_TEXT_LINE_STYLE_TEXTBASELINE, TextBaseline);
703     WRITE_TEXT_STYLE_TLV(textLineStyle, BaselineOffset, TLV_SPAN_TEXT_LINE_STYLE_BASELINEOFFSET, Dimension);
704     WRITE_TEXT_STYLE_TLV(textLineStyle, TextOverflow, TLV_SPAN_TEXT_LINE_STYLE_TEXTOVERFLOW, TextOverflow);
705     WRITE_TEXT_STYLE_TLV(textLineStyle, TextAlign, TLV_SPAN_TEXT_LINE_STYLE_TEXTALIGN, TextAlign);
706     WRITE_TEXT_STYLE_TLV(textLineStyle, MaxLength, TLV_SPAN_TEXT_LINE_STYLE_MAXLENGTH, Int32);
707     WRITE_TEXT_STYLE_TLV(textLineStyle, MaxLines, TLV_SPAN_TEXT_LINE_STYLE_MAXLINES, Int32);
708     WRITE_TEXT_STYLE_TLV(textLineStyle, HeightAdaptivePolicy,
709         TLV_SPAN_TEXT_LINE_STYLE_HEIGHTADAPTIVEPOLICY, TextHeightAdaptivePolicy);
710     WRITE_TEXT_STYLE_TLV(textLineStyle, TextIndent, TLV_SPAN_TEXT_LINE_STYLE_TEXTINDENT, Dimension);
711     WRITE_TEXT_STYLE_TLV(textLineStyle, LeadingMargin, TLV_SPAN_TEXT_LINE_STYLE_LEADINGMARGIN, LeadingMargin);
712     WRITE_TEXT_STYLE_TLV(textLineStyle, WordBreak, TLV_SPAN_TEXT_LINE_STYLE_WORDBREAK, WordBreak);
713     WRITE_TEXT_STYLE_TLV(textLineStyle, LineBreakStrategy,
714         TLV_SPAN_TEXT_LINE_STYLE_LINEBREAKSTRATEGY, LineBreakStrategy);
715     WRITE_TEXT_STYLE_TLV(textLineStyle, EllipsisMode, TLV_SPAN_TEXT_LINE_STYLE_ELLIPSISMODE, EllipsisMode);
716     if (backgroundStyle.has_value()) {
717         if (backgroundStyle->backgroundColor.has_value()) {
718             TLVUtil::WriteUint8(buff, TLV_SPAN_BACKGROUND_BACKGROUNDCOLOR);
719             TLVUtil::WriteColor(buff, backgroundStyle->backgroundColor.value());
720         }
721         if (backgroundStyle->backgroundRadius.has_value()) {
722             TLVUtil::WriteUint8(buff, TLV_SPAN_BACKGROUND_BACKGROUNDRADIUS);
723             TLVUtil::WriteBorderRadiusProperty(buff, backgroundStyle->backgroundRadius.value());
724         }
725         TLVUtil::WriteUint8(buff, TLV_SPAN_BACKGROUND_GROUPID);
726         TLVUtil::WriteInt32(buff, backgroundStyle->groupId);
727     }
728     TLVUtil::WriteUint8(buff, TLV_SPANITEM_END_TAG);
729     return true;
730 };
731 
DecodeTlv(std::vector<uint8_t> & buff,int32_t & cursor)732 RefPtr<SpanItem> SpanItem::DecodeTlv(std::vector<uint8_t>& buff, int32_t& cursor)
733 {
734     auto sameSpan = MakeRefPtr<SpanItem>();
735     if (TLVUtil::ReadUint8(buff, cursor) != TLV_SPANITEM_TAG) {
736         return sameSpan;
737     }
738 
739     int32_t start = TLVUtil::ReadInt32(buff, cursor);
740     int32_t end = TLVUtil::ReadInt32(buff, cursor);
741     sameSpan->interval = {start, end};
742     sameSpan->content = TLVUtil::ReadString(buff, cursor);
743 
744     for (uint8_t tag = TLVUtil::ReadUint8(buff, cursor);
745         tag != TLV_SPANITEM_END_TAG; tag = TLVUtil::ReadUint8(buff, cursor)) {
746         switch (tag) {
747             READ_TEXT_STYLE_TLV(fontStyle, UpdateFontSize, TLV_SPAN_FONT_STYLE_FONTSIZE, Dimension);
748             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextColor, TLV_SPAN_FONT_STYLE_TEXTCOLOR, Color);
749             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextShadow, TLV_SPAN_FONT_STYLE_TEXTSHADOW, TextShadows);
750             READ_TEXT_STYLE_TLV(fontStyle, UpdateItalicFontStyle, TLV_SPAN_FONT_STYLE_ITALICFONTSTYLE, FontStyle);
751             READ_TEXT_STYLE_TLV(fontStyle, UpdateFontWeight, TLV_SPAN_FONT_STYLE_FONTWEIGHT, FontWeight);
752             READ_TEXT_STYLE_TLV(fontStyle, UpdateFontFamily, TLV_SPAN_FONT_STYLE_FONTFAMILY, FontFamily);
753             READ_TEXT_STYLE_TLV(fontStyle, UpdateFontFeature, TLV_SPAN_FONT_STYLE_FONTFEATURE, FontFeature);
754             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextDecoration, TLV_SPAN_FONT_STYLE_TEXTDECORATION, TextDecoration);
755             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextDecorationColor, TLV_SPAN_FONT_STYLE_TEXTDECORATIONCOLOR, Color);
756             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextDecorationStyle,
757                 TLV_SPAN_FONT_STYLE_TEXTDECORATIONSTYLE, TextDecorationStyle);
758             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextCase, TLV_SPAN_FONT_STYLE_TEXTCASE, TextCase);
759             READ_TEXT_STYLE_TLV(fontStyle, UpdateAdaptMinFontSize, TLV_SPAN_FONT_STYLE_ADPATMINFONTSIZE, Dimension);
760             READ_TEXT_STYLE_TLV(fontStyle, UpdateAdaptMaxFontSize, TLV_SPAN_FONT_STYLE_ADPATMAXFONTSIZE, Dimension);
761             READ_TEXT_STYLE_TLV(fontStyle, UpdateLetterSpacing, TLV_SPAN_FONT_STYLE_LETTERSPACING, Dimension);
762 
763             READ_TEXT_STYLE_TLV(textLineStyle, UpdateLineHeight, TLV_SPAN_TEXT_LINE_STYLE_LINEHEIGHT, Dimension);
764             READ_TEXT_STYLE_TLV(textLineStyle, UpdateLineSpacing, TLV_SPAN_TEXT_LINE_STYLE_LINESPACING, Dimension);
765             READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextBaseline, TLV_SPAN_TEXT_LINE_STYLE_TEXTBASELINE, TextBaseline);
766             READ_TEXT_STYLE_TLV(textLineStyle, UpdateBaselineOffset,
767                 TLV_SPAN_TEXT_LINE_STYLE_BASELINEOFFSET, Dimension);
768             READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextOverflow, TLV_SPAN_TEXT_LINE_STYLE_TEXTOVERFLOW, TextOverflow);
769             READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextAlign, TLV_SPAN_TEXT_LINE_STYLE_TEXTALIGN, TextAlign);
770             READ_TEXT_STYLE_TLV(textLineStyle, UpdateMaxLength, TLV_SPAN_TEXT_LINE_STYLE_MAXLENGTH, Int32);
771             READ_TEXT_STYLE_TLV(textLineStyle, UpdateMaxLines, TLV_SPAN_TEXT_LINE_STYLE_MAXLINES, Int32);
772             READ_TEXT_STYLE_TLV(textLineStyle, UpdateHeightAdaptivePolicy,
773                 TLV_SPAN_TEXT_LINE_STYLE_HEIGHTADAPTIVEPOLICY, TextHeightAdaptivePolicy);
774             READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextIndent, TLV_SPAN_TEXT_LINE_STYLE_TEXTINDENT, Dimension);
775             READ_TEXT_STYLE_TLV(textLineStyle, UpdateLeadingMargin,
776                 TLV_SPAN_TEXT_LINE_STYLE_LEADINGMARGIN, LeadingMargin);
777             READ_TEXT_STYLE_TLV(textLineStyle, UpdateWordBreak, TLV_SPAN_TEXT_LINE_STYLE_WORDBREAK, WordBreak);
778             READ_TEXT_STYLE_TLV(textLineStyle, UpdateLineBreakStrategy,
779                 TLV_SPAN_TEXT_LINE_STYLE_LINEBREAKSTRATEGY, LineBreakStrategy);
780             READ_TEXT_STYLE_TLV(textLineStyle, UpdateEllipsisMode, TLV_SPAN_TEXT_LINE_STYLE_ELLIPSISMODE, EllipsisMode);
781 
782             case TLV_SPAN_BACKGROUND_BACKGROUNDCOLOR: {
783                 sameSpan->backgroundStyle->backgroundColor = TLVUtil::ReadColor(buff, cursor);
784                 break;
785             }
786             case TLV_SPAN_BACKGROUND_BACKGROUNDRADIUS: {
787                 sameSpan->backgroundStyle->backgroundRadius = TLVUtil::ReadBorderRadiusProperty(buff, cursor);
788                 break;
789             }
790             case TLV_SPAN_BACKGROUND_GROUPID: {
791                 sameSpan->backgroundStyle->groupId = TLVUtil::ReadInt32(buff, cursor);
792                 break;
793             }
794             default:
795                 break;
796         }
797     }
798 
799     return sameSpan;
800 }
801 
SymbolColorToString()802 std::string SpanItem::SymbolColorToString()
803 {
804     auto colors = fontStyle->GetSymbolColorList();
805     auto colorStr = std::string("[");
806     if (colors.has_value()) {
807         for (const auto& color : colors.value()) {
808             colorStr.append(color.ColorToString());
809             colorStr.append(",");
810         }
811     }
812     colorStr.append("]");
813     return colorStr;
814 }
815 
GetIntersectionInterval(std::pair<int32_t,int32_t> interval) const816 std::optional<std::pair<int32_t, int32_t>> SpanItem::GetIntersectionInterval(std::pair<int32_t, int32_t> interval) const
817 {
818     // Check the intersection
819     if (this->interval.second <= interval.first || interval.second <= this->interval.first) {
820         return std::nullopt;
821     }
822 
823     // Calculate the intersection interval
824     int32_t start = std::max(this->interval.first, interval.first);
825     int32_t end = std::min(this->interval.second, interval.second);
826     return std::make_optional<std::pair<int32_t, int32_t>>(std::make_pair(start, end));
827 }
828 
EncodeTlv(std::vector<uint8_t> & buff)829 bool ImageSpanItem::EncodeTlv(std::vector<uint8_t>& buff)
830 {
831     TLVUtil::WriteUint8(buff, TLV_IMAGESPANITEM_TAG);
832     TLVUtil::WriteInt32(buff, interval.first);
833     TLVUtil::WriteInt32(buff, interval.second);
834     TLVUtil::WriteString(buff, content);
835     if (options.offset.has_value()) {
836         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_OFFSET_TAG);
837         TLVUtil::WriteInt32(buff, options.offset.value());
838     }
839     if (options.image.has_value()) {
840         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_IMAGE_TAG);
841         TLVUtil::WriteString(buff, options.image.value());
842     }
843     if (options.bundleName.has_value()) {
844         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_BUNDLENAME_TAG);
845         TLVUtil::WriteString(buff, options.bundleName.value());
846     }
847     if (options.bundleName.has_value()) {
848         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_MODULENAME_TAG);
849         TLVUtil::WriteString(buff, options.moduleName.value());
850     }
851     if (options.imagePixelMap.has_value()) {
852         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_IMAGEPIXELMAP_TAG);
853         TLVUtil::WritePixelMap(buff, options.imagePixelMap.value());
854     }
855     if (options.imageAttribute.has_value()) {
856         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_IMAGEATTRIBUTE_TAG);
857         TLVUtil::WriteImageSpanAttribute(buff, options.imageAttribute.value());
858     }
859     TLVUtil::WriteUint8(buff, TLV_SPANITEM_END_TAG);
860     return true;
861 }
862 
DecodeTlv(std::vector<uint8_t> & buff,int32_t & cursor)863 RefPtr<ImageSpanItem> ImageSpanItem::DecodeTlv(std::vector<uint8_t>& buff, int32_t& cursor)
864 {
865     auto sameSpan = MakeRefPtr<ImageSpanItem>();
866 
867     if (TLVUtil::ReadUint8(buff, cursor) != TLV_IMAGESPANITEM_TAG) {
868         return sameSpan;
869     }
870 
871     int32_t start = TLVUtil::ReadInt32(buff, cursor);
872     int32_t end = TLVUtil::ReadInt32(buff, cursor);
873     sameSpan->interval = {start, end};
874     sameSpan->content = TLVUtil::ReadString(buff, cursor);
875 
876     for (uint8_t tag = TLVUtil::ReadUint8(buff, cursor);
877         tag != TLV_SPANITEM_END_TAG; tag = TLVUtil::ReadUint8(buff, cursor)) {
878         switch (tag) {
879             case TLV_IMAGESPANOPTION_OFFSET_TAG: {
880                 sameSpan->options.offset = TLVUtil::ReadInt32(buff, cursor);
881                 break;
882             }
883             case TLV_IMAGESPANOPTION_IMAGE_TAG: {
884                 sameSpan->options.image = TLVUtil::ReadString(buff, cursor);
885                 break;
886             }
887             case TLV_IMAGESPANOPTION_BUNDLENAME_TAG: {
888                 sameSpan->options.bundleName = TLVUtil::ReadString(buff, cursor);
889                 break;
890             }
891             case TLV_IMAGESPANOPTION_MODULENAME_TAG: {
892                 sameSpan->options.moduleName = TLVUtil::ReadString(buff, cursor);
893                 break;
894             }
895             case TLV_IMAGESPANOPTION_IMAGEPIXELMAP_TAG: {
896                 sameSpan->options.imagePixelMap = TLVUtil::ReadPixelMap(buff, cursor);
897                 break;
898             }
899             case TLV_IMAGESPANOPTION_IMAGEATTRIBUTE_TAG: {
900                 sameSpan->options.imageAttribute = TLVUtil::ReadImageSpanAttribute(buff, cursor);
901                 break;
902             }
903             default:
904                 break;
905         }
906     }
907     return sameSpan;
908 }
909 
UpdateParagraph(const RefPtr<FrameNode> &,const RefPtr<Paragraph> & builder,bool,PlaceholderStyle placeholderStyle,bool)910 int32_t ImageSpanItem::UpdateParagraph(const RefPtr<FrameNode>& /* frameNode */, const RefPtr<Paragraph>& builder,
911     bool /* isSpanStringMode */, PlaceholderStyle placeholderStyle, bool /* isMarquee*/)
912 {
913     CHECK_NULL_RETURN(builder, -1);
914     PlaceholderRun run;
915     run.width = placeholderStyle.width;
916     run.height = placeholderStyle.height;
917     if (!NearZero(placeholderStyle.baselineOffset)) {
918         run.baseline_offset = placeholderStyle.baselineOffset;
919         run.alignment = PlaceholderAlignment::BASELINE;
920     } else {
921         switch (placeholderStyle.verticalAlign) {
922             case VerticalAlign::TOP:
923                 run.alignment = PlaceholderAlignment::TOP;
924                 break;
925             case VerticalAlign::CENTER:
926                 run.alignment = PlaceholderAlignment::MIDDLE;
927                 break;
928             case VerticalAlign::BOTTOM:
929             case VerticalAlign::NONE:
930                 run.alignment = PlaceholderAlignment::BOTTOM;
931                 break;
932             case VerticalAlign::BASELINE:
933                 run.alignment = PlaceholderAlignment::ABOVEBASELINE;
934                 break;
935             default:
936                 run.alignment = PlaceholderAlignment::BOTTOM;
937         }
938     }
939 
940     // ImageSpan should ignore decoration styles
941     textStyle.SetTextDecoration(TextDecoration::NONE);
942     textStyle.SetTextBackgroundStyle(backgroundStyle);
943     textStyle.SetFontSize(placeholderStyle.paragraphFontSize);
944     textStyle.SetTextColor(placeholderStyle.paragraphTextColor);
945     builder->PushStyle(textStyle);
946     int32_t index = builder->AddPlaceholder(run);
947     run_ = run;
948     builder->PopStyle();
949     return index;
950 }
951 
UpdatePlaceholderBackgroundStyle(const RefPtr<FrameNode> & imageNode)952 void ImageSpanItem::UpdatePlaceholderBackgroundStyle(const RefPtr<FrameNode>& imageNode)
953 {
954     CHECK_NULL_VOID(imageNode);
955     auto property = imageNode->GetLayoutProperty<ImageLayoutProperty>();
956     CHECK_NULL_VOID(property);
957     backgroundStyle = property->GetPlaceHolderStyle();
958 }
959 
SetImageSpanOptions(const ImageSpanOptions & options)960 void ImageSpanItem::SetImageSpanOptions(const ImageSpanOptions& options)
961 {
962     this->options = options;
963 }
964 
ResetImageSpanOptions()965 void ImageSpanItem::ResetImageSpanOptions()
966 {
967     options.imageAttribute.reset();
968 }
969 
GetSameStyleSpanItem() const970 RefPtr<SpanItem> ImageSpanItem::GetSameStyleSpanItem() const
971 {
972     auto sameSpan = MakeRefPtr<ImageSpanItem>();
973     sameSpan->SetImageSpanOptions(options);
974     sameSpan->onClick = onClick;
975     sameSpan->onLongPress = onLongPress;
976     return sameSpan;
977 }
978 
GetSpanResultObject(int32_t start,int32_t end)979 ResultObject ImageSpanItem::GetSpanResultObject(int32_t start, int32_t end)
980 {
981     int32_t itemLength = 1;
982     ResultObject resultObject;
983 
984     int32_t endPosition = interval.second;
985     int32_t startPosition = interval.first;
986     resultObject.type = SelectSpanType::TYPEIMAGE;
987     if ((start <= startPosition) && (end >= endPosition)) {
988         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGESTART] = startPosition;
989         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGEEND] = endPosition;
990         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
991         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
992         if (options.image.has_value()) {
993             resultObject.valueString = options.image.value();
994         }
995         if (options.imagePixelMap.has_value()) {
996             resultObject.valuePixelMap = options.imagePixelMap.value();
997         }
998         resultObject.isInit = true;
999     }
1000     return resultObject;
1001 }
1002 
GetSpanResultObject(int32_t start,int32_t end)1003 ResultObject CustomSpanItem::GetSpanResultObject(int32_t start, int32_t end)
1004 {
1005     int32_t itemLength = 1;
1006     ResultObject resultObject;
1007 
1008     int32_t endPosition = interval.second;
1009     int32_t startPosition = interval.first;
1010     resultObject.type = SelectSpanType::TYPEBUILDERSPAN;
1011     if ((start <= startPosition) && (end >= endPosition)) {
1012         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGESTART] = startPosition;
1013         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGEEND] = endPosition;
1014         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
1015         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
1016         resultObject.valueString = " ";
1017         resultObject.isInit = true;
1018     }
1019     return resultObject;
1020 }
1021 
UpdateSpanTextColor(Color color)1022 bool SpanItem::UpdateSpanTextColor(Color color)
1023 {
1024     auto pattern = pattern_.Upgrade();
1025     CHECK_NULL_RETURN(pattern, false);
1026     auto textPattern = DynamicCast<TextPattern>(pattern);
1027     CHECK_NULL_RETURN(textPattern, false);
1028     auto paragraphManager = textPattern->GetParagraphManager();
1029     CHECK_NULL_RETURN(paragraphManager, false);
1030     auto paragraphInfos = paragraphManager->GetParagraphs();
1031     if (paragraphIndex != 0 || paragraphInfos.size() != 1) {
1032         return false;
1033     }
1034     auto iter = paragraphInfos.begin();
1035     auto paragraphInfo = *iter;
1036     auto paragraph = paragraphInfo.paragraph;
1037     CHECK_NULL_RETURN(paragraph, false);
1038     paragraph->UpdateColor(position - length, position, color);
1039     textPattern->MarkDirtyNodeRender();
1040     return true;
1041 }
1042 
GetIndex(int32_t & start,int32_t & end) const1043 void SpanItem::GetIndex(int32_t& start, int32_t& end) const
1044 {
1045     auto contentLen = StringUtils::ToWstring(content).length();
1046     start = position - contentLen;
1047     end = position;
1048 }
1049 
UpdateParagraph(const RefPtr<FrameNode> &,const RefPtr<Paragraph> & builder,bool,PlaceholderStyle placeholderStyle,bool)1050 int32_t PlaceholderSpanItem::UpdateParagraph(const RefPtr<FrameNode>& /* frameNode */, const RefPtr<Paragraph>& builder,
1051     bool /* isSpanStringMode */, PlaceholderStyle placeholderStyle, bool /* isMarquee*/)
1052 {
1053     CHECK_NULL_RETURN(builder, -1);
1054     PlaceholderRun run;
1055     run.width = placeholderStyle.width;
1056     run.height = placeholderStyle.height;
1057     textStyle.SetTextDecoration(TextDecoration::NONE);
1058     builder->PushStyle(textStyle);
1059     int32_t index = builder->AddPlaceholder(run);
1060     run_ = run;
1061     builder->PopStyle();
1062     return index;
1063 }
1064 
GetSameStyleSpanItem() const1065 RefPtr<SpanItem> CustomSpanItem::GetSameStyleSpanItem() const
1066 {
1067     auto sameSpan = MakeRefPtr<CustomSpanItem>();
1068     sameSpan->onMeasure = onMeasure;
1069     sameSpan->onDraw = onDraw;
1070     sameSpan->onClick = onClick;
1071     sameSpan->onLongPress = onLongPress;
1072     return sameSpan;
1073 }
1074 
SetTextBackgroundStyle(const TextBackgroundStyle & style)1075 void BaseSpan::SetTextBackgroundStyle(const TextBackgroundStyle& style)
1076 {
1077     textBackgroundStyle_ = style;
1078     textBackgroundStyle_->groupId = groupId_;
1079     SetHasTextBackgroundStyle(style.backgroundColor.has_value() || style.backgroundRadius.has_value());
1080     MarkTextDirty();
1081 }
1082 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1083 void ContainerSpanNode::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1084 {
1085     TextBackgroundStyle::ToJsonValue(json, GetTextBackgroundStyle(), filter);
1086 }
1087 
CalculateInheritPropertyInfo()1088 std::set<PropertyInfo> SpanNode::CalculateInheritPropertyInfo()
1089 {
1090     std::set<PropertyInfo> inheritPropertyInfo;
1091     static const std::set<PropertyInfo> propertyInfoContainer = { PropertyInfo::FONTSIZE, PropertyInfo::FONTCOLOR,
1092         PropertyInfo::FONTSTYLE, PropertyInfo::FONTWEIGHT, PropertyInfo::FONTFAMILY, PropertyInfo::TEXTDECORATION,
1093         PropertyInfo::TEXTCASE, PropertyInfo::LETTERSPACE, PropertyInfo::BASELINE_OFFSET, PropertyInfo::LINEHEIGHT,
1094         PropertyInfo::TEXT_ALIGN, PropertyInfo::LEADING_MARGIN, PropertyInfo::TEXTSHADOW, PropertyInfo::SYMBOL_COLOR,
1095         PropertyInfo::MIN_FONT_SCALE, PropertyInfo::MAX_FONT_SCALE,
1096         PropertyInfo::SYMBOL_RENDERING_STRATEGY, PropertyInfo::SYMBOL_EFFECT_STRATEGY, PropertyInfo::WORD_BREAK,
1097         PropertyInfo::LINE_BREAK_STRATEGY, PropertyInfo::FONTFEATURE, PropertyInfo::LINESPACING,
1098         PropertyInfo::SYMBOL_EFFECT_OPTIONS, PropertyInfo::HALFLEADING, PropertyInfo::VARIABLE_FONT_WEIGHT,
1099         PropertyInfo::ENABLE_VARIABLE_FONT_WEIGHT };
1100     set_difference(propertyInfoContainer.begin(), propertyInfoContainer.end(), propertyInfo_.begin(),
1101         propertyInfo_.end(), inserter(inheritPropertyInfo, inheritPropertyInfo.begin()));
1102     return inheritPropertyInfo;
1103 }
1104 } // namespace OHOS::Ace::NG
1105