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