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