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