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/string_utils.h"
24 #include "base/utils/utf_helper.h"
25 #include "base/utils/utils.h"
26 #include "core/common/font_manager.h"
27 #include "core/components/common/layout/constants.h"
28 #include "core/components/common/properties/text_style.h"
29 #include "core/components/hyperlink/hyperlink_theme.h"
30 #include "core/components/text/text_theme.h"
31 #include "core/components_ng/base/frame_node.h"
32 #include "core/components_ng/base/inspector_filter.h"
33 #include "core/components_ng/pattern/text/text_pattern.h"
34 #include "core/components_ng/pattern/text/text_styles.h"
35 #include "core/components_ng/property/property.h"
36 #include "core/components_ng/render/drawing_prop_convertor.h"
37 #include "core/components_ng/render/paragraph.h"
38 #include "core/pipeline/pipeline_context.h"
39 #include "core/pipeline_ng/pipeline_context.h"
40 #include "core/text/text_emoji_processor.h"
41
42 namespace OHOS::Ace::NG {
43 namespace {
44 const std::string CUSTOM_SYMBOL_SUFFIX = "_CustomSymbol";
45 const std::string DEFAULT_SYMBOL_FONTFAMILY = "HM Symbol";
46
GetDeclaration(const std::optional<Color> & color,const std::optional<TextDecoration> & textDecoration,const std::optional<TextDecorationStyle> & textDecorationStyle)47 std::string GetDeclaration(const std::optional<Color>& color, const std::optional<TextDecoration>& textDecoration,
48 const std::optional<TextDecorationStyle>& textDecorationStyle)
49 {
50 auto jsonSpanDeclaration = JsonUtil::Create(true);
51 jsonSpanDeclaration->Put(
52 "type", V2::ConvertWrapTextDecorationToStirng(textDecoration.value_or(TextDecoration::NONE)).c_str());
53 jsonSpanDeclaration->Put("color", (color.value_or(Color::BLACK).ColorToString()).c_str());
54 jsonSpanDeclaration->Put("style",
55 V2::ConvertWrapTextDecorationStyleToString(textDecorationStyle.value_or(TextDecorationStyle::SOLID))
56 .c_str());
57 return jsonSpanDeclaration->ToString();
58 }
ConvertShadowToJson(const Shadow & shadow)59 inline std::unique_ptr<JsonValue> ConvertShadowToJson(const Shadow& shadow)
60 {
61 auto jsonShadow = JsonUtil::Create(true);
62 jsonShadow->Put("radius", std::to_string(shadow.GetBlurRadius()).c_str());
63 jsonShadow->Put("color", shadow.GetColor().ColorToString().c_str());
64 jsonShadow->Put("offsetX", std::to_string(shadow.GetOffset().GetX()).c_str());
65 jsonShadow->Put("offsetY", std::to_string(shadow.GetOffset().GetY()).c_str());
66 jsonShadow->Put("type", std::to_string(static_cast<int32_t>(shadow.GetShadowType())).c_str());
67 return jsonShadow;
68 }
ConvertShadowsToJson(const std::vector<Shadow> & shadows)69 std::unique_ptr<JsonValue> ConvertShadowsToJson(const std::vector<Shadow>& shadows)
70 {
71 auto jsonShadows = JsonUtil::CreateArray(true);
72 for (const auto& shadow : shadows) {
73 jsonShadows->Put(ConvertShadowToJson(shadow));
74 }
75 return jsonShadows;
76 }
77 } // namespace
78
GetFont() const79 std::string SpanItem::GetFont() const
80 {
81 auto pattern = pattern_.Upgrade();
82 CHECK_NULL_RETURN(pattern, "");
83 auto textPattern = DynamicCast<TextPattern>(pattern);
84 CHECK_NULL_RETURN(textPattern, "");
85 auto jsonValue = JsonUtil::Create(true);
86 jsonValue->Put("style", GetFontStyleInJson(fontStyle->GetItalicFontStyle()).c_str());
87 jsonValue->Put("size", textPattern->GetFontSizeWithThemeInJson(fontStyle->GetFontSize()).c_str());
88 jsonValue->Put("weight", GetFontWeightInJson(fontStyle->GetFontWeight()).c_str());
89 jsonValue->Put("family", GetFontFamilyInJson(fontStyle->GetFontFamily()).c_str());
90 return jsonValue->ToString();
91 }
92
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const93 void SpanItem::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
94 {
95 json->PutFixedAttr("content", UtfUtils::Str16DebugToStr8(content).c_str(), filter, FIXED_ATTR_CONTENT);
96 /* no fixed attr below, just return */
97 if (filter.IsFastFilter()) {
98 TextBackgroundStyle::ToJsonValue(json, backgroundStyle, filter);
99 return;
100 }
101 auto pattern = pattern_.Upgrade();
102 CHECK_NULL_VOID(pattern);
103 auto textPattern = DynamicCast<TextPattern>(pattern);
104 CHECK_NULL_VOID(textPattern);
105 if (fontStyle) {
106 json->PutExtAttr("font", GetFont().c_str(), filter);
107 json->PutExtAttr("fontSize", textPattern->GetFontSizeWithThemeInJson(fontStyle->GetFontSize()).c_str(), filter);
108 json->PutExtAttr("decoration", GetDeclaration(fontStyle->GetTextDecorationColor(),
109 fontStyle->GetTextDecoration(), fontStyle->GetTextDecorationStyle()).c_str(), filter);
110 json->PutExtAttr("letterSpacing",
111 fontStyle->GetLetterSpacing().value_or(Dimension()).ToString().c_str(), filter);
112 json->PutExtAttr("textCase",
113 V2::ConvertWrapTextCaseToStirng(fontStyle->GetTextCase().value_or(TextCase::NORMAL)).c_str(), filter);
114 json->PutExtAttr("fontColor", fontStyle->GetForegroundColor().value_or(fontStyle->GetTextColor()
115 .value_or(Color::BLACK)).ColorToString().c_str(), filter);
116 json->PutExtAttr("fontStyle", GetFontStyleInJson(fontStyle->GetItalicFontStyle()).c_str(), filter);
117 json->PutExtAttr("fontWeight", GetFontWeightInJson(fontStyle->GetFontWeight()).c_str(), filter);
118 json->PutExtAttr("fontFamily", GetFontFamilyInJson(fontStyle->GetFontFamily()).c_str(), filter);
119 json->PutExtAttr("renderingStrategy",
120 GetSymbolRenderingStrategyInJson(fontStyle->GetSymbolRenderingStrategy()).c_str(), filter);
121 json->PutExtAttr(
122 "effectStrategy", GetSymbolEffectStrategyInJson(fontStyle->GetSymbolEffectStrategy()).c_str(), filter);
123 json->Put("symbolEffect",
124 GetSymbolEffectOptionsInJson(fontStyle->GetSymbolEffectOptions().value_or(SymbolEffectOptions())).c_str());
125
126 auto shadow = fontStyle->GetTextShadow().value_or(std::vector<Shadow> { Shadow() });
127 // Determines if there are multiple textShadows
128 auto jsonShadow = (shadow.size() == 1) ? ConvertShadowToJson(shadow.front()) : ConvertShadowsToJson(shadow);
129 json->PutExtAttr("textShadow", jsonShadow, filter);
130 }
131 if (textLineStyle) {
132 json->PutExtAttr("lineHeight",
133 textLineStyle->GetLineHeight().value_or(Dimension()).ToString().c_str(), filter);
134 json->PutExtAttr("lineSpacing",
135 textLineStyle->GetLineSpacing().value_or(Dimension()).ToString().c_str(), filter);
136 json->PutExtAttr("baselineOffset",
137 textLineStyle->GetBaselineOffset().value_or(Dimension()).ToString().c_str(), filter);
138 }
139 TextBackgroundStyle::ToJsonValue(json, backgroundStyle, filter);
140 }
141
ToTreeJson(std::unique_ptr<JsonValue> & json,const InspectorConfig & config) const142 void SpanItem::ToTreeJson(std::unique_ptr<JsonValue>& json, const InspectorConfig& config) const
143 {
144 if (!content.empty()) {
145 json->Put(TreeKey::CONTENT, content.c_str());
146 }
147 }
148
GetOrCreateSpanNode(int32_t nodeId)149 RefPtr<SpanNode> SpanNode::GetOrCreateSpanNode(int32_t nodeId)
150 {
151 auto spanNode = ElementRegister::GetInstance()->GetSpecificItemById<SpanNode>(nodeId);
152 if (spanNode) {
153 return spanNode;
154 }
155 spanNode = MakeRefPtr<SpanNode>(nodeId);
156 ElementRegister::GetInstance()->AddUINode(spanNode);
157 return spanNode;
158 }
159
CreateSpanNode(int32_t nodeId)160 RefPtr<SpanNode> SpanNode::CreateSpanNode(int32_t nodeId)
161 {
162 auto spanNode = MakeRefPtr<SpanNode>(nodeId);
163 ElementRegister::GetInstance()->AddUINode(spanNode);
164 return spanNode;
165 }
166
GetOrCreateSpanNode(const std::string & tag,int32_t nodeId)167 RefPtr<SpanNode> SpanNode::GetOrCreateSpanNode(const std::string& tag, int32_t nodeId)
168 {
169 auto spanNode = ElementRegister::GetInstance()->GetSpecificItemById<SpanNode>(nodeId);
170 if (spanNode) {
171 return spanNode;
172 }
173 spanNode = MakeRefPtr<SpanNode>(tag, nodeId);
174 ElementRegister::GetInstance()->AddUINode(spanNode);
175 return spanNode;
176 }
177
MountToParagraph()178 void SpanNode::MountToParagraph()
179 {
180 auto parent = GetParent();
181 while (parent) {
182 auto spanNode = DynamicCast<SpanNode>(parent);
183 if (spanNode) {
184 spanNode->AddChildSpanItem(Claim(this));
185 return;
186 }
187 auto textNode = DynamicCast<FrameNode>(parent);
188 if (textNode) {
189 auto textPattern = textNode->GetPattern<TextPattern>();
190 if (textPattern) {
191 textPattern->AddChildSpanItem(Claim(this));
192 return;
193 }
194 }
195 parent = parent->GetParent();
196 }
197 }
198
RequestTextFlushDirty(bool markModifyDone)199 void SpanNode::RequestTextFlushDirty(bool markModifyDone)
200 {
201 RequestTextFlushDirty(Claim<UINode>(this), markModifyDone);
202 }
203
RequestTextFlushDirty(const RefPtr<UINode> & node,bool markModifyDone)204 void SpanNode::RequestTextFlushDirty(const RefPtr<UINode>& node, bool markModifyDone)
205 {
206 CHECK_NULL_VOID(node);
207 auto parent = node->GetParent();
208 while (parent) {
209 auto textNode = DynamicCast<FrameNode>(parent);
210 if (textNode) {
211 textNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
212 auto textPattern = textNode->GetPattern<TextPattern>();
213 if (textPattern) {
214 ACE_TEXT_SCOPED_TRACE("RequestTextFlushDirty [Parent:%d,Tag:%s][Span:%d]", textNode->GetId(),
215 textNode->GetTag().c_str(), node->GetId());
216 CHECK_NULL_VOID(markModifyDone);
217 textPattern->OnModifyDone();
218 return;
219 }
220 }
221 parent = parent->GetParent();
222 }
223 }
224
SetTextBackgroundStyle(const TextBackgroundStyle & style)225 void SpanNode::SetTextBackgroundStyle(const TextBackgroundStyle& style)
226 {
227 BaseSpan::SetTextBackgroundStyle(style);
228 spanItem_->backgroundStyle = GetTextBackgroundStyle();
229 }
230
UpdateTextBackgroundFromParent(const std::optional<TextBackgroundStyle> & style)231 void SpanNode::UpdateTextBackgroundFromParent(const std::optional<TextBackgroundStyle>& style)
232 {
233 BaseSpan::UpdateTextBackgroundFromParent(style);
234 spanItem_->backgroundStyle = GetTextBackgroundStyle();
235 spanItem_->MarkDirty();
236 }
237
DumpInfo()238 void SpanNode::DumpInfo()
239 {
240 auto& dumpLog = DumpLog::GetInstance();
241 dumpLog.AddDesc(
242 std::string("Content: ").append("\"").append(UtfUtils::Str16DebugToStr8(spanItem_->content)).append("\""));
243 auto textStyle = spanItem_->GetTextStyle();
244 if (!textStyle) {
245 return;
246 }
247 dumpLog.AddDesc(std::string("FontSize: ").append(textStyle->GetFontSize().ToString()));
248 dumpLog.AddDesc(std::string("LineHeight: ").append(textStyle->GetLineHeight().ToString()));
249 dumpLog.AddDesc(std::string("LineSpacing: ").append(textStyle->GetLineSpacing().ToString()));
250 dumpLog.AddDesc(std::string("BaselineOffset: ").append(textStyle->GetBaselineOffset().ToString()));
251 dumpLog.AddDesc(std::string("WordSpacing: ").append(textStyle->GetWordSpacing().ToString()));
252 dumpLog.AddDesc(std::string("TextIndent: ").append(textStyle->GetTextIndent().ToString()));
253 dumpLog.AddDesc(std::string("LetterSpacing: ").append(textStyle->GetLetterSpacing().ToString()));
254 dumpLog.AddDesc(std::string("TextColor: ").append(textStyle->GetTextColor().ColorToString()));
255 if (spanItem_ && spanItem_->fontStyle) {
256 dumpLog.AddDesc(std::string("SpanTextColor: ")
257 .append(spanItem_->fontStyle->GetTextColor().value_or(Color::FOREGROUND).ColorToString()));
258 }
259 dumpLog.AddDesc(std::string("FontWeight: ").append(StringUtils::ToString(textStyle->GetFontWeight())));
260 dumpLog.AddDesc(std::string("FontStyle: ").append(StringUtils::ToString(textStyle->GetFontStyle())));
261 dumpLog.AddDesc(std::string("TextBaseline: ").append(StringUtils::ToString(textStyle->GetTextBaseline())));
262 dumpLog.AddDesc(std::string("TextOverflow: ").append(StringUtils::ToString(textStyle->GetTextOverflow())));
263 dumpLog.AddDesc(std::string("VerticalAlign: ").append(StringUtils::ToString(textStyle->GetTextVerticalAlign())));
264 dumpLog.AddDesc(std::string("TextAlign: ").append(StringUtils::ToString(textStyle->GetTextAlign())));
265 dumpLog.AddDesc(std::string("WordBreak: ").append(StringUtils::ToString(textStyle->GetWordBreak())));
266 dumpLog.AddDesc(std::string("TextCase: ").append(StringUtils::ToString(textStyle->GetTextCase())));
267 dumpLog.AddDesc(std::string("EllipsisMode: ").append(StringUtils::ToString(textStyle->GetEllipsisMode())));
268 dumpLog.AddDesc(std::string("HalfLeading: ").append(std::to_string(textStyle->GetHalfLeading())));
269 if (GetTag() == V2::SYMBOL_SPAN_ETS_TAG) {
270 dumpLog.AddDesc(std::string("SymbolColor:").append(spanItem_->SymbolColorToString()));
271 dumpLog.AddDesc(std::string("RenderStrategy: ").append(std::to_string(textStyle->GetRenderStrategy())));
272 dumpLog.AddDesc(std::string("EffectStrategy: ").append(std::to_string(textStyle->GetEffectStrategy())));
273 dumpLog.AddDesc(std::string("SymbolEffect:").append(
274 spanItem_->fontStyle->GetSymbolEffectOptions().value_or(NG::SymbolEffectOptions()).ToString()));
275 }
276 }
277
SpanDumpInfo()278 void SpanItem::SpanDumpInfo()
279 {
280 auto& dumpLog = DumpLog::GetInstance();
281 dumpLog.AddDesc(
282 std::string("---Content length: ").append(std::to_string(content.length())));
283 auto textStyle = textStyle_;
284 if (!textStyle) {
285 return;
286 }
287 dumpLog.AddDesc(
288 std::string("FontSize: ")
289 .append(textStyle->GetFontSize().ToString())
290 .append(" self: ")
291 .append(fontStyle && fontStyle->HasFontSize() ? fontStyle->GetFontSizeValue().ToString() : "Na"));
292 dumpLog.AddDesc(
293 std::string("TextColor: ")
294 .append(textStyle->GetTextColor().ColorToString())
295 .append(" self: ")
296 .append(fontStyle && fontStyle->HasTextColor() ? fontStyle->GetTextColorValue().ColorToString() : "Na"));
297 dumpLog.AddDesc(
298 std::string("LineHeight: ")
299 .append(textStyle->GetLineHeight().ToString())
300 .append(" self: ")
301 .append(textLineStyle
302 ? textLineStyle->GetLineHeight().value_or(Dimension(0.0, DimensionUnit::FP)).ToString()
303 : "Na"));
304 dumpLog.AddDesc(std::string("BaselineOffset: ")
305 .append(textStyle->GetBaselineOffset().ToString())
306 .append(textLineStyle && textLineStyle->HasBaselineOffset()
307 ? textLineStyle->GetBaselineOffsetValue().ToString()
308 : "Na"));
309 dumpLog.AddDesc(std::string("HalfLeading: ").append(std::to_string(textStyle->GetHalfLeading())));
310 SpanDumpInfoAdvance();
311 }
312
SpanDumpInfoAdvance()313 void SpanItem::SpanDumpInfoAdvance()
314 {
315 CHECK_NULL_VOID(SystemProperties::GetDebugEnabled());
316 auto& dumpLog = DumpLog::GetInstance();
317 auto textStyle = textStyle_;
318 if (!textStyle) {
319 return;
320 }
321 dumpLog.AddDesc(std::string("WordSpacing: ").append(textStyle->GetWordSpacing().ToString()));
322 dumpLog.AddDesc(
323 std::string("TextIndent: ")
324 .append(textStyle->GetTextIndent().ToString())
325 .append(" self: ")
326 .append(textLineStyle && textLineStyle->HasTextIndent() ? textLineStyle->GetTextIndentValue().ToString()
327 : "Na"));
328 dumpLog.AddDesc(
329 std::string("LetterSpacing: ")
330 .append(textStyle->GetLetterSpacing().ToString())
331 .append(" self: ")
332 .append(fontStyle ? fontStyle->GetLetterSpacing().value_or(Dimension(0.0, DimensionUnit::FP)).ToString()
333 : "Na"));
334 dumpLog.AddDesc(
335 std::string("FontWeight: ")
336 .append(StringUtils::ToString(textStyle->GetFontWeight()))
337 .append(" self: ")
338 .append(fontStyle && fontStyle->HasFontWeight() ? StringUtils::ToString(fontStyle->GetFontWeightValue())
339 : "Na"));
340 dumpLog.AddDesc(std::string("FontStyle: ")
341 .append(StringUtils::ToString(textStyle->GetFontStyle()))
342 .append(" self: ")
343 .append(fontStyle && fontStyle->HasItalicFontStyle()
344 ? StringUtils::ToString(fontStyle->GetItalicFontStyleValue())
345 : "Na"));
346 dumpLog.AddDesc(std::string("WordBreak: ").append(StringUtils::ToString(textStyle->GetWordBreak())));
347 dumpLog.AddDesc(std::string("TextCase: ").append(StringUtils::ToString(textStyle->GetTextCase())));
348 dumpLog.AddDesc(std::string("EllipsisMode: ").append(StringUtils::ToString(textStyle->GetEllipsisMode())));
349 }
350
UpdateParagraph(const RefPtr<FrameNode> & frameNode,const RefPtr<Paragraph> & builder,const TextStyle & textStyle,PlaceholderStyle,bool isMarquee)351 int32_t SpanItem::UpdateParagraph(const RefPtr<FrameNode>& frameNode, const RefPtr<Paragraph>& builder,
352 const TextStyle& textStyle, PlaceholderStyle /*placeholderStyle*/, bool isMarquee)
353 {
354 CHECK_NULL_RETURN(builder, -1);
355 CHECK_NULL_RETURN(frameNode, -1);
356 auto pipelineContext = frameNode->GetContextRefPtr();
357 CHECK_NULL_RETURN(pipelineContext, -1);
358 auto spanTextStyle = textStyle;
359 UseSelfStyle(fontStyle, textLineStyle, spanTextStyle);
360 if (fontStyle && fontStyle->HasFontWeight()) {
361 spanTextStyle.SetEnableVariableFontWeight(false);
362 }
363 auto fontManager = pipelineContext->GetFontManager();
364 if (fontManager && !(fontManager->GetAppCustomFont().empty()) && (spanTextStyle.GetFontFamilies().empty())) {
365 spanTextStyle.SetFontFamilies(Framework::ConvertStrToFontFamilies(fontManager->GetAppCustomFont()));
366 }
367 FontRegisterCallback(frameNode, spanTextStyle);
368 if (NearZero(spanTextStyle.GetFontSize().Value())) {
369 return -1;
370 }
371 auto spanContent = GetSpanContent(content, isMarquee);
372 auto pattern = frameNode->GetPattern<TextPattern>();
373 CHECK_NULL_RETURN(pattern, -1);
374 spanTextStyle.SetTextBackgroundStyle(backgroundStyle);
375 if (fontStyle && !fontStyle->HasTextColor() && urlOnRelease) {
376 auto urlSpanColor = pattern->GetUrlSpanColor();
377 spanTextStyle.SetTextColor(urlSpanColor);
378 UpdateTextStyle(spanContent, builder, spanTextStyle, selectedStart, selectedEnd);
379 } else if (pattern->NeedShowAIDetect() && !aiSpanMap.empty()) {
380 TextStyle aiSpanStyle = spanTextStyle;
381 pattern->ModifyAISpanStyle(aiSpanStyle);
382 UpdateTextStyleForAISpan(spanContent, builder, spanTextStyle, aiSpanStyle);
383 } else {
384 UpdateTextStyle(spanContent, builder, spanTextStyle, selectedStart, selectedEnd);
385 }
386 textStyle_ = spanTextStyle;
387 return -1;
388 }
389
UpdateSymbolSpanFontFamily(TextStyle & symbolSpanStyle)390 bool SpanItem::UpdateSymbolSpanFontFamily(TextStyle& symbolSpanStyle)
391 {
392 auto symbolType = symbolSpanStyle.GetSymbolType();
393 std::vector<std::string> fontFamilies;
394 if (symbolType == SymbolType::CUSTOM) {
395 auto symbolFontFamily = symbolSpanStyle.GetFontFamilies();
396 for (auto& name : symbolFontFamily) {
397 if (name.find(CUSTOM_SYMBOL_SUFFIX) != std::string::npos) {
398 fontFamilies.push_back(name);
399 break;
400 }
401 }
402 if (fontFamilies.empty()) {
403 return false;
404 }
405 symbolSpanStyle.SetFontFamilies(fontFamilies);
406 } else {
407 fontFamilies.push_back(DEFAULT_SYMBOL_FONTFAMILY);
408 symbolSpanStyle.SetFontFamilies(fontFamilies);
409 }
410 return true;
411 }
412
UpdateSymbolSpanParagraph(const RefPtr<FrameNode> & frameNode,const TextStyle & textStyle,const RefPtr<Paragraph> & builder,bool isDragging)413 void SpanItem::UpdateSymbolSpanParagraph(
414 const RefPtr<FrameNode>& frameNode, const TextStyle& textStyle, const RefPtr<Paragraph>& builder, bool isDragging)
415 {
416 CHECK_NULL_VOID(builder);
417 auto symbolSpanStyle = textStyle;
418 auto symbolUnicode = GetSymbolUnicode();
419 if (fontStyle || textLineStyle) {
420 UseSelfStyle(fontStyle, textLineStyle, symbolSpanStyle);
421 if (fontStyle && fontStyle->HasFontWeight()) {
422 symbolSpanStyle.SetEnableVariableFontWeight(false);
423 }
424 if (frameNode) {
425 FontRegisterCallback(frameNode, symbolSpanStyle);
426 }
427 if (NearZero(symbolSpanStyle.GetFontSize().Value())) {
428 return;
429 }
430 if (symbolUnicode != 0) {
431 UpdateSymbolSpanColor(frameNode, symbolSpanStyle);
432 }
433 if (!symbolEffectSwitch_ || isDragging) {
434 symbolSpanStyle.SetEffectStrategy(0);
435 }
436 if (!UpdateSymbolSpanFontFamily(symbolSpanStyle)) {
437 return;
438 }
439 builder->PushStyle(symbolSpanStyle);
440 }
441 textStyle_ = symbolSpanStyle;
442
443 if (symbolUnicode != 0) {
444 textStyle_->isSymbolGlyph_ = true;
445 builder->AddSymbol(symbolUnicode);
446 }
447
448 if (fontStyle || textLineStyle) {
449 builder->PopStyle();
450 }
451 }
452
UpdateSymbolSpanColor(const RefPtr<FrameNode> & frameNode,TextStyle & symbolSpanStyle)453 void SpanItem::UpdateSymbolSpanColor(const RefPtr<FrameNode>& frameNode, TextStyle& symbolSpanStyle)
454 {
455 symbolSpanStyle.isSymbolGlyph_ = true;
456 CHECK_NULL_VOID(frameNode);
457 if (GetIsParentText() && symbolSpanStyle.GetSymbolColorList().empty()) {
458 RefPtr<LayoutProperty> layoutProperty = frameNode->GetLayoutProperty();
459 CHECK_NULL_VOID(layoutProperty);
460 RefPtr<TextLayoutProperty> textLayoutProperty = DynamicCast<TextLayoutProperty>(layoutProperty);
461 CHECK_NULL_VOID(textLayoutProperty);
462 if (textLayoutProperty->GetTextColor().has_value()) {
463 std::vector<Color> symbolColor;
464 symbolColor.emplace_back(textLayoutProperty->GetTextColor().value());
465 symbolSpanStyle.SetSymbolColorList(symbolColor);
466 }
467 }
468 }
469
UpdateTextStyleForAISpan(const std::u16string & spanContent,const RefPtr<Paragraph> & builder,const TextStyle & textStyle,const TextStyle & aiSpanStyle)470 void SpanItem::UpdateTextStyleForAISpan(const std::u16string& spanContent, const RefPtr<Paragraph>& builder,
471 const TextStyle& textStyle, const TextStyle& aiSpanStyle)
472 {
473 int32_t spanContentLength = static_cast<int32_t>(spanContent.length());
474 int32_t spanStart = this->position - spanContentLength;
475 if (needRemoveNewLine) {
476 spanStart -= 1;
477 }
478 int32_t preEnd = spanStart;
479 while (!aiSpanMap.empty()) {
480 auto aiSpan = aiSpanMap.begin()->second;
481 if (aiSpan.start >= this->position || preEnd >= this->position) {
482 break;
483 }
484 int32_t aiSpanStartInSpan = std::max(spanStart, aiSpan.start);
485 int32_t aiSpanEndInSpan = std::min(position, aiSpan.end);
486 if (aiSpan.end <= spanStart || aiSpanStartInSpan < preEnd) {
487 TAG_LOGI(AceLogTag::ACE_TEXT, "Error prediction");
488 aiSpanMap.erase(aiSpanMap.begin());
489 continue;
490 }
491 /*
492 | content has been handled | normal text | aiSpan text style | remain text |
493 spanStart(fix) preEnd aiSpanStartInSpan aiSpanEndInSpan spanStart + spanContentLength(fix)
494 */
495 int32_t contentStart = preEnd - spanStart;
496 if (preEnd < aiSpanStartInSpan) {
497 contentStart = std::clamp(contentStart, 0, static_cast<int32_t>(spanContent.length()));
498 UpdateTextStyle(spanContent.substr(contentStart, aiSpanStartInSpan - preEnd),
499 builder, textStyle, this->selectedStart - contentStart, this->selectedEnd - contentStart);
500 contentStart = contentStart + aiSpanStartInSpan - preEnd; // aiSpan's relative offset from span
501 }
502 auto startIndex = aiSpanStartInSpan - aiSpan.start;
503 startIndex = std::clamp(startIndex, 0, static_cast<int32_t>(
504 UtfUtils::Str8DebugToStr16(aiSpan.content).length()));
505 auto displayContent = UtfUtils::Str8DebugToStr16(aiSpan.content)
506 .substr(startIndex, aiSpanEndInSpan - aiSpanStartInSpan);
507 UpdateTextStyle(displayContent, builder, aiSpanStyle,
508 this->selectedStart - contentStart, this->selectedEnd - contentStart);
509 preEnd = aiSpanEndInSpan;
510 if (aiSpan.end > position) {
511 return;
512 } else {
513 aiSpanMap.erase(aiSpanMap.begin());
514 }
515 }
516 if (preEnd < position) {
517 int32_t contentStart = preEnd - spanStart;
518 contentStart = std::clamp(contentStart, 0, static_cast<int32_t>(spanContent.length()));
519 UpdateTextStyle(spanContent.substr(contentStart, position - preEnd),
520 builder, textStyle, selectedStart - contentStart, selectedEnd - contentStart);
521 }
522 }
523
FontRegisterCallback(const RefPtr<FrameNode> & frameNode,const TextStyle & textStyle)524 void SpanItem::FontRegisterCallback(const RefPtr<FrameNode>& frameNode, const TextStyle& textStyle)
525 {
526 auto callback = [weakNode = WeakPtr<FrameNode>(frameNode)] {
527 auto frameNode = weakNode.Upgrade();
528 CHECK_NULL_VOID(frameNode);
529 frameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
530 auto pattern = frameNode->GetPattern<TextPattern>();
531 CHECK_NULL_VOID(pattern);
532 auto modifier = DynamicCast<TextContentModifier>(pattern->GetContentModifier());
533 CHECK_NULL_VOID(modifier);
534 modifier->SetFontReady(true);
535 };
536 auto pipeline = frameNode->GetContext();
537 CHECK_NULL_VOID(pipeline);
538 auto fontManager = pipeline->GetFontManager();
539 if (fontManager) {
540 bool isCustomFont = false;
541 for (const auto& familyName : textStyle.GetFontFamilies()) {
542 bool customFont = fontManager->RegisterCallbackNG(frameNode, familyName, callback);
543 if (customFont) {
544 isCustomFont = true;
545 }
546 }
547 if (isCustomFont) {
548 auto pattern = frameNode->GetPattern<TextPattern>();
549 CHECK_NULL_VOID(pattern);
550 pattern->SetIsCustomFont(true);
551 auto modifier = DynamicCast<TextContentModifier>(pattern->GetContentModifier());
552 CHECK_NULL_VOID(modifier);
553 modifier->SetIsCustomFont(true);
554 }
555 }
556 }
557
UpdateTextStyle(const std::u16string & content,const RefPtr<Paragraph> & builder,const TextStyle & textStyle,int32_t selStart,int32_t selEnd)558 void SpanItem::UpdateTextStyle(const std::u16string& content, const RefPtr<Paragraph>& builder,
559 const TextStyle& textStyle, int32_t selStart, int32_t selEnd)
560 {
561 if (!IsDragging()) {
562 UpdateContentTextStyle(content, builder, textStyle);
563 } else {
564 // for content such as Hellow Wrold, update text style for three parts:
565 // [0, selStart), [selStart, selEnd), [selEnd, content.length) through UpdateContentTextStyle
566 auto contentLength = static_cast<int32_t>(content.length());
567 CHECK_NULL_VOID(selEnd > 0);
568 selStart = selStart < 0 ? 0: selStart;
569 selEnd = selEnd > contentLength ? contentLength : selEnd;
570 if (content.empty()) {
571 builder->PushStyle(textStyle);
572 builder->PopStyle();
573 return;
574 }
575 if (selStart > 0) {
576 UpdateContentTextStyle(
577 TextEmojiProcessor::SubU16string(0, selStart, content, false, true), builder, textStyle);
578 }
579 if (selStart < contentLength) {
580 TextStyle selectedTextStyle = textStyle;
581 Color color = selectedTextStyle.GetTextColor().ChangeAlpha(DRAGGED_TEXT_OPACITY);
582 selectedTextStyle.SetTextColor(color);
583 Color textDecorationColor = selectedTextStyle.GetTextDecorationColor().ChangeAlpha(DRAGGED_TEXT_OPACITY);
584 selectedTextStyle.SetTextDecorationColor(textDecorationColor);
585 UpdateContentTextStyle(
586 TextEmojiProcessor::SubU16string(selStart, selEnd - selStart, content, false, true),
587 builder, selectedTextStyle);
588 }
589 if (selEnd < contentLength) {
590 UpdateContentTextStyle(
591 TextEmojiProcessor::SubU16string(selEnd, content.length() - selEnd, content, false, true),
592 builder, textStyle);
593 }
594 }
595 }
596
UpdateContentTextStyle(const std::u16string & content,const RefPtr<Paragraph> & builder,const TextStyle & textStyle)597 void SpanItem::UpdateContentTextStyle(
598 const std::u16string& content, const RefPtr<Paragraph>& builder, const TextStyle& textStyle)
599 {
600 builder->PushStyle(textStyle);
601 if (!content.empty()) {
602 auto displayText = content;
603 auto textCase = textStyle.GetTextCase();
604 StringUtils::TransformStrCase(displayText, static_cast<int32_t>(textCase));
605 UtfUtils::HandleInvalidUTF16(reinterpret_cast<uint16_t*>(displayText.data()), displayText.length(), 0);
606 builder->AddText(displayText);
607 }
608 builder->PopStyle();
609 }
610
GetSpanContent(const std::u16string & rawContent,bool isMarquee)611 std::u16string SpanItem::GetSpanContent(const std::u16string& rawContent, bool isMarquee)
612 {
613 std::u16string data;
614 if (needRemoveNewLine && !rawContent.empty()) {
615 data = rawContent.substr(0, static_cast<int32_t>(rawContent.length()) - 1);
616 } else {
617 data = rawContent;
618 }
619 if (isMarquee) {
620 std::replace(data.begin(), data.end(), u'\n', u' ');
621 }
622 return data;
623 }
624
GetSpanContent()625 std::u16string SpanItem::GetSpanContent()
626 {
627 return content;
628 }
629
GetSymbolUnicode()630 uint32_t SpanItem::GetSymbolUnicode()
631 {
632 return unicode;
633 }
634
StartDrag(int32_t start,int32_t end)635 void SpanItem::StartDrag(int32_t start, int32_t end)
636 {
637 selectedStart = std::max(0, start);
638 auto contentLen = static_cast<int32_t>(content.size());
639 selectedEnd = std::min(contentLen, end);
640 }
641
EndDrag()642 void SpanItem::EndDrag()
643 {
644 selectedStart = -1;
645 selectedEnd = -1;
646 }
647
IsDragging()648 bool SpanItem::IsDragging()
649 {
650 return selectedStart >= 0 && selectedEnd >= 0;
651 }
652
GetSpanResultObject(int32_t start,int32_t end)653 ResultObject SpanItem::GetSpanResultObject(int32_t start, int32_t end)
654 {
655 bool selectFlag = true;
656 ResultObject resultObject;
657 int32_t endPosition = interval.second;
658 int32_t startPosition = interval.first;
659 int32_t itemLength = endPosition - startPosition;
660
661 if (startPosition >= start && endPosition <= end) {
662 resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
663 resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
664 } else if (startPosition < start && endPosition <= end && endPosition > start) {
665 resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = start - startPosition;
666 resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
667 } else if (startPosition >= start && startPosition < end && endPosition >= end) {
668 resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
669 resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = end - startPosition;
670 } else if (startPosition <= start && endPosition >= end) {
671 resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = start - startPosition;
672 resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = end - startPosition;
673 } else {
674 selectFlag = false;
675 }
676 if (selectFlag) {
677 resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGESTART] = startPosition;
678 resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGEEND] = endPosition;
679 resultObject.type = SelectSpanType::TYPESPAN;
680 resultObject.valueString = content;
681 resultObject.span = WeakClaim(this);
682 resultObject.isInit = true;
683 }
684 return resultObject;
685 }
686
687 #define COPY_TEXT_STYLE(group, name, func) \
688 do { \
689 if ((group)->Has##name()) { \
690 sameSpan->group->func((group)->prop##name.value()); \
691 } \
692 } while (false)
693
GetSameStyleSpanItem(bool isEncodeTlvS) const694 RefPtr<SpanItem> SpanItem::GetSameStyleSpanItem(bool isEncodeTlvS) const
695 {
696 auto sameSpan = MakeRefPtr<SpanItem>();
697 COPY_TEXT_STYLE(fontStyle, FontSize, UpdateFontSize);
698 COPY_TEXT_STYLE(fontStyle, TextColor, UpdateTextColor);
699 COPY_TEXT_STYLE(fontStyle, TextShadow, UpdateTextShadow);
700 COPY_TEXT_STYLE(fontStyle, ItalicFontStyle, UpdateItalicFontStyle);
701 COPY_TEXT_STYLE(fontStyle, FontWeight, UpdateFontWeight);
702 COPY_TEXT_STYLE(fontStyle, FontFamily, UpdateFontFamily);
703 COPY_TEXT_STYLE(fontStyle, FontFeature, UpdateFontFeature);
704 COPY_TEXT_STYLE(fontStyle, TextDecoration, UpdateTextDecoration);
705 COPY_TEXT_STYLE(fontStyle, TextDecorationColor, UpdateTextDecorationColor);
706 COPY_TEXT_STYLE(fontStyle, TextDecorationStyle, UpdateTextDecorationStyle);
707 COPY_TEXT_STYLE(fontStyle, TextCase, UpdateTextCase);
708 COPY_TEXT_STYLE(fontStyle, AdaptMinFontSize, UpdateAdaptMinFontSize);
709 COPY_TEXT_STYLE(fontStyle, AdaptMaxFontSize, UpdateAdaptMaxFontSize);
710 COPY_TEXT_STYLE(fontStyle, LetterSpacing, UpdateLetterSpacing);
711 COPY_TEXT_STYLE(fontStyle, MinFontScale, UpdateMinFontScale);
712 COPY_TEXT_STYLE(fontStyle, MaxFontScale, UpdateMaxFontScale);
713 COPY_TEXT_STYLE(textLineStyle, LineHeight, UpdateLineHeight);
714 COPY_TEXT_STYLE(textLineStyle, LineSpacing, UpdateLineSpacing);
715 COPY_TEXT_STYLE(textLineStyle, TextBaseline, UpdateTextBaseline);
716 COPY_TEXT_STYLE(textLineStyle, BaselineOffset, UpdateBaselineOffset);
717 COPY_TEXT_STYLE(textLineStyle, TextOverflow, UpdateTextOverflow);
718 COPY_TEXT_STYLE(textLineStyle, TextAlign, UpdateTextAlign);
719 COPY_TEXT_STYLE(textLineStyle, MaxLength, UpdateMaxLength);
720 COPY_TEXT_STYLE(textLineStyle, MaxLines, UpdateMaxLines);
721 COPY_TEXT_STYLE(textLineStyle, HeightAdaptivePolicy, UpdateHeightAdaptivePolicy);
722 COPY_TEXT_STYLE(textLineStyle, TextIndent, UpdateTextIndent);
723 COPY_TEXT_STYLE(textLineStyle, LeadingMargin, UpdateLeadingMargin);
724 COPY_TEXT_STYLE(textLineStyle, WordBreak, UpdateWordBreak);
725 COPY_TEXT_STYLE(textLineStyle, LineBreakStrategy, UpdateLineBreakStrategy);
726 COPY_TEXT_STYLE(textLineStyle, EllipsisMode, UpdateEllipsisMode);
727 COPY_TEXT_STYLE(textLineStyle, HalfLeading, UpdateHalfLeading);
728 COPY_TEXT_STYLE(textLineStyle, ParagraphSpacing, UpdateParagraphSpacing);
729 if (textStyle_.has_value()) {
730 sameSpan->textStyle_ = textStyle_;
731 }
732 if (backgroundStyle.has_value()) {
733 sameSpan->backgroundStyle = backgroundStyle;
734 }
735 sameSpan->urlOnRelease = urlOnRelease;
736 sameSpan->onClick = onClick;
737 sameSpan->onLongPress = onLongPress;
738 return sameSpan;
739 }
740
741 #define WRITE_TLV_INHERIT(group, name, tag, type, inheritName) \
742 if ((group)->Has##name()) { \
743 TLVUtil::WriteUint8(buff, (tag)); \
744 TLVUtil::Write##type(buff, (group)->prop##name.value()); \
745 } else if (textStyle_.has_value()) { \
746 auto temp##name = textStyle_->Get##inheritName(); \
747 TLVUtil::WriteUint8(buff, (tag)); \
748 TLVUtil::Write##type(buff, temp##name); \
749 }
750
751 #define WRITE_TEXT_STYLE_TLV(group, name, tag, type) \
752 do { \
753 if ((group)->Has##name()) { \
754 TLVUtil::WriteUint8(buff, (tag)); \
755 TLVUtil::Write##type(buff, (group)->prop##name.value()); \
756 } \
757 } while (false)
758
759 #define READ_TEXT_STYLE_TLV(group, func, tag, type) \
760 case tag: { \
761 sameSpan->group->func(TLVUtil::Read##type(buff, cursor)); \
762 break; \
763 }
764
EncodeTlv(std::vector<uint8_t> & buff)765 bool SpanItem::EncodeTlv(std::vector<uint8_t>& buff)
766 {
767 TLVUtil::WriteUint8(buff, TLV_SPANITEM_TAG);
768 TLVUtil::WriteInt32(buff, interval.first);
769 TLVUtil::WriteInt32(buff, interval.second);
770 TLVUtil::WriteString(buff, UtfUtils::Str16DebugToStr8(content));
771 EncodeFontStyleTlv(buff);
772 EncodeTextLineStyleTlv(buff);
773 if (backgroundStyle.has_value()) {
774 if (backgroundStyle->backgroundColor.has_value()) {
775 TLVUtil::WriteUint8(buff, TLV_SPAN_BACKGROUND_BACKGROUNDCOLOR);
776 TLVUtil::WriteColor(buff, backgroundStyle->backgroundColor.value());
777 }
778 if (backgroundStyle->backgroundRadius.has_value()) {
779 TLVUtil::WriteUint8(buff, TLV_SPAN_BACKGROUND_BACKGROUNDRADIUS);
780 TLVUtil::WriteBorderRadiusProperty(buff, backgroundStyle->backgroundRadius.value());
781 }
782 TLVUtil::WriteUint8(buff, TLV_SPAN_BACKGROUND_GROUPID);
783 TLVUtil::WriteInt32(buff, backgroundStyle->groupId);
784 }
785 WRITE_TLV_INHERIT(textLineStyle, ParagraphSpacing, TLV_SPAN_TEXT_LINE_STYLE_PARAGRAPH_SPACING, Dimension,
786 ParagraphSpacing);
787 TLVUtil::WriteUint8(buff, TLV_SPANITEM_END_TAG);
788 return true;
789 };
790
EncodeFontStyleTlv(std::vector<uint8_t> & buff) const791 void SpanItem::EncodeFontStyleTlv(std::vector<uint8_t>& buff) const
792 {
793 WRITE_TLV_INHERIT(fontStyle, FontSize, TLV_SPAN_FONT_STYLE_FONTSIZE, Dimension, FontSize);
794 WRITE_TLV_INHERIT(fontStyle, TextColor, TLV_SPAN_FONT_STYLE_TEXTCOLOR, Color, TextColor);
795 WRITE_TLV_INHERIT(fontStyle, TextShadow, TLV_SPAN_FONT_STYLE_TEXTSHADOW, TextShadows, TextShadows);
796 WRITE_TLV_INHERIT(fontStyle, ItalicFontStyle, TLV_SPAN_FONT_STYLE_ITALICFONTSTYLE, FontStyle, FontStyle);
797 WRITE_TLV_INHERIT(fontStyle, FontWeight, TLV_SPAN_FONT_STYLE_FONTWEIGHT, FontWeight, FontWeight);
798 WRITE_TLV_INHERIT(fontStyle, FontFamily, TLV_SPAN_FONT_STYLE_FONTFAMILY, FontFamily, FontFamilies);
799 WRITE_TLV_INHERIT(fontStyle, FontFeature, TLV_SPAN_FONT_STYLE_FONTFEATURE, FontFeature, FontFeatures);
800 WRITE_TLV_INHERIT(fontStyle, TextDecoration, TLV_SPAN_FONT_STYLE_TEXTDECORATION, TextDecoration, TextDecoration);
801 WRITE_TLV_INHERIT(
802 fontStyle, TextDecorationColor, TLV_SPAN_FONT_STYLE_TEXTDECORATIONCOLOR, Color, TextDecorationColor);
803 WRITE_TLV_INHERIT(fontStyle, TextDecorationStyle, TLV_SPAN_FONT_STYLE_TEXTDECORATIONSTYLE, TextDecorationStyle,
804 TextDecorationStyle);
805 WRITE_TLV_INHERIT(fontStyle, TextCase, TLV_SPAN_FONT_STYLE_TEXTCASE, TextCase, TextCase);
806 WRITE_TLV_INHERIT(fontStyle, AdaptMinFontSize, TLV_SPAN_FONT_STYLE_ADPATMINFONTSIZE, Dimension, AdaptMinFontSize);
807 WRITE_TLV_INHERIT(fontStyle, AdaptMaxFontSize, TLV_SPAN_FONT_STYLE_ADPATMAXFONTSIZE, Dimension, AdaptMaxFontSize);
808 WRITE_TLV_INHERIT(fontStyle, LetterSpacing, TLV_SPAN_FONT_STYLE_LETTERSPACING, Dimension, LetterSpacing);
809 }
810
EncodeTextLineStyleTlv(std::vector<uint8_t> & buff) const811 void SpanItem::EncodeTextLineStyleTlv(std::vector<uint8_t>& buff) const
812 {
813 WRITE_TLV_INHERIT(textLineStyle, LineHeight, TLV_SPAN_TEXT_LINE_STYLE_LINEHEIGHT, Dimension, LineHeight);
814 WRITE_TLV_INHERIT(textLineStyle, LineSpacing, TLV_SPAN_TEXT_LINE_STYLE_LINESPACING, Dimension, LineSpacing);
815 WRITE_TLV_INHERIT(textLineStyle, TextBaseline, TLV_SPAN_TEXT_LINE_STYLE_TEXTBASELINE, TextBaseline, TextBaseline);
816 // text's baselineOffset attribute is not span's baselineOffset attribute
817 WRITE_TEXT_STYLE_TLV(textLineStyle, BaselineOffset, TLV_SPAN_TEXT_LINE_STYLE_BASELINEOFFSET, Dimension);
818 WRITE_TLV_INHERIT(textLineStyle, TextOverflow, TLV_SPAN_TEXT_LINE_STYLE_TEXTOVERFLOW, TextOverflow, TextOverflow);
819 WRITE_TLV_INHERIT(textLineStyle, TextAlign, TLV_SPAN_TEXT_LINE_STYLE_TEXTALIGN, TextAlign, TextAlign);
820 WRITE_TEXT_STYLE_TLV(textLineStyle, MaxLength, TLV_SPAN_TEXT_LINE_STYLE_MAXLENGTH, Int32);
821 WRITE_TLV_INHERIT(textLineStyle, MaxLines, TLV_SPAN_TEXT_LINE_STYLE_MAXLINES, Int32, MaxLines);
822 WRITE_TEXT_STYLE_TLV(
823 textLineStyle, HeightAdaptivePolicy, TLV_SPAN_TEXT_LINE_STYLE_HEIGHTADAPTIVEPOLICY, TextHeightAdaptivePolicy);
824 WRITE_TLV_INHERIT(textLineStyle, TextIndent, TLV_SPAN_TEXT_LINE_STYLE_TEXTINDENT, Dimension, TextIndent);
825 WRITE_TEXT_STYLE_TLV(textLineStyle, LeadingMargin, TLV_SPAN_TEXT_LINE_STYLE_LEADINGMARGIN, LeadingMargin);
826 WRITE_TLV_INHERIT(textLineStyle, WordBreak, TLV_SPAN_TEXT_LINE_STYLE_WORDBREAK, WordBreak, WordBreak);
827 WRITE_TLV_INHERIT(textLineStyle, LineBreakStrategy, TLV_SPAN_TEXT_LINE_STYLE_LINEBREAKSTRATEGY, LineBreakStrategy,
828 LineBreakStrategy);
829 WRITE_TLV_INHERIT(textLineStyle, EllipsisMode, TLV_SPAN_TEXT_LINE_STYLE_ELLIPSISMODE, EllipsisMode, EllipsisMode);
830 }
831
DecodeTlv(std::vector<uint8_t> & buff,int32_t & cursor)832 RefPtr<SpanItem> SpanItem::DecodeTlv(std::vector<uint8_t>& buff, int32_t& cursor)
833 {
834 auto sameSpan = MakeRefPtr<SpanItem>();
835 if (TLVUtil::ReadUint8(buff, cursor) != TLV_SPANITEM_TAG) {
836 return sameSpan;
837 }
838
839 int32_t start = TLVUtil::ReadInt32(buff, cursor);
840 int32_t end = TLVUtil::ReadInt32(buff, cursor);
841 sameSpan->interval = {start, end};
842 sameSpan->content = UtfUtils::Str8DebugToStr16(TLVUtil::ReadString(buff, cursor));
843
844 for (uint8_t tag = TLVUtil::ReadUint8(buff, cursor);
845 tag != TLV_SPANITEM_END_TAG; tag = TLVUtil::ReadUint8(buff, cursor)) {
846 switch (tag) {
847 READ_TEXT_STYLE_TLV(fontStyle, UpdateFontSize, TLV_SPAN_FONT_STYLE_FONTSIZE, Dimension);
848 READ_TEXT_STYLE_TLV(fontStyle, UpdateTextColor, TLV_SPAN_FONT_STYLE_TEXTCOLOR, Color);
849 READ_TEXT_STYLE_TLV(fontStyle, UpdateTextShadow, TLV_SPAN_FONT_STYLE_TEXTSHADOW, TextShadows);
850 READ_TEXT_STYLE_TLV(fontStyle, UpdateItalicFontStyle, TLV_SPAN_FONT_STYLE_ITALICFONTSTYLE, FontStyle);
851 READ_TEXT_STYLE_TLV(fontStyle, UpdateFontWeight, TLV_SPAN_FONT_STYLE_FONTWEIGHT, FontWeight);
852 READ_TEXT_STYLE_TLV(fontStyle, UpdateFontFamily, TLV_SPAN_FONT_STYLE_FONTFAMILY, FontFamily);
853 READ_TEXT_STYLE_TLV(fontStyle, UpdateFontFeature, TLV_SPAN_FONT_STYLE_FONTFEATURE, FontFeature);
854 READ_TEXT_STYLE_TLV(fontStyle, UpdateTextDecoration, TLV_SPAN_FONT_STYLE_TEXTDECORATION, TextDecoration);
855 READ_TEXT_STYLE_TLV(fontStyle, UpdateTextDecorationColor, TLV_SPAN_FONT_STYLE_TEXTDECORATIONCOLOR, Color);
856 READ_TEXT_STYLE_TLV(fontStyle, UpdateTextDecorationStyle,
857 TLV_SPAN_FONT_STYLE_TEXTDECORATIONSTYLE, TextDecorationStyle);
858 READ_TEXT_STYLE_TLV(fontStyle, UpdateTextCase, TLV_SPAN_FONT_STYLE_TEXTCASE, TextCase);
859 READ_TEXT_STYLE_TLV(fontStyle, UpdateAdaptMinFontSize, TLV_SPAN_FONT_STYLE_ADPATMINFONTSIZE, Dimension);
860 READ_TEXT_STYLE_TLV(fontStyle, UpdateAdaptMaxFontSize, TLV_SPAN_FONT_STYLE_ADPATMAXFONTSIZE, Dimension);
861 READ_TEXT_STYLE_TLV(fontStyle, UpdateLetterSpacing, TLV_SPAN_FONT_STYLE_LETTERSPACING, Dimension);
862
863 READ_TEXT_STYLE_TLV(textLineStyle, UpdateLineHeight, TLV_SPAN_TEXT_LINE_STYLE_LINEHEIGHT, Dimension);
864 READ_TEXT_STYLE_TLV(textLineStyle, UpdateLineSpacing, TLV_SPAN_TEXT_LINE_STYLE_LINESPACING, Dimension);
865 READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextBaseline, TLV_SPAN_TEXT_LINE_STYLE_TEXTBASELINE, TextBaseline);
866 READ_TEXT_STYLE_TLV(textLineStyle, UpdateBaselineOffset,
867 TLV_SPAN_TEXT_LINE_STYLE_BASELINEOFFSET, Dimension);
868 READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextOverflow, TLV_SPAN_TEXT_LINE_STYLE_TEXTOVERFLOW, TextOverflow);
869 READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextAlign, TLV_SPAN_TEXT_LINE_STYLE_TEXTALIGN, TextAlign);
870 READ_TEXT_STYLE_TLV(textLineStyle, UpdateMaxLength, TLV_SPAN_TEXT_LINE_STYLE_MAXLENGTH, Int32);
871 READ_TEXT_STYLE_TLV(textLineStyle, UpdateMaxLines, TLV_SPAN_TEXT_LINE_STYLE_MAXLINES, Int32);
872 READ_TEXT_STYLE_TLV(textLineStyle, UpdateHeightAdaptivePolicy,
873 TLV_SPAN_TEXT_LINE_STYLE_HEIGHTADAPTIVEPOLICY, TextHeightAdaptivePolicy);
874 READ_TEXT_STYLE_TLV(textLineStyle, UpdateTextIndent, TLV_SPAN_TEXT_LINE_STYLE_TEXTINDENT, Dimension);
875 READ_TEXT_STYLE_TLV(textLineStyle, UpdateLeadingMargin,
876 TLV_SPAN_TEXT_LINE_STYLE_LEADINGMARGIN, LeadingMargin);
877 READ_TEXT_STYLE_TLV(textLineStyle, UpdateWordBreak, TLV_SPAN_TEXT_LINE_STYLE_WORDBREAK, WordBreak);
878 READ_TEXT_STYLE_TLV(textLineStyle, UpdateLineBreakStrategy,
879 TLV_SPAN_TEXT_LINE_STYLE_LINEBREAKSTRATEGY, LineBreakStrategy);
880 READ_TEXT_STYLE_TLV(textLineStyle, UpdateEllipsisMode, TLV_SPAN_TEXT_LINE_STYLE_ELLIPSISMODE, EllipsisMode);
881
882 case TLV_SPAN_BACKGROUND_BACKGROUNDCOLOR: {
883 if (!sameSpan->backgroundStyle.has_value()) {
884 sameSpan->backgroundStyle = TextBackgroundStyle();
885 }
886 sameSpan->backgroundStyle->backgroundColor = TLVUtil::ReadColor(buff, cursor);
887 break;
888 }
889 case TLV_SPAN_BACKGROUND_BACKGROUNDRADIUS: {
890 sameSpan->backgroundStyle->backgroundRadius = TLVUtil::ReadBorderRadiusProperty(buff, cursor);
891 break;
892 }
893 case TLV_SPAN_BACKGROUND_GROUPID: {
894 sameSpan->backgroundStyle->groupId = TLVUtil::ReadInt32(buff, cursor);
895 break;
896 }
897 READ_TEXT_STYLE_TLV(textLineStyle, UpdateParagraphSpacing,
898 TLV_SPAN_TEXT_LINE_STYLE_PARAGRAPH_SPACING, Dimension);
899 default:
900 break;
901 }
902 }
903 if (!Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
904 sameSpan->textLineStyle->ResetParagraphSpacing();
905 }
906 return sameSpan;
907 }
908
SymbolColorToString()909 std::string SpanItem::SymbolColorToString()
910 {
911 auto colors = fontStyle->GetSymbolColorList();
912 auto colorStr = std::string("[");
913 if (colors.has_value()) {
914 for (const auto& color : colors.value()) {
915 colorStr.append(color.ColorToString());
916 colorStr.append(",");
917 }
918 }
919 colorStr.append("]");
920 return colorStr;
921 }
922
GetIntersectionInterval(std::pair<int32_t,int32_t> interval) const923 std::optional<std::pair<int32_t, int32_t>> SpanItem::GetIntersectionInterval(std::pair<int32_t, int32_t> interval) const
924 {
925 // Check the intersection
926 if (this->interval.second <= interval.first || interval.second <= this->interval.first) {
927 return std::nullopt;
928 }
929
930 // Calculate the intersection interval
931 int32_t start = std::max(this->interval.first, interval.first);
932 int32_t end = std::min(this->interval.second, interval.second);
933 return std::make_optional<std::pair<int32_t, int32_t>>(std::make_pair(start, end));
934 }
935
EncodeTlv(std::vector<uint8_t> & buff)936 bool ImageSpanItem::EncodeTlv(std::vector<uint8_t>& buff)
937 {
938 if (spanItemType == SpanItemType::NORMAL) {
939 // ImageSpan(resource)场景,复制图片为属性字符串为空格。ImageSpanItem::GetSameStyleSpanItem获取到的spanItemType为NORMAL
940 TLVUtil::WriteUint8(buff, TLV_SPANITEM_TAG);
941 TLVUtil::WriteInt32(buff, interval.first);
942 TLVUtil::WriteInt32(buff, interval.second);
943 TLVUtil::WriteString(buff, UtfUtils::Str16DebugToStr8(content));
944 TLVUtil::WriteUint8(buff, TLV_SPANITEM_END_TAG);
945 return true;
946 }
947 TLVUtil::WriteUint8(buff, TLV_IMAGESPANITEM_TAG);
948 TLVUtil::WriteInt32(buff, interval.first);
949 TLVUtil::WriteInt32(buff, interval.second);
950 TLVUtil::WriteString(buff, UtfUtils::Str16DebugToStr8(content));
951 if (options.offset.has_value()) {
952 TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_OFFSET_TAG);
953 TLVUtil::WriteInt32(buff, options.offset.value());
954 }
955 if (options.image.has_value()) {
956 TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_IMAGE_TAG);
957 TLVUtil::WriteString(buff, options.image.value());
958 }
959 if (options.bundleName.has_value()) {
960 TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_BUNDLENAME_TAG);
961 TLVUtil::WriteString(buff, options.bundleName.value());
962 }
963 if (options.bundleName.has_value()) {
964 TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_MODULENAME_TAG);
965 TLVUtil::WriteString(buff, options.moduleName.value());
966 }
967 if (options.imagePixelMap.has_value()) {
968 TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_IMAGEPIXELMAP_TAG);
969 TLVUtil::WritePixelMap(buff, options.imagePixelMap.value());
970 }
971 if (options.imageAttribute.has_value()) {
972 TLVUtil::WriteUint8(buff, TLV_IMAGESPANOPTION_IMAGEATTRIBUTE_TAG);
973 TLVUtil::WriteImageSpanAttribute(buff, options.imageAttribute.value());
974 }
975 TLVUtil::WriteUint8(buff, TLV_SPANITEM_END_TAG);
976 return true;
977 }
978
DecodeTlv(std::vector<uint8_t> & buff,int32_t & cursor)979 RefPtr<ImageSpanItem> ImageSpanItem::DecodeTlv(std::vector<uint8_t>& buff, int32_t& cursor)
980 {
981 auto sameSpan = MakeRefPtr<ImageSpanItem>();
982
983 if (TLVUtil::ReadUint8(buff, cursor) != TLV_IMAGESPANITEM_TAG) {
984 return sameSpan;
985 }
986
987 int32_t start = TLVUtil::ReadInt32(buff, cursor);
988 int32_t end = TLVUtil::ReadInt32(buff, cursor);
989 sameSpan->interval = {start, end};
990 sameSpan->content = UtfUtils::Str8DebugToStr16(TLVUtil::ReadString(buff, cursor));
991
992 for (uint8_t tag = TLVUtil::ReadUint8(buff, cursor);
993 tag != TLV_SPANITEM_END_TAG; tag = TLVUtil::ReadUint8(buff, cursor)) {
994 switch (tag) {
995 case TLV_IMAGESPANOPTION_OFFSET_TAG: {
996 sameSpan->options.offset = TLVUtil::ReadInt32(buff, cursor);
997 break;
998 }
999 case TLV_IMAGESPANOPTION_IMAGE_TAG: {
1000 sameSpan->options.image = TLVUtil::ReadString(buff, cursor);
1001 break;
1002 }
1003 case TLV_IMAGESPANOPTION_BUNDLENAME_TAG: {
1004 sameSpan->options.bundleName = TLVUtil::ReadString(buff, cursor);
1005 break;
1006 }
1007 case TLV_IMAGESPANOPTION_MODULENAME_TAG: {
1008 sameSpan->options.moduleName = TLVUtil::ReadString(buff, cursor);
1009 break;
1010 }
1011 case TLV_IMAGESPANOPTION_IMAGEPIXELMAP_TAG: {
1012 sameSpan->options.imagePixelMap = TLVUtil::ReadPixelMap(buff, cursor);
1013 break;
1014 }
1015 case TLV_IMAGESPANOPTION_IMAGEATTRIBUTE_TAG: {
1016 sameSpan->options.imageAttribute = TLVUtil::ReadImageSpanAttribute(buff, cursor);
1017 break;
1018 }
1019 default:
1020 break;
1021 }
1022 }
1023 return sameSpan;
1024 }
1025
UpdateParagraph(const RefPtr<FrameNode> &,const RefPtr<Paragraph> & builder,const TextStyle & textStyle,PlaceholderStyle placeholderStyle,bool)1026 int32_t ImageSpanItem::UpdateParagraph(const RefPtr<FrameNode>& /* frameNode */, const RefPtr<Paragraph>& builder,
1027 const TextStyle& textStyle, PlaceholderStyle placeholderStyle, bool /* isMarquee*/)
1028 {
1029 CHECK_NULL_RETURN(builder, -1);
1030 PlaceholderRun run;
1031 auto spanTextStyle = textStyle;
1032 run.width = placeholderStyle.width;
1033 run.height = placeholderStyle.height;
1034 if (!NearZero(placeholderStyle.baselineOffset)) {
1035 run.baseline_offset = placeholderStyle.baselineOffset;
1036 run.alignment = PlaceholderAlignment::BASELINE;
1037 } else {
1038 switch (placeholderStyle.verticalAlign) {
1039 case VerticalAlign::TOP:
1040 run.alignment = PlaceholderAlignment::TOP;
1041 break;
1042 case VerticalAlign::CENTER:
1043 run.alignment = PlaceholderAlignment::MIDDLE;
1044 break;
1045 case VerticalAlign::BOTTOM:
1046 case VerticalAlign::NONE:
1047 run.alignment = PlaceholderAlignment::BOTTOM;
1048 break;
1049 case VerticalAlign::BASELINE:
1050 run.alignment = PlaceholderAlignment::ABOVEBASELINE;
1051 break;
1052 default:
1053 run.alignment = PlaceholderAlignment::BOTTOM;
1054 }
1055 }
1056
1057 // ImageSpan should ignore decoration styles
1058 spanTextStyle.SetTextDecoration(TextDecoration::NONE);
1059 spanTextStyle.SetTextBackgroundStyle(backgroundStyle);
1060 spanTextStyle.SetFontSize(placeholderStyle.paragraphFontSize);
1061 builder->PushStyle(spanTextStyle);
1062 int32_t index = builder->AddPlaceholder(run);
1063 run_ = run;
1064 builder->PopStyle();
1065 return index;
1066 }
1067
UpdatePlaceholderBackgroundStyle(const RefPtr<FrameNode> & imageNode)1068 void ImageSpanItem::UpdatePlaceholderBackgroundStyle(const RefPtr<FrameNode>& imageNode)
1069 {
1070 CHECK_NULL_VOID(imageNode);
1071 auto property = imageNode->GetLayoutProperty<ImageLayoutProperty>();
1072 CHECK_NULL_VOID(property);
1073 backgroundStyle = property->GetPlaceHolderStyle();
1074 }
1075
SetImageSpanOptions(const ImageSpanOptions & options)1076 void ImageSpanItem::SetImageSpanOptions(const ImageSpanOptions& options)
1077 {
1078 this->options = options;
1079 }
1080
ResetImageSpanOptions()1081 void ImageSpanItem::ResetImageSpanOptions()
1082 {
1083 options.imageAttribute.reset();
1084 }
1085
GetSameStyleSpanItem(bool isEncodeTlvS) const1086 RefPtr<SpanItem> ImageSpanItem::GetSameStyleSpanItem(bool isEncodeTlvS) const
1087 {
1088 auto sameSpan = MakeRefPtr<ImageSpanItem>();
1089 if (isEncodeTlvS) {
1090 if (options.HasValue()) {
1091 sameSpan->SetImageSpanOptions(options);
1092 } else {
1093 // 用与Text控件复制ImageSpan子控件,生成并保存options数据
1094 sameSpan->SetImageSpanOptions(GetImageSpanOptionsFromImageNode());
1095 if (!(sameSpan->options.imagePixelMap.value_or(nullptr))) {
1096 /*
1097 ImageSpan子控件,存在resource和pixelMap两种来源。
1098 ImageSpan(resource)场景,复制图片为属性字符串为空格。
1099 因此设置为NORMAL。在ImageSpanItem::EncodeTlv时,SpanItemType为NORMAL时,组装SpanItem。
1100 */
1101 sameSpan->spanItemType = SpanItemType::NORMAL;
1102 }
1103 }
1104 } else {
1105 sameSpan->SetImageSpanOptions(options);
1106 }
1107 sameSpan->urlOnRelease = urlOnRelease;
1108 sameSpan->onClick = onClick;
1109 sameSpan->onLongPress = onLongPress;
1110 if (backgroundStyle.has_value()) {
1111 sameSpan->backgroundStyle = backgroundStyle;
1112 }
1113 return sameSpan;
1114 }
1115
GetImageSpanOptionsFromImageNode() const1116 ImageSpanOptions ImageSpanItem::GetImageSpanOptionsFromImageNode() const
1117 {
1118 ImageSpanOptions imageSpanOptions;
1119 auto frameNode = FrameNode::GetFrameNode(V2::IMAGE_ETS_TAG, imageNodeId);
1120 CHECK_NULL_RETURN(frameNode, imageSpanOptions);
1121 auto layoutProperty = frameNode->GetLayoutProperty<ImageLayoutProperty>();
1122 CHECK_NULL_RETURN(layoutProperty, imageSpanOptions);
1123 auto sourceInfo = layoutProperty->GetImageSourceInfo();
1124 if (sourceInfo.has_value()) {
1125 imageSpanOptions.image = sourceInfo->GetSrc();
1126 imageSpanOptions.bundleName = sourceInfo->GetBundleName();
1127 imageSpanOptions.moduleName = sourceInfo->GetModuleName();
1128 imageSpanOptions.imagePixelMap = sourceInfo->GetPixmap();
1129 }
1130 imageSpanOptions.imageAttribute = CreateImageSpanAttribute(layoutProperty);
1131 auto renderContext = frameNode->GetRenderContext();
1132 if (renderContext && renderContext->HasBorderRadius()) {
1133 imageSpanOptions.imageAttribute->borderRadius = renderContext->GetBorderRadius();
1134 }
1135 return imageSpanOptions;
1136 }
1137
CreateImageSpanAttribute(const RefPtr<ImageLayoutProperty> & layoutProperty) const1138 ImageSpanAttribute ImageSpanItem::CreateImageSpanAttribute(const RefPtr<ImageLayoutProperty>& layoutProperty) const
1139 {
1140 ImageSpanAttribute imageSpanAttribute;
1141 auto& layoutConstraint = layoutProperty->GetCalcLayoutConstraint();
1142
1143 if (layoutConstraint && layoutConstraint->selfIdealSize) {
1144 auto width = layoutConstraint->selfIdealSize->Width();
1145 auto height = layoutConstraint->selfIdealSize->Height();
1146 ImageSpanSize imageSpanSize;
1147 if (width.has_value()) {
1148 imageSpanSize.width = width->GetDimension();
1149 }
1150 if (height.has_value()) {
1151 imageSpanSize.height = height->GetDimension();
1152 }
1153 imageSpanAttribute.size = imageSpanSize;
1154 }
1155 imageSpanAttribute.verticalAlign = layoutProperty->GetVerticalAlign();
1156 imageSpanAttribute.objectFit = layoutProperty->GetImageFit();
1157 auto& margin = layoutProperty->GetMarginProperty();
1158 if (margin) {
1159 MarginProperty marginProperty;
1160 marginProperty.UpdateWithCheck(*margin);
1161 imageSpanAttribute.marginProp = marginProperty;
1162 }
1163 auto& padding = layoutProperty->GetPaddingProperty();
1164 if (padding) {
1165 MarginProperty paddingProperty;
1166 paddingProperty.UpdateWithCheck(*padding);
1167 imageSpanAttribute.paddingProp = paddingProperty;
1168 }
1169 return imageSpanAttribute;
1170 }
1171
GetSpanResultObject(int32_t start,int32_t end)1172 ResultObject ImageSpanItem::GetSpanResultObject(int32_t start, int32_t end)
1173 {
1174 int32_t itemLength = 1;
1175 ResultObject resultObject;
1176
1177 int32_t endPosition = interval.second;
1178 int32_t startPosition = interval.first;
1179 resultObject.type = SelectSpanType::TYPEIMAGE;
1180 if ((start <= startPosition) && (end >= endPosition)) {
1181 resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGESTART] = startPosition;
1182 resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGEEND] = endPosition;
1183 resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
1184 resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
1185 if (options.image.has_value()) {
1186 resultObject.valueString = UtfUtils::Str8DebugToStr16(options.image.value());
1187 }
1188 if (options.imagePixelMap.has_value()) {
1189 resultObject.valuePixelMap = options.imagePixelMap.value();
1190 }
1191 resultObject.isInit = true;
1192 }
1193 return resultObject;
1194 }
1195
GetSpanResultObject(int32_t start,int32_t end)1196 ResultObject CustomSpanItem::GetSpanResultObject(int32_t start, int32_t end)
1197 {
1198 int32_t itemLength = 1;
1199 ResultObject resultObject;
1200
1201 int32_t endPosition = interval.second;
1202 int32_t startPosition = interval.first;
1203 resultObject.type = SelectSpanType::TYPEBUILDERSPAN;
1204 if ((start <= startPosition) && (end >= endPosition)) {
1205 resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGESTART] = startPosition;
1206 resultObject.spanPosition.spanRange[RichEditorSpanRange::RANGEEND] = endPosition;
1207 resultObject.offsetInSpan[RichEditorSpanRange::RANGESTART] = 0;
1208 resultObject.offsetInSpan[RichEditorSpanRange::RANGEEND] = itemLength;
1209 resultObject.valueString = u" ";
1210 resultObject.isInit = true;
1211 }
1212 return resultObject;
1213 }
1214
UpdateSpanTextColor(Color color)1215 bool SpanItem::UpdateSpanTextColor(Color color)
1216 {
1217 auto pattern = pattern_.Upgrade();
1218 CHECK_NULL_RETURN(pattern, false);
1219 auto textPattern = DynamicCast<TextPattern>(pattern);
1220 CHECK_NULL_RETURN(textPattern, false);
1221 auto paragraphManager = textPattern->GetParagraphManager();
1222 CHECK_NULL_RETURN(paragraphManager, false);
1223 auto paragraphInfos = paragraphManager->GetParagraphs();
1224 if (paragraphIndex != 0 || paragraphInfos.size() != 1) {
1225 return false;
1226 }
1227 auto iter = paragraphInfos.begin();
1228 auto paragraphInfo = *iter;
1229 auto paragraph = paragraphInfo.paragraph;
1230 CHECK_NULL_RETURN(paragraph, false);
1231 paragraph->UpdateColor(position - length, position, color);
1232 textPattern->MarkDirtyNodeRender();
1233 return true;
1234 }
1235
GetIndex(int32_t & start,int32_t & end) const1236 void SpanItem::GetIndex(int32_t& start, int32_t& end) const
1237 {
1238 auto contentLen = content.length();
1239 start = position - contentLen;
1240 end = position;
1241 }
1242
UpdateParagraph(const RefPtr<FrameNode> &,const RefPtr<Paragraph> & builder,const TextStyle & textStyle,PlaceholderStyle placeholderStyle,bool)1243 int32_t PlaceholderSpanItem::UpdateParagraph(const RefPtr<FrameNode>& /* frameNode */, const RefPtr<Paragraph>& builder,
1244 const TextStyle& textStyle, PlaceholderStyle placeholderStyle, bool /* isMarquee*/)
1245 {
1246 CHECK_NULL_RETURN(builder, -1);
1247 auto spanTextStyle = textStyle;
1248 PlaceholderRun run;
1249 run.width = placeholderStyle.width;
1250 run.height = placeholderStyle.height;
1251 spanTextStyle.SetTextDecoration(TextDecoration::NONE);
1252 spanTextStyle.SetTextBackgroundStyle(backgroundStyle);
1253 builder->PushStyle(spanTextStyle);
1254 int32_t index = builder->AddPlaceholder(run);
1255 run_ = run;
1256 builder->PopStyle();
1257 return index;
1258 }
1259
DumpInfo() const1260 void PlaceholderSpanItem::DumpInfo() const
1261 {
1262 auto& dumpLog = DumpLog::GetInstance();
1263 dumpLog.AddDesc("--------------- print run info ---------------");
1264 dumpLog.AddDesc(std::string("Width: ").append(std::to_string(run_.width)));
1265 dumpLog.AddDesc(std::string("Height: ").append(std::to_string(run_.height)));
1266 dumpLog.AddDesc(std::string("Alignment: ").append(StringUtils::ToString(run_.alignment)));
1267 dumpLog.AddDesc(std::string("Baseline: ").append(StringUtils::ToString(run_.baseline)));
1268 dumpLog.AddDesc(std::string("BaselineOffset: ").append(std::to_string(run_.baseline_offset)));
1269 dumpLog.AddDesc("--------------- print text style ---------------");
1270 dumpLog.AddDesc(
1271 std::string("FontSize: ")
1272 .append(textStyle.GetFontSize().ToString())
1273 .append(" self: ")
1274 .append(fontStyle && fontStyle->HasFontSize() ? fontStyle->GetFontSizeValue().ToString() : "Na"));
1275 dumpLog.AddDesc(
1276 std::string("TextColor: ")
1277 .append(textStyle.GetTextColor().ColorToString())
1278 .append(" self: ")
1279 .append(
1280 fontStyle && fontStyle->HasTextColor() ? fontStyle->GetTextColorValue().ColorToString() : "Na"));
1281 dumpLog.AddDesc(std::string("BaselineOffset: ")
1282 .append(textStyle.GetBaselineOffset().ToString())
1283 .append(" self: ")
1284 .append(textLineStyle && textLineStyle->HasBaselineOffset()
1285 ? textLineStyle->GetBaselineOffsetValue().ToString()
1286 : "Na"));
1287 dumpLog.AddDesc(
1288 std::string("LineHeight: ")
1289 .append(textStyle.GetLineHeight().ToString())
1290 .append(" self: ")
1291 .append(textLineStyle
1292 ? textLineStyle->GetLineHeight().value_or(Dimension(0.0, DimensionUnit::FP)).ToString()
1293 : "Na"));
1294 dumpLog.AddDesc(std::string("LineSpacing: ").append(textStyle.GetLineSpacing().ToString()));
1295 dumpLog.AddDesc(std::string("VerticalAlign: ").append(StringUtils::ToString(textStyle.GetTextVerticalAlign())));
1296 dumpLog.AddDesc(std::string("HalfLeading: ").append(std::to_string(textStyle.GetHalfLeading())));
1297 dumpLog.AddDesc(std::string("TextBaseline: ").append(StringUtils::ToString(textStyle.GetTextBaseline())));
1298 }
1299
GetSameStyleSpanItem(bool isEncodeTlvS) const1300 RefPtr<SpanItem> CustomSpanItem::GetSameStyleSpanItem(bool isEncodeTlvS) const
1301 {
1302 auto sameSpan = MakeRefPtr<CustomSpanItem>();
1303 sameSpan->onMeasure = onMeasure;
1304 sameSpan->onDraw = onDraw;
1305 sameSpan->urlOnRelease = urlOnRelease;
1306 sameSpan->onClick = onClick;
1307 sameSpan->onLongPress = onLongPress;
1308 if (backgroundStyle.has_value()) {
1309 sameSpan->backgroundStyle = backgroundStyle;
1310 }
1311 return sameSpan;
1312 }
1313
SetTextBackgroundStyle(const TextBackgroundStyle & style)1314 void BaseSpan::SetTextBackgroundStyle(const TextBackgroundStyle& style)
1315 {
1316 textBackgroundStyle_ = style;
1317 textBackgroundStyle_->groupId = groupId_;
1318 SetHasTextBackgroundStyle(style.backgroundColor.has_value() || style.backgroundRadius.has_value());
1319 MarkTextDirty();
1320 }
1321
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1322 void ContainerSpanNode::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1323 {
1324 TextBackgroundStyle::ToJsonValue(json, GetTextBackgroundStyle(), filter);
1325 }
1326
DumpInfo(std::unique_ptr<JsonValue> & json)1327 void SpanNode::DumpInfo(std::unique_ptr<JsonValue>& json)
1328 {
1329 json->Put("Content", UtfUtils::Str16DebugToStr8(spanItem_->content).c_str());
1330 auto textStyle = spanItem_->GetTextStyle();
1331 if (!textStyle) {
1332 return;
1333 }
1334 json->Put("FontSize", textStyle->GetFontSize().ToString().c_str());
1335 json->Put("LineHeight", textStyle->GetLineHeight().ToString().c_str());
1336 json->Put("LineSpacing", textStyle->GetLineSpacing().ToString().c_str());
1337 json->Put("BaselineOffset", textStyle->GetBaselineOffset().ToString().c_str());
1338 json->Put("WordSpacing", textStyle->GetWordSpacing().ToString().c_str());
1339 json->Put("TextIndent", textStyle->GetTextIndent().ToString().c_str());
1340 json->Put("LetterSpacing", textStyle->GetLetterSpacing().ToString().c_str());
1341 json->Put("TextColor", textStyle->GetTextColor().ColorToString().c_str());
1342 if (spanItem_ && spanItem_->fontStyle) {
1343 json->Put(
1344 "SpanTextColor", spanItem_->fontStyle->GetTextColor().value_or(Color::FOREGROUND).ColorToString().c_str());
1345 }
1346 json->Put("FontWeight", StringUtils::ToString(textStyle->GetFontWeight()).c_str());
1347 json->Put("FontStyle", StringUtils::ToString(textStyle->GetFontStyle()).c_str());
1348 json->Put("TextBaseline", StringUtils::ToString(textStyle->GetTextBaseline()).c_str());
1349 json->Put("TextOverflow", StringUtils::ToString(textStyle->GetTextOverflow()).c_str());
1350 json->Put("VerticalAlign", StringUtils::ToString(textStyle->GetTextVerticalAlign()).c_str());
1351 json->Put("TextAlign", StringUtils::ToString(textStyle->GetTextAlign()).c_str());
1352 json->Put("WordBreak", StringUtils::ToString(textStyle->GetWordBreak()).c_str());
1353 json->Put("TextCase", StringUtils::ToString(textStyle->GetTextCase()).c_str());
1354 json->Put("EllipsisMode", StringUtils::ToString(textStyle->GetEllipsisMode()).c_str());
1355 json->Put("HalfLeading", std::to_string(textStyle->GetHalfLeading()).c_str());
1356 if (GetTag() == V2::SYMBOL_SPAN_ETS_TAG) {
1357 json->Put("SymbolColor", spanItem_->SymbolColorToString().c_str());
1358 json->Put("RenderStrategy", std::to_string(textStyle->GetRenderStrategy()).c_str());
1359 json->Put("EffectStrategy", std::to_string(textStyle->GetEffectStrategy()).c_str());
1360 json->Put("SymbolEffect",
1361 spanItem_->fontStyle->GetSymbolEffectOptions().value_or(NG::SymbolEffectOptions()).ToString().c_str());
1362 }
1363 }
1364 } // namespace OHOS::Ace::NG
1365