• 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 "text_layout_adapter.h"
23 
24 #include "base/geometry/dimension.h"
25 #include "base/utils/string_utils.h"
26 #include "base/utils/utf_helper.h"
27 #include "base/utils/utils.h"
28 #include "core/common/font_manager.h"
29 #include "core/common/resource/resource_parse_utils.h"
30 #include "core/components/common/layout/constants.h"
31 #include "core/components/common/properties/text_style.h"
32 #include "core/components/hyperlink/hyperlink_theme.h"
33 #include "core/components/text/text_theme.h"
34 #include "core/components_ng/base/frame_node.h"
35 #include "core/components_ng/base/inspector_filter.h"
36 #include "core/components_ng/pattern/text/text_pattern.h"
37 #include "core/components_ng/pattern/text/text_styles.h"
38 #include "core/components_ng/property/property.h"
39 #include "core/components_ng/render/drawing_prop_convertor.h"
40 #include "core/components_ng/render/paragraph.h"
41 #include "core/pipeline/pipeline_context.h"
42 #include "core/pipeline_ng/pipeline_context.h"
43 #include "core/text/text_emoji_processor.h"
44 
45 namespace OHOS::Ace::NG {
46 namespace {
47 const std::string CUSTOM_SYMBOL_SUFFIX = "_CustomSymbol";
48 const std::string DEFAULT_SYMBOL_FONTFAMILY = "HM Symbol";
49 
GetDeclaration(const std::optional<Color> & color,const std::vector<TextDecoration> & textDecorations,const std::optional<TextDecorationStyle> & textDecorationStyle)50 std::string GetDeclaration(const std::optional<Color>& color, const std::vector<TextDecoration>& textDecorations,
51     const std::optional<TextDecorationStyle>& textDecorationStyle)
52 {
53     auto jsonSpanDeclaration = JsonUtil::Create(true);
54     jsonSpanDeclaration->Put(
55         "type", V2::ConvertWrapTextDecorationToStirng(textDecorations).c_str());
56     jsonSpanDeclaration->Put("color", (color.value_or(Color::BLACK).ColorToString()).c_str());
57     jsonSpanDeclaration->Put("style",
58         V2::ConvertWrapTextDecorationStyleToString(textDecorationStyle.value_or(TextDecorationStyle::SOLID))
59             .c_str());
60     return jsonSpanDeclaration->ToString();
61 }
62 
ConvertShadowToJson(const Shadow & shadow)63 inline std::unique_ptr<JsonValue> ConvertShadowToJson(const Shadow& shadow)
64 {
65     auto jsonShadow = JsonUtil::Create(true);
66     jsonShadow->Put("radius", std::to_string(shadow.GetBlurRadius()).c_str());
67     jsonShadow->Put("color", shadow.GetColor().ColorToString().c_str());
68     jsonShadow->Put("offsetX", std::to_string(shadow.GetOffset().GetX()).c_str());
69     jsonShadow->Put("offsetY", std::to_string(shadow.GetOffset().GetY()).c_str());
70     jsonShadow->Put("type", std::to_string(static_cast<int32_t>(shadow.GetShadowType())).c_str());
71     return jsonShadow;
72 }
ConvertShadowsToJson(const std::vector<Shadow> & shadows)73 std::unique_ptr<JsonValue> ConvertShadowsToJson(const std::vector<Shadow>& shadows)
74 {
75     auto jsonShadows = JsonUtil::CreateArray(true);
76     for (const auto& shadow : shadows) {
77         jsonShadows->Put(ConvertShadowToJson(shadow));
78     }
79     return jsonShadows;
80 }
81 } // namespace
82 
GetFont() const83 std::string SpanItem::GetFont() const
84 {
85     auto pattern = pattern_.Upgrade();
86     CHECK_NULL_RETURN(pattern, "");
87     auto textPattern = DynamicCast<TextPattern>(pattern);
88     CHECK_NULL_RETURN(textPattern, "");
89     auto jsonValue = JsonUtil::Create(true);
90     jsonValue->Put("style", GetFontStyleInJson(fontStyle->GetItalicFontStyle()).c_str());
91     jsonValue->Put("size", textPattern->GetFontSizeWithThemeInJson(fontStyle->GetFontSize()).c_str());
92     jsonValue->Put("weight", GetFontWeightInJson(fontStyle->GetFontWeight()).c_str());
93     jsonValue->Put("family", GetFontFamilyInJson(fontStyle->GetFontFamily()).c_str());
94     return jsonValue->ToString();
95 }
96 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const97 void SpanItem::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
98 {
99     json->PutFixedAttr("content", UtfUtils::Str16DebugToStr8(content).c_str(), filter, FIXED_ATTR_CONTENT);
100     if (filter.IsFastFilter()) {
101         TextBackgroundStyle::ToJsonValue(json, backgroundStyle, filter);
102         return;
103     }
104     auto pattern = pattern_.Upgrade();
105     CHECK_NULL_VOID(pattern);
106     auto textPattern = DynamicCast<TextPattern>(pattern);
107     CHECK_NULL_VOID(textPattern);
108     if (fontStyle) {
109         json->PutExtAttr("font", GetFont().c_str(), filter);
110         json->PutExtAttr("fontSize", textPattern->GetFontSizeWithThemeInJson(fontStyle->GetFontSize()).c_str(), filter);
111         json->PutExtAttr("decoration", GetDeclaration(fontStyle->GetTextDecorationColor(),
112             fontStyle->GetTextDecoration().value_or(std::vector<TextDecoration>({TextDecoration::NONE})),
113             fontStyle->GetTextDecorationStyle()).c_str(), filter);
114         json->PutExtAttr("letterSpacing",
115             fontStyle->GetLetterSpacing().value_or(Dimension()).ToString().c_str(), filter);
116         json->PutExtAttr("textCase",
117             V2::ConvertWrapTextCaseToStirng(fontStyle->GetTextCase().value_or(TextCase::NORMAL)).c_str(), filter);
118         if (spanItemType == SpanItemType::SYMBOL) {
119             const std::optional<std::vector<Color>>& colorListOptional = fontStyle->GetSymbolColorList();
120             auto colorListValue = colorListOptional.has_value() ? colorListOptional.value() : std::vector<Color>();
121             json->PutExtAttr("fontColor", StringUtils::SymbolColorListToString(colorListValue).c_str(), filter);
122         } else {
123             json->PutExtAttr("fontColor", fontStyle->GetForegroundColor().value_or(fontStyle->GetTextColor()
124                 .value_or(Color::BLACK)).ColorToString().c_str(), filter);
125         }
126         json->PutExtAttr("fontStyle", GetFontStyleInJson(fontStyle->GetItalicFontStyle()).c_str(), filter);
127         json->PutExtAttr("fontWeight", GetFontWeightInJson(fontStyle->GetFontWeight()).c_str(), filter);
128         json->PutExtAttr("fontFamily", GetFontFamilyInJson(fontStyle->GetFontFamily()).c_str(), filter);
129         json->PutExtAttr("renderingStrategy",
130             GetSymbolRenderingStrategyInJson(fontStyle->GetSymbolRenderingStrategy()).c_str(), filter);
131         json->PutExtAttr(
132             "effectStrategy", GetSymbolEffectStrategyInJson(fontStyle->GetSymbolEffectStrategy()).c_str(), filter);
133         json->Put("symbolEffect",
134             GetSymbolEffectOptionsInJson(fontStyle->GetSymbolEffectOptions().value_or(SymbolEffectOptions())).c_str());
135         auto shadow = fontStyle->GetTextShadow().value_or(std::vector<Shadow> { Shadow() });
136         auto jsonShadow = (shadow.size() == 1) ? ConvertShadowToJson(shadow.front()) : ConvertShadowsToJson(shadow);
137         json->PutExtAttr("textShadow", jsonShadow, filter);
138     }
139     auto dim = Dimension();
140     if (textLineStyle) {
141         json->PutExtAttr("lineHeight", textLineStyle->GetLineHeight().value_or(dim).ToString().c_str(), filter);
142         json->PutExtAttr("lineSpacing", textLineStyle->GetLineSpacing().value_or(dim).ToString().c_str(), filter);
143         json->PutExtAttr("baselineOffset",
144             textLineStyle->GetBaselineOffset().value_or(dim).ToString().c_str(), filter);
145     }
146     TextBackgroundStyle::ToJsonValue(json, backgroundStyle, filter);
147 }
148 
ToTreeJson(std::unique_ptr<JsonValue> & json,const InspectorConfig & config) const149 void SpanItem::ToTreeJson(std::unique_ptr<JsonValue>& json, const InspectorConfig& config) const
150 {
151     if (!content.empty()) {
152         json->Put(TreeKey::CONTENT, content.c_str());
153     }
154 }
155 
GetOrCreateSpanNode(int32_t nodeId)156 RefPtr<SpanNode> SpanNode::GetOrCreateSpanNode(int32_t nodeId)
157 {
158     auto spanNode = ElementRegister::GetInstance()->GetSpecificItemById<SpanNode>(nodeId);
159     if (spanNode) {
160         return spanNode;
161     }
162     spanNode = MakeRefPtr<SpanNode>(nodeId);
163     ElementRegister::GetInstance()->AddUINode(spanNode);
164     return spanNode;
165 }
166 
CreateSpanNode(int32_t nodeId)167 RefPtr<SpanNode> SpanNode::CreateSpanNode(int32_t nodeId)
168 {
169     auto spanNode = MakeRefPtr<SpanNode>(nodeId);
170     ElementRegister::GetInstance()->AddUINode(spanNode);
171     return spanNode;
172 }
173 
GetOrCreateSpanNode(const std::string & tag,int32_t nodeId)174 RefPtr<SpanNode> SpanNode::GetOrCreateSpanNode(const std::string& tag, int32_t nodeId)
175 {
176     auto spanNode = ElementRegister::GetInstance()->GetSpecificItemById<SpanNode>(nodeId);
177     if (spanNode) {
178         return spanNode;
179     }
180     spanNode = MakeRefPtr<SpanNode>(tag, nodeId);
181     ElementRegister::GetInstance()->AddUINode(spanNode);
182     return spanNode;
183 }
184 
MountToParagraph()185 void SpanNode::MountToParagraph()
186 {
187     auto parent = GetParent();
188     while (parent) {
189         auto spanNode = DynamicCast<SpanNode>(parent);
190         if (spanNode) {
191             spanNode->AddChildSpanItem(Claim(this));
192             return;
193         }
194         auto textNode = DynamicCast<FrameNode>(parent);
195         if (textNode) {
196             auto textPattern = textNode->GetPattern<TextPattern>();
197             if (textPattern) {
198                 textPattern->AddChildSpanItem(Claim(this));
199                 return;
200             }
201         }
202         parent = parent->GetParent();
203     }
204 }
205 
RequestTextFlushDirty(bool markModifyDone)206 void SpanNode::RequestTextFlushDirty(bool markModifyDone)
207 {
208     RequestTextFlushDirty(Claim<UINode>(this), markModifyDone);
209 }
210 
RequestTextFlushDirty(const RefPtr<UINode> & node,bool markModifyDone)211 void SpanNode::RequestTextFlushDirty(const RefPtr<UINode>& node, bool markModifyDone)
212 {
213     CHECK_NULL_VOID(node);
214     auto parent = node->GetParent();
215     while (parent) {
216         auto textNode = DynamicCast<FrameNode>(parent);
217         if (textNode) {
218             textNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
219             auto textPattern = textNode->GetPattern<TextPattern>();
220             if (textPattern) {
221                 CHECK_NULL_VOID(markModifyDone);
222                 textPattern->OnModifyDone();
223                 return;
224             }
225         }
226         parent = parent->GetParent();
227     }
228 }
229 
SetTextBackgroundStyle(const TextBackgroundStyle & style)230 void SpanNode::SetTextBackgroundStyle(const TextBackgroundStyle& style)
231 {
232     BaseSpan::SetTextBackgroundStyle(style);
233     spanItem_->backgroundStyle = GetTextBackgroundStyle();
234     spanItem_->MarkReLayoutParagraph();
235 }
236 
UpdateTextBackgroundFromParent(const std::optional<TextBackgroundStyle> & style)237 void SpanNode::UpdateTextBackgroundFromParent(const std::optional<TextBackgroundStyle>& style)
238 {
239     BaseSpan::UpdateTextBackgroundFromParent(style);
240     spanItem_->backgroundStyle = GetTextBackgroundStyle();
241     spanItem_->MarkReLayoutParagraph();
242 }
243 
DumpInfo()244 void SpanNode::DumpInfo()
245 {
246     auto& dumpLog = DumpLog::GetInstance();
247     spanItem_->SpanDumpInfo();
248     if (GetTag() == V2::SYMBOL_SPAN_ETS_TAG) {
249         auto textStyle = spanItem_->GetTextStyle();
250         if (!textStyle) {
251             return;
252         }
253         dumpLog.AddDesc(std::string("SymbolColor:").append(spanItem_->SymbolColorToString()));
254         dumpLog.AddDesc(std::string("RenderStrategy: ").append(std::to_string(textStyle->GetRenderStrategy())));
255         dumpLog.AddDesc(std::string("EffectStrategy: ").append(std::to_string(textStyle->GetEffectStrategy())));
256         dumpLog.AddDesc(std::string("SymbolEffect:").append(
257             spanItem_->fontStyle->GetSymbolEffectOptions().value_or(NG::SymbolEffectOptions()).ToString()));
258     }
259 }
260 
261 #define ADD_FONT_STYLE_DESC_UTILS(name, property)                                                  \
262     do {                                                                                           \
263         dumpLog.AddDesc(std::string(#name ": ")                                                    \
264                             .append(StringUtils::ToString(textStyle->Get##name()))                 \
265                             .append(" self: ")                                                     \
266                             .append(fontStyle && fontStyle->Has##property()                        \
267                                         ? StringUtils::ToString(fontStyle->Get##property##Value()) \
268                                         : "Na"));                                                  \
269     } while (0)
270 
271 #define ADD_FONT_STYLE_DESC(name)                                                                                \
272     do {                                                                                                         \
273         dumpLog.AddDesc(                                                                                         \
274             std::string(#name ": ")                                                                              \
275                 .append(textStyle->Get##name().ToString())                                                       \
276                 .append(" self: ")                                                                               \
277                 .append(fontStyle && fontStyle->Has##name() ? fontStyle->Get##name##Value().ToString() : "Na")); \
278     } while (0)
279 
280 #define ADD_LINE_STYLE_DESC_UTILS(name, property)                                                      \
281     do {                                                                                               \
282         dumpLog.AddDesc(std::string(#name ": ")                                                        \
283                             .append(StringUtils::ToString(textStyle->Get##name()))                     \
284                             .append(" self: ")                                                         \
285                             .append(textLineStyle && textLineStyle->Has##property()                    \
286                                         ? StringUtils::ToString(textLineStyle->Get##property##Value()) \
287                                         : "Na"));                                                      \
288     } while (0)
289 
290 #define ADD_LINE_STYLE_DESC(name)                                                                                  \
291     do {                                                                                                           \
292         dumpLog.AddDesc(                                                                                           \
293             std::string(#name ": ")                                                                                \
294                 .append(textStyle->Get##name().ToString())                                                         \
295                 .append(" self: ")                                                                                 \
296                 .append(textLineStyle && textLineStyle->Has##name() ? textLineStyle->Get##name##Value().ToString() \
297                                                                     : "Na"));                                      \
298     } while (0)
299 
SpanDumpInfo()300 void SpanItem::SpanDumpInfo()
301 {
302     auto& dumpLog = DumpLog::GetInstance();
303     dumpLog.AddDesc(std::string("--------Content: ")
304                         .append("\"")
305                         .append(UtfUtils::Str16DebugToStr8(content))
306                         .append("\"")
307                         .append(",spanItemType:")
308                         .append(StringUtils::ToString(spanItemType)));
309     auto textStyle = textStyle_;
310     if (!textStyle || (spanItemType != SpanItemType::NORMAL && spanItemType != SpanItemType::SYMBOL)) {
311         return;
312     }
313     ADD_LINE_STYLE_DESC(BaselineOffset);
314     ADD_LINE_STYLE_DESC_UTILS(EllipsisMode, EllipsisMode);
315     ADD_FONT_STYLE_DESC(FontSize);
316     ADD_FONT_STYLE_DESC_UTILS(FontWeight, FontWeight);
317     ADD_FONT_STYLE_DESC_UTILS(FontStyle, ItalicFontStyle);
318     dumpLog.AddDesc(std::string("HalfLeading: ").append(std::to_string(textStyle->GetHalfLeading())));
319     SpanDumpInfoAdvance();
320 }
321 
SpanDumpInfoAdvance()322 void SpanItem::SpanDumpInfoAdvance()
323 {
324     CHECK_NULL_VOID(SystemProperties::GetDebugEnabled());
325     auto& dumpLog = DumpLog::GetInstance();
326     auto textStyle = textStyle_;
327     if (!textStyle) {
328         return;
329     }
330     ADD_LINE_STYLE_DESC(LineHeight);
331     ADD_FONT_STYLE_DESC(LetterSpacing);
332     dumpLog.AddDesc(std::string("LineSpacing: ")
333             .append(textStyle->GetLineSpacing().ToString())
334             .append(" isOnlyBetweenLines: ")
335             .append((textStyle->GetIsOnlyBetweenLines()) ? "true" : "false"));
336     ADD_LINE_STYLE_DESC_UTILS(TextAlign, TextAlign);
337     ADD_LINE_STYLE_DESC(TextIndent);
338     dumpLog.AddDesc(
339         std::string("TextColor: ")
340             .append(textStyle->GetTextColor().ColorToString())
341             .append(" self: ")
342             .append(fontStyle && fontStyle->HasTextColor() ? fontStyle->GetTextColorValue().ColorToString() : "Na"));
343     ADD_FONT_STYLE_DESC_UTILS(TextCase, TextCase);
344     ADD_LINE_STYLE_DESC_UTILS(TextOverflow, TextOverflow);
345     ADD_LINE_STYLE_DESC_UTILS(WordBreak, WordBreak);
346     dumpLog.AddDesc(std::string("WordSpacing: ")
347                         .append(textStyle->GetWordSpacing().ToString())
348                         .append(" Decoration: ")
349                         .append(StringUtils::ToString(textStyle->GetTextDecorationFirst()))
350                         .append(" ")
351                         .append(StringUtils::ToString(textStyle->GetTextDecorationStyle()))
352                         .append(" ")
353                         .append(textStyle->GetTextDecorationColor().ColorToString())
354                         .append(" self: ")
355                         .append(fontStyle && fontStyle->HasTextDecoration()
356                                     ? StringUtils::ToString(fontStyle->GetTextDecorationFirst())
357                                     : "Na")
358                         .append(" ")
359                         .append(fontStyle && fontStyle->HasTextDecorationStyle()
360                                     ? StringUtils::ToString(fontStyle->GetTextDecorationStyleValue())
361                                     : "Na")
362                         .append(" ")
363                         .append(fontStyle && fontStyle->HasTextDecorationColor()
364                                     ? fontStyle->GetTextDecorationColorValue().ColorToString()
365                                     : "Na"));
366 }
367 
368 #define DEFINE_SPAN_PROP_HANDLER(KEY_TYPE, VALUE_TYPE, UPDATE_METHOD)                           \
369     {                                                                                           \
370         #KEY_TYPE, [](int32_t nodeId, RefPtr<PropertyValueBase> value) {                        \
371             auto spanNode = ElementRegister::GetInstance()->GetSpecificItemById                 \
372                 <SpanNode>(nodeId);                                                             \
373             CHECK_NULL_VOID(spanNode);                                                          \
374             if (auto realValue = std::get_if<VALUE_TYPE>(&(value->GetValue()))) {                             \
375                 spanNode->UPDATE_METHOD(*realValue);                                             \
376                                                                                                 \
377             }                                                                                   \
378         }                                                                                       \
379     }
380 
381 #define DEFINE_CONTAINER_SPAN_PROP_HANDLER(KEY_TYPE, VALUE_TYPE, UPDATE_METHOD)                 \
382     {                                                                                           \
383         #KEY_TYPE, [](int32_t nodeId, RefPtr<PropertyValueBase> value) {                        \
384             auto spanNode = ElementRegister::GetInstance()->GetSpecificItemById                 \
385                 <ContainerSpanNode>(nodeId);                                                    \
386             CHECK_NULL_VOID(spanNode);                                                          \
387             if (auto castedVal = DynamicCast<PropertyValue<VALUE_TYPE>>(value)) {               \
388                 spanNode->UPDATE_METHOD(castedVal->value);                                      \
389             }                                                                                   \
390         }                                                                                       \
391     }
392 
393 template<typename T>
RegisterResource(const std::string & key,const RefPtr<ResourceObject> & resObj,T value)394 void ContainerSpanNode::RegisterResource(const std::string& key, const RefPtr<ResourceObject>& resObj, T value)
395 {
396     auto&& updateFunc = [weakptr = AceType::WeakClaim(this), key](const RefPtr<ResourceObject>& resObj) {
397         auto spanNode = weakptr.Upgrade();
398         CHECK_NULL_VOID(spanNode);
399         spanNode->UpdateSpanResource<T>(key, resObj);
400     };
401     AddResObj(key, resObj, std::move(updateFunc));
402 }
403 
404 template void ContainerSpanNode::RegisterResource<Color>(
405     const std::string&, const RefPtr<ResourceObject>&, Color);
406 template void ContainerSpanNode::RegisterResource<CalcDimension>(
407     const std::string&, const RefPtr<ResourceObject>&, CalcDimension);
408 template void ContainerSpanNode::RegisterResource<std::vector<std::string>>(
409     const std::string&, const RefPtr<ResourceObject>&, std::vector<std::string>);
410 template void ContainerSpanNode::RegisterResource<std::u16string>(
411     const std::string&, const RefPtr<ResourceObject>&, std::u16string);
412 template void ContainerSpanNode::RegisterResource<FontWeight>(
413     const std::string&, const RefPtr<ResourceObject>&, FontWeight);
414 
415 
416 template<typename T>
UpdateSpanResource(const std::string & key,const RefPtr<ResourceObject> & resObj)417 void ContainerSpanNode::UpdateSpanResource(const std::string& key, const RefPtr<ResourceObject>& resObj)
418 {
419     UpdateProperty<T>(key, resObj);
420     MarkTextDirty();
421 }
422 
423 using Handler = std::function<void(int32_t, RefPtr<PropertyValueBase>)>;
424 
425 template<typename T>
UpdateProperty(std::string key,const RefPtr<ResourceObject> & resObj)426 void ContainerSpanNode::UpdateProperty(std::string key, const RefPtr<ResourceObject>& resObj)
427 {
428     auto value = AceType::MakeRefPtr<PropertyValueBase>();
429     if constexpr (std::is_same_v<T, std::string>) {
430         value->SetValueType(ValueType::STRING);
431     } else if (std::is_same_v<T, std::u16string>) {
432         value->SetValueType(ValueType::U16STRING);
433     } else if constexpr(std::is_same_v<T, Color>) {
434         value->SetValueType(ValueType::COLOR);
435     } else if constexpr(std::is_same_v<T, double>) {
436         value->SetValueType(ValueType::DOUBLE);
437     } else if constexpr(std::is_same_v<T, CalcDimension>) {
438         value->SetValueType(ValueType::CALDIMENSION);
439     } else if constexpr(std::is_same_v<T, float>) {
440         value->SetValueType(ValueType::FLOAT);
441     } else if constexpr(std::is_same_v<T, std::vector<std::string>>) {
442         value->SetValueType(ValueType::VECTOR_STRING);
443     } else if constexpr(std::is_same_v<T, FontWeight>) {
444         value->SetValueType(ValueType::FONT_WEIGHT);
445     }
446     ParseResToObject(resObj, value);
447     UpdatePropertyImpl(key, value);
448 }
449 
UpdatePropertyImpl(const std::string & key,RefPtr<PropertyValueBase> value)450 void ContainerSpanNode::UpdatePropertyImpl(
451     const std::string& key, RefPtr<PropertyValueBase> value)
452 {
453     return;
454 }
455 
456 template<typename T>
RegisterResource(const std::string & key,const RefPtr<ResourceObject> & resObj,T value)457 void SpanNode::RegisterResource(const std::string& key, const RefPtr<ResourceObject>& resObj, T value)
458 {
459     auto&& updateFunc = [weakptr = AceType::WeakClaim(this), key](const RefPtr<ResourceObject>& resObj) {
460         auto spanNode = weakptr.Upgrade();
461         CHECK_NULL_VOID(spanNode);
462         spanNode->UpdateSpanResource<T>(key, resObj);
463     };
464     AddResObj(key, resObj, std::move(updateFunc));
465 }
466 
467 template void SpanNode::RegisterResource<CalcDimension>(
468     const std::string&, const RefPtr<ResourceObject>&, CalcDimension);
469 template void SpanNode::RegisterResource<Color>(
470     const std::string&, const RefPtr<ResourceObject>&, Color);
471 template void SpanNode::RegisterResource<std::vector<std::string>>(
472     const std::string&, const RefPtr<ResourceObject>&, std::vector<std::string>);
473 template void SpanNode::RegisterResource<std::u16string>(
474     const std::string&, const RefPtr<ResourceObject>&, std::u16string);
475 template void SpanNode::RegisterResource<FontWeight>(
476     const std::string&, const RefPtr<ResourceObject>&, FontWeight);
477 
478 template<typename T>
UpdateSpanResource(const std::string & key,const RefPtr<ResourceObject> & resObj)479 void SpanNode::UpdateSpanResource(const std::string& key, const RefPtr<ResourceObject>& resObj)
480 {
481     UpdateProperty<T>(key, resObj);
482     auto spanItem = GetSpanItem();
483     auto pattern = spanItem->GetTextPattern().Upgrade();
484     CHECK_NULL_VOID(pattern);
485     auto textPattern = DynamicCast<TextPattern>(pattern);
486     CHECK_NULL_VOID(textPattern);
487     if (GetRerenderable()) {
488         textPattern->MarkDirtyNodeRender();
489         textPattern->MarkDirtyNodeMeasure();
490     }
491 }
492 
ParseResToObject(const RefPtr<ResourceObject> & resObj,RefPtr<PropertyValueBase> valueBase)493 void BaseSpan::ParseResToObject(const RefPtr<ResourceObject>& resObj, RefPtr<PropertyValueBase> valueBase)
494 {
495     if (valueBase->GetValueType() == ValueType::STRING) {
496         std::string value;
497         ResourceParseUtils::ParseResString(resObj, value);
498         valueBase->SetValue(value);
499     } else if (valueBase->GetValueType() == ValueType::U16STRING) {
500         std::u16string value;
501         ResourceParseUtils::ParseResString(resObj, value);
502         valueBase->SetValue(value);
503     } else if (valueBase->GetValueType() == ValueType::FONT_WEIGHT) {
504         std::string fontWeightStr;
505         ResourceParseUtils::ParseResString(resObj, fontWeightStr);
506         auto value = Framework::ConvertStrToFontWeight(fontWeightStr);
507         valueBase->SetValue(value);
508     } else if (valueBase->GetValueType() == ValueType::COLOR) {
509         Color value;
510         ResourceParseUtils::ParseResColor(resObj, value);
511         valueBase->SetValue(value);
512     } else if (valueBase->GetValueType() == ValueType::DOUBLE) {
513         double value;
514         ResourceParseUtils::ParseResDouble(resObj, value);
515         valueBase->SetValue(value);
516     } else if (valueBase->GetValueType() == ValueType::CALDIMENSION) {
517         CalcDimension value;
518         ResourceParseUtils::ParseResDimensionNG(resObj, value, DimensionUnit::FP, false);
519         valueBase->SetValue(value);
520     } else if (valueBase->GetValueType() == ValueType::VECTOR_STRING) {
521         std::vector<std::string> value;
522         ResourceParseUtils::ParseResFontFamilies(resObj, value);
523         valueBase->SetValue(value);
524     }
525 }
526 
UnregisterResource(const std::string & key)527 void SpanNode::UnregisterResource(const std::string& key)
528 {
529     if (key == "symbolColor") {
530         for (auto index : symbolFontColorResObjIndexArr) {
531             auto storeKey = key + "_" + std::to_string(index);
532             RemoveResObj(storeKey);
533         }
534         symbolFontColorResObjIndexArr.clear();
535         return;
536     }
537     BaseSpan::UnregisterResource(key);
538 }
539 
RegisterSymbolFontColorResource(const std::string & key,std::vector<Color> & symbolColor,const std::vector<std::pair<int32_t,RefPtr<ResourceObject>>> & resObjArr)540 void SpanNode::RegisterSymbolFontColorResource(const std::string& key,
541     std::vector<Color>& symbolColor, const std::vector<std::pair<int32_t, RefPtr<ResourceObject>>>& resObjArr)
542 {
543     for (auto i = 0; i < static_cast<int32_t>(resObjArr.size()); ++i) {
544         auto resObjIndex = resObjArr[i].first;
545         auto resObj = resObjArr[i].second;
546         auto storeKey = key + "_" + std::to_string(resObjIndex);
547         symbolFontColorResObjIndexArr.emplace_back(resObjIndex);
548         auto&& updateFunc = [weakptr = AceType::WeakClaim(this), storeKey, resObjIndex]
549             (const RefPtr<ResourceObject>& resObj) {
550             auto spanNode = weakptr.Upgrade();
551             CHECK_NULL_VOID(spanNode);
552             Color fontColor;
553             ResourceParseUtils::ParseResColor(resObj, fontColor);
554             auto colorVec = spanNode->GetSymbolColorList();
555             if (colorVec.has_value() && GreatNotEqual(colorVec.value().size(), resObjIndex)) {
556                 auto colorVecArr = colorVec.value();
557                 colorVecArr[resObjIndex] = fontColor;
558                 spanNode->UpdateSymbolColorList(colorVecArr);
559             }
560         };
561         AddResObj(storeKey, resObj, std::move(updateFunc));
562     }
563     UpdateSymbolColorList(symbolColor);
564 }
565 
566 template<typename T>
UpdateProperty(std::string key,const RefPtr<ResourceObject> & resObj)567 void SpanNode::UpdateProperty(std::string key, const RefPtr<ResourceObject>& resObj)
568 {
569     auto value = AceType::MakeRefPtr<PropertyValueBase>();
570     if constexpr (std::is_same_v<T, std::string>) {
571         value->SetValueType(ValueType::STRING);
572     } else if (std::is_same_v<T, std::u16string>) {
573         value->SetValueType(ValueType::U16STRING);
574     } else if constexpr(std::is_same_v<T, Color>) {
575         value->SetValueType(ValueType::COLOR);
576     } else if constexpr(std::is_same_v<T, double>) {
577         value->SetValueType(ValueType::DOUBLE);
578     } else if constexpr(std::is_same_v<T, CalcDimension>) {
579         value->SetValueType(ValueType::CALDIMENSION);
580     } else if constexpr(std::is_same_v<T, float>) {
581         value->SetValueType(ValueType::FLOAT);
582     } else if constexpr(std::is_same_v<T, std::vector<std::string>>) {
583         value->SetValueType(ValueType::VECTOR_STRING);
584     } else if constexpr(std::is_same_v<T, FontWeight>) {
585         value->SetValueType(ValueType::FONT_WEIGHT);
586     }
587     ParseResToObject(resObj, value);
588     UpdatePropertyImpl(key, value);
589 }
590 
UpdatePropertyImpl(const std::string & key,RefPtr<PropertyValueBase> value)591 void SpanNode::UpdatePropertyImpl(
592     const std::string& key, RefPtr<PropertyValueBase> value)
593 {
594     CHECK_NULL_VOID(value);
595     const std::unordered_map<std::string, Handler> span_handlers = {
596         DEFINE_SPAN_PROP_HANDLER(fontSize, CalcDimension, UpdateFontSize),
597         DEFINE_SPAN_PROP_HANDLER(fontColor, Color, UpdateTextColor),
598         DEFINE_SPAN_PROP_HANDLER(fontWeight, FontWeight, UpdateFontWeight),
599         DEFINE_SPAN_PROP_HANDLER(letterSpacing, CalcDimension, UpdateLetterSpacing),
600         DEFINE_SPAN_PROP_HANDLER(decorationColor, Color, UpdateTextDecorationColor),
601         DEFINE_SPAN_PROP_HANDLER(lineHeight, CalcDimension, UpdateLineHeight),
602         DEFINE_SPAN_PROP_HANDLER(baselineOffset, CalcDimension, UpdateBaselineOffset),
603         DEFINE_SPAN_PROP_HANDLER(value, std::u16string, UpdateContent),
604         DEFINE_SPAN_PROP_HANDLER(fontFamily, std::vector<std::string>, UpdateFontFamily),
605     };
606     auto it = span_handlers.find(key);
607     if (it != span_handlers.end()) {
608         it->second(GetId(), value);
609     }
610 }
611 
UpdateParagraph(const RefPtr<FrameNode> & frameNode,const RefPtr<Paragraph> & builder,const TextStyle & textStyle,bool isMarquee)612 int32_t SpanItem::UpdateParagraph(const RefPtr<FrameNode>& frameNode, const RefPtr<Paragraph>& builder,
613     const TextStyle& textStyle, bool isMarquee)
614 {
615     CHECK_NULL_RETURN(builder, -1);
616     CHECK_NULL_RETURN(frameNode, -1);
617     auto pipelineContext = frameNode->GetContextRefPtr();
618     CHECK_NULL_RETURN(pipelineContext, -1);
619     auto spanTextStyle = textStyle;
620     UseSelfStyle(fontStyle, textLineStyle, spanTextStyle, false);
621     if (fontStyle && fontStyle->HasFontWeight()) {
622         spanTextStyle.SetEnableVariableFontWeight(false);
623     }
624     auto fontManager = pipelineContext->GetFontManager();
625     if (fontManager && !(fontManager->GetAppCustomFont().empty()) && (spanTextStyle.GetFontFamilies().empty())) {
626         spanTextStyle.SetFontFamilies(Framework::ConvertStrToFontFamilies(fontManager->GetAppCustomFont()));
627     }
628     FontRegisterCallback(frameNode, spanTextStyle);
629     auto spanContent = GetSpanContent(content, isMarquee);
630     auto pattern = frameNode->GetPattern<TextPattern>();
631     CHECK_NULL_RETURN(pattern, -1);
632     spanTextStyle.SetTextBackgroundStyle(backgroundStyle);
633     spanTextStyle.SetTextStyleUid(nodeId_);
634     if (fontStyle && !fontStyle->HasTextColor() && urlOnRelease) {
635         auto urlSpanColor = pattern->GetUrlSpanColor();
636         spanTextStyle.SetTextColor(urlSpanColor);
637         UpdateTextStyle(spanContent, builder, spanTextStyle, selectedStart, selectedEnd);
638     } else if (pattern->NeedShowAIDetect() && !aiSpanMap.empty()) {
639         TextStyle aiSpanStyle = spanTextStyle;
640         pattern->ModifyAISpanStyle(aiSpanStyle);
641         UpdateTextStyleForAISpan(spanContent, builder, spanTextStyle, aiSpanStyle);
642     } else {
643         UpdateTextStyle(spanContent, builder, spanTextStyle, selectedStart, selectedEnd);
644     }
645     textStyle_ = spanTextStyle;
646     ResetReCreateAndReLayout();
647     return -1;
648 }
649 
UpdateSpanTextStyle(const TextStyle & textStyle,const RefPtr<FrameNode> & frameNode)650 bool SpanItem::UpdateSpanTextStyle(const TextStyle& textStyle, const RefPtr<FrameNode>& frameNode)
651 {
652     CHECK_NULL_RETURN(frameNode, false);
653     auto pipelineContext = frameNode->GetContextRefPtr();
654     CHECK_NULL_RETURN(pipelineContext, false);
655     CHECK_NULL_RETURN(textStyle_.has_value(), true);
656     UpdateReLayoutTextStyle(textStyle_.value(), textStyle, unicode != 0);
657     if (fontStyle && fontStyle->HasFontWeight()) {
658         textStyle_.value().SetEnableVariableFontWeight(false);
659     } else {
660         textStyle_.value().SetEnableVariableFontWeight(textStyle.GetEnableVariableFontWeight());
661     }
662     auto fontManager = pipelineContext->GetFontManager();
663     if (fontManager && !(fontManager->GetAppCustomFont().empty()) && (textStyle_.value().GetFontFamilies().empty())) {
664         textStyle_.value().SetFontFamilies(Framework::ConvertStrToFontFamilies(fontManager->GetAppCustomFont()));
665     }
666 
667     if (unicode != 0) {
668         auto pattern = frameNode->GetPattern<TextPattern>();
669         CHECK_NULL_RETURN(pattern, false);
670         UpdateSymbolSpanColor(frameNode, textStyle_.value());
671         if (!symbolEffectSwitch_ || pattern->IsDragging()) {
672             textStyle_.value().SetEffectStrategy(0);
673         } else if (fontStyle) {
674             textStyle_.value().SetEffectStrategy(fontStyle->propSymbolEffectStrategy.value_or(0));
675         }
676     }
677     FontRegisterCallback(frameNode, textStyle_.value());
678     textStyle_.value().SetTextBackgroundStyle(backgroundStyle);
679     return textStyle_.value().NeedReCreateParagraph();
680 }
681 
CheckSpanNeedReCreate(int32_t index)682 bool SpanItem::CheckSpanNeedReCreate(int32_t index)
683 {
684     needReCreateParagraph_ |= (index != itemIndex_);
685     itemIndex_ = index;
686     CHECK_NULL_RETURN(unicode != 0, needReCreateParagraph_);
687     if (fontStyle && fontStyle->HasSymbolType()) {
688         return (fontStyle->GetSymbolType().value() == SymbolType::CUSTOM) | needReCreateParagraph_;
689     }
690     return needReCreateParagraph_;
691 }
692 
693 #define UPDATE_SPAN_TEXT_STYLE(group, name, styleName)                 \
694     do {                                                               \
695         if (group && (group)->prop##name.has_value()) {                \
696             spanTextStyle.Set##styleName((group)->prop##name.value()); \
697         } else {                                                       \
698             spanTextStyle.Set##styleName(textStyle.Get##styleName());  \
699         }                                                              \
700     } while (false)
701 
UpdateReLayoutTextStyle(TextStyle & spanTextStyle,const TextStyle & textStyle,bool isSymbol)702 void SpanItem::UpdateReLayoutTextStyle(
703     TextStyle& spanTextStyle, const TextStyle& textStyle, bool isSymbol)
704 {
705     // The setting of AllowScale, MinFontScale, MaxFontScale must be done before any Dimension-type properties that
706     // depend on its value.
707     UPDATE_SPAN_TEXT_STYLE(textLineStyle, AllowScale, AllowScale);
708     UPDATE_SPAN_TEXT_STYLE(fontStyle, MinFontScale, MinFontScale);
709     UPDATE_SPAN_TEXT_STYLE(fontStyle, MaxFontScale, MaxFontScale);
710 
711     UPDATE_SPAN_TEXT_STYLE(fontStyle, FontSize, FontSize);
712     UPDATE_SPAN_TEXT_STYLE(fontStyle, AdaptMinFontSize, AdaptMinFontSize);
713     UPDATE_SPAN_TEXT_STYLE(fontStyle, AdaptMaxFontSize, AdaptMaxFontSize);
714     UPDATE_SPAN_TEXT_STYLE(fontStyle, LetterSpacing, LetterSpacing);
715     if (!urlOnRelease || (fontStyle && fontStyle->propTextColor.has_value())) {
716         UPDATE_SPAN_TEXT_STYLE(fontStyle, TextColor, TextColor);
717     }
718     UPDATE_SPAN_TEXT_STYLE(fontStyle, TextShadow, TextShadows);
719     UPDATE_SPAN_TEXT_STYLE(fontStyle, ItalicFontStyle, FontStyle);
720     UPDATE_SPAN_TEXT_STYLE(fontStyle, Superscript, Superscript);
721     UPDATE_SPAN_TEXT_STYLE(fontStyle, FontWeight, FontWeight);
722     UPDATE_SPAN_TEXT_STYLE(fontStyle, FontFeature, FontFeatures);
723     UPDATE_SPAN_TEXT_STYLE(fontStyle, TextDecoration, TextDecoration);
724     UPDATE_SPAN_TEXT_STYLE(fontStyle, TextDecorationColor, TextDecorationColor);
725     UPDATE_SPAN_TEXT_STYLE(fontStyle, TextDecorationStyle, TextDecorationStyle);
726     UPDATE_SPAN_TEXT_STYLE(fontStyle, TextCase, TextCase);
727     UPDATE_SPAN_TEXT_STYLE(fontStyle, VariableFontWeight, VariableFontWeight);
728     UPDATE_SPAN_TEXT_STYLE(fontStyle, LineThicknessScale, LineThicknessScale);
729 
730     UPDATE_SPAN_TEXT_STYLE(fontStyle, StrokeWidth, StrokeWidth);
731     UPDATE_SPAN_TEXT_STYLE(fontStyle, StrokeColor, StrokeColor);
732 
733     if (isSymbol) {
734         UPDATE_SPAN_TEXT_STYLE(fontStyle, SymbolColorList, SymbolColorList);
735         UPDATE_SPAN_TEXT_STYLE(fontStyle, SymbolRenderingStrategy, RenderStrategy);
736         UPDATE_SPAN_TEXT_STYLE(fontStyle, SymbolEffectOptions, SymbolEffectOptions);
737         UPDATE_SPAN_TEXT_STYLE(fontStyle, SymbolType, SymbolType);
738     } else {
739         UPDATE_SPAN_TEXT_STYLE(fontStyle, FontFamily, FontFamilies);
740     }
741 
742     UPDATE_SPAN_TEXT_STYLE(textLineStyle, LineHeight, LineHeight);
743     UPDATE_SPAN_TEXT_STYLE(textLineStyle, BaselineOffset, BaselineOffset);
744     UPDATE_SPAN_TEXT_STYLE(textLineStyle, LineSpacing, LineSpacing);
745 
746     UPDATE_SPAN_TEXT_STYLE(textLineStyle, OptimizeTrailingSpace, OptimizeTrailingSpace);
747     UPDATE_SPAN_TEXT_STYLE(textLineStyle, HalfLeading, HalfLeading);
748     UPDATE_SPAN_TEXT_STYLE(textLineStyle, TextBaseline, TextBaseline);
749     UPDATE_SPAN_TEXT_STYLE(textLineStyle, TextOverflow, TextOverflow);
750     UPDATE_SPAN_TEXT_STYLE(textLineStyle, TextAlign, TextAlign);
751     UPDATE_SPAN_TEXT_STYLE(textLineStyle, TextVerticalAlign, ParagraphVerticalAlign);
752     UPDATE_SPAN_TEXT_STYLE(textLineStyle, MaxLines, MaxLines);
753     UPDATE_SPAN_TEXT_STYLE(textLineStyle, WordBreak, WordBreak);
754     UPDATE_SPAN_TEXT_STYLE(textLineStyle, EllipsisMode, EllipsisMode);
755     UPDATE_SPAN_TEXT_STYLE(textLineStyle, LineBreakStrategy, LineBreakStrategy);
756     UPDATE_SPAN_TEXT_STYLE(textLineStyle, IsOnlyBetweenLines, IsOnlyBetweenLines);
757     UPDATE_SPAN_TEXT_STYLE(textLineStyle, ParagraphSpacing, ParagraphSpacing);
758     UpdateReLayoutGradient(spanTextStyle, textStyle);
759 }
760 
UpdateReLayoutGradient(TextStyle & spanTextStyle,const TextStyle & textStyle)761 void SpanItem::UpdateReLayoutGradient(TextStyle& spanTextStyle, const TextStyle& textStyle)
762 {
763     if (textStyle.GetGradient().has_value()) {
764         auto gradient = textStyle.GetGradient();
765         spanTextStyle.SetGradient(gradient);
766     } else {
767         spanTextStyle.SetGradient(std::nullopt);
768     }
769 }
770 
UpdateSymbolSpanFontFamily(TextStyle & symbolSpanStyle)771 bool SpanItem::UpdateSymbolSpanFontFamily(TextStyle& symbolSpanStyle)
772 {
773     auto symbolType = symbolSpanStyle.GetSymbolType();
774     std::vector<std::string> fontFamilies;
775     if (symbolType == SymbolType::CUSTOM) {
776         auto symbolFontFamily = symbolSpanStyle.GetFontFamilies();
777         for (auto& name : symbolFontFamily) {
778             if (name.find(CUSTOM_SYMBOL_SUFFIX) != std::string::npos) {
779                 fontFamilies.push_back(name);
780                 break;
781             }
782         }
783         if (fontFamilies.empty()) {
784             return false;
785         }
786         symbolSpanStyle.SetFontFamilies(fontFamilies);
787     } else {
788         fontFamilies.push_back(DEFAULT_SYMBOL_FONTFAMILY);
789         symbolSpanStyle.SetFontFamilies(fontFamilies);
790     }
791     return true;
792 }
793 
UpdateSymbolSpanParagraph(const RefPtr<FrameNode> & frameNode,const TextStyle & textStyle,const RefPtr<Paragraph> & builder,bool isDragging)794 void SpanItem::UpdateSymbolSpanParagraph(
795     const RefPtr<FrameNode>& frameNode, const TextStyle& textStyle, const RefPtr<Paragraph>& builder, bool isDragging)
796 {
797     CHECK_NULL_VOID(builder);
798     auto symbolSpanStyle = textStyle;
799     auto symbolUnicode = GetSymbolUnicode();
800     symbolSpanStyle.SetTextStyleUid(nodeId_);
801     if (fontStyle || textLineStyle) {
802         UseSelfStyle(fontStyle, textLineStyle, symbolSpanStyle, true);
803         if (fontStyle && fontStyle->HasFontWeight()) {
804             symbolSpanStyle.SetEnableVariableFontWeight(false);
805         }
806         if (frameNode) {
807             FontRegisterCallback(frameNode, symbolSpanStyle);
808         }
809         if (symbolUnicode != 0) {
810             UpdateSymbolSpanColor(frameNode, symbolSpanStyle);
811         }
812         if (!symbolEffectSwitch_ || isDragging) {
813             symbolSpanStyle.SetEffectStrategy(0);
814         }
815         if (!UpdateSymbolSpanFontFamily(symbolSpanStyle)) {
816             return;
817         }
818         builder->PushStyle(symbolSpanStyle);
819     }
820     textStyle_ = symbolSpanStyle;
821 
822     if (symbolUnicode != 0) {
823         textStyle_->isSymbolGlyph_ = true;
824         builder->AddSymbol(symbolUnicode);
825     }
826 
827     if (fontStyle || textLineStyle) {
828         builder->PopStyle();
829     }
830 }
831 
UpdateSymbolSpanColor(const RefPtr<FrameNode> & frameNode,TextStyle & symbolSpanStyle)832 void SpanItem::UpdateSymbolSpanColor(const RefPtr<FrameNode>& frameNode, TextStyle& symbolSpanStyle)
833 {
834     symbolSpanStyle.isSymbolGlyph_ = true;
835     CHECK_NULL_VOID(frameNode);
836     if (GetIsParentText() && symbolSpanStyle.GetSymbolColorList().empty()) {
837         RefPtr<LayoutProperty> layoutProperty = frameNode->GetLayoutProperty();
838         CHECK_NULL_VOID(layoutProperty);
839         RefPtr<TextLayoutProperty> textLayoutProperty = DynamicCast<TextLayoutProperty>(layoutProperty);
840         CHECK_NULL_VOID(textLayoutProperty);
841         if (textLayoutProperty->GetTextColor().has_value()) {
842             std::vector<Color> symbolColor;
843             symbolColor.emplace_back(textLayoutProperty->GetTextColor().value());
844             symbolSpanStyle.SetSymbolColorList(symbolColor);
845         }
846     }
847 }
848 
UpdateTextStyleForAISpan(const std::u16string & spanContent,const RefPtr<Paragraph> & builder,const TextStyle & textStyle,const TextStyle & aiSpanStyle)849 void SpanItem::UpdateTextStyleForAISpan(const std::u16string& spanContent, const RefPtr<Paragraph>& builder,
850     const TextStyle& textStyle, const TextStyle& aiSpanStyle)
851 {
852     int32_t spanContentLength = static_cast<int32_t>(spanContent.length());
853     int32_t spanStart = this->position - spanContentLength;
854     if (needRemoveNewLine) {
855         spanStart -= 1;
856     }
857     int32_t preEnd = spanStart;
858     while (!aiSpanMap.empty()) {
859         auto aiSpan = aiSpanMap.begin()->second;
860         if (aiSpan.start >= this->position || preEnd >= this->position) {
861             break;
862         }
863         int32_t aiSpanStartInSpan = std::max(spanStart, aiSpan.start);
864         int32_t aiSpanEndInSpan = std::min(position, aiSpan.end);
865         if (aiSpan.end <= spanStart || aiSpanStartInSpan < preEnd) {
866             TAG_LOGI(AceLogTag::ACE_TEXT, "Error prediction");
867             aiSpanMap.erase(aiSpanMap.begin());
868             continue;
869         }
870         /*
871         | content has been handled | normal text | aiSpan text style | remain text   |
872         spanStart(fix)             preEnd        aiSpanStartInSpan   aiSpanEndInSpan spanStart + spanContentLength(fix)
873         */
874         int32_t contentStart = preEnd - spanStart;
875         if (preEnd < aiSpanStartInSpan) {
876             contentStart = std::clamp(contentStart, 0, static_cast<int32_t>(spanContent.length()));
877             UpdateTextStyle(spanContent.substr(contentStart, aiSpanStartInSpan - preEnd),
878                 builder, textStyle, this->selectedStart - contentStart, this->selectedEnd - contentStart);
879             contentStart = contentStart + aiSpanStartInSpan - preEnd; // aiSpan's relative offset from span
880         }
881         auto startIndex = aiSpanStartInSpan - aiSpan.start;
882         startIndex = std::clamp(startIndex, 0, static_cast<int32_t>(
883             UtfUtils::Str8DebugToStr16(aiSpan.content).length()));
884         auto displayContent = UtfUtils::Str8DebugToStr16(aiSpan.content)
885             .substr(startIndex, aiSpanEndInSpan - aiSpanStartInSpan);
886         UpdateTextStyle(displayContent, builder, aiSpanStyle,
887             this->selectedStart - contentStart, this->selectedEnd - contentStart);
888         preEnd = aiSpanEndInSpan;
889         if (aiSpan.end > position) {
890             return;
891         } else {
892             aiSpanMap.erase(aiSpanMap.begin());
893         }
894     }
895     if (preEnd < position) {
896         int32_t contentStart = preEnd - spanStart;
897         contentStart = std::clamp(contentStart, 0, static_cast<int32_t>(spanContent.length()));
898         UpdateTextStyle(spanContent.substr(contentStart, position - preEnd),
899             builder, textStyle, selectedStart - contentStart, selectedEnd - contentStart);
900     }
901 }
902 
FontRegisterCallback(const RefPtr<FrameNode> & frameNode,const TextStyle & textStyle)903 void SpanItem::FontRegisterCallback(const RefPtr<FrameNode>& frameNode, const TextStyle& textStyle)
904 {
905     auto callback = [weakNode = WeakPtr<FrameNode>(frameNode)] {
906         auto frameNode = weakNode.Upgrade();
907         CHECK_NULL_VOID(frameNode);
908         frameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
909         auto pattern = frameNode->GetPattern<TextPattern>();
910         CHECK_NULL_VOID(pattern);
911         auto modifier = DynamicCast<TextContentModifier>(pattern->GetContentModifier());
912         CHECK_NULL_VOID(modifier);
913         modifier->SetFontReady(true);
914         auto layoutProperty = frameNode->GetLayoutProperty();
915         CHECK_NULL_VOID(layoutProperty);
916         layoutProperty->OnPropertyChangeMeasure();
917     };
918     auto pipeline = frameNode->GetContext();
919     CHECK_NULL_VOID(pipeline);
920     auto fontManager = pipeline->GetFontManager();
921     if (fontManager) {
922         bool isCustomFont = false;
923         for (const auto& familyName : textStyle.GetFontFamilies()) {
924             bool customFont = fontManager->RegisterCallbackNG(frameNode, familyName, callback);
925             if (customFont) {
926                 isCustomFont = true;
927             }
928         }
929         if (isCustomFont) {
930             auto pattern = frameNode->GetPattern<TextPattern>();
931             CHECK_NULL_VOID(pattern);
932             pattern->SetIsCustomFont(true);
933             auto modifier = DynamicCast<TextContentModifier>(pattern->GetContentModifier());
934             CHECK_NULL_VOID(modifier);
935             modifier->SetIsCustomFont(true);
936         }
937     }
938 }
939 
UpdateTextStyle(const std::u16string & content,const RefPtr<Paragraph> & builder,const TextStyle & textStyle,int32_t selStart,int32_t selEnd)940 void SpanItem::UpdateTextStyle(const std::u16string& content, const RefPtr<Paragraph>& builder,
941     const TextStyle& textStyle, int32_t selStart, int32_t selEnd)
942 {
943     if (!IsDragging()) {
944         UpdateContentTextStyle(content, builder, textStyle);
945     } else {
946         // for content such as Hellow Wrold, update text style for three parts:
947         // [0, selStart), [selStart, selEnd), [selEnd, content.length) through UpdateContentTextStyle
948         auto contentLength = static_cast<int32_t>(content.length());
949         selStart = selStart < 0 ? 0: selStart;
950         selEnd = selEnd < 0 ? 0 : selEnd;
951         selEnd = selEnd > contentLength ? contentLength : selEnd;
952         if (content.empty()) {
953             builder->PushStyle(textStyle);
954             builder->PopStyle();
955             return;
956         }
957         if (selStart > 0) {
958             UpdateContentTextStyle(
959                 TextEmojiProcessor::SubU16string(0, selStart, content, false, true), builder, textStyle);
960         }
961         if (selStart < contentLength) {
962             TextStyle selectedTextStyle = textStyle;
963             Color color = selectedTextStyle.GetTextColor().ChangeAlpha(DRAGGED_TEXT_OPACITY);
964             selectedTextStyle.SetTextColor(color);
965             Color textDecorationColor = selectedTextStyle.GetTextDecorationColor().ChangeAlpha(DRAGGED_TEXT_OPACITY);
966             selectedTextStyle.SetTextDecorationColor(textDecorationColor);
967             UpdateContentTextStyle(
968                 TextEmojiProcessor::SubU16string(selStart, selEnd - selStart, content, false, true),
969                 builder, selectedTextStyle);
970         }
971         if (selEnd < contentLength) {
972             UpdateContentTextStyle(
973                 TextEmojiProcessor::SubU16string(selEnd, content.length() - selEnd, content, false, true),
974                 builder, textStyle);
975         }
976     }
977 }
978 
UpdateContentTextStyle(const std::u16string & content,const RefPtr<Paragraph> & builder,const TextStyle & textStyle)979 void SpanItem::UpdateContentTextStyle(
980     const std::u16string& content, const RefPtr<Paragraph>& builder, const TextStyle& textStyle)
981 {
982     builder->PushStyle(textStyle);
983     if (!content.empty()) {
984         auto displayText = content;
985         auto textCase = textStyle.GetTextCase();
986         StringUtils::TransformStrCase(displayText, static_cast<int32_t>(textCase));
987         UtfUtils::HandleInvalidUTF16(reinterpret_cast<uint16_t*>(displayText.data()), displayText.length(), 0);
988         builder->AddText(displayText);
989     }
990     builder->PopStyle();
991 }
992 
GetSpanContent(const std::u16string & rawContent,bool isMarquee)993 std::u16string SpanItem::GetSpanContent(const std::u16string& rawContent, bool isMarquee)
994 {
995     std::u16string data;
996     if (needRemoveNewLine && !rawContent.empty()) {
997         data = rawContent.substr(0, static_cast<int32_t>(rawContent.length()) - 1);
998     } else {
999         data = rawContent;
1000     }
1001     if (isMarquee) {
1002         std::replace(data.begin(), data.end(), u'\n', u' ');
1003     }
1004     return data;
1005 }
1006 
GetSpanContent()1007 std::u16string SpanItem::GetSpanContent()
1008 {
1009     return content;
1010 }
1011 
GetSymbolUnicode()1012 uint32_t SpanItem::GetSymbolUnicode()
1013 {
1014     return unicode;
1015 }
1016 
StartDrag(int32_t start,int32_t end)1017 void SpanItem::StartDrag(int32_t start, int32_t end)
1018 {
1019     selectedStart = std::max(0, start);
1020     auto contentLen = static_cast<int32_t>(content.size());
1021     selectedEnd = std::min(contentLen, end);
1022 }
1023 
EndDrag()1024 void SpanItem::EndDrag()
1025 {
1026     selectedStart = -1;
1027     selectedEnd = -1;
1028 }
1029 
IsDragging()1030 bool SpanItem::IsDragging()
1031 {
1032     return selectedStart >= 0 && selectedEnd >= 0;
1033 }
1034 
GetSpanResultObject(int32_t start,int32_t end)1035 ResultObject SpanItem::GetSpanResultObject(int32_t start, int32_t end)
1036 {
1037     bool selectFlag = true;
1038     ResultObject resultObject;
1039     int32_t endPosition = interval.second;
1040     int32_t startPosition = interval.first;
1041     int32_t itemLength = endPosition - startPosition;
1042 
1043     if (startPosition >= start && endPosition <= end) {
1044         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
1045         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
1046     } else if (startPosition < start && endPosition <= end && endPosition > start) {
1047         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = start - startPosition;
1048         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
1049     } else if (startPosition >= start && startPosition < end && endPosition >= end) {
1050         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
1051         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = end - startPosition;
1052     } else if (startPosition <= start && endPosition >= end) {
1053         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = start - startPosition;
1054         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = end - startPosition;
1055     } else {
1056         selectFlag = false;
1057     }
1058     if (selectFlag) {
1059         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGESTART] = startPosition;
1060         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGEEND] = endPosition;
1061         resultObject.type = SelectSpanType::TYPESPAN;
1062         resultObject.valueString = content;
1063         resultObject.span = WeakClaim(this);
1064         resultObject.isInit = true;
1065     }
1066     return resultObject;
1067 }
1068 
1069 #define COPY_TEXT_STYLE(group, name, func)                      \
1070     do {                                                        \
1071         if ((group)->Has##name()) {                             \
1072             sameSpan->group->func((group)->prop##name.value()); \
1073         }                                                       \
1074     } while (false)
1075 
GetSameStyleSpanItem(bool isEncodeTlvS) const1076 RefPtr<SpanItem> SpanItem::GetSameStyleSpanItem(bool isEncodeTlvS) const
1077 {
1078     auto sameSpan = MakeRefPtr<SpanItem>();
1079     GetFontStyleSpanItem(sameSpan);
1080     COPY_TEXT_STYLE(textLineStyle, LineHeight, UpdateLineHeight);
1081     COPY_TEXT_STYLE(textLineStyle, LineSpacing, UpdateLineSpacing);
1082     COPY_TEXT_STYLE(textLineStyle, OptimizeTrailingSpace, UpdateOptimizeTrailingSpace);
1083     COPY_TEXT_STYLE(textLineStyle, TextBaseline, UpdateTextBaseline);
1084     COPY_TEXT_STYLE(textLineStyle, BaselineOffset, UpdateBaselineOffset);
1085     COPY_TEXT_STYLE(textLineStyle, TextOverflow, UpdateTextOverflow);
1086     COPY_TEXT_STYLE(textLineStyle, TextAlign, UpdateTextAlign);
1087     COPY_TEXT_STYLE(textLineStyle, TextVerticalAlign, UpdateTextVerticalAlign);
1088     COPY_TEXT_STYLE(textLineStyle, MaxLength, UpdateMaxLength);
1089     COPY_TEXT_STYLE(textLineStyle, MaxLines, UpdateMaxLines);
1090     COPY_TEXT_STYLE(textLineStyle, HeightAdaptivePolicy, UpdateHeightAdaptivePolicy);
1091     COPY_TEXT_STYLE(textLineStyle, TextIndent, UpdateTextIndent);
1092     COPY_TEXT_STYLE(textLineStyle, LeadingMargin, UpdateLeadingMargin);
1093     COPY_TEXT_STYLE(textLineStyle, WordBreak, UpdateWordBreak);
1094     COPY_TEXT_STYLE(textLineStyle, LineBreakStrategy, UpdateLineBreakStrategy);
1095     COPY_TEXT_STYLE(textLineStyle, EllipsisMode, UpdateEllipsisMode);
1096     COPY_TEXT_STYLE(textLineStyle, HalfLeading, UpdateHalfLeading);
1097     COPY_TEXT_STYLE(textLineStyle, ParagraphSpacing, UpdateParagraphSpacing);
1098     if (textStyle_.has_value()) {
1099         sameSpan->textStyle_ = textStyle_;
1100     }
1101     if (backgroundStyle.has_value()) {
1102         sameSpan->backgroundStyle = backgroundStyle;
1103     }
1104     sameSpan->urlAddress = urlAddress;
1105     sameSpan->urlOnRelease = urlOnRelease;
1106     sameSpan->onClick = onClick;
1107     sameSpan->onLongPress = onLongPress;
1108     sameSpan->onTouch = onTouch;
1109     return sameSpan;
1110 }
1111 
GetFontStyleSpanItem(RefPtr<SpanItem> & sameSpan) const1112 void SpanItem::GetFontStyleSpanItem(RefPtr<SpanItem>& sameSpan) const
1113 {
1114     COPY_TEXT_STYLE(fontStyle, FontSize, UpdateFontSize);
1115     COPY_TEXT_STYLE(fontStyle, TextColor, UpdateTextColor);
1116     COPY_TEXT_STYLE(fontStyle, TextShadow, UpdateTextShadow);
1117     COPY_TEXT_STYLE(fontStyle, ItalicFontStyle, UpdateItalicFontStyle);
1118     COPY_TEXT_STYLE(fontStyle, FontWeight, UpdateFontWeight);
1119     COPY_TEXT_STYLE(fontStyle, FontFamily, UpdateFontFamily);
1120     COPY_TEXT_STYLE(fontStyle, FontFeature, UpdateFontFeature);
1121     COPY_TEXT_STYLE(fontStyle, StrokeWidth, UpdateStrokeWidth);
1122     COPY_TEXT_STYLE(fontStyle, StrokeColor, UpdateStrokeColor);
1123     COPY_TEXT_STYLE(fontStyle, Superscript, UpdateSuperscript);
1124     COPY_TEXT_STYLE(fontStyle, TextDecoration, UpdateTextDecoration);
1125     COPY_TEXT_STYLE(fontStyle, TextDecorationColor, UpdateTextDecorationColor);
1126     COPY_TEXT_STYLE(fontStyle, TextDecorationStyle, UpdateTextDecorationStyle);
1127     COPY_TEXT_STYLE(fontStyle, LineThicknessScale, UpdateLineThicknessScale);
1128     COPY_TEXT_STYLE(fontStyle, TextCase, UpdateTextCase);
1129     COPY_TEXT_STYLE(fontStyle, AdaptMinFontSize, UpdateAdaptMinFontSize);
1130     COPY_TEXT_STYLE(fontStyle, AdaptMaxFontSize, UpdateAdaptMaxFontSize);
1131     COPY_TEXT_STYLE(fontStyle, LetterSpacing, UpdateLetterSpacing);
1132     COPY_TEXT_STYLE(fontStyle, MinFontScale, UpdateMinFontScale);
1133     COPY_TEXT_STYLE(fontStyle, MaxFontScale, UpdateMaxFontScale);
1134 }
1135 
1136 #define WRITE_TLV_INHERIT(group, name, tag, type, inheritName)   \
1137     if ((group)->Has##name()) {                                  \
1138         TLVUtil::WriteUint8(buff, (tag));                        \
1139         TLVUtil::Write##type(buff, (group)->prop##name.value()); \
1140     } else if (textStyle_.has_value()) {                         \
1141         auto temp##name = textStyle_->Get##inheritName();        \
1142         TLVUtil::WriteUint8(buff, (tag));                        \
1143         TLVUtil::Write##type(buff, temp##name);                  \
1144     }
1145 
1146 #define WRITE_TEXT_STYLE_TLV(group, name, tag, type)                   \
1147     do {                                                               \
1148         if ((group)->Has##name()) {                                    \
1149             TLVUtil::WriteUint8(buff, (tag));                          \
1150             TLVUtil::Write##type(buff, (group)->prop##name.value());   \
1151         }                                                              \
1152     } while (false)
1153 
1154 #define READ_TEXT_STYLE_TLV(group, func, tag, type)                         \
1155     case tag: {                                                             \
1156         sameSpan->group->func(TLVUtil::Read##type(buff, cursor));           \
1157         break;                                                              \
1158     }
1159 
EncodeTlv(std::vector<uint8_t> & buff)1160 bool SpanItem::EncodeTlv(std::vector<uint8_t>& buff)
1161 {
1162     TLVUtil::WriteUint8(buff, TLV_SPANITEM_TAG);
1163     TLVUtil::WriteInt32(buff, interval.first);
1164     TLVUtil::WriteInt32(buff, interval.second);
1165     TLVUtil::WriteU16String(buff, content);
1166     EncodeFontStyleTlv(buff);
1167     EncodeTextLineStyleTlv(buff);
1168     if (backgroundStyle.has_value()) {
1169         if (backgroundStyle->backgroundColor.has_value()) {
1170             TLVUtil::WriteUint8(buff, TLV_SPAN_BACKGROUND_BACKGROUNDCOLOR);
1171             TLVUtil::WriteColor(buff, backgroundStyle->backgroundColor.value());
1172         }
1173         if (backgroundStyle->backgroundRadius.has_value()) {
1174             TLVUtil::WriteUint8(buff, TLV_SPAN_BACKGROUND_BACKGROUNDRADIUS);
1175             TLVUtil::WriteBorderRadiusProperty(buff, backgroundStyle->backgroundRadius.value());
1176         }
1177         TLVUtil::WriteUint8(buff, TLV_SPAN_BACKGROUND_GROUPID);
1178         TLVUtil::WriteInt32(buff, backgroundStyle->groupId);
1179     }
1180     WRITE_TLV_INHERIT(textLineStyle, ParagraphSpacing, TLV_SPAN_TEXT_LINE_STYLE_PARAGRAPH_SPACING, Dimension,
1181         ParagraphSpacing);
1182     if (urlAddress.has_value()) {
1183         TLVUtil::WriteUint8(buff, TLV_SPAN_URL_CONTENT);
1184         TLVUtil::WriteU16String(buff, GetUrlAddress());
1185     }
1186     TLVUtil::WriteUint8(buff, TLV_SPANITEM_END_TAG);
1187     return true;
1188 };
1189 
EncodeFontStyleTlv(std::vector<uint8_t> & buff) const1190 void SpanItem::EncodeFontStyleTlv(std::vector<uint8_t>& buff) const
1191 {
1192     WRITE_TLV_INHERIT(fontStyle, FontSize, TLV_SPAN_FONT_STYLE_FONTSIZE, Dimension, FontSize);
1193     WRITE_TLV_INHERIT(fontStyle, TextColor, TLV_SPAN_FONT_STYLE_TEXTCOLOR, Color, TextColor);
1194     WRITE_TLV_INHERIT(fontStyle, TextShadow, TLV_SPAN_FONT_STYLE_TEXTSHADOW, TextShadows, TextShadows);
1195     WRITE_TLV_INHERIT(fontStyle, ItalicFontStyle, TLV_SPAN_FONT_STYLE_ITALICFONTSTYLE, FontStyle, FontStyle);
1196     WRITE_TLV_INHERIT(fontStyle, FontWeight, TLV_SPAN_FONT_STYLE_FONTWEIGHT, FontWeight, FontWeight);
1197     WRITE_TLV_INHERIT(fontStyle, FontFamily, TLV_SPAN_FONT_STYLE_FONTFAMILY, FontFamily, FontFamilies);
1198     WRITE_TLV_INHERIT(fontStyle, FontFeature, TLV_SPAN_FONT_STYLE_FONTFEATURE, FontFeature, FontFeatures);
1199     WRITE_TLV_INHERIT(fontStyle, Superscript, TLV_SPAN_FONT_STYLE_SUPERSCRIPT, SuperscriptStyle, Superscript);
1200     WRITE_TLV_INHERIT(fontStyle, StrokeWidth, TLV_SPAN_FONT_STYLE_STROKEWIDTH, Dimension, StrokeWidth);
1201     WRITE_TLV_INHERIT(fontStyle, StrokeColor, TLV_SPAN_FONT_STYLE_STROKECOLOR, Color, StrokeColor);
1202     WRITE_TLV_INHERIT(
1203         fontStyle, TextDecorationColor, TLV_SPAN_FONT_STYLE_TEXTDECORATIONCOLOR, Color, TextDecorationColor);
1204     WRITE_TLV_INHERIT(fontStyle, TextDecorationStyle, TLV_SPAN_FONT_STYLE_TEXTDECORATIONSTYLE, TextDecorationStyle,
1205         TextDecorationStyle);
1206     WRITE_TLV_INHERIT(fontStyle, TextCase, TLV_SPAN_FONT_STYLE_TEXTCASE, TextCase, TextCase);
1207     WRITE_TLV_INHERIT(fontStyle, AdaptMinFontSize, TLV_SPAN_FONT_STYLE_ADPATMINFONTSIZE, Dimension, AdaptMinFontSize);
1208     WRITE_TLV_INHERIT(fontStyle, AdaptMaxFontSize, TLV_SPAN_FONT_STYLE_ADPATMAXFONTSIZE, Dimension, AdaptMaxFontSize);
1209     WRITE_TLV_INHERIT(fontStyle, LetterSpacing, TLV_SPAN_FONT_STYLE_LETTERSPACING, Dimension, LetterSpacing);
1210     WRITE_TLV_INHERIT(fontStyle, LineThicknessScale, TLV_SPAN_FONT_STYLE_LineThicknessScale, Float,
1211         LineThicknessScale);
1212     if (fontStyle->HasTextDecoration()) {
1213         TLVUtil::WriteTextDecorations(buff, fontStyle->GetTextDecoration().value());
1214     } else if (textStyle_.has_value()) {
1215         TLVUtil::WriteTextDecorations(buff, textStyle_->GetTextDecoration());
1216     }
1217 }
1218 
EncodeTextLineStyleTlv(std::vector<uint8_t> & buff) const1219 void SpanItem::EncodeTextLineStyleTlv(std::vector<uint8_t>& buff) const
1220 {
1221     WRITE_TLV_INHERIT(textLineStyle, LineHeight, TLV_SPAN_TEXT_LINE_STYLE_LINEHEIGHT, Dimension, LineHeight);
1222     WRITE_TLV_INHERIT(textLineStyle, LineSpacing, TLV_SPAN_TEXT_LINE_STYLE_LINESPACING, Dimension, LineSpacing);
1223     WRITE_TLV_INHERIT(textLineStyle, TextBaseline, TLV_SPAN_TEXT_LINE_STYLE_TEXTBASELINE, TextBaseline, TextBaseline);
1224     // text's baselineOffset attribute is not span's baselineOffset attribute
1225     WRITE_TEXT_STYLE_TLV(textLineStyle, BaselineOffset, TLV_SPAN_TEXT_LINE_STYLE_BASELINEOFFSET, Dimension);
1226     WRITE_TLV_INHERIT(textLineStyle, TextOverflow, TLV_SPAN_TEXT_LINE_STYLE_TEXTOVERFLOW, TextOverflow, TextOverflow);
1227     WRITE_TLV_INHERIT(textLineStyle, TextAlign, TLV_SPAN_TEXT_LINE_STYLE_TEXTALIGN, TextAlign, TextAlign);
1228     WRITE_TEXT_STYLE_TLV(textLineStyle, MaxLength, TLV_SPAN_TEXT_LINE_STYLE_MAXLENGTH, Int32);
1229     WRITE_TLV_INHERIT(textLineStyle, MaxLines, TLV_SPAN_TEXT_LINE_STYLE_MAXLINES, Int32, MaxLines);
1230     WRITE_TEXT_STYLE_TLV(
1231         textLineStyle, HeightAdaptivePolicy, TLV_SPAN_TEXT_LINE_STYLE_HEIGHTADAPTIVEPOLICY, TextHeightAdaptivePolicy);
1232     WRITE_TLV_INHERIT(textLineStyle, TextIndent, TLV_SPAN_TEXT_LINE_STYLE_TEXTINDENT, Dimension, TextIndent);
1233     WRITE_TEXT_STYLE_TLV(textLineStyle, LeadingMargin, TLV_SPAN_TEXT_LINE_STYLE_LEADINGMARGIN, LeadingMargin);
1234     WRITE_TLV_INHERIT(textLineStyle, WordBreak, TLV_SPAN_TEXT_LINE_STYLE_WORDBREAK, WordBreak, WordBreak);
1235     WRITE_TLV_INHERIT(textLineStyle, LineBreakStrategy, TLV_SPAN_TEXT_LINE_STYLE_LINEBREAKSTRATEGY, LineBreakStrategy,
1236         LineBreakStrategy);
1237     WRITE_TLV_INHERIT(textLineStyle, EllipsisMode, TLV_SPAN_TEXT_LINE_STYLE_ELLIPSISMODE, EllipsisMode, EllipsisMode);
1238     WRITE_TLV_INHERIT(textLineStyle, TextVerticalAlign, TLV_SPAN_TEXT_LINE_STYLE_TEXTVERTICALALIGN, TextVerticalAlign,
1239         ParagraphVerticalAlign);
1240 }
1241 
DecodeTlv(std::vector<uint8_t> & buff,int32_t & cursor)1242 RefPtr<SpanItem> SpanItem::DecodeTlv(std::vector<uint8_t>& buff, int32_t& cursor)
1243 {
1244     auto sameSpan = MakeRefPtr<SpanItem>();
1245     if (TLVUtil::ReadUint8(buff, cursor) != TLV_SPANITEM_TAG) {
1246         return sameSpan;
1247     }
1248 
1249     int32_t start = TLVUtil::ReadInt32(buff, cursor);
1250     int32_t end = TLVUtil::ReadInt32(buff, cursor);
1251     sameSpan->interval = {start, end};
1252     sameSpan->content = UtfUtils::Str8DebugToStr16(TLVUtil::ReadString(buff, cursor));
1253 
1254     for (uint8_t tag = TLVUtil::ReadUint8(buff, cursor);
1255         tag != TLV_SPANITEM_END_TAG; tag = TLVUtil::ReadUint8(buff, cursor)) {
1256         switch (tag) {
1257             READ_TEXT_STYLE_TLV(fontStyle, UpdateFontSize, TLV_SPAN_FONT_STYLE_FONTSIZE, Dimension);
1258             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextColor, TLV_SPAN_FONT_STYLE_TEXTCOLOR, Color);
1259             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextShadow, TLV_SPAN_FONT_STYLE_TEXTSHADOW, TextShadows);
1260             READ_TEXT_STYLE_TLV(fontStyle, UpdateItalicFontStyle, TLV_SPAN_FONT_STYLE_ITALICFONTSTYLE, FontStyle);
1261             READ_TEXT_STYLE_TLV(fontStyle, UpdateFontWeight, TLV_SPAN_FONT_STYLE_FONTWEIGHT, FontWeight);
1262             READ_TEXT_STYLE_TLV(fontStyle, UpdateFontFamily, TLV_SPAN_FONT_STYLE_FONTFAMILY, FontFamily);
1263             READ_TEXT_STYLE_TLV(fontStyle, UpdateFontFeature, TLV_SPAN_FONT_STYLE_FONTFEATURE, FontFeature);
1264             READ_TEXT_STYLE_TLV(fontStyle, UpdateStrokeWidth, TLV_SPAN_FONT_STYLE_STROKEWIDTH, Dimension);
1265             READ_TEXT_STYLE_TLV(fontStyle, UpdateStrokeColor, TLV_SPAN_FONT_STYLE_STROKECOLOR, Color);
1266             READ_TEXT_STYLE_TLV(fontStyle, UpdateSuperscript, TLV_SPAN_FONT_STYLE_SUPERSCRIPT, SuperscriptStyle);
1267             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextDecorationColor, TLV_SPAN_FONT_STYLE_TEXTDECORATIONCOLOR, Color);
1268             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextDecorationStyle,
1269                 TLV_SPAN_FONT_STYLE_TEXTDECORATIONSTYLE, TextDecorationStyle);
1270             READ_TEXT_STYLE_TLV(fontStyle, UpdateTextCase, TLV_SPAN_FONT_STYLE_TEXTCASE, TextCase);
1271             READ_TEXT_STYLE_TLV(fontStyle, UpdateAdaptMinFontSize, TLV_SPAN_FONT_STYLE_ADPATMINFONTSIZE, Dimension);
1272             READ_TEXT_STYLE_TLV(fontStyle, UpdateAdaptMaxFontSize, TLV_SPAN_FONT_STYLE_ADPATMAXFONTSIZE, Dimension);
1273             READ_TEXT_STYLE_TLV(fontStyle, UpdateLetterSpacing, TLV_SPAN_FONT_STYLE_LETTERSPACING, Dimension);
1274             READ_TEXT_STYLE_TLV(fontStyle, UpdateLineThicknessScale, TLV_SPAN_FONT_STYLE_LineThicknessScale, Float);
1275             case TLV_SPAN_FONT_STYLE_TEXTDECORATION: {
1276                 sameSpan->fontStyle->UpdateTextDecoration(TLVUtil::ReadTextDecorations(buff, cursor));
1277                 break;
1278             }
1279 
1280             READ_TEXT_STYLE_TLV(textLineStyle, UpdateLineHeight, TLV_SPAN_TEXT_LINE_STYLE_LINEHEIGHT, Dimension);
1281             READ_TEXT_STYLE_TLV(textLineStyle, UpdateLineSpacing, TLV_SPAN_TEXT_LINE_STYLE_LINESPACING, Dimension);
1282             READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextBaseline, TLV_SPAN_TEXT_LINE_STYLE_TEXTBASELINE, TextBaseline);
1283             READ_TEXT_STYLE_TLV(textLineStyle, UpdateBaselineOffset,
1284                 TLV_SPAN_TEXT_LINE_STYLE_BASELINEOFFSET, Dimension);
1285             READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextOverflow, TLV_SPAN_TEXT_LINE_STYLE_TEXTOVERFLOW, TextOverflow);
1286             READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextAlign, TLV_SPAN_TEXT_LINE_STYLE_TEXTALIGN, TextAlign);
1287             READ_TEXT_STYLE_TLV(textLineStyle, UpdateMaxLength, TLV_SPAN_TEXT_LINE_STYLE_MAXLENGTH, Int32);
1288             READ_TEXT_STYLE_TLV(textLineStyle, UpdateMaxLines, TLV_SPAN_TEXT_LINE_STYLE_MAXLINES, Int32);
1289             READ_TEXT_STYLE_TLV(textLineStyle, UpdateHeightAdaptivePolicy,
1290                 TLV_SPAN_TEXT_LINE_STYLE_HEIGHTADAPTIVEPOLICY, TextHeightAdaptivePolicy);
1291             READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextIndent, TLV_SPAN_TEXT_LINE_STYLE_TEXTINDENT, Dimension);
1292             READ_TEXT_STYLE_TLV(textLineStyle, UpdateLeadingMargin,
1293                 TLV_SPAN_TEXT_LINE_STYLE_LEADINGMARGIN, LeadingMargin);
1294             READ_TEXT_STYLE_TLV(textLineStyle, UpdateWordBreak, TLV_SPAN_TEXT_LINE_STYLE_WORDBREAK, WordBreak);
1295             READ_TEXT_STYLE_TLV(textLineStyle, UpdateLineBreakStrategy,
1296                 TLV_SPAN_TEXT_LINE_STYLE_LINEBREAKSTRATEGY, LineBreakStrategy);
1297             READ_TEXT_STYLE_TLV(textLineStyle, UpdateEllipsisMode, TLV_SPAN_TEXT_LINE_STYLE_ELLIPSISMODE, EllipsisMode);
1298             READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextVerticalAlign, TLV_SPAN_TEXT_LINE_STYLE_TEXTVERTICALALIGN,
1299                 TextVerticalAlign);
1300 
1301             case TLV_SPAN_BACKGROUND_BACKGROUNDCOLOR: {
1302                 if (!sameSpan->backgroundStyle.has_value()) {
1303                     sameSpan->backgroundStyle = TextBackgroundStyle();
1304                 }
1305                 sameSpan->backgroundStyle->backgroundColor = TLVUtil::ReadColor(buff, cursor);
1306                 break;
1307             }
1308             case TLV_SPAN_BACKGROUND_BACKGROUNDRADIUS: {
1309                 sameSpan->backgroundStyle->backgroundRadius = TLVUtil::ReadBorderRadiusProperty(buff, cursor);
1310                 break;
1311             }
1312             case TLV_SPAN_BACKGROUND_GROUPID: {
1313                 sameSpan->backgroundStyle->groupId = TLVUtil::ReadInt32(buff, cursor);
1314                 break;
1315             }
1316             READ_TEXT_STYLE_TLV(textLineStyle, UpdateParagraphSpacing,
1317                 TLV_SPAN_TEXT_LINE_STYLE_PARAGRAPH_SPACING, Dimension);
1318             case TLV_SPAN_URL_CONTENT: {
1319                 std::string address = TLVUtil::ReadString(buff, cursor);
1320                 sameSpan->urlAddress = UtfUtils::Str8DebugToStr16(address);
1321                 auto urlOnRelease = [address]() {
1322                     auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
1323                     CHECK_NULL_VOID(pipelineContext);
1324                     pipelineContext->HyperlinkStartAbility(address);
1325                 };
1326                 sameSpan->SetUrlOnReleaseEvent(std::move(urlOnRelease));
1327                 break;
1328             }
1329             default:
1330                 break;
1331         }
1332     }
1333     if (!Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_NINETEEN)) {
1334         sameSpan->textLineStyle->ResetParagraphSpacing();
1335         sameSpan->urlAddress = std::nullopt;
1336         sameSpan->urlOnRelease = nullptr;
1337     }
1338     if (!Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWENTY)) {
1339         sameSpan->textLineStyle->ResetTextVerticalAlign();
1340     }
1341     return sameSpan;
1342 }
1343 
SymbolColorToString()1344 std::string SpanItem::SymbolColorToString()
1345 {
1346     auto colors = fontStyle->GetSymbolColorList();
1347     auto colorStr = std::string("[");
1348     if (colors.has_value()) {
1349         for (const auto& color : colors.value()) {
1350             colorStr.append(color.ColorToString());
1351             colorStr.append(",");
1352         }
1353     }
1354     colorStr.append("]");
1355     return colorStr;
1356 }
1357 
GetIntersectionInterval(std::pair<int32_t,int32_t> interval) const1358 std::optional<std::pair<int32_t, int32_t>> SpanItem::GetIntersectionInterval(std::pair<int32_t, int32_t> interval) const
1359 {
1360     // Check the intersection
1361     if (this->interval.second <= interval.first || interval.second <= this->interval.first) {
1362         return std::nullopt;
1363     }
1364 
1365     // Calculate the intersection interval
1366     int32_t start = std::max(this->interval.first, interval.first);
1367     int32_t end = std::min(this->interval.second, interval.second);
1368     return std::make_optional<std::pair<int32_t, int32_t>>(std::make_pair(start, end));
1369 }
1370 
EncodeTlv(std::vector<uint8_t> & buff)1371 bool ImageSpanItem::EncodeTlv(std::vector<uint8_t>& buff)
1372 {
1373     if (spanItemType == SpanItemType::NORMAL) {
1374         // ImageSpan(resource)场景,复制图片为属性字符串为空格。ImageSpanItem::GetSameStyleSpanItem获取到的spanItemType为NORMAL
1375         TLVUtil::WriteUint8(buff, TLV_SPANITEM_TAG);
1376         TLVUtil::WriteInt32(buff, interval.first);
1377         TLVUtil::WriteInt32(buff, interval.second);
1378         TLVUtil::WriteU16String(buff, content);
1379         TLVUtil::WriteUint8(buff, TLV_SPANITEM_END_TAG);
1380         return true;
1381     }
1382     TLVUtil::WriteUint8(buff, TLV_IMAGESPANITEM_TAG);
1383     TLVUtil::WriteInt32(buff, interval.first);
1384     TLVUtil::WriteInt32(buff, interval.second);
1385     TLVUtil::WriteU16String(buff, content);
1386     if (options.offset.has_value()) {
1387         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_OFFSET_TAG);
1388         TLVUtil::WriteInt32(buff, options.offset.value());
1389     }
1390     if (options.image.has_value()) {
1391         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_IMAGE_TAG);
1392         TLVUtil::WriteString(buff, options.image.value());
1393     }
1394     if (options.bundleName.has_value()) {
1395         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_BUNDLENAME_TAG);
1396         TLVUtil::WriteString(buff, options.bundleName.value());
1397     }
1398     if (options.bundleName.has_value()) {
1399         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_MODULENAME_TAG);
1400         TLVUtil::WriteString(buff, options.moduleName.value());
1401     }
1402     if (options.imagePixelMap.has_value()) {
1403         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_IMAGEPIXELMAP_TAG);
1404         TLVUtil::WritePixelMap(buff, options.imagePixelMap.value());
1405     }
1406     if (options.imageAttribute.has_value()) {
1407         TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_IMAGEATTRIBUTE_TAG);
1408         TLVUtil::WriteImageSpanAttribute(buff, options.imageAttribute.value());
1409     }
1410     TLVUtil::WriteUint8(buff, TLV_SPANITEM_END_TAG);
1411     return true;
1412 }
1413 
DecodeTlv(std::vector<uint8_t> & buff,int32_t & cursor)1414 RefPtr<ImageSpanItem> ImageSpanItem::DecodeTlv(std::vector<uint8_t>& buff, int32_t& cursor)
1415 {
1416     auto sameSpan = MakeRefPtr<ImageSpanItem>();
1417 
1418     if (TLVUtil::ReadUint8(buff, cursor) != TLV_IMAGESPANITEM_TAG) {
1419         return sameSpan;
1420     }
1421 
1422     int32_t start = TLVUtil::ReadInt32(buff, cursor);
1423     int32_t end = TLVUtil::ReadInt32(buff, cursor);
1424     sameSpan->interval = {start, end};
1425     sameSpan->content = UtfUtils::Str8DebugToStr16(TLVUtil::ReadString(buff, cursor));
1426 
1427     for (uint8_t tag = TLVUtil::ReadUint8(buff, cursor);
1428         tag != TLV_SPANITEM_END_TAG; tag = TLVUtil::ReadUint8(buff, cursor)) {
1429         switch (tag) {
1430             case TLV_IMAGESPANOPTION_OFFSET_TAG: {
1431                 sameSpan->options.offset = TLVUtil::ReadInt32(buff, cursor);
1432                 break;
1433             }
1434             case TLV_IMAGESPANOPTION_IMAGE_TAG: {
1435                 sameSpan->options.image = TLVUtil::ReadString(buff, cursor);
1436                 break;
1437             }
1438             case TLV_IMAGESPANOPTION_BUNDLENAME_TAG: {
1439                 sameSpan->options.bundleName = TLVUtil::ReadString(buff, cursor);
1440                 break;
1441             }
1442             case TLV_IMAGESPANOPTION_MODULENAME_TAG: {
1443                 sameSpan->options.moduleName = TLVUtil::ReadString(buff, cursor);
1444                 break;
1445             }
1446             case TLV_IMAGESPANOPTION_IMAGEPIXELMAP_TAG: {
1447                 sameSpan->options.imagePixelMap = TLVUtil::ReadPixelMap(buff, cursor);
1448                 break;
1449             }
1450             case TLV_IMAGESPANOPTION_IMAGEATTRIBUTE_TAG: {
1451                 sameSpan->options.imageAttribute = TLVUtil::ReadImageSpanAttribute(buff, cursor);
1452                 break;
1453             }
1454             default:
1455                 break;
1456         }
1457     }
1458     return sameSpan;
1459 }
1460 
UpdatePlaceholderRun(PlaceholderStyle placeholderStyle)1461 bool ImageSpanItem::UpdatePlaceholderRun(PlaceholderStyle placeholderStyle)
1462 {
1463     PlaceholderRun run;
1464     run.width = placeholderStyle.width;
1465     run.height = placeholderStyle.height;
1466     if (!NearZero(placeholderStyle.baselineOffset)) {
1467         run.baseline_offset = placeholderStyle.baselineOffset;
1468         run.alignment = PlaceholderAlignment::BASELINE;
1469     } else {
1470         run.alignment = GetPlaceHolderAlignmentFromVerticalAlign(placeholderStyle.verticalAlign);
1471     }
1472     auto needReCreate = run_ != run;
1473     run_ = run;
1474     return needReCreate;
1475 }
1476 
UpdatePlaceholderBackgroundStyle(const RefPtr<FrameNode> & imageNode)1477 void ImageSpanItem::UpdatePlaceholderBackgroundStyle(const RefPtr<FrameNode>& imageNode)
1478 {
1479     CHECK_NULL_VOID(imageNode);
1480     auto property = imageNode->GetLayoutProperty<ImageLayoutProperty>();
1481     CHECK_NULL_VOID(property);
1482     backgroundStyle = property->GetPlaceHolderStyle();
1483 }
1484 
SetImageSpanOptions(const ImageSpanOptions & options)1485 void ImageSpanItem::SetImageSpanOptions(const ImageSpanOptions& options)
1486 {
1487     this->options = options;
1488 }
1489 
ResetImageSpanOptions()1490 void ImageSpanItem::ResetImageSpanOptions()
1491 {
1492     options.imageAttribute.reset();
1493 }
1494 
GetSameStyleSpanItem(bool isEncodeTlvS) const1495 RefPtr<SpanItem> ImageSpanItem::GetSameStyleSpanItem(bool isEncodeTlvS) const
1496 {
1497     auto sameSpan = MakeRefPtr<ImageSpanItem>();
1498     if (isEncodeTlvS) {
1499         if (options.HasValue()) {
1500             sameSpan->SetImageSpanOptions(options);
1501         } else {
1502             // 用与Text控件复制ImageSpan子控件,生成并保存options数据
1503             sameSpan->SetImageSpanOptions(GetImageSpanOptionsFromImageNode());
1504             if (!(sameSpan->options.imagePixelMap.value_or(nullptr))) {
1505                 /*
1506                     ImageSpan子控件,存在resource和pixelMap两种来源。
1507                     ImageSpan(resource)场景,复制图片为属性字符串为空格。
1508                     因此设置为NORMAL。在ImageSpanItem::EncodeTlv时,SpanItemType为NORMAL时,组装SpanItem。
1509                 */
1510                 sameSpan->spanItemType = SpanItemType::NORMAL;
1511             }
1512         }
1513     } else {
1514         sameSpan->SetImageSpanOptions(options);
1515     }
1516     sameSpan->urlOnRelease = urlOnRelease;
1517     sameSpan->onClick = onClick;
1518     sameSpan->onLongPress = onLongPress;
1519     if (backgroundStyle.has_value()) {
1520         sameSpan->backgroundStyle = backgroundStyle;
1521     }
1522     return sameSpan;
1523 }
1524 
GetImageSpanOptionsFromImageNode() const1525 ImageSpanOptions ImageSpanItem::GetImageSpanOptionsFromImageNode() const
1526 {
1527     ImageSpanOptions imageSpanOptions;
1528     auto frameNode = FrameNode::GetFrameNode(V2::IMAGE_ETS_TAG, nodeId_);
1529     CHECK_NULL_RETURN(frameNode, imageSpanOptions);
1530     auto layoutProperty = frameNode->GetLayoutProperty<ImageLayoutProperty>();
1531     CHECK_NULL_RETURN(layoutProperty, imageSpanOptions);
1532     auto sourceInfo = layoutProperty->GetImageSourceInfo();
1533     if (sourceInfo.has_value()) {
1534         imageSpanOptions.image = sourceInfo->GetSrc();
1535         imageSpanOptions.bundleName = sourceInfo->GetBundleName();
1536         imageSpanOptions.moduleName = sourceInfo->GetModuleName();
1537         imageSpanOptions.imagePixelMap = sourceInfo->GetPixmap();
1538     }
1539     imageSpanOptions.imageAttribute = CreateImageSpanAttribute(layoutProperty);
1540     auto renderContext = frameNode->GetRenderContext();
1541     if (renderContext && renderContext->HasBorderRadius()) {
1542         imageSpanOptions.imageAttribute->borderRadius = renderContext->GetBorderRadius();
1543     }
1544     return imageSpanOptions;
1545 }
1546 
CreateImageSpanAttribute(const RefPtr<ImageLayoutProperty> & layoutProperty) const1547 ImageSpanAttribute ImageSpanItem::CreateImageSpanAttribute(const RefPtr<ImageLayoutProperty>& layoutProperty) const
1548 {
1549     ImageSpanAttribute imageSpanAttribute;
1550     auto& layoutConstraint = layoutProperty->GetCalcLayoutConstraint();
1551 
1552     if (layoutConstraint && layoutConstraint->selfIdealSize) {
1553         auto width = layoutConstraint->selfIdealSize->Width();
1554         auto height = layoutConstraint->selfIdealSize->Height();
1555         ImageSpanSize imageSpanSize;
1556         if (width.has_value()) {
1557             imageSpanSize.width = width->GetDimension();
1558         }
1559         if (height.has_value()) {
1560             imageSpanSize.height = height->GetDimension();
1561         }
1562         imageSpanAttribute.size = imageSpanSize;
1563     }
1564     imageSpanAttribute.verticalAlign = layoutProperty->GetVerticalAlign();
1565     imageSpanAttribute.objectFit = layoutProperty->GetImageFit();
1566     auto& margin = layoutProperty->GetMarginProperty();
1567     if (margin) {
1568         MarginProperty marginProperty;
1569         marginProperty.UpdateWithCheck(*margin);
1570         imageSpanAttribute.marginProp = marginProperty;
1571     }
1572     auto& padding = layoutProperty->GetPaddingProperty();
1573     if (padding) {
1574         MarginProperty paddingProperty;
1575         paddingProperty.UpdateWithCheck(*padding);
1576         imageSpanAttribute.paddingProp = paddingProperty;
1577     }
1578     return imageSpanAttribute;
1579 }
1580 
GetSpanResultObject(int32_t start,int32_t end)1581 ResultObject ImageSpanItem::GetSpanResultObject(int32_t start, int32_t end)
1582 {
1583     int32_t itemLength = 1;
1584     ResultObject resultObject;
1585 
1586     int32_t endPosition = interval.second;
1587     int32_t startPosition = interval.first;
1588     resultObject.type = SelectSpanType::TYPEIMAGE;
1589     if ((start <= startPosition) && (end >= endPosition)) {
1590         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGESTART] = startPosition;
1591         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGEEND] = endPosition;
1592         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
1593         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
1594         if (options.image.has_value()) {
1595             resultObject.valueString = UtfUtils::Str8DebugToStr16(options.image.value());
1596         }
1597         if (options.imagePixelMap.has_value()) {
1598             resultObject.valuePixelMap = options.imagePixelMap.value();
1599         }
1600         resultObject.isInit = true;
1601     }
1602     return resultObject;
1603 }
1604 
GetSpanResultObject(int32_t start,int32_t end)1605 ResultObject CustomSpanItem::GetSpanResultObject(int32_t start, int32_t end)
1606 {
1607     int32_t itemLength = 1;
1608     ResultObject resultObject;
1609 
1610     int32_t endPosition = interval.second;
1611     int32_t startPosition = interval.first;
1612     resultObject.type = SelectSpanType::TYPEBUILDERSPAN;
1613     if ((start <= startPosition) && (end >= endPosition)) {
1614         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGESTART] = startPosition;
1615         resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGEEND] = endPosition;
1616         resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
1617         resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
1618         resultObject.valueString = u" ";
1619         resultObject.isInit = true;
1620     }
1621     return resultObject;
1622 }
1623 
UpdateSpanTextColor(Color color)1624 bool SpanItem::UpdateSpanTextColor(Color color)
1625 {
1626     auto pattern = pattern_.Upgrade();
1627     CHECK_NULL_RETURN(pattern, false);
1628     auto textPattern = DynamicCast<TextPattern>(pattern);
1629     CHECK_NULL_RETURN(textPattern, false);
1630     auto paragraphManager = textPattern->GetParagraphManager();
1631     CHECK_NULL_RETURN(paragraphManager, false);
1632     auto paragraphInfos = paragraphManager->GetParagraphs();
1633     if (paragraphIndex != 0 || paragraphInfos.size() != 1) {
1634         return false;
1635     }
1636     auto iter = paragraphInfos.begin();
1637     auto paragraphInfo = *iter;
1638     auto paragraph = paragraphInfo.paragraph;
1639     CHECK_NULL_RETURN(paragraph, false);
1640     CHECK_NULL_RETURN(paragraph, false);
1641     if (SystemProperties::GetTextTraceEnabled()) {
1642         ACE_TEXT_SCOPED_TRACE("UpdateSpanTextColor[id:%d][color:%s][position:%d][length:%d]", nodeId_,
1643             color.ColorToString().c_str(), position, length);
1644     }
1645     paragraph->UpdateColor(position - length, position, color);
1646     textPattern->MarkDirtyNodeRender();
1647     return true;
1648 }
1649 
GetIndex(int32_t & start,int32_t & end) const1650 void SpanItem::GetIndex(int32_t& start, int32_t& end) const
1651 {
1652     auto contentLen = content.length();
1653     start = position - contentLen;
1654     end = position;
1655 }
1656 
UpdatePlaceholderRun(PlaceholderStyle placeholderStyle)1657 bool PlaceholderSpanItem::UpdatePlaceholderRun(PlaceholderStyle placeholderStyle)
1658 {
1659     PlaceholderRun run;
1660     run.width = placeholderStyle.width;
1661     run.height = placeholderStyle.height;
1662     auto needReCreate = run_ != run;
1663     run_ = run;
1664     return needReCreate;
1665 }
1666 
UpdateParagraph(const RefPtr<FrameNode> &,const RefPtr<Paragraph> & builder,const TextStyle & textStyle,bool)1667 int32_t PlaceholderSpanItem::UpdateParagraph(const RefPtr<FrameNode>& /* frameNode */, const RefPtr<Paragraph>& builder,
1668     const TextStyle& textStyle, bool /* isMarquee*/)
1669 {
1670     CHECK_NULL_RETURN(builder, -1);
1671     auto spanTextStyle = textStyle;
1672     // ignore decoration styles
1673     spanTextStyle.SetTextDecoration(TextDecoration::NONE);
1674     spanTextStyle.SetTextBackgroundStyle(backgroundStyle);
1675     spanTextStyle.SetTextStyleUid(nodeId_);
1676     builder->PushStyle(spanTextStyle);
1677     int32_t index = builder->AddPlaceholder(run_);
1678     builder->PopStyle();
1679     textStyle_ = spanTextStyle;
1680     return index;
1681 }
1682 
UpdateSpanTextStyle(const TextStyle & textStyle,const RefPtr<FrameNode> & frameNode)1683 bool PlaceholderSpanItem::UpdateSpanTextStyle(const TextStyle& textStyle, const RefPtr<FrameNode>& frameNode)
1684 {
1685     CHECK_NULL_RETURN(textStyle_.has_value(), true);
1686     UpdateReLayoutTextStyle(textStyle_.value(), textStyle, false);
1687     textStyle_->SetTextDecoration(TextDecoration::NONE);
1688     textStyle_->SetTextBackgroundStyle(backgroundStyle);
1689     textStyle_->SetTextStyleUid(nodeId_);
1690     return textStyle_.value().NeedReCreateParagraph();
1691 }
1692 
DumpInfo() const1693 void PlaceholderSpanItem::DumpInfo() const
1694 {
1695     auto& dumpLog = DumpLog::GetInstance();
1696     dumpLog.AddDesc("--------------- print run info ---------------");
1697     dumpLog.AddDesc(std::string("Width: ").append(std::to_string(run_.width)));
1698     dumpLog.AddDesc(std::string("Height: ").append(std::to_string(run_.height)));
1699     dumpLog.AddDesc(std::string("Alignment: ").append(StringUtils::ToString(run_.alignment)));
1700     dumpLog.AddDesc(std::string("Baseline: ").append(StringUtils::ToString(run_.baseline)));
1701     dumpLog.AddDesc(std::string("BaselineOffset: ").append(std::to_string(run_.baseline_offset)));
1702     dumpLog.AddDesc("--------------- print text style ---------------");
1703     auto textStyle = textStyle_.value_or(TextStyle());
1704     dumpLog.AddDesc(
1705         std::string("FontSize: ")
1706             .append(textStyle.GetFontSize().ToString())
1707             .append(" self: ")
1708             .append(fontStyle && fontStyle->HasFontSize() ? fontStyle->GetFontSizeValue().ToString() : "Na"));
1709     dumpLog.AddDesc(
1710         std::string("TextColor: ")
1711             .append(textStyle.GetTextColor().ColorToString())
1712             .append(" self: ")
1713             .append(
1714             fontStyle && fontStyle->HasTextColor() ? fontStyle->GetTextColorValue().ColorToString() : "Na"));
1715     dumpLog.AddDesc(std::string("BaselineOffset: ")
1716                         .append(textStyle.GetBaselineOffset().ToString())
1717                         .append(" self: ")
1718                         .append(textLineStyle && textLineStyle->HasBaselineOffset()
1719                                     ? textLineStyle->GetBaselineOffsetValue().ToString()
1720                                     : "Na"));
1721     dumpLog.AddDesc(
1722         std::string("LineHeight: ")
1723             .append(textStyle.GetLineHeight().ToString())
1724             .append(" self: ")
1725             .append(textLineStyle
1726                         ? textLineStyle->GetLineHeight().value_or(Dimension(0.0, DimensionUnit::FP)).ToString()
1727                         : "Na"));
1728     dumpLog.AddDesc(
1729         std::string("LineSpacing: ")
1730             .append(textStyle.GetLineSpacing().ToString())
1731             .append(" isOnlyBetweenLines: ")
1732             .append((textStyle.GetIsOnlyBetweenLines()) ? "true" : "false"));
1733     dumpLog.AddDesc(std::string("VerticalAlign: ").append(StringUtils::ToString(textStyle.GetTextVerticalAlign())));
1734     dumpLog.AddDesc(std::string("HalfLeading: ").append(std::to_string(textStyle.GetHalfLeading())));
1735     dumpLog.AddDesc(std::string("TextBaseline: ").append(StringUtils::ToString(textStyle.GetTextBaseline())));
1736 }
1737 
GetSameStyleSpanItem(bool isEncodeTlvS) const1738 RefPtr<SpanItem> CustomSpanItem::GetSameStyleSpanItem(bool isEncodeTlvS) const
1739 {
1740     auto sameSpan = MakeRefPtr<CustomSpanItem>();
1741     sameSpan->onMeasure = onMeasure;
1742     sameSpan->onDraw = onDraw;
1743     sameSpan->urlOnRelease = urlOnRelease;
1744     sameSpan->onClick = onClick;
1745     sameSpan->onLongPress = onLongPress;
1746     if (backgroundStyle.has_value()) {
1747         sameSpan->backgroundStyle = backgroundStyle;
1748     }
1749     return sameSpan;
1750 }
1751 
SetTextBackgroundStyle(const TextBackgroundStyle & style)1752 void BaseSpan::SetTextBackgroundStyle(const TextBackgroundStyle& style)
1753 {
1754     textBackgroundStyle_ = style;
1755     textBackgroundStyle_->groupId = groupId_;
1756     SetHasTextBackgroundStyle(style.backgroundColor.has_value() || style.backgroundRadius.has_value());
1757     MarkTextDirty();
1758 }
1759 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1760 void ContainerSpanNode::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1761 {
1762     TextBackgroundStyle::ToJsonValue(json, GetTextBackgroundStyle(), filter);
1763 }
1764 
DumpInfo(std::unique_ptr<JsonValue> & json)1765 void SpanNode::DumpInfo(std::unique_ptr<JsonValue>& json)
1766 {
1767     json->Put("Content", UtfUtils::Str16DebugToStr8(spanItem_->content).c_str());
1768     auto textStyle = spanItem_->GetTextStyle();
1769     if (!textStyle) {
1770         return;
1771     }
1772     json->Put("FontSize", textStyle->GetFontSize().ToString().c_str());
1773     json->Put("LineHeight", textStyle->GetLineHeight().ToString().c_str());
1774     json->Put("LineSpacing", textStyle->GetLineSpacing().ToString().c_str());
1775     json->Put("isOnlyBetweenLines", (textStyle->GetIsOnlyBetweenLines()) ? "true" : "false");
1776     json->Put("BaselineOffset", textStyle->GetBaselineOffset().ToString().c_str());
1777     json->Put("WordSpacing", textStyle->GetWordSpacing().ToString().c_str());
1778     json->Put("TextIndent", textStyle->GetTextIndent().ToString().c_str());
1779     json->Put("LetterSpacing", textStyle->GetLetterSpacing().ToString().c_str());
1780     json->Put("TextColor", textStyle->GetTextColor().ColorToString().c_str());
1781     json->Put("FontWeight", StringUtils::ToString(textStyle->GetFontWeight()).c_str());
1782     json->Put("FontStyle", StringUtils::ToString(textStyle->GetFontStyle()).c_str());
1783     json->Put("TextBaseline", StringUtils::ToString(textStyle->GetTextBaseline()).c_str());
1784     json->Put("TextOverflow", StringUtils::ToString(textStyle->GetTextOverflow()).c_str());
1785     json->Put("VerticalAlign", StringUtils::ToString(textStyle->GetTextVerticalAlign()).c_str());
1786     json->Put("TextAlign", StringUtils::ToString(textStyle->GetTextAlign()).c_str());
1787     json->Put("TextVerticalAlign", StringUtils::ToString(textStyle->GetParagraphVerticalAlign()).c_str());
1788     json->Put("WordBreak", StringUtils::ToString(textStyle->GetWordBreak()).c_str());
1789     json->Put("TextCase", StringUtils::ToString(textStyle->GetTextCase()).c_str());
1790     json->Put("EllipsisMode", StringUtils::ToString(textStyle->GetEllipsisMode()).c_str());
1791     json->Put("HalfLeading", std::to_string(textStyle->GetHalfLeading()).c_str());
1792     if (GetTag() == V2::SYMBOL_SPAN_ETS_TAG) {
1793         json->Put("SymbolColor", spanItem_->SymbolColorToString().c_str());
1794         json->Put("RenderStrategy", std::to_string(textStyle->GetRenderStrategy()).c_str());
1795         json->Put("EffectStrategy", std::to_string(textStyle->GetEffectStrategy()).c_str());
1796         json->Put("SymbolEffect",
1797             spanItem_->fontStyle->GetSymbolEffectOptions().value_or(NG::SymbolEffectOptions()).ToString().c_str());
1798     }
1799     json->Put("LineThicknessScale", std::to_string(textStyle->GetLineThicknessScale()).c_str());
1800 }
1801 } // namespace OHOS::Ace::NG
1802