• 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/string_utils.h"
24 #include "base/utils/utf_helper.h"
25 #include "base/utils/utils.h"
26 #include "core/common/font_manager.h"
27 #include "core/components/common/layout/constants.h"
28 #include "core/components/common/properties/text_style.h"
29 #include "core/components/hyperlink/hyperlink_theme.h"
30 #include "core/components/text/text_theme.h"
31 #include "core/components_ng/base/frame_node.h"
32 #include "core/components_ng/base/inspector_filter.h"
33 #include "core/components_ng/pattern/text/text_pattern.h"
34 #include "core/components_ng/pattern/text/text_styles.h"
35 #include "core/components_ng/property/property.h"
36 #include "core/components_ng/render/drawing_prop_convertor.h"
37 #include "core/components_ng/render/paragraph.h"
38 #include "core/pipeline/pipeline_context.h"
39 #include "core/pipeline_ng/pipeline_context.h"
40 #include "core/text/text_emoji_processor.h"
41 
42 namespace OHOS::Ace::NG {
43 namespace {
44 const std::string CUSTOM_SYMBOL_SUFFIX = "_CustomSymbol";
45 const std::string DEFAULT_SYMBOL_FONTFAMILY = "HM Symbol";
46 
GetDeclaration(const std::optional<Color> & color,const std::optional<TextDecoration> & textDecoration,const std::optional<TextDecorationStyle> & textDecorationStyle)47 std::string GetDeclaration(const std::optional<Color>& color, const std::optional<TextDecoration>& textDecoration,
48     const std::optional<TextDecorationStyle>& textDecorationStyle)
49 {
50     auto jsonSpanDeclaration = JsonUtil::Create(true);
51     jsonSpanDeclaration->Put(
52         "type", V2::ConvertWrapTextDecorationToStirng(textDecoration.value_or(TextDecoration::NONE)).c_str());
53     jsonSpanDeclaration->Put("color", (color.value_or(Color::BLACK).ColorToString()).c_str());
54     jsonSpanDeclaration->Put("style",
55         V2::ConvertWrapTextDecorationStyleToString(textDecorationStyle.value_or(TextDecorationStyle::SOLID))
56             .c_str());
57     return jsonSpanDeclaration->ToString();
58 }
ConvertShadowToJson(const Shadow & shadow)59 inline std::unique_ptr<JsonValue> ConvertShadowToJson(const Shadow& shadow)
60 {
61     auto jsonShadow = JsonUtil::Create(true);
62     jsonShadow->Put("radius", std::to_string(shadow.GetBlurRadius()).c_str());
63     jsonShadow->Put("color", shadow.GetColor().ColorToString().c_str());
64     jsonShadow->Put("offsetX", std::to_string(shadow.GetOffset().GetX()).c_str());
65     jsonShadow->Put("offsetY", std::to_string(shadow.GetOffset().GetY()).c_str());
66     jsonShadow->Put("type", std::to_string(static_cast<int32_t>(shadow.GetShadowType())).c_str());
67     return jsonShadow;
68 }
ConvertShadowsToJson(const std::vector<Shadow> & shadows)69 std::unique_ptr<JsonValue> ConvertShadowsToJson(const std::vector<Shadow>& shadows)
70 {
71     auto jsonShadows = JsonUtil::CreateArray(true);
72     for (const auto& shadow : shadows) {
73         jsonShadows->Put(ConvertShadowToJson(shadow));
74     }
75     return jsonShadows;
76 }
77 } // namespace
78 
GetFont() const79 std::string SpanItem::GetFont() const
80 {
81     auto pattern = pattern_.Upgrade();
82     CHECK_NULL_RETURN(pattern, "");
83     auto textPattern = DynamicCast<TextPattern>(pattern);
84     CHECK_NULL_RETURN(textPattern, "");
85     auto jsonValue = JsonUtil::Create(true);
86     jsonValue->Put("style", GetFontStyleInJson(fontStyle->GetItalicFontStyle()).c_str());
87     jsonValue->Put("size", textPattern->GetFontSizeWithThemeInJson(fontStyle->GetFontSize()).c_str());
88     jsonValue->Put("weight", GetFontWeightInJson(fontStyle->GetFontWeight()).c_str());
89     jsonValue->Put("family", GetFontFamilyInJson(fontStyle->GetFontFamily()).c_str());
90     return jsonValue->ToString();
91 }
92 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const93 void SpanItem::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
94 {
95     json->PutFixedAttr("content", UtfUtils::Str16DebugToStr8(content).c_str(), filter, FIXED_ATTR_CONTENT);
96     /* no fixed attr below, just return */
97     if (filter.IsFastFilter()) {
98         TextBackgroundStyle::ToJsonValue(json, backgroundStyle, filter);
99         return;
100     }
101     auto pattern = pattern_.Upgrade();
102     CHECK_NULL_VOID(pattern);
103     auto textPattern = DynamicCast<TextPattern>(pattern);
104     CHECK_NULL_VOID(textPattern);
105     if (fontStyle) {
106         json->PutExtAttr("font", GetFont().c_str(), filter);
107         json->PutExtAttr("fontSize", textPattern->GetFontSizeWithThemeInJson(fontStyle->GetFontSize()).c_str(), filter);
108         json->PutExtAttr("decoration", GetDeclaration(fontStyle->GetTextDecorationColor(),
109             fontStyle->GetTextDecoration(), fontStyle->GetTextDecorationStyle()).c_str(), filter);
110         json->PutExtAttr("letterSpacing",
111             fontStyle->GetLetterSpacing().value_or(Dimension()).ToString().c_str(), filter);
112         json->PutExtAttr("textCase",
113             V2::ConvertWrapTextCaseToStirng(fontStyle->GetTextCase().value_or(TextCase::NORMAL)).c_str(), filter);
114         json->PutExtAttr("fontColor", fontStyle->GetForegroundColor().value_or(fontStyle->GetTextColor()
115             .value_or(Color::BLACK)).ColorToString().c_str(), filter);
116         json->PutExtAttr("fontStyle", GetFontStyleInJson(fontStyle->GetItalicFontStyle()).c_str(), filter);
117         json->PutExtAttr("fontWeight", GetFontWeightInJson(fontStyle->GetFontWeight()).c_str(), filter);
118         json->PutExtAttr("fontFamily", GetFontFamilyInJson(fontStyle->GetFontFamily()).c_str(), filter);
119         json->PutExtAttr("renderingStrategy",
120             GetSymbolRenderingStrategyInJson(fontStyle->GetSymbolRenderingStrategy()).c_str(), filter);
121         json->PutExtAttr(
122             "effectStrategy", GetSymbolEffectStrategyInJson(fontStyle->GetSymbolEffectStrategy()).c_str(), filter);
123         json->Put("symbolEffect",
124             GetSymbolEffectOptionsInJson(fontStyle->GetSymbolEffectOptions().value_or(SymbolEffectOptions())).c_str());
125 
126         auto shadow = fontStyle->GetTextShadow().value_or(std::vector<Shadow> { Shadow() });
127         // Determines if there are multiple textShadows
128         auto jsonShadow = (shadow.size() == 1) ? ConvertShadowToJson(shadow.front()) : ConvertShadowsToJson(shadow);
129         json->PutExtAttr("textShadow", jsonShadow, filter);
130     }
131     if (textLineStyle) {
132         json->PutExtAttr("lineHeight",
133             textLineStyle->GetLineHeight().value_or(Dimension()).ToString().c_str(), filter);
134         json->PutExtAttr("lineSpacing",
135             textLineStyle->GetLineSpacing().value_or(Dimension()).ToString().c_str(), filter);
136         json->PutExtAttr("baselineOffset",
137             textLineStyle->GetBaselineOffset().value_or(Dimension()).ToString().c_str(), filter);
138     }
139     TextBackgroundStyle::ToJsonValue(json, backgroundStyle, filter);
140 }
141 
ToTreeJson(std::unique_ptr<JsonValue> & json,const InspectorConfig & config) const142 void SpanItem::ToTreeJson(std::unique_ptr<JsonValue>& json, const InspectorConfig& config) const
143 {
144     if (!content.empty()) {
145         json->Put(TreeKey::CONTENT, content.c_str());
146     }
147 }
148 
GetOrCreateSpanNode(int32_t nodeId)149 RefPtr<SpanNode> SpanNode::GetOrCreateSpanNode(int32_t nodeId)
150 {
151     auto spanNode = ElementRegister::GetInstance()->GetSpecificItemById<SpanNode>(nodeId);
152     if (spanNode) {
153         return spanNode;
154     }
155     spanNode = MakeRefPtr<SpanNode>(nodeId);
156     ElementRegister::GetInstance()->AddUINode(spanNode);
157     return spanNode;
158 }
159 
CreateSpanNode(int32_t nodeId)160 RefPtr<SpanNode> SpanNode::CreateSpanNode(int32_t nodeId)
161 {
162     auto spanNode = MakeRefPtr<SpanNode>(nodeId);
163     ElementRegister::GetInstance()->AddUINode(spanNode);
164     return spanNode;
165 }
166 
GetOrCreateSpanNode(const std::string & tag,int32_t nodeId)167 RefPtr<SpanNode> SpanNode::GetOrCreateSpanNode(const std::string& tag, int32_t nodeId)
168 {
169     auto spanNode = ElementRegister::GetInstance()->GetSpecificItemById<SpanNode>(nodeId);
170     if (spanNode) {
171         return spanNode;
172     }
173     spanNode = MakeRefPtr<SpanNode>(tag, nodeId);
174     ElementRegister::GetInstance()->AddUINode(spanNode);
175     return spanNode;
176 }
177 
MountToParagraph()178 void SpanNode::MountToParagraph()
179 {
180     auto parent = GetParent();
181     while (parent) {
182         auto spanNode = DynamicCast<SpanNode>(parent);
183         if (spanNode) {
184             spanNode->AddChildSpanItem(Claim(this));
185             return;
186         }
187         auto textNode = DynamicCast<FrameNode>(parent);
188         if (textNode) {
189             auto textPattern = textNode->GetPattern<TextPattern>();
190             if (textPattern) {
191                 textPattern->AddChildSpanItem(Claim(this));
192                 return;
193             }
194         }
195         parent = parent->GetParent();
196     }
197 }
198 
RequestTextFlushDirty(bool markModifyDone)199 void SpanNode::RequestTextFlushDirty(bool markModifyDone)
200 {
201     RequestTextFlushDirty(Claim<UINode>(this), markModifyDone);
202 }
203 
RequestTextFlushDirty(const RefPtr<UINode> & node,bool markModifyDone)204 void SpanNode::RequestTextFlushDirty(const RefPtr<UINode>& node, bool markModifyDone)
205 {
206     CHECK_NULL_VOID(node);
207     auto parent = node->GetParent();
208     while (parent) {
209         auto textNode = DynamicCast<FrameNode>(parent);
210         if (textNode) {
211             textNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
212             auto textPattern = textNode->GetPattern<TextPattern>();
213             if (textPattern) {
214                 ACE_TEXT_SCOPED_TRACE("RequestTextFlushDirty [Parent:%d,Tag:%s][Span:%d]", textNode->GetId(),
215                     textNode->GetTag().c_str(), node->GetId());
216                 CHECK_NULL_VOID(markModifyDone);
217                 textPattern->OnModifyDone();
218                 return;
219             }
220         }
221         parent = parent->GetParent();
222     }
223 }
224 
SetTextBackgroundStyle(const TextBackgroundStyle & style)225 void SpanNode::SetTextBackgroundStyle(const TextBackgroundStyle& style)
226 {
227     BaseSpan::SetTextBackgroundStyle(style);
228     spanItem_->backgroundStyle = GetTextBackgroundStyle();
229 }
230 
UpdateTextBackgroundFromParent(const std::optional<TextBackgroundStyle> & style)231 void SpanNode::UpdateTextBackgroundFromParent(const std::optional<TextBackgroundStyle>& style)
232 {
233     BaseSpan::UpdateTextBackgroundFromParent(style);
234     spanItem_->backgroundStyle = GetTextBackgroundStyle();
235     spanItem_->MarkDirty();
236 }
237 
DumpInfo()238 void SpanNode::DumpInfo()
239 {
240     auto& dumpLog = DumpLog::GetInstance();
241     dumpLog.AddDesc(
242         std::string("Content: ").append("\"").append(UtfUtils::Str16DebugToStr8(spanItem_->content)).append("\""));
243     auto textStyle = spanItem_->GetTextStyle();
244     if (!textStyle) {
245         return;
246     }
247     dumpLog.AddDesc(std::string("FontSize: ").append(textStyle->GetFontSize().ToString()));
248     dumpLog.AddDesc(std::string("LineHeight: ").append(textStyle->GetLineHeight().ToString()));
249     dumpLog.AddDesc(std::string("LineSpacing: ").append(textStyle->GetLineSpacing().ToString()));
250     dumpLog.AddDesc(std::string("BaselineOffset: ").append(textStyle->GetBaselineOffset().ToString()));
251     dumpLog.AddDesc(std::string("WordSpacing: ").append(textStyle->GetWordSpacing().ToString()));
252     dumpLog.AddDesc(std::string("TextIndent: ").append(textStyle->GetTextIndent().ToString()));
253     dumpLog.AddDesc(std::string("LetterSpacing: ").append(textStyle->GetLetterSpacing().ToString()));
254     dumpLog.AddDesc(std::string("TextColor: ").append(textStyle->GetTextColor().ColorToString()));
255     if (spanItem_ && spanItem_->fontStyle) {
256         dumpLog.AddDesc(std::string("SpanTextColor: ")
257                             .append(spanItem_->fontStyle->GetTextColor().value_or(Color::FOREGROUND).ColorToString()));
258     }
259     dumpLog.AddDesc(std::string("FontWeight: ").append(StringUtils::ToString(textStyle->GetFontWeight())));
260     dumpLog.AddDesc(std::string("FontStyle: ").append(StringUtils::ToString(textStyle->GetFontStyle())));
261     dumpLog.AddDesc(std::string("TextBaseline: ").append(StringUtils::ToString(textStyle->GetTextBaseline())));
262     dumpLog.AddDesc(std::string("TextOverflow: ").append(StringUtils::ToString(textStyle->GetTextOverflow())));
263     dumpLog.AddDesc(std::string("VerticalAlign: ").append(StringUtils::ToString(textStyle->GetTextVerticalAlign())));
264     dumpLog.AddDesc(std::string("TextAlign: ").append(StringUtils::ToString(textStyle->GetTextAlign())));
265     dumpLog.AddDesc(std::string("WordBreak: ").append(StringUtils::ToString(textStyle->GetWordBreak())));
266     dumpLog.AddDesc(std::string("TextCase: ").append(StringUtils::ToString(textStyle->GetTextCase())));
267     dumpLog.AddDesc(std::string("EllipsisMode: ").append(StringUtils::ToString(textStyle->GetEllipsisMode())));
268     dumpLog.AddDesc(std::string("HalfLeading: ").append(std::to_string(textStyle->GetHalfLeading())));
269     if (GetTag() == V2::SYMBOL_SPAN_ETS_TAG) {
270         dumpLog.AddDesc(std::string("SymbolColor:").append(spanItem_->SymbolColorToString()));
271         dumpLog.AddDesc(std::string("RenderStrategy: ").append(std::to_string(textStyle->GetRenderStrategy())));
272         dumpLog.AddDesc(std::string("EffectStrategy: ").append(std::to_string(textStyle->GetEffectStrategy())));
273         dumpLog.AddDesc(std::string("SymbolEffect:").append(
274             spanItem_->fontStyle->GetSymbolEffectOptions().value_or(NG::SymbolEffectOptions()).ToString()));
275     }
276 }
277 
SpanDumpInfo()278 void SpanItem::SpanDumpInfo()
279 {
280     auto& dumpLog = DumpLog::GetInstance();
281     dumpLog.AddDesc(
282         std::string("---Content length: ").append(std::to_string(content.length())));
283     auto textStyle = textStyle_;
284     if (!textStyle) {
285         return;
286     }
287     dumpLog.AddDesc(
288         std::string("FontSize: ")
289             .append(textStyle->GetFontSize().ToString())
290             .append(" self: ")
291             .append(fontStyle && fontStyle->HasFontSize() ? fontStyle->GetFontSizeValue().ToString() : "Na"));
292     dumpLog.AddDesc(
293         std::string("TextColor: ")
294             .append(textStyle->GetTextColor().ColorToString())
295             .append(" self: ")
296             .append(fontStyle && fontStyle->HasTextColor() ? fontStyle->GetTextColorValue().ColorToString() : "Na"));
297     dumpLog.AddDesc(
298         std::string("LineHeight: ")
299             .append(textStyle->GetLineHeight().ToString())
300             .append(" self: ")
301             .append(textLineStyle
302                         ? textLineStyle->GetLineHeight().value_or(Dimension(0.0, DimensionUnit::FP)).ToString()
303                         : "Na"));
304     dumpLog.AddDesc(std::string("BaselineOffset: ")
305                         .append(textStyle->GetBaselineOffset().ToString())
306                         .append(textLineStyle && textLineStyle->HasBaselineOffset()
307                                     ? textLineStyle->GetBaselineOffsetValue().ToString()
308                                     : "Na"));
309     dumpLog.AddDesc(std::string("HalfLeading: ").append(std::to_string(textStyle->GetHalfLeading())));
310     SpanDumpInfoAdvance();
311 }
312 
SpanDumpInfoAdvance()313 void SpanItem::SpanDumpInfoAdvance()
314 {
315     CHECK_NULL_VOID(SystemProperties::GetDebugEnabled());
316     auto& dumpLog = DumpLog::GetInstance();
317     auto textStyle = textStyle_;
318     if (!textStyle) {
319         return;
320     }
321     dumpLog.AddDesc(std::string("WordSpacing: ").append(textStyle->GetWordSpacing().ToString()));
322     dumpLog.AddDesc(
323         std::string("TextIndent: ")
324             .append(textStyle->GetTextIndent().ToString())
325             .append(" self: ")
326             .append(textLineStyle && textLineStyle->HasTextIndent() ? textLineStyle->GetTextIndentValue().ToString()
327                                                                     : "Na"));
328     dumpLog.AddDesc(
329         std::string("LetterSpacing: ")
330             .append(textStyle->GetLetterSpacing().ToString())
331             .append(" self: ")
332             .append(fontStyle ? fontStyle->GetLetterSpacing().value_or(Dimension(0.0, DimensionUnit::FP)).ToString()
333                               : "Na"));
334     dumpLog.AddDesc(
335         std::string("FontWeight: ")
336             .append(StringUtils::ToString(textStyle->GetFontWeight()))
337             .append(" self: ")
338             .append(fontStyle && fontStyle->HasFontWeight() ? StringUtils::ToString(fontStyle->GetFontWeightValue())
339                                                             : "Na"));
340     dumpLog.AddDesc(std::string("FontStyle: ")
341                         .append(StringUtils::ToString(textStyle->GetFontStyle()))
342                         .append(" self: ")
343                         .append(fontStyle && fontStyle->HasItalicFontStyle()
344                                     ? StringUtils::ToString(fontStyle->GetItalicFontStyleValue())
345                                     : "Na"));
346     dumpLog.AddDesc(std::string("WordBreak: ").append(StringUtils::ToString(textStyle->GetWordBreak())));
347     dumpLog.AddDesc(std::string("TextCase: ").append(StringUtils::ToString(textStyle->GetTextCase())));
348     dumpLog.AddDesc(std::string("EllipsisMode: ").append(StringUtils::ToString(textStyle->GetEllipsisMode())));
349 }
350 
UpdateParagraph(const RefPtr<FrameNode> & frameNode,const RefPtr<Paragraph> & builder,const TextStyle & textStyle,PlaceholderStyle,bool isMarquee)351 int32_t SpanItem::UpdateParagraph(const RefPtr<FrameNode>& frameNode, const RefPtr<Paragraph>& builder,
352     const TextStyle& textStyle, PlaceholderStyle /*placeholderStyle*/, bool isMarquee)
353 {
354     CHECK_NULL_RETURN(builder, -1);
355     CHECK_NULL_RETURN(frameNode, -1);
356     auto pipelineContext = frameNode->GetContextRefPtr();
357     CHECK_NULL_RETURN(pipelineContext, -1);
358     auto spanTextStyle = textStyle;
359     UseSelfStyle(fontStyle, textLineStyle, spanTextStyle);
360     if (fontStyle && fontStyle->HasFontWeight()) {
361         spanTextStyle.SetEnableVariableFontWeight(false);
362     }
363     auto fontManager = pipelineContext->GetFontManager();
364     if (fontManager && !(fontManager->GetAppCustomFont().empty()) && (spanTextStyle.GetFontFamilies().empty())) {
365         spanTextStyle.SetFontFamilies(Framework::ConvertStrToFontFamilies(fontManager->GetAppCustomFont()));
366     }
367     FontRegisterCallback(frameNode, spanTextStyle);
368     if (NearZero(spanTextStyle.GetFontSize().Value())) {
369         return -1;
370     }
371     auto spanContent = GetSpanContent(content, isMarquee);
372     auto pattern = frameNode->GetPattern<TextPattern>();
373     CHECK_NULL_RETURN(pattern, -1);
374     spanTextStyle.SetTextBackgroundStyle(backgroundStyle);
375     if (fontStyle && !fontStyle->HasTextColor() && urlOnRelease) {
376         auto urlSpanColor = pattern->GetUrlSpanColor();
377         spanTextStyle.SetTextColor(urlSpanColor);
378         UpdateTextStyle(spanContent, builder, spanTextStyle, selectedStart, selectedEnd);
379     } else if (pattern->NeedShowAIDetect() && !aiSpanMap.empty()) {
380         TextStyle aiSpanStyle = spanTextStyle;
381         pattern->ModifyAISpanStyle(aiSpanStyle);
382         UpdateTextStyleForAISpan(spanContent, builder, spanTextStyle, aiSpanStyle);
383     } else {
384         UpdateTextStyle(spanContent, builder, spanTextStyle, selectedStart, selectedEnd);
385     }
386     textStyle_ = spanTextStyle;
387     return -1;
388 }
389 
UpdateSymbolSpanFontFamily(TextStyle & symbolSpanStyle)390 bool SpanItem::UpdateSymbolSpanFontFamily(TextStyle& symbolSpanStyle)
391 {
392     auto symbolType = symbolSpanStyle.GetSymbolType();
393     std::vector<std::string> fontFamilies;
394     if (symbolType == SymbolType::CUSTOM) {
395         auto symbolFontFamily = symbolSpanStyle.GetFontFamilies();
396         for (auto& name : symbolFontFamily) {
397             if (name.find(CUSTOM_SYMBOL_SUFFIX) != std::string::npos) {
398                 fontFamilies.push_back(name);
399                 break;
400             }
401         }
402         if (fontFamilies.empty()) {
403             return false;
404         }
405         symbolSpanStyle.SetFontFamilies(fontFamilies);
406     } else {
407         fontFamilies.push_back(DEFAULT_SYMBOL_FONTFAMILY);
408         symbolSpanStyle.SetFontFamilies(fontFamilies);
409     }
410     return true;
411 }
412 
UpdateSymbolSpanParagraph(const RefPtr<FrameNode> & frameNode,const TextStyle & textStyle,const RefPtr<Paragraph> & builder,bool isDragging)413 void SpanItem::UpdateSymbolSpanParagraph(
414     const RefPtr<FrameNode>& frameNode, const TextStyle& textStyle, const RefPtr<Paragraph>& builder, bool isDragging)
415 {
416     CHECK_NULL_VOID(builder);
417     auto symbolSpanStyle = textStyle;
418     auto symbolUnicode = GetSymbolUnicode();
419     if (fontStyle || textLineStyle) {
420         UseSelfStyle(fontStyle, textLineStyle, symbolSpanStyle);
421         if (fontStyle && fontStyle->HasFontWeight()) {
422             symbolSpanStyle.SetEnableVariableFontWeight(false);
423         }
424         if (frameNode) {
425             FontRegisterCallback(frameNode, symbolSpanStyle);
426         }
427         if (NearZero(symbolSpanStyle.GetFontSize().Value())) {
428             return;
429         }
430         if (symbolUnicode != 0) {
431             UpdateSymbolSpanColor(frameNode, symbolSpanStyle);
432         }
433         if (!symbolEffectSwitch_ || isDragging) {
434             symbolSpanStyle.SetEffectStrategy(0);
435         }
436         if (!UpdateSymbolSpanFontFamily(symbolSpanStyle)) {
437             return;
438         }
439         builder->PushStyle(symbolSpanStyle);
440     }
441     textStyle_ = symbolSpanStyle;
442 
443     if (symbolUnicode != 0) {
444         textStyle_->isSymbolGlyph_ = true;
445         builder->AddSymbol(symbolUnicode);
446     }
447 
448     if (fontStyle || textLineStyle) {
449         builder->PopStyle();
450     }
451 }
452 
UpdateSymbolSpanColor(const RefPtr<FrameNode> & frameNode,TextStyle & symbolSpanStyle)453 void SpanItem::UpdateSymbolSpanColor(const RefPtr<FrameNode>& frameNode, TextStyle& symbolSpanStyle)
454 {
455     symbolSpanStyle.isSymbolGlyph_ = true;
456     CHECK_NULL_VOID(frameNode);
457     if (GetIsParentText() && symbolSpanStyle.GetSymbolColorList().empty()) {
458         RefPtr<LayoutProperty> layoutProperty = frameNode->GetLayoutProperty();
459         CHECK_NULL_VOID(layoutProperty);
460         RefPtr<TextLayoutProperty> textLayoutProperty = DynamicCast<TextLayoutProperty>(layoutProperty);
461         CHECK_NULL_VOID(textLayoutProperty);
462         if (textLayoutProperty->GetTextColor().has_value()) {
463             std::vector<Color> symbolColor;
464             symbolColor.emplace_back(textLayoutProperty->GetTextColor().value());
465             symbolSpanStyle.SetSymbolColorList(symbolColor);
466         }
467     }
468 }
469 
UpdateTextStyleForAISpan(const std::u16string & spanContent,const RefPtr<Paragraph> & builder,const TextStyle & textStyle,const TextStyle & aiSpanStyle)470 void SpanItem::UpdateTextStyleForAISpan(const std::u16string& spanContent, const RefPtr<Paragraph>& builder,
471     const TextStyle& textStyle, const TextStyle& aiSpanStyle)
472 {
473     int32_t spanContentLength = static_cast<int32_t>(spanContent.length());
474     int32_t spanStart = this->position - spanContentLength;
475     if (needRemoveNewLine) {
476         spanStart -= 1;
477     }
478     int32_t preEnd = spanStart;
479     while (!aiSpanMap.empty()) {
480         auto aiSpan = aiSpanMap.begin()->second;
481         if (aiSpan.start >= this->position || preEnd >= this->position) {
482             break;
483         }
484         int32_t aiSpanStartInSpan = std::max(spanStart, aiSpan.start);
485         int32_t aiSpanEndInSpan = std::min(position, aiSpan.end);
486         if (aiSpan.end <= spanStart || aiSpanStartInSpan < preEnd) {
487             TAG_LOGI(AceLogTag::ACE_TEXT, "Error prediction");
488             aiSpanMap.erase(aiSpanMap.begin());
489             continue;
490         }
491         /*
492         | content has been handled | normal text | aiSpan text style | remain text   |
493         spanStart(fix)             preEnd        aiSpanStartInSpan   aiSpanEndInSpan spanStart + spanContentLength(fix)
494         */
495         int32_t contentStart = preEnd - spanStart;
496         if (preEnd < aiSpanStartInSpan) {
497             contentStart = std::clamp(contentStart, 0, static_cast<int32_t>(spanContent.length()));
498             UpdateTextStyle(spanContent.substr(contentStart, aiSpanStartInSpan - preEnd),
499                 builder, textStyle, this->selectedStart - contentStart, this->selectedEnd - contentStart);
500             contentStart = contentStart + aiSpanStartInSpan - preEnd; // aiSpan's relative offset from span
501         }
502         auto startIndex = aiSpanStartInSpan - aiSpan.start;
503         startIndex = std::clamp(startIndex, 0, static_cast<int32_t>(
504             UtfUtils::Str8DebugToStr16(aiSpan.content).length()));
505         auto displayContent = UtfUtils::Str8DebugToStr16(aiSpan.content)
506             .substr(startIndex, aiSpanEndInSpan - aiSpanStartInSpan);
507         UpdateTextStyle(displayContent, builder, aiSpanStyle,
508             this->selectedStart - contentStart, this->selectedEnd - contentStart);
509         preEnd = aiSpanEndInSpan;
510         if (aiSpan.end > position) {
511             return;
512         } else {
513             aiSpanMap.erase(aiSpanMap.begin());
514         }
515     }
516     if (preEnd < position) {
517         int32_t contentStart = preEnd - spanStart;
518         contentStart = std::clamp(contentStart, 0, static_cast<int32_t>(spanContent.length()));
519         UpdateTextStyle(spanContent.substr(contentStart, position - preEnd),
520             builder, textStyle, selectedStart - contentStart, selectedEnd - contentStart);
521     }
522 }
523 
FontRegisterCallback(const RefPtr<FrameNode> & frameNode,const TextStyle & textStyle)524 void SpanItem::FontRegisterCallback(const RefPtr<FrameNode>& frameNode, const TextStyle& textStyle)
525 {
526     auto callback = [weakNode = WeakPtr<FrameNode>(frameNode)] {
527         auto frameNode = weakNode.Upgrade();
528         CHECK_NULL_VOID(frameNode);
529         frameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
530         auto pattern = frameNode->GetPattern<TextPattern>();
531         CHECK_NULL_VOID(pattern);
532         auto modifier = DynamicCast<TextContentModifier>(pattern->GetContentModifier());
533         CHECK_NULL_VOID(modifier);
534         modifier->SetFontReady(true);
535     };
536     auto pipeline = frameNode->GetContext();
537     CHECK_NULL_VOID(pipeline);
538     auto fontManager = pipeline->GetFontManager();
539     if (fontManager) {
540         bool isCustomFont = false;
541         for (const auto& familyName : textStyle.GetFontFamilies()) {
542             bool customFont = fontManager->RegisterCallbackNG(frameNode, familyName, callback);
543             if (customFont) {
544                 isCustomFont = true;
545             }
546         }
547         if (isCustomFont) {
548             auto pattern = frameNode->GetPattern<TextPattern>();
549             CHECK_NULL_VOID(pattern);
550             pattern->SetIsCustomFont(true);
551             auto modifier = DynamicCast<TextContentModifier>(pattern->GetContentModifier());
552             CHECK_NULL_VOID(modifier);
553             modifier->SetIsCustomFont(true);
554         }
555     }
556 }
557 
UpdateTextStyle(const std::u16string & content,const RefPtr<Paragraph> & builder,const TextStyle & textStyle,int32_t selStart,int32_t selEnd)558 void SpanItem::UpdateTextStyle(const std::u16string& content, const RefPtr<Paragraph>& builder,
559     const TextStyle& textStyle, int32_t selStart, int32_t selEnd)
560 {
561     if (!IsDragging()) {
562         UpdateContentTextStyle(content, builder, textStyle);
563     } else {
564         // for content such as Hellow Wrold, update text style for three parts:
565         // [0, selStart), [selStart, selEnd), [selEnd, content.length) through UpdateContentTextStyle
566         auto contentLength = static_cast<int32_t>(content.length());
567         CHECK_NULL_VOID(selEnd > 0);
568         selStart = selStart < 0 ? 0: selStart;
569         selEnd = selEnd > contentLength ? contentLength : selEnd;
570         if (content.empty()) {
571             builder->PushStyle(textStyle);
572             builder->PopStyle();
573             return;
574         }
575         if (selStart > 0) {
576             UpdateContentTextStyle(
577                 TextEmojiProcessor::SubU16string(0, selStart, content, false, true), builder, textStyle);
578         }
579         if (selStart < contentLength) {
580             TextStyle selectedTextStyle = textStyle;
581             Color color = selectedTextStyle.GetTextColor().ChangeAlpha(DRAGGED_TEXT_OPACITY);
582             selectedTextStyle.SetTextColor(color);
583             Color textDecorationColor = selectedTextStyle.GetTextDecorationColor().ChangeAlpha(DRAGGED_TEXT_OPACITY);
584             selectedTextStyle.SetTextDecorationColor(textDecorationColor);
585             UpdateContentTextStyle(
586                 TextEmojiProcessor::SubU16string(selStart, selEnd - selStart, content, false, true),
587                 builder, selectedTextStyle);
588         }
589         if (selEnd < contentLength) {
590             UpdateContentTextStyle(
591                 TextEmojiProcessor::SubU16string(selEnd, content.length() - selEnd, content, false, true),
592                 builder, textStyle);
593         }
594     }
595 }
596 
UpdateContentTextStyle(const std::u16string & content,const RefPtr<Paragraph> & builder,const TextStyle & textStyle)597 void SpanItem::UpdateContentTextStyle(
598     const std::u16string& content, const RefPtr<Paragraph>& builder, const TextStyle& textStyle)
599 {
600     builder->PushStyle(textStyle);
601     if (!content.empty()) {
602         auto displayText = content;
603         auto textCase = textStyle.GetTextCase();
604         StringUtils::TransformStrCase(displayText, static_cast<int32_t>(textCase));
605         UtfUtils::HandleInvalidUTF16(reinterpret_cast<uint16_t*>(displayText.data()), displayText.length(), 0);
606         builder->AddText(displayText);
607     }
608     builder->PopStyle();
609 }
610 
GetSpanContent(const std::u16string & rawContent,bool isMarquee)611 std::u16string SpanItem::GetSpanContent(const std::u16string& rawContent, bool isMarquee)
612 {
613     std::u16string data;
614     if (needRemoveNewLine && !rawContent.empty()) {
615         data = rawContent.substr(0, static_cast<int32_t>(rawContent.length()) - 1);
616     } else {
617         data = rawContent;
618     }
619     if (isMarquee) {
620         std::replace(data.begin(), data.end(), u'\n', u' ');
621     }
622     return data;
623 }
624 
GetSpanContent()625 std::u16string SpanItem::GetSpanContent()
626 {
627     return content;
628 }
629 
GetSymbolUnicode()630 uint32_t SpanItem::GetSymbolUnicode()
631 {
632     return unicode;
633 }
634 
StartDrag(int32_t start,int32_t end)635 void SpanItem::StartDrag(int32_t start, int32_t end)
636 {
637     selectedStart = std::max(0, start);
638     auto contentLen = static_cast<int32_t>(content.size());
639     selectedEnd = std::min(contentLen, end);
640 }
641 
EndDrag()642 void SpanItem::EndDrag()
643 {
644     selectedStart = -1;
645     selectedEnd = -1;
646 }
647 
IsDragging()648 bool SpanItem::IsDragging()
649 {
650     return selectedStart >= 0 && selectedEnd >= 0;
651 }
652 
GetSpanResultObject(int32_t start,int32_t end)653 ResultObject SpanItem::GetSpanResultObject(int32_t start, int32_t end)
654 {
655     bool selectFlag = true;
656     ResultObject resultObject;
657     int32_t endPosition = interval.second;
658     int32_t startPosition = interval.first;
659     int32_t itemLength = endPosition - startPosition;
660 
661     if (startPosition >= start && endPosition <= end) {
662         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
663         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
664     } else if (startPosition < start && endPosition <= end && endPosition > start) {
665         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = start - startPosition;
666         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
667     } else if (startPosition >= start && startPosition < end && endPosition >= end) {
668         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
669         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = end - startPosition;
670     } else if (startPosition <= start && endPosition >= end) {
671         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = start - startPosition;
672         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = end - startPosition;
673     } else {
674         selectFlag = false;
675     }
676     if (selectFlag) {
677         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGESTART] = startPosition;
678         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGEEND] = endPosition;
679         resultObject.type = SelectSpanType::TYPESPAN;
680         resultObject.valueString = content;
681         resultObject.span = WeakClaim(this);
682         resultObject.isInit = true;
683     }
684     return resultObject;
685 }
686 
687 #define COPY_TEXT_STYLE(group, name, func)                      \
688     do {                                                        \
689         if ((group)->Has##name()) {                             \
690             sameSpan->group->func((group)->prop##name.value()); \
691         }                                                       \
692     } while (false)
693 
GetSameStyleSpanItem(bool isEncodeTlvS) const694 RefPtr<SpanItem> SpanItem::GetSameStyleSpanItem(bool isEncodeTlvS) const
695 {
696     auto sameSpan = MakeRefPtr<SpanItem>();
697     COPY_TEXT_STYLE(fontStyle, FontSize, UpdateFontSize);
698     COPY_TEXT_STYLE(fontStyle, TextColor, UpdateTextColor);
699     COPY_TEXT_STYLE(fontStyle, TextShadow, UpdateTextShadow);
700     COPY_TEXT_STYLE(fontStyle, ItalicFontStyle, UpdateItalicFontStyle);
701     COPY_TEXT_STYLE(fontStyle, FontWeight, UpdateFontWeight);
702     COPY_TEXT_STYLE(fontStyle, FontFamily, UpdateFontFamily);
703     COPY_TEXT_STYLE(fontStyle, FontFeature, UpdateFontFeature);
704     COPY_TEXT_STYLE(fontStyle, TextDecoration, UpdateTextDecoration);
705     COPY_TEXT_STYLE(fontStyle, TextDecorationColor, UpdateTextDecorationColor);
706     COPY_TEXT_STYLE(fontStyle, TextDecorationStyle, UpdateTextDecorationStyle);
707     COPY_TEXT_STYLE(fontStyle, TextCase, UpdateTextCase);
708     COPY_TEXT_STYLE(fontStyle, AdaptMinFontSize, UpdateAdaptMinFontSize);
709     COPY_TEXT_STYLE(fontStyle, AdaptMaxFontSize, UpdateAdaptMaxFontSize);
710     COPY_TEXT_STYLE(fontStyle, LetterSpacing, UpdateLetterSpacing);
711     COPY_TEXT_STYLE(fontStyle, MinFontScale, UpdateMinFontScale);
712     COPY_TEXT_STYLE(fontStyle, MaxFontScale, UpdateMaxFontScale);
713     COPY_TEXT_STYLE(textLineStyle, LineHeight, UpdateLineHeight);
714     COPY_TEXT_STYLE(textLineStyle, LineSpacing, UpdateLineSpacing);
715     COPY_TEXT_STYLE(textLineStyle, TextBaseline, UpdateTextBaseline);
716     COPY_TEXT_STYLE(textLineStyle, BaselineOffset, UpdateBaselineOffset);
717     COPY_TEXT_STYLE(textLineStyle, TextOverflow, UpdateTextOverflow);
718     COPY_TEXT_STYLE(textLineStyle, TextAlign, UpdateTextAlign);
719     COPY_TEXT_STYLE(textLineStyle, MaxLength, UpdateMaxLength);
720     COPY_TEXT_STYLE(textLineStyle, MaxLines, UpdateMaxLines);
721     COPY_TEXT_STYLE(textLineStyle, HeightAdaptivePolicy, UpdateHeightAdaptivePolicy);
722     COPY_TEXT_STYLE(textLineStyle, TextIndent, UpdateTextIndent);
723     COPY_TEXT_STYLE(textLineStyle, LeadingMargin, UpdateLeadingMargin);
724     COPY_TEXT_STYLE(textLineStyle, WordBreak, UpdateWordBreak);
725     COPY_TEXT_STYLE(textLineStyle, LineBreakStrategy, UpdateLineBreakStrategy);
726     COPY_TEXT_STYLE(textLineStyle, EllipsisMode, UpdateEllipsisMode);
727     COPY_TEXT_STYLE(textLineStyle, HalfLeading, UpdateHalfLeading);
728     COPY_TEXT_STYLE(textLineStyle, ParagraphSpacing, UpdateParagraphSpacing);
729     if (textStyle_.has_value()) {
730         sameSpan->textStyle_ = textStyle_;
731     }
732     if (backgroundStyle.has_value()) {
733         sameSpan->backgroundStyle = backgroundStyle;
734     }
735     sameSpan->urlOnRelease = urlOnRelease;
736     sameSpan->onClick = onClick;
737     sameSpan->onLongPress = onLongPress;
738     return sameSpan;
739 }
740 
741 #define WRITE_TLV_INHERIT(group, name, tag, type, inheritName)   \
742     if ((group)->Has##name()) {                                  \
743         TLVUtil::WriteUint8(buff, (tag));                        \
744         TLVUtil::Write##type(buff, (group)->prop##name.value()); \
745     } else if (textStyle_.has_value()) {                         \
746         auto temp##name = textStyle_->Get##inheritName();        \
747         TLVUtil::WriteUint8(buff, (tag));                        \
748         TLVUtil::Write##type(buff, temp##name);                  \
749     }
750 
751 #define WRITE_TEXT_STYLE_TLV(group, name, tag, type)                   \
752     do {                                                               \
753         if ((group)->Has##name()) {                                    \
754             TLVUtil::WriteUint8(buff, (tag));                          \
755             TLVUtil::Write##type(buff, (group)->prop##name.value());   \
756         }                                                              \
757     } while (false)
758 
759 #define READ_TEXT_STYLE_TLV(group, func, tag, type)                         \
760     case tag: {                                                             \
761         sameSpan->group->func(TLVUtil::Read##type(buff, cursor));           \
762         break;                                                              \
763     }
764 
EncodeTlv(std::vector<uint8_t> & buff)765 bool SpanItem::EncodeTlv(std::vector<uint8_t>& buff)
766 {
767     TLVUtil::WriteUint8(buff, TLV_SPANITEM_TAG);
768     TLVUtil::WriteInt32(buff, interval.first);
769     TLVUtil::WriteInt32(buff, interval.second);
770     TLVUtil::WriteString(buff, UtfUtils::Str16DebugToStr8(content));
771     EncodeFontStyleTlv(buff);
772     EncodeTextLineStyleTlv(buff);
773     if (backgroundStyle.has_value()) {
774         if (backgroundStyle->backgroundColor.has_value()) {
775             TLVUtil::WriteUint8(buff, TLV_SPAN_BACKGROUND_BACKGROUNDCOLOR);
776             TLVUtil::WriteColor(buff, backgroundStyle->backgroundColor.value());
777         }
778         if (backgroundStyle->backgroundRadius.has_value()) {
779             TLVUtil::WriteUint8(buff, TLV_SPAN_BACKGROUND_BACKGROUNDRADIUS);
780             TLVUtil::WriteBorderRadiusProperty(buff, backgroundStyle->backgroundRadius.value());
781         }
782         TLVUtil::WriteUint8(buff, TLV_SPAN_BACKGROUND_GROUPID);
783         TLVUtil::WriteInt32(buff, backgroundStyle->groupId);
784     }
785     WRITE_TLV_INHERIT(textLineStyle, ParagraphSpacing, TLV_SPAN_TEXT_LINE_STYLE_PARAGRAPH_SPACING, Dimension,
786         ParagraphSpacing);
787     TLVUtil::WriteUint8(buff, TLV_SPANITEM_END_TAG);
788     return true;
789 };
790 
EncodeFontStyleTlv(std::vector<uint8_t> & buff) const791 void SpanItem::EncodeFontStyleTlv(std::vector<uint8_t>& buff) const
792 {
793     WRITE_TLV_INHERIT(fontStyle, FontSize, TLV_SPAN_FONT_STYLE_FONTSIZE, Dimension, FontSize);
794     WRITE_TLV_INHERIT(fontStyle, TextColor, TLV_SPAN_FONT_STYLE_TEXTCOLOR, Color, TextColor);
795     WRITE_TLV_INHERIT(fontStyle, TextShadow, TLV_SPAN_FONT_STYLE_TEXTSHADOW, TextShadows, TextShadows);
796     WRITE_TLV_INHERIT(fontStyle, ItalicFontStyle, TLV_SPAN_FONT_STYLE_ITALICFONTSTYLE, FontStyle, FontStyle);
797     WRITE_TLV_INHERIT(fontStyle, FontWeight, TLV_SPAN_FONT_STYLE_FONTWEIGHT, FontWeight, FontWeight);
798     WRITE_TLV_INHERIT(fontStyle, FontFamily, TLV_SPAN_FONT_STYLE_FONTFAMILY, FontFamily, FontFamilies);
799     WRITE_TLV_INHERIT(fontStyle, FontFeature, TLV_SPAN_FONT_STYLE_FONTFEATURE, FontFeature, FontFeatures);
800     WRITE_TLV_INHERIT(fontStyle, TextDecoration, TLV_SPAN_FONT_STYLE_TEXTDECORATION, TextDecoration, TextDecoration);
801     WRITE_TLV_INHERIT(
802         fontStyle, TextDecorationColor, TLV_SPAN_FONT_STYLE_TEXTDECORATIONCOLOR, Color, TextDecorationColor);
803     WRITE_TLV_INHERIT(fontStyle, TextDecorationStyle, TLV_SPAN_FONT_STYLE_TEXTDECORATIONSTYLE, TextDecorationStyle,
804         TextDecorationStyle);
805     WRITE_TLV_INHERIT(fontStyle, TextCase, TLV_SPAN_FONT_STYLE_TEXTCASE, TextCase, TextCase);
806     WRITE_TLV_INHERIT(fontStyle, AdaptMinFontSize, TLV_SPAN_FONT_STYLE_ADPATMINFONTSIZE, Dimension, AdaptMinFontSize);
807     WRITE_TLV_INHERIT(fontStyle, AdaptMaxFontSize, TLV_SPAN_FONT_STYLE_ADPATMAXFONTSIZE, Dimension, AdaptMaxFontSize);
808     WRITE_TLV_INHERIT(fontStyle, LetterSpacing, TLV_SPAN_FONT_STYLE_LETTERSPACING, Dimension, LetterSpacing);
809 }
810 
EncodeTextLineStyleTlv(std::vector<uint8_t> & buff) const811 void SpanItem::EncodeTextLineStyleTlv(std::vector<uint8_t>& buff) const
812 {
813     WRITE_TLV_INHERIT(textLineStyle, LineHeight, TLV_SPAN_TEXT_LINE_STYLE_LINEHEIGHT, Dimension, LineHeight);
814     WRITE_TLV_INHERIT(textLineStyle, LineSpacing, TLV_SPAN_TEXT_LINE_STYLE_LINESPACING, Dimension, LineSpacing);
815     WRITE_TLV_INHERIT(textLineStyle, TextBaseline, TLV_SPAN_TEXT_LINE_STYLE_TEXTBASELINE, TextBaseline, TextBaseline);
816     // text's baselineOffset attribute is not span's baselineOffset attribute
817     WRITE_TEXT_STYLE_TLV(textLineStyle, BaselineOffset, TLV_SPAN_TEXT_LINE_STYLE_BASELINEOFFSET, Dimension);
818     WRITE_TLV_INHERIT(textLineStyle, TextOverflow, TLV_SPAN_TEXT_LINE_STYLE_TEXTOVERFLOW, TextOverflow, TextOverflow);
819     WRITE_TLV_INHERIT(textLineStyle, TextAlign, TLV_SPAN_TEXT_LINE_STYLE_TEXTALIGN, TextAlign, TextAlign);
820     WRITE_TEXT_STYLE_TLV(textLineStyle, MaxLength, TLV_SPAN_TEXT_LINE_STYLE_MAXLENGTH, Int32);
821     WRITE_TLV_INHERIT(textLineStyle, MaxLines, TLV_SPAN_TEXT_LINE_STYLE_MAXLINES, Int32, MaxLines);
822     WRITE_TEXT_STYLE_TLV(
823         textLineStyle, HeightAdaptivePolicy, TLV_SPAN_TEXT_LINE_STYLE_HEIGHTADAPTIVEPOLICY, TextHeightAdaptivePolicy);
824     WRITE_TLV_INHERIT(textLineStyle, TextIndent, TLV_SPAN_TEXT_LINE_STYLE_TEXTINDENT, Dimension, TextIndent);
825     WRITE_TEXT_STYLE_TLV(textLineStyle, LeadingMargin, TLV_SPAN_TEXT_LINE_STYLE_LEADINGMARGIN, LeadingMargin);
826     WRITE_TLV_INHERIT(textLineStyle, WordBreak, TLV_SPAN_TEXT_LINE_STYLE_WORDBREAK, WordBreak, WordBreak);
827     WRITE_TLV_INHERIT(textLineStyle, LineBreakStrategy, TLV_SPAN_TEXT_LINE_STYLE_LINEBREAKSTRATEGY, LineBreakStrategy,
828         LineBreakStrategy);
829     WRITE_TLV_INHERIT(textLineStyle, EllipsisMode, TLV_SPAN_TEXT_LINE_STYLE_ELLIPSISMODE, EllipsisMode, EllipsisMode);
830 }
831 
DecodeTlv(std::vector<uint8_t> & buff,int32_t & cursor)832 RefPtr<SpanItem> SpanItem::DecodeTlv(std::vector<uint8_t>& buff, int32_t& cursor)
833 {
834     auto sameSpan = MakeRefPtr<SpanItem>();
835     if (TLVUtil::ReadUint8(buff, cursor) != TLV_SPANITEM_TAG) {
836         return sameSpan;
837     }
838 
839     int32_t start = TLVUtil::ReadInt32(buff, cursor);
840     int32_t end = TLVUtil::ReadInt32(buff, cursor);
841     sameSpan->interval = {start, end};
842     sameSpan->content = UtfUtils::Str8DebugToStr16(TLVUtil::ReadString(buff, cursor));
843 
844     for (uint8_t tag = TLVUtil::ReadUint8(buff, cursor);
845         tag != TLV_SPANITEM_END_TAG; tag = TLVUtil::ReadUint8(buff, cursor)) {
846         switch (tag) {
847             READ_TEXT_STYLE_TLV(fontStyle, UpdateFontSize, TLV_SPAN_FONT_STYLE_FONTSIZE, Dimension);
848             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextColor, TLV_SPAN_FONT_STYLE_TEXTCOLOR, Color);
849             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextShadow, TLV_SPAN_FONT_STYLE_TEXTSHADOW, TextShadows);
850             READ_TEXT_STYLE_TLV(fontStyle, UpdateItalicFontStyle, TLV_SPAN_FONT_STYLE_ITALICFONTSTYLE, FontStyle);
851             READ_TEXT_STYLE_TLV(fontStyle, UpdateFontWeight, TLV_SPAN_FONT_STYLE_FONTWEIGHT, FontWeight);
852             READ_TEXT_STYLE_TLV(fontStyle, UpdateFontFamily, TLV_SPAN_FONT_STYLE_FONTFAMILY, FontFamily);
853             READ_TEXT_STYLE_TLV(fontStyle, UpdateFontFeature, TLV_SPAN_FONT_STYLE_FONTFEATURE, FontFeature);
854             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextDecoration, TLV_SPAN_FONT_STYLE_TEXTDECORATION, TextDecoration);
855             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextDecorationColor, TLV_SPAN_FONT_STYLE_TEXTDECORATIONCOLOR, Color);
856             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextDecorationStyle,
857                 TLV_SPAN_FONT_STYLE_TEXTDECORATIONSTYLE, TextDecorationStyle);
858             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextCase, TLV_SPAN_FONT_STYLE_TEXTCASE, TextCase);
859             READ_TEXT_STYLE_TLV(fontStyle, UpdateAdaptMinFontSize, TLV_SPAN_FONT_STYLE_ADPATMINFONTSIZE, Dimension);
860             READ_TEXT_STYLE_TLV(fontStyle, UpdateAdaptMaxFontSize, TLV_SPAN_FONT_STYLE_ADPATMAXFONTSIZE, Dimension);
861             READ_TEXT_STYLE_TLV(fontStyle, UpdateLetterSpacing, TLV_SPAN_FONT_STYLE_LETTERSPACING, Dimension);
862 
863             READ_TEXT_STYLE_TLV(textLineStyle, UpdateLineHeight, TLV_SPAN_TEXT_LINE_STYLE_LINEHEIGHT, Dimension);
864             READ_TEXT_STYLE_TLV(textLineStyle, UpdateLineSpacing, TLV_SPAN_TEXT_LINE_STYLE_LINESPACING, Dimension);
865             READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextBaseline, TLV_SPAN_TEXT_LINE_STYLE_TEXTBASELINE, TextBaseline);
866             READ_TEXT_STYLE_TLV(textLineStyle, UpdateBaselineOffset,
867                 TLV_SPAN_TEXT_LINE_STYLE_BASELINEOFFSET, Dimension);
868             READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextOverflow, TLV_SPAN_TEXT_LINE_STYLE_TEXTOVERFLOW, TextOverflow);
869             READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextAlign, TLV_SPAN_TEXT_LINE_STYLE_TEXTALIGN, TextAlign);
870             READ_TEXT_STYLE_TLV(textLineStyle, UpdateMaxLength, TLV_SPAN_TEXT_LINE_STYLE_MAXLENGTH, Int32);
871             READ_TEXT_STYLE_TLV(textLineStyle, UpdateMaxLines, TLV_SPAN_TEXT_LINE_STYLE_MAXLINES, Int32);
872             READ_TEXT_STYLE_TLV(textLineStyle, UpdateHeightAdaptivePolicy,
873                 TLV_SPAN_TEXT_LINE_STYLE_HEIGHTADAPTIVEPOLICY, TextHeightAdaptivePolicy);
874             READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextIndent, TLV_SPAN_TEXT_LINE_STYLE_TEXTINDENT, Dimension);
875             READ_TEXT_STYLE_TLV(textLineStyle, UpdateLeadingMargin,
876                 TLV_SPAN_TEXT_LINE_STYLE_LEADINGMARGIN, LeadingMargin);
877             READ_TEXT_STYLE_TLV(textLineStyle, UpdateWordBreak, TLV_SPAN_TEXT_LINE_STYLE_WORDBREAK, WordBreak);
878             READ_TEXT_STYLE_TLV(textLineStyle, UpdateLineBreakStrategy,
879                 TLV_SPAN_TEXT_LINE_STYLE_LINEBREAKSTRATEGY, LineBreakStrategy);
880             READ_TEXT_STYLE_TLV(textLineStyle, UpdateEllipsisMode, TLV_SPAN_TEXT_LINE_STYLE_ELLIPSISMODE, EllipsisMode);
881 
882             case TLV_SPAN_BACKGROUND_BACKGROUNDCOLOR: {
883                 if (!sameSpan->backgroundStyle.has_value()) {
884                     sameSpan->backgroundStyle = TextBackgroundStyle();
885                 }
886                 sameSpan->backgroundStyle->backgroundColor = TLVUtil::ReadColor(buff, cursor);
887                 break;
888             }
889             case TLV_SPAN_BACKGROUND_BACKGROUNDRADIUS: {
890                 sameSpan->backgroundStyle->backgroundRadius = TLVUtil::ReadBorderRadiusProperty(buff, cursor);
891                 break;
892             }
893             case TLV_SPAN_BACKGROUND_GROUPID: {
894                 sameSpan->backgroundStyle->groupId = TLVUtil::ReadInt32(buff, cursor);
895                 break;
896             }
897             READ_TEXT_STYLE_TLV(textLineStyle, UpdateParagraphSpacing,
898                 TLV_SPAN_TEXT_LINE_STYLE_PARAGRAPH_SPACING, Dimension);
899             default:
900                 break;
901         }
902     }
903     if (!Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
904         sameSpan->textLineStyle->ResetParagraphSpacing();
905     }
906     return sameSpan;
907 }
908 
SymbolColorToString()909 std::string SpanItem::SymbolColorToString()
910 {
911     auto colors = fontStyle->GetSymbolColorList();
912     auto colorStr = std::string("[");
913     if (colors.has_value()) {
914         for (const auto& color : colors.value()) {
915             colorStr.append(color.ColorToString());
916             colorStr.append(",");
917         }
918     }
919     colorStr.append("]");
920     return colorStr;
921 }
922 
GetIntersectionInterval(std::pair<int32_t,int32_t> interval) const923 std::optional<std::pair<int32_t, int32_t>> SpanItem::GetIntersectionInterval(std::pair<int32_t, int32_t> interval) const
924 {
925     // Check the intersection
926     if (this->interval.second <= interval.first || interval.second <= this->interval.first) {
927         return std::nullopt;
928     }
929 
930     // Calculate the intersection interval
931     int32_t start = std::max(this->interval.first, interval.first);
932     int32_t end = std::min(this->interval.second, interval.second);
933     return std::make_optional<std::pair<int32_t, int32_t>>(std::make_pair(start, end));
934 }
935 
EncodeTlv(std::vector<uint8_t> & buff)936 bool ImageSpanItem::EncodeTlv(std::vector<uint8_t>& buff)
937 {
938     if (spanItemType == SpanItemType::NORMAL) {
939         // ImageSpan(resource)场景,复制图片为属性字符串为空格。ImageSpanItem::GetSameStyleSpanItem获取到的spanItemType为NORMAL
940         TLVUtil::WriteUint8(buff, TLV_SPANITEM_TAG);
941         TLVUtil::WriteInt32(buff, interval.first);
942         TLVUtil::WriteInt32(buff, interval.second);
943         TLVUtil::WriteString(buff, UtfUtils::Str16DebugToStr8(content));
944         TLVUtil::WriteUint8(buff, TLV_SPANITEM_END_TAG);
945         return true;
946     }
947     TLVUtil::WriteUint8(buff, TLV_IMAGESPANITEM_TAG);
948     TLVUtil::WriteInt32(buff, interval.first);
949     TLVUtil::WriteInt32(buff, interval.second);
950     TLVUtil::WriteString(buff, UtfUtils::Str16DebugToStr8(content));
951     if (options.offset.has_value()) {
952         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_OFFSET_TAG);
953         TLVUtil::WriteInt32(buff, options.offset.value());
954     }
955     if (options.image.has_value()) {
956         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_IMAGE_TAG);
957         TLVUtil::WriteString(buff, options.image.value());
958     }
959     if (options.bundleName.has_value()) {
960         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_BUNDLENAME_TAG);
961         TLVUtil::WriteString(buff, options.bundleName.value());
962     }
963     if (options.bundleName.has_value()) {
964         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_MODULENAME_TAG);
965         TLVUtil::WriteString(buff, options.moduleName.value());
966     }
967     if (options.imagePixelMap.has_value()) {
968         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_IMAGEPIXELMAP_TAG);
969         TLVUtil::WritePixelMap(buff, options.imagePixelMap.value());
970     }
971     if (options.imageAttribute.has_value()) {
972         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_IMAGEATTRIBUTE_TAG);
973         TLVUtil::WriteImageSpanAttribute(buff, options.imageAttribute.value());
974     }
975     TLVUtil::WriteUint8(buff, TLV_SPANITEM_END_TAG);
976     return true;
977 }
978 
DecodeTlv(std::vector<uint8_t> & buff,int32_t & cursor)979 RefPtr<ImageSpanItem> ImageSpanItem::DecodeTlv(std::vector<uint8_t>& buff, int32_t& cursor)
980 {
981     auto sameSpan = MakeRefPtr<ImageSpanItem>();
982 
983     if (TLVUtil::ReadUint8(buff, cursor) != TLV_IMAGESPANITEM_TAG) {
984         return sameSpan;
985     }
986 
987     int32_t start = TLVUtil::ReadInt32(buff, cursor);
988     int32_t end = TLVUtil::ReadInt32(buff, cursor);
989     sameSpan->interval = {start, end};
990     sameSpan->content = UtfUtils::Str8DebugToStr16(TLVUtil::ReadString(buff, cursor));
991 
992     for (uint8_t tag = TLVUtil::ReadUint8(buff, cursor);
993         tag != TLV_SPANITEM_END_TAG; tag = TLVUtil::ReadUint8(buff, cursor)) {
994         switch (tag) {
995             case TLV_IMAGESPANOPTION_OFFSET_TAG: {
996                 sameSpan->options.offset = TLVUtil::ReadInt32(buff, cursor);
997                 break;
998             }
999             case TLV_IMAGESPANOPTION_IMAGE_TAG: {
1000                 sameSpan->options.image = TLVUtil::ReadString(buff, cursor);
1001                 break;
1002             }
1003             case TLV_IMAGESPANOPTION_BUNDLENAME_TAG: {
1004                 sameSpan->options.bundleName = TLVUtil::ReadString(buff, cursor);
1005                 break;
1006             }
1007             case TLV_IMAGESPANOPTION_MODULENAME_TAG: {
1008                 sameSpan->options.moduleName = TLVUtil::ReadString(buff, cursor);
1009                 break;
1010             }
1011             case TLV_IMAGESPANOPTION_IMAGEPIXELMAP_TAG: {
1012                 sameSpan->options.imagePixelMap = TLVUtil::ReadPixelMap(buff, cursor);
1013                 break;
1014             }
1015             case TLV_IMAGESPANOPTION_IMAGEATTRIBUTE_TAG: {
1016                 sameSpan->options.imageAttribute = TLVUtil::ReadImageSpanAttribute(buff, cursor);
1017                 break;
1018             }
1019             default:
1020                 break;
1021         }
1022     }
1023     return sameSpan;
1024 }
1025 
UpdateParagraph(const RefPtr<FrameNode> &,const RefPtr<Paragraph> & builder,const TextStyle & textStyle,PlaceholderStyle placeholderStyle,bool)1026 int32_t ImageSpanItem::UpdateParagraph(const RefPtr<FrameNode>& /* frameNode */, const RefPtr<Paragraph>& builder,
1027     const TextStyle& textStyle, PlaceholderStyle placeholderStyle, bool /* isMarquee*/)
1028 {
1029     CHECK_NULL_RETURN(builder, -1);
1030     PlaceholderRun run;
1031     auto spanTextStyle = textStyle;
1032     run.width = placeholderStyle.width;
1033     run.height = placeholderStyle.height;
1034     if (!NearZero(placeholderStyle.baselineOffset)) {
1035         run.baseline_offset = placeholderStyle.baselineOffset;
1036         run.alignment = PlaceholderAlignment::BASELINE;
1037     } else {
1038         switch (placeholderStyle.verticalAlign) {
1039             case VerticalAlign::TOP:
1040                 run.alignment = PlaceholderAlignment::TOP;
1041                 break;
1042             case VerticalAlign::CENTER:
1043                 run.alignment = PlaceholderAlignment::MIDDLE;
1044                 break;
1045             case VerticalAlign::BOTTOM:
1046             case VerticalAlign::NONE:
1047                 run.alignment = PlaceholderAlignment::BOTTOM;
1048                 break;
1049             case VerticalAlign::BASELINE:
1050                 run.alignment = PlaceholderAlignment::ABOVEBASELINE;
1051                 break;
1052             default:
1053                 run.alignment = PlaceholderAlignment::BOTTOM;
1054         }
1055     }
1056 
1057     // ImageSpan should ignore decoration styles
1058     spanTextStyle.SetTextDecoration(TextDecoration::NONE);
1059     spanTextStyle.SetTextBackgroundStyle(backgroundStyle);
1060     spanTextStyle.SetFontSize(placeholderStyle.paragraphFontSize);
1061     builder->PushStyle(spanTextStyle);
1062     int32_t index = builder->AddPlaceholder(run);
1063     run_ = run;
1064     builder->PopStyle();
1065     return index;
1066 }
1067 
UpdatePlaceholderBackgroundStyle(const RefPtr<FrameNode> & imageNode)1068 void ImageSpanItem::UpdatePlaceholderBackgroundStyle(const RefPtr<FrameNode>& imageNode)
1069 {
1070     CHECK_NULL_VOID(imageNode);
1071     auto property = imageNode->GetLayoutProperty<ImageLayoutProperty>();
1072     CHECK_NULL_VOID(property);
1073     backgroundStyle = property->GetPlaceHolderStyle();
1074 }
1075 
SetImageSpanOptions(const ImageSpanOptions & options)1076 void ImageSpanItem::SetImageSpanOptions(const ImageSpanOptions& options)
1077 {
1078     this->options = options;
1079 }
1080 
ResetImageSpanOptions()1081 void ImageSpanItem::ResetImageSpanOptions()
1082 {
1083     options.imageAttribute.reset();
1084 }
1085 
GetSameStyleSpanItem(bool isEncodeTlvS) const1086 RefPtr<SpanItem> ImageSpanItem::GetSameStyleSpanItem(bool isEncodeTlvS) const
1087 {
1088     auto sameSpan = MakeRefPtr<ImageSpanItem>();
1089     if (isEncodeTlvS) {
1090         if (options.HasValue()) {
1091             sameSpan->SetImageSpanOptions(options);
1092         } else {
1093             // 用与Text控件复制ImageSpan子控件,生成并保存options数据
1094             sameSpan->SetImageSpanOptions(GetImageSpanOptionsFromImageNode());
1095             if (!(sameSpan->options.imagePixelMap.value_or(nullptr))) {
1096                 /*
1097                     ImageSpan子控件,存在resource和pixelMap两种来源。
1098                     ImageSpan(resource)场景,复制图片为属性字符串为空格。
1099                     因此设置为NORMAL。在ImageSpanItem::EncodeTlv时,SpanItemType为NORMAL时,组装SpanItem。
1100                 */
1101                 sameSpan->spanItemType = SpanItemType::NORMAL;
1102             }
1103         }
1104     } else {
1105         sameSpan->SetImageSpanOptions(options);
1106     }
1107     sameSpan->urlOnRelease = urlOnRelease;
1108     sameSpan->onClick = onClick;
1109     sameSpan->onLongPress = onLongPress;
1110     if (backgroundStyle.has_value()) {
1111         sameSpan->backgroundStyle = backgroundStyle;
1112     }
1113     return sameSpan;
1114 }
1115 
GetImageSpanOptionsFromImageNode() const1116 ImageSpanOptions ImageSpanItem::GetImageSpanOptionsFromImageNode() const
1117 {
1118     ImageSpanOptions imageSpanOptions;
1119     auto frameNode = FrameNode::GetFrameNode(V2::IMAGE_ETS_TAG, imageNodeId);
1120     CHECK_NULL_RETURN(frameNode, imageSpanOptions);
1121     auto layoutProperty = frameNode->GetLayoutProperty<ImageLayoutProperty>();
1122     CHECK_NULL_RETURN(layoutProperty, imageSpanOptions);
1123     auto sourceInfo = layoutProperty->GetImageSourceInfo();
1124     if (sourceInfo.has_value()) {
1125         imageSpanOptions.image = sourceInfo->GetSrc();
1126         imageSpanOptions.bundleName = sourceInfo->GetBundleName();
1127         imageSpanOptions.moduleName = sourceInfo->GetModuleName();
1128         imageSpanOptions.imagePixelMap = sourceInfo->GetPixmap();
1129     }
1130     imageSpanOptions.imageAttribute = CreateImageSpanAttribute(layoutProperty);
1131     auto renderContext = frameNode->GetRenderContext();
1132     if (renderContext && renderContext->HasBorderRadius()) {
1133         imageSpanOptions.imageAttribute->borderRadius = renderContext->GetBorderRadius();
1134     }
1135     return imageSpanOptions;
1136 }
1137 
CreateImageSpanAttribute(const RefPtr<ImageLayoutProperty> & layoutProperty) const1138 ImageSpanAttribute ImageSpanItem::CreateImageSpanAttribute(const RefPtr<ImageLayoutProperty>& layoutProperty) const
1139 {
1140     ImageSpanAttribute imageSpanAttribute;
1141     auto& layoutConstraint = layoutProperty->GetCalcLayoutConstraint();
1142 
1143     if (layoutConstraint && layoutConstraint->selfIdealSize) {
1144         auto width = layoutConstraint->selfIdealSize->Width();
1145         auto height = layoutConstraint->selfIdealSize->Height();
1146         ImageSpanSize imageSpanSize;
1147         if (width.has_value()) {
1148             imageSpanSize.width = width->GetDimension();
1149         }
1150         if (height.has_value()) {
1151             imageSpanSize.height = height->GetDimension();
1152         }
1153         imageSpanAttribute.size = imageSpanSize;
1154     }
1155     imageSpanAttribute.verticalAlign = layoutProperty->GetVerticalAlign();
1156     imageSpanAttribute.objectFit = layoutProperty->GetImageFit();
1157     auto& margin = layoutProperty->GetMarginProperty();
1158     if (margin) {
1159         MarginProperty marginProperty;
1160         marginProperty.UpdateWithCheck(*margin);
1161         imageSpanAttribute.marginProp = marginProperty;
1162     }
1163     auto& padding = layoutProperty->GetPaddingProperty();
1164     if (padding) {
1165         MarginProperty paddingProperty;
1166         paddingProperty.UpdateWithCheck(*padding);
1167         imageSpanAttribute.paddingProp = paddingProperty;
1168     }
1169     return imageSpanAttribute;
1170 }
1171 
GetSpanResultObject(int32_t start,int32_t end)1172 ResultObject ImageSpanItem::GetSpanResultObject(int32_t start, int32_t end)
1173 {
1174     int32_t itemLength = 1;
1175     ResultObject resultObject;
1176 
1177     int32_t endPosition = interval.second;
1178     int32_t startPosition = interval.first;
1179     resultObject.type = SelectSpanType::TYPEIMAGE;
1180     if ((start <= startPosition) && (end >= endPosition)) {
1181         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGESTART] = startPosition;
1182         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGEEND] = endPosition;
1183         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
1184         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
1185         if (options.image.has_value()) {
1186             resultObject.valueString = UtfUtils::Str8DebugToStr16(options.image.value());
1187         }
1188         if (options.imagePixelMap.has_value()) {
1189             resultObject.valuePixelMap = options.imagePixelMap.value();
1190         }
1191         resultObject.isInit = true;
1192     }
1193     return resultObject;
1194 }
1195 
GetSpanResultObject(int32_t start,int32_t end)1196 ResultObject CustomSpanItem::GetSpanResultObject(int32_t start, int32_t end)
1197 {
1198     int32_t itemLength = 1;
1199     ResultObject resultObject;
1200 
1201     int32_t endPosition = interval.second;
1202     int32_t startPosition = interval.first;
1203     resultObject.type = SelectSpanType::TYPEBUILDERSPAN;
1204     if ((start <= startPosition) && (end >= endPosition)) {
1205         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGESTART] = startPosition;
1206         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGEEND] = endPosition;
1207         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
1208         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
1209         resultObject.valueString = u" ";
1210         resultObject.isInit = true;
1211     }
1212     return resultObject;
1213 }
1214 
UpdateSpanTextColor(Color color)1215 bool SpanItem::UpdateSpanTextColor(Color color)
1216 {
1217     auto pattern = pattern_.Upgrade();
1218     CHECK_NULL_RETURN(pattern, false);
1219     auto textPattern = DynamicCast<TextPattern>(pattern);
1220     CHECK_NULL_RETURN(textPattern, false);
1221     auto paragraphManager = textPattern->GetParagraphManager();
1222     CHECK_NULL_RETURN(paragraphManager, false);
1223     auto paragraphInfos = paragraphManager->GetParagraphs();
1224     if (paragraphIndex != 0 || paragraphInfos.size() != 1) {
1225         return false;
1226     }
1227     auto iter = paragraphInfos.begin();
1228     auto paragraphInfo = *iter;
1229     auto paragraph = paragraphInfo.paragraph;
1230     CHECK_NULL_RETURN(paragraph, false);
1231     paragraph->UpdateColor(position - length, position, color);
1232     textPattern->MarkDirtyNodeRender();
1233     return true;
1234 }
1235 
GetIndex(int32_t & start,int32_t & end) const1236 void SpanItem::GetIndex(int32_t& start, int32_t& end) const
1237 {
1238     auto contentLen = content.length();
1239     start = position - contentLen;
1240     end = position;
1241 }
1242 
UpdateParagraph(const RefPtr<FrameNode> &,const RefPtr<Paragraph> & builder,const TextStyle & textStyle,PlaceholderStyle placeholderStyle,bool)1243 int32_t PlaceholderSpanItem::UpdateParagraph(const RefPtr<FrameNode>& /* frameNode */, const RefPtr<Paragraph>& builder,
1244     const TextStyle& textStyle, PlaceholderStyle placeholderStyle, bool /* isMarquee*/)
1245 {
1246     CHECK_NULL_RETURN(builder, -1);
1247     auto spanTextStyle = textStyle;
1248     PlaceholderRun run;
1249     run.width = placeholderStyle.width;
1250     run.height = placeholderStyle.height;
1251     spanTextStyle.SetTextDecoration(TextDecoration::NONE);
1252     spanTextStyle.SetTextBackgroundStyle(backgroundStyle);
1253     builder->PushStyle(spanTextStyle);
1254     int32_t index = builder->AddPlaceholder(run);
1255     run_ = run;
1256     builder->PopStyle();
1257     return index;
1258 }
1259 
DumpInfo() const1260 void PlaceholderSpanItem::DumpInfo() const
1261 {
1262         auto& dumpLog = DumpLog::GetInstance();
1263         dumpLog.AddDesc("--------------- print run info ---------------");
1264         dumpLog.AddDesc(std::string("Width: ").append(std::to_string(run_.width)));
1265         dumpLog.AddDesc(std::string("Height: ").append(std::to_string(run_.height)));
1266         dumpLog.AddDesc(std::string("Alignment: ").append(StringUtils::ToString(run_.alignment)));
1267         dumpLog.AddDesc(std::string("Baseline: ").append(StringUtils::ToString(run_.baseline)));
1268         dumpLog.AddDesc(std::string("BaselineOffset: ").append(std::to_string(run_.baseline_offset)));
1269         dumpLog.AddDesc("--------------- print text style ---------------");
1270         dumpLog.AddDesc(
1271             std::string("FontSize: ")
1272                 .append(textStyle.GetFontSize().ToString())
1273                 .append(" self: ")
1274                 .append(fontStyle && fontStyle->HasFontSize() ? fontStyle->GetFontSizeValue().ToString() : "Na"));
1275         dumpLog.AddDesc(
1276             std::string("TextColor: ")
1277                 .append(textStyle.GetTextColor().ColorToString())
1278                 .append(" self: ")
1279                 .append(
1280                 fontStyle && fontStyle->HasTextColor() ? fontStyle->GetTextColorValue().ColorToString() : "Na"));
1281         dumpLog.AddDesc(std::string("BaselineOffset: ")
1282                             .append(textStyle.GetBaselineOffset().ToString())
1283                             .append(" self: ")
1284                             .append(textLineStyle && textLineStyle->HasBaselineOffset()
1285                                         ? textLineStyle->GetBaselineOffsetValue().ToString()
1286                                         : "Na"));
1287         dumpLog.AddDesc(
1288             std::string("LineHeight: ")
1289                 .append(textStyle.GetLineHeight().ToString())
1290                 .append(" self: ")
1291                 .append(textLineStyle
1292                             ? textLineStyle->GetLineHeight().value_or(Dimension(0.0, DimensionUnit::FP)).ToString()
1293                             : "Na"));
1294         dumpLog.AddDesc(std::string("LineSpacing: ").append(textStyle.GetLineSpacing().ToString()));
1295         dumpLog.AddDesc(std::string("VerticalAlign: ").append(StringUtils::ToString(textStyle.GetTextVerticalAlign())));
1296         dumpLog.AddDesc(std::string("HalfLeading: ").append(std::to_string(textStyle.GetHalfLeading())));
1297         dumpLog.AddDesc(std::string("TextBaseline: ").append(StringUtils::ToString(textStyle.GetTextBaseline())));
1298 }
1299 
GetSameStyleSpanItem(bool isEncodeTlvS) const1300 RefPtr<SpanItem> CustomSpanItem::GetSameStyleSpanItem(bool isEncodeTlvS) const
1301 {
1302     auto sameSpan = MakeRefPtr<CustomSpanItem>();
1303     sameSpan->onMeasure = onMeasure;
1304     sameSpan->onDraw = onDraw;
1305     sameSpan->urlOnRelease = urlOnRelease;
1306     sameSpan->onClick = onClick;
1307     sameSpan->onLongPress = onLongPress;
1308     if (backgroundStyle.has_value()) {
1309         sameSpan->backgroundStyle = backgroundStyle;
1310     }
1311     return sameSpan;
1312 }
1313 
SetTextBackgroundStyle(const TextBackgroundStyle & style)1314 void BaseSpan::SetTextBackgroundStyle(const TextBackgroundStyle& style)
1315 {
1316     textBackgroundStyle_ = style;
1317     textBackgroundStyle_->groupId = groupId_;
1318     SetHasTextBackgroundStyle(style.backgroundColor.has_value() || style.backgroundRadius.has_value());
1319     MarkTextDirty();
1320 }
1321 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1322 void ContainerSpanNode::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1323 {
1324     TextBackgroundStyle::ToJsonValue(json, GetTextBackgroundStyle(), filter);
1325 }
1326 
DumpInfo(std::unique_ptr<JsonValue> & json)1327 void SpanNode::DumpInfo(std::unique_ptr<JsonValue>& json)
1328 {
1329     json->Put("Content", UtfUtils::Str16DebugToStr8(spanItem_->content).c_str());
1330     auto textStyle = spanItem_->GetTextStyle();
1331     if (!textStyle) {
1332         return;
1333     }
1334     json->Put("FontSize", textStyle->GetFontSize().ToString().c_str());
1335     json->Put("LineHeight", textStyle->GetLineHeight().ToString().c_str());
1336     json->Put("LineSpacing", textStyle->GetLineSpacing().ToString().c_str());
1337     json->Put("BaselineOffset", textStyle->GetBaselineOffset().ToString().c_str());
1338     json->Put("WordSpacing", textStyle->GetWordSpacing().ToString().c_str());
1339     json->Put("TextIndent", textStyle->GetTextIndent().ToString().c_str());
1340     json->Put("LetterSpacing", textStyle->GetLetterSpacing().ToString().c_str());
1341     json->Put("TextColor", textStyle->GetTextColor().ColorToString().c_str());
1342     if (spanItem_ && spanItem_->fontStyle) {
1343         json->Put(
1344             "SpanTextColor", spanItem_->fontStyle->GetTextColor().value_or(Color::FOREGROUND).ColorToString().c_str());
1345     }
1346     json->Put("FontWeight", StringUtils::ToString(textStyle->GetFontWeight()).c_str());
1347     json->Put("FontStyle", StringUtils::ToString(textStyle->GetFontStyle()).c_str());
1348     json->Put("TextBaseline", StringUtils::ToString(textStyle->GetTextBaseline()).c_str());
1349     json->Put("TextOverflow", StringUtils::ToString(textStyle->GetTextOverflow()).c_str());
1350     json->Put("VerticalAlign", StringUtils::ToString(textStyle->GetTextVerticalAlign()).c_str());
1351     json->Put("TextAlign", StringUtils::ToString(textStyle->GetTextAlign()).c_str());
1352     json->Put("WordBreak", StringUtils::ToString(textStyle->GetWordBreak()).c_str());
1353     json->Put("TextCase", StringUtils::ToString(textStyle->GetTextCase()).c_str());
1354     json->Put("EllipsisMode", StringUtils::ToString(textStyle->GetEllipsisMode()).c_str());
1355     json->Put("HalfLeading", std::to_string(textStyle->GetHalfLeading()).c_str());
1356     if (GetTag() == V2::SYMBOL_SPAN_ETS_TAG) {
1357         json->Put("SymbolColor", spanItem_->SymbolColorToString().c_str());
1358         json->Put("RenderStrategy", std::to_string(textStyle->GetRenderStrategy()).c_str());
1359         json->Put("EffectStrategy", std::to_string(textStyle->GetEffectStrategy()).c_str());
1360         json->Put("SymbolEffect",
1361             spanItem_->fontStyle->GetSymbolEffectOptions().value_or(NG::SymbolEffectOptions()).ToString().c_str());
1362     }
1363 }
1364 } // namespace OHOS::Ace::NG
1365