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 <optional>
19
20 #include "base/geometry/dimension.h"
21 #include "base/utils/utils.h"
22 #include "core/common/font_manager.h"
23 #include "core/components/common/layout/constants.h"
24 #include "core/components/common/properties/text_style.h"
25 #include "core/components_ng/base/frame_node.h"
26 #include "core/components_ng/pattern/text/text_pattern.h"
27 #include "core/components_ng/pattern/text/text_styles.h"
28 #include "core/components_ng/property/property.h"
29 #include "core/components_ng/render/drawing_prop_convertor.h"
30 #include "core/components_ng/render/paragraph.h"
31 #include "core/pipeline/pipeline_context.h"
32
33 namespace OHOS::Ace::NG {
34 namespace {
GetDeclaration(const std::optional<Color> & color,const std::optional<TextDecoration> & textDecoration,const std::optional<TextDecorationStyle> & textDecorationStyle)35 std::string GetDeclaration(const std::optional<Color>& color, const std::optional<TextDecoration>& textDecoration,
36 const std::optional<TextDecorationStyle>& textDecorationStyle)
37 {
38 auto jsonSpanDeclaration = JsonUtil::Create(true);
39 jsonSpanDeclaration->Put(
40 "type", V2::ConvertWrapTextDecorationToStirng(textDecoration.value_or(TextDecoration::NONE)).c_str());
41 jsonSpanDeclaration->Put("color", (color.value_or(Color::BLACK).ColorToString()).c_str());
42 jsonSpanDeclaration->Put("style",
43 V2::ConvertWrapTextDecorationStyleToString(textDecorationStyle.value_or(TextDecorationStyle::SOLID)).c_str());
44 return jsonSpanDeclaration->ToString();
45 }
ConvertShadowToJson(const Shadow & shadow)46 inline std::unique_ptr<JsonValue> ConvertShadowToJson(const Shadow& shadow)
47 {
48 auto jsonShadow = JsonUtil::Create(true);
49 jsonShadow->Put("radius", std::to_string(shadow.GetBlurRadius()).c_str());
50 jsonShadow->Put("color", shadow.GetColor().ColorToString().c_str());
51 jsonShadow->Put("offsetX", std::to_string(shadow.GetOffset().GetX()).c_str());
52 jsonShadow->Put("offsetY", std::to_string(shadow.GetOffset().GetY()).c_str());
53 jsonShadow->Put("type", std::to_string(static_cast<int32_t>(shadow.GetShadowType())).c_str());
54 return jsonShadow;
55 }
ConvertShadowsToJson(const std::vector<Shadow> & shadows)56 std::unique_ptr<JsonValue> ConvertShadowsToJson(const std::vector<Shadow>& shadows)
57 {
58 auto jsonShadows = JsonUtil::CreateArray(true);
59 for (const auto& shadow : shadows) {
60 jsonShadows->Put(ConvertShadowToJson(shadow));
61 }
62 return jsonShadows;
63 }
64 } // namespace
65
GetFont() const66 std::string SpanItem::GetFont() const
67 {
68 auto jsonValue = JsonUtil::Create(true);
69 jsonValue->Put("style", GetFontStyleInJson(fontStyle->GetItalicFontStyle()).c_str());
70 jsonValue->Put("size", GetFontSizeInJson(fontStyle->GetFontSize()).c_str());
71 jsonValue->Put("weight", GetFontWeightInJson(fontStyle->GetFontWeight()).c_str());
72 jsonValue->Put("family", GetFontFamilyInJson(fontStyle->GetFontFamily()).c_str());
73 return jsonValue->ToString();
74 }
75
ToJsonValue(std::unique_ptr<JsonValue> & json) const76 void SpanItem::ToJsonValue(std::unique_ptr<JsonValue>& json) const
77 {
78 json->Put("content", content.c_str());
79 if (fontStyle) {
80 json->Put("font", GetFont().c_str());
81 json->Put("fontSize", GetFontSizeInJson(fontStyle->GetFontSize()).c_str());
82 json->Put("decoration", GetDeclaration(fontStyle->GetTextDecorationColor(), fontStyle->GetTextDecoration(),
83 fontStyle->GetTextDecorationStyle()).c_str());
84 json->Put("letterSpacing", fontStyle->GetLetterSpacing().value_or(Dimension()).ToString().c_str());
85 json->Put(
86 "textCase", V2::ConvertWrapTextCaseToStirng(fontStyle->GetTextCase().value_or(TextCase::NORMAL)).c_str());
87 json->Put("fontColor", fontStyle->GetForegroundColor()
88 .value_or(fontStyle->GetTextColor().value_or(Color::BLACK)).ColorToString().c_str());
89 json->Put("fontStyle", GetFontStyleInJson(fontStyle->GetItalicFontStyle()).c_str());
90 json->Put("fontWeight", GetFontWeightInJson(fontStyle->GetFontWeight()).c_str());
91 json->Put("fontFamily", GetFontFamilyInJson(fontStyle->GetFontFamily()).c_str());
92 json->Put("renderingStrategy",
93 GetSymbolRenderingStrategyInJson(fontStyle->GetSymbolRenderingStrategy()).c_str());
94 json->Put("effectStrategy", GetSymbolEffectStrategyInJson(fontStyle->GetSymbolEffectStrategy()).c_str());
95
96 auto shadow = fontStyle->GetTextShadow().value_or(std::vector<Shadow> { Shadow() });
97 // Determines if there are multiple textShadows
98 auto jsonShadow = (shadow.size() == 1) ? ConvertShadowToJson(shadow.front()) : ConvertShadowsToJson(shadow);
99 json->Put("textShadow", jsonShadow);
100 }
101 if (textLineStyle) {
102 json->Put("lineHeight", textLineStyle->GetLineHeight().value_or(Dimension()).ToString().c_str());
103 }
104 TextBackgroundStyle::ToJsonValue(json, backgroundStyle);
105 }
106
GetOrCreateSpanNode(int32_t nodeId)107 RefPtr<SpanNode> SpanNode::GetOrCreateSpanNode(int32_t nodeId)
108 {
109 auto spanNode = ElementRegister::GetInstance()->GetSpecificItemById<SpanNode>(nodeId);
110 if (spanNode) {
111 return spanNode;
112 }
113 spanNode = MakeRefPtr<SpanNode>(nodeId);
114 ElementRegister::GetInstance()->AddUINode(spanNode);
115 return spanNode;
116 }
117
CreateSpanNode(int32_t nodeId)118 RefPtr<SpanNode> SpanNode::CreateSpanNode(int32_t nodeId)
119 {
120 auto spanNode = MakeRefPtr<SpanNode>(nodeId);
121 ElementRegister::GetInstance()->AddUINode(spanNode);
122 return spanNode;
123 }
124
GetOrCreateSpanNode(const std::string & tag,int32_t nodeId)125 RefPtr<SpanNode> SpanNode::GetOrCreateSpanNode(const std::string& tag, int32_t nodeId)
126 {
127 auto spanNode = ElementRegister::GetInstance()->GetSpecificItemById<SpanNode>(nodeId);
128 if (spanNode) {
129 return spanNode;
130 }
131 spanNode = MakeRefPtr<SpanNode>(tag, nodeId);
132 ElementRegister::GetInstance()->AddUINode(spanNode);
133 return spanNode;
134 }
135
MountToParagraph()136 void SpanNode::MountToParagraph()
137 {
138 auto parent = GetParent();
139 while (parent) {
140 auto spanNode = DynamicCast<SpanNode>(parent);
141 if (spanNode) {
142 spanNode->AddChildSpanItem(Claim(this));
143 return;
144 }
145 auto textNode = DynamicCast<FrameNode>(parent);
146 if (textNode) {
147 auto textPattern = textNode->GetPattern<TextPattern>();
148 if (textPattern) {
149 textPattern->AddChildSpanItem(Claim(this));
150 return;
151 }
152 }
153 parent = parent->GetParent();
154 }
155 }
156
RequestTextFlushDirty()157 void SpanNode::RequestTextFlushDirty()
158 {
159 RequestTextFlushDirty(Claim<UINode>(this));
160 }
161
RequestTextFlushDirty(const RefPtr<UINode> & node)162 void SpanNode::RequestTextFlushDirty(const RefPtr<UINode>& node)
163 {
164 CHECK_NULL_VOID(node);
165 auto parent = node->GetParent();
166 while (parent) {
167 auto textNode = DynamicCast<FrameNode>(parent);
168 if (textNode) {
169 textNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
170 auto textPattern = textNode->GetPattern<TextPattern>();
171 if (textPattern) {
172 textPattern->OnModifyDone();
173 return;
174 }
175 }
176 parent = parent->GetParent();
177 }
178 }
179
SetTextBackgroundStyle(const TextBackgroundStyle & style)180 void SpanNode::SetTextBackgroundStyle(const TextBackgroundStyle& style)
181 {
182 BaseSpan::SetTextBackgroundStyle(style);
183 spanItem_->backgroundStyle = GetTextBackgroundStyle();
184 }
185
UpdateTextBackgroundFromParent(const std::optional<TextBackgroundStyle> & style)186 void SpanNode::UpdateTextBackgroundFromParent(const std::optional<TextBackgroundStyle>& style)
187 {
188 BaseSpan::UpdateTextBackgroundFromParent(style);
189 spanItem_->backgroundStyle = GetTextBackgroundStyle();
190 }
191
UpdateParagraph(const RefPtr<FrameNode> & frameNode,const RefPtr<Paragraph> & builder,double,double,VerticalAlign)192 int32_t SpanItem::UpdateParagraph(const RefPtr<FrameNode>& frameNode,
193 const RefPtr<Paragraph>& builder, double /* width */, double /* height */, VerticalAlign /* verticalAlign */)
194 {
195 CHECK_NULL_RETURN(builder, -1);
196 std::optional<TextStyle> textStyle;
197 if (fontStyle || textLineStyle) {
198 auto pipelineContext = PipelineContext::GetCurrentContext();
199 CHECK_NULL_RETURN(pipelineContext, -1);
200 TextStyle themeTextStyle =
201 CreateTextStyleUsingTheme(fontStyle, textLineStyle, pipelineContext->GetTheme<TextTheme>());
202 if (frameNode) {
203 FontRegisterCallback(frameNode, themeTextStyle);
204 }
205 if (NearZero(themeTextStyle.GetFontSize().Value())) {
206 return -1;
207 }
208 textStyle = themeTextStyle;
209 textStyle->SetHalfLeading(pipelineContext->GetHalfLeading());
210 builder->PushStyle(themeTextStyle);
211 }
212
213 auto spanContent = GetSpanContent(content);
214 auto pattern = frameNode->GetPattern<TextPattern>();
215 CHECK_NULL_RETURN(pattern, -1);
216 if (textStyle.has_value()) {
217 textStyle->SetTextBackgroundStyle(backgroundStyle);
218 }
219 if (pattern->NeedShowAIDetect() && !aiSpanMap.empty()) {
220 UpdateTextStyleForAISpan(spanContent, builder, textStyle);
221 } else {
222 UpdateTextStyle(spanContent, builder, textStyle);
223 }
224 textStyle_ = textStyle;
225
226 for (const auto& child : children) {
227 if (child) {
228 if (!aiSpanMap.empty()) {
229 child->aiSpanMap = aiSpanMap;
230 }
231 child->UpdateParagraph(frameNode, builder);
232 }
233 }
234 if (fontStyle || textLineStyle) {
235 builder->PopStyle();
236 }
237 return -1;
238 }
239
UpdateSymbolSpanParagraph(const RefPtr<FrameNode> & frameNode,const RefPtr<Paragraph> & builder)240 void SpanItem::UpdateSymbolSpanParagraph(const RefPtr<FrameNode>& frameNode, const RefPtr<Paragraph>& builder)
241 {
242 CHECK_NULL_VOID(builder);
243 std::optional<TextStyle> textStyle;
244 auto symbolUnicode = GetSymbolUnicode();
245 if (fontStyle || textLineStyle) {
246 auto pipelineContext = PipelineContext::GetCurrentContext();
247 CHECK_NULL_VOID(pipelineContext);
248 TextStyle themeTextStyle =
249 CreateTextStyleUsingTheme(fontStyle, textLineStyle, pipelineContext->GetTheme<TextTheme>());
250 if (frameNode) {
251 FontRegisterCallback(frameNode, themeTextStyle);
252 }
253 if (NearZero(themeTextStyle.GetFontSize().Value())) {
254 return;
255 }
256 textStyle = themeTextStyle;
257 textStyle->SetHalfLeading(pipelineContext->GetHalfLeading());
258 if (symbolUnicode != 0) {
259 UpdateSymbolSpanColor(frameNode, themeTextStyle);
260 }
261 builder->PushStyle(themeTextStyle);
262 }
263 textStyle_ = textStyle;
264
265 if (symbolUnicode != 0) {
266 textStyle_->isSymbolGlyph_ = true;
267 builder->AddSymbol(symbolUnicode);
268 }
269
270 if (fontStyle || textLineStyle) {
271 builder->PopStyle();
272 }
273 }
274
UpdateSymbolSpanColor(const RefPtr<FrameNode> & frameNode,TextStyle & symbolSpanStyle)275 void SpanItem::UpdateSymbolSpanColor(const RefPtr<FrameNode>& frameNode, TextStyle& symbolSpanStyle)
276 {
277 symbolSpanStyle.isSymbolGlyph_ = true;
278 CHECK_NULL_VOID(frameNode);
279 if (GetIsParentText() && symbolSpanStyle.GetSymbolColorList().empty()) {
280 RefPtr<LayoutProperty> layoutProperty = frameNode->GetLayoutProperty();
281 CHECK_NULL_VOID(layoutProperty);
282 RefPtr<TextLayoutProperty> textLayoutProperty = DynamicCast<TextLayoutProperty>(layoutProperty);
283 CHECK_NULL_VOID(textLayoutProperty);
284 if (textLayoutProperty->GetTextColor().has_value()) {
285 std::vector<Color> symbolColor;
286 symbolColor.emplace_back(textLayoutProperty->GetTextColor().value());
287 symbolSpanStyle.SetSymbolColorList(symbolColor);
288 }
289 }
290 }
291
UpdateTextStyleForAISpan(const std::string & spanContent,const RefPtr<Paragraph> & builder,const std::optional<TextStyle> & textStyle)292 void SpanItem::UpdateTextStyleForAISpan(
293 const std::string& spanContent, const RefPtr<Paragraph>& builder, const std::optional<TextStyle>& textStyle)
294 {
295 auto wSpanContent = StringUtils::ToWstring(spanContent);
296 int32_t wSpanContentLength = static_cast<int32_t>(wSpanContent.length());
297 int32_t spanStart = position - wSpanContentLength;
298 if (needRemoveNewLine) {
299 spanStart -= 1;
300 }
301 int32_t preEnd = spanStart;
302 std::optional<TextStyle> aiSpanTextStyle = textStyle;
303 SetAiSpanTextStyle(aiSpanTextStyle);
304 while (!aiSpanMap.empty()) {
305 auto aiSpan = aiSpanMap.begin()->second;
306 if (aiSpan.start >= position || preEnd >= position) {
307 break;
308 }
309 int32_t aiSpanStartInSpan = std::max(spanStart, aiSpan.start);
310 int32_t aiSpanEndInSpan = std::min(position, aiSpan.end);
311 if (aiSpan.end <= spanStart || aiSpanStartInSpan < preEnd) {
312 TAG_LOGI(AceLogTag::ACE_TEXT, "Error prediction");
313 aiSpanMap.erase(aiSpanMap.begin());
314 continue;
315 }
316 if (preEnd < aiSpanStartInSpan) {
317 auto beforeContent =
318 StringUtils::ToString(wSpanContent.substr(preEnd - spanStart, aiSpanStartInSpan - preEnd));
319 UpdateTextStyle(beforeContent, builder, textStyle);
320 }
321 auto displayContent = StringUtils::ToWstring(
322 aiSpan.content).substr(aiSpanStartInSpan - aiSpan.start, aiSpanEndInSpan - aiSpanStartInSpan);
323 UpdateTextStyle(StringUtils::ToString(displayContent), builder, aiSpanTextStyle);
324 preEnd = aiSpanEndInSpan;
325 if (aiSpan.end > position) {
326 return;
327 } else {
328 aiSpanMap.erase(aiSpanMap.begin());
329 }
330 }
331 if (preEnd < position) {
332 auto afterContent = StringUtils::ToString(wSpanContent.substr(preEnd - spanStart, position - preEnd));
333 UpdateTextStyle(afterContent, builder, textStyle);
334 }
335 }
336
SetAiSpanTextStyle(std::optional<TextStyle> & aiSpanTextStyle)337 void SpanItem::SetAiSpanTextStyle(std::optional<TextStyle>& aiSpanTextStyle)
338 {
339 if (!aiSpanTextStyle.has_value()) {
340 auto pipelineContext = PipelineContext::GetCurrentContext();
341 CHECK_NULL_VOID(pipelineContext);
342 TextStyle themeTextStyle =
343 CreateTextStyleUsingTheme(fontStyle, textLineStyle, pipelineContext->GetTheme<TextTheme>());
344 if (NearZero(themeTextStyle.GetFontSize().Value())) {
345 return;
346 }
347 aiSpanTextStyle = themeTextStyle;
348 } else {
349 aiSpanTextStyle.value().SetTextColor(Color::BLUE);
350 aiSpanTextStyle.value().SetTextDecoration(TextDecoration::UNDERLINE);
351 aiSpanTextStyle.value().SetTextDecorationColor(Color::BLUE);
352 }
353 }
354
FontRegisterCallback(const RefPtr<FrameNode> & frameNode,const TextStyle & textStyle)355 void SpanItem::FontRegisterCallback(const RefPtr<FrameNode>& frameNode, const TextStyle& textStyle)
356 {
357 auto callback = [weakNode = WeakPtr<FrameNode>(frameNode)] {
358 auto frameNode = weakNode.Upgrade();
359 CHECK_NULL_VOID(frameNode);
360 frameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
361 auto pattern = frameNode->GetPattern<TextPattern>();
362 CHECK_NULL_VOID(pattern);
363 auto modifier = DynamicCast<TextContentModifier>(pattern->GetContentModifier());
364 CHECK_NULL_VOID(modifier);
365 modifier->SetFontReady(true);
366 };
367 auto pipeline = frameNode->GetContext();
368 CHECK_NULL_VOID(pipeline);
369 auto fontManager = pipeline->GetFontManager();
370 if (fontManager) {
371 bool isCustomFont = false;
372 for (const auto& familyName : textStyle.GetFontFamilies()) {
373 bool customFont = fontManager->RegisterCallbackNG(frameNode, familyName, callback);
374 if (customFont) {
375 isCustomFont = true;
376 }
377 }
378 if (isCustomFont) {
379 auto pattern = frameNode->GetPattern<TextPattern>();
380 CHECK_NULL_VOID(pattern);
381 pattern->SetIsCustomFont(true);
382 auto modifier = DynamicCast<TextContentModifier>(pattern->GetContentModifier());
383 CHECK_NULL_VOID(modifier);
384 modifier->SetIsCustomFont(true);
385 }
386 }
387 }
388
UpdateTextStyle(const std::string & content,const RefPtr<Paragraph> & builder,const std::optional<TextStyle> & textStyle)389 void SpanItem::UpdateTextStyle(
390 const std::string& content, const RefPtr<Paragraph>& builder, const std::optional<TextStyle>& textStyle)
391 {
392 auto textCase = fontStyle ? fontStyle->GetTextCase().value_or(TextCase::NORMAL) : TextCase::NORMAL;
393 auto updateTextAction = [builder, textCase](const std::string& content, const std::optional<TextStyle>& textStyle) {
394 if (content.empty()) {
395 return;
396 }
397 auto displayText = content;
398 StringUtils::TransformStrCase(displayText, static_cast<int32_t>(textCase));
399 if (textStyle.has_value()) {
400 builder->PushStyle(textStyle.value());
401 }
402 builder->AddText(StringUtils::Str8ToStr16(displayText));
403 if (textStyle.has_value()) {
404 builder->PopStyle();
405 }
406 };
407 if (!IsDragging()) {
408 updateTextAction(content, textStyle);
409 } else {
410 if (content.empty()) {
411 return;
412 }
413 auto displayContent = StringUtils::Str8ToStr16(content);
414 auto contentLength = static_cast<int32_t>(displayContent.length());
415 auto beforeSelectedText = displayContent.substr(0, selectedStart);
416 updateTextAction(StringUtils::Str16ToStr8(beforeSelectedText), textStyle);
417
418 if (selectedStart < contentLength) {
419 auto pipelineContext = PipelineContext::GetCurrentContext();
420 TextStyle normalStyle =
421 !pipelineContext ? TextStyle()
422 : CreateTextStyleUsingTheme(nullptr, nullptr, pipelineContext->GetTheme<TextTheme>());
423 TextStyle selectedTextStyle = textStyle.value_or(normalStyle);
424 Color color = selectedTextStyle.GetTextColor().ChangeAlpha(DRAGGED_TEXT_OPACITY);
425 selectedTextStyle.SetTextColor(color);
426 auto selectedText = displayContent.substr(selectedStart, selectedEnd - selectedStart);
427 updateTextAction(StringUtils::Str16ToStr8(selectedText), selectedTextStyle);
428 }
429
430 if (selectedEnd < contentLength) {
431 auto afterSelectedText = displayContent.substr(selectedEnd);
432 updateTextAction(StringUtils::Str16ToStr8(afterSelectedText), textStyle);
433 }
434 }
435 }
436
GetSpanContent(const std::string & rawContent)437 std::string SpanItem::GetSpanContent(const std::string& rawContent)
438 {
439 std::string data;
440 if (needRemoveNewLine) {
441 data = rawContent.substr(0, rawContent.length() - 1);
442 } else {
443 data = rawContent;
444 }
445 return data;
446 }
447
GetSpanContent()448 std::string SpanItem::GetSpanContent()
449 {
450 return content;
451 }
452
GetSymbolUnicode()453 uint32_t SpanItem::GetSymbolUnicode()
454 {
455 return unicode;
456 }
457
StartDrag(int32_t start,int32_t end)458 void SpanItem::StartDrag(int32_t start, int32_t end)
459 {
460 selectedStart = std::max(0, start);
461 int contentLen = content.size();
462 selectedEnd = std::min(contentLen, end);
463 }
464
EndDrag()465 void SpanItem::EndDrag()
466 {
467 selectedStart = -1;
468 selectedEnd = -1;
469 }
470
IsDragging()471 bool SpanItem::IsDragging()
472 {
473 return selectedStart >= 0 && selectedEnd >= 0;
474 }
475
UpdateParagraph(const RefPtr<FrameNode> &,const RefPtr<Paragraph> & builder,double width,double height,VerticalAlign verticalAlign)476 int32_t ImageSpanItem::UpdateParagraph(const RefPtr<FrameNode>& /* frameNode */, const RefPtr<Paragraph>& builder,
477 double width, double height, VerticalAlign verticalAlign)
478 {
479 CHECK_NULL_RETURN(builder, -1);
480 PlaceholderRun run;
481 textStyle = TextStyle();
482 run.width = width;
483 run.height = height;
484 switch (verticalAlign) {
485 case VerticalAlign::TOP:
486 run.alignment = PlaceholderAlignment::TOP;
487 break;
488 case VerticalAlign::CENTER:
489 run.alignment = PlaceholderAlignment::MIDDLE;
490 break;
491 case VerticalAlign::BOTTOM:
492 case VerticalAlign::NONE:
493 run.alignment = PlaceholderAlignment::BOTTOM;
494 break;
495 case VerticalAlign::BASELINE:
496 run.alignment = PlaceholderAlignment::ABOVEBASELINE;
497 break;
498 default:
499 run.alignment = PlaceholderAlignment::BOTTOM;
500 }
501 // ImageSpan should ignore decoration styles
502 textStyle.SetTextDecoration(TextDecoration::NONE);
503 textStyle.SetTextBackgroundStyle(backgroundStyle);
504 builder->PushStyle(textStyle);
505 int32_t index = builder->AddPlaceholder(run);
506 builder->PopStyle();
507 return index;
508 }
509
UpdatePlaceholderBackgroundStyle(const RefPtr<FrameNode> & imageNode)510 void ImageSpanItem::UpdatePlaceholderBackgroundStyle(const RefPtr<FrameNode>& imageNode)
511 {
512 CHECK_NULL_VOID(imageNode);
513 auto property = imageNode->GetLayoutProperty<ImageLayoutProperty>();
514 CHECK_NULL_VOID(property);
515 backgroundStyle = property->GetPlaceHolderStyle();
516 }
517
GetIndex(int32_t & start,int32_t & end) const518 void SpanItem::GetIndex(int32_t& start, int32_t& end) const
519 {
520 auto contentLen = StringUtils::ToWstring(content).length();
521 start = position - contentLen;
522 end = position;
523 }
524
UpdateParagraph(const RefPtr<FrameNode> &,const RefPtr<Paragraph> & builder,double width,double height,VerticalAlign)525 int32_t PlaceholderSpanItem::UpdateParagraph(const RefPtr<FrameNode>& /* frameNode */, const RefPtr<Paragraph>& builder,
526 double width, double height, VerticalAlign /* verticalAlign */)
527 {
528 CHECK_NULL_RETURN(builder, -1);
529 textStyle = TextStyle();
530 PlaceholderRun run;
531 run.width = width;
532 run.height = height;
533 textStyle.SetTextDecoration(TextDecoration::NONE);
534 builder->PushStyle(textStyle);
535 int32_t index = builder->AddPlaceholder(run);
536 builder->PopStyle();
537 return index;
538 }
539
SetTextBackgroundStyle(const TextBackgroundStyle & style)540 void BaseSpan::SetTextBackgroundStyle(const TextBackgroundStyle& style)
541 {
542 textBackgroundStyle_ = style;
543 textBackgroundStyle_->groupId = groupId_;
544 SetHasTextBackgroundStyle(style.backgroundColor.has_value() || style.backgroundRadius.has_value());
545 MarkTextDirty();
546 }
547
ToJsonValue(std::unique_ptr<JsonValue> & json) const548 void ContainerSpanNode::ToJsonValue(std::unique_ptr<JsonValue>& json) const
549 {
550 TextBackgroundStyle::ToJsonValue(json, GetTextBackgroundStyle());
551 }
552 } // namespace OHOS::Ace::NG
553