• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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/utils/utils.h"
21 #include "core/components/common/layout/constants.h"
22 #include "core/components/common/properties/text_style.h"
23 #include "core/components_ng/base/frame_node.h"
24 #include "core/components_ng/pattern/text/text_pattern.h"
25 #include "core/components_ng/pattern/text/text_styles.h"
26 #include "core/components_ng/property/property.h"
27 #include "core/components_ng/render/drawing.h"
28 #include "core/components_ng/render/drawing_prop_convertor.h"
29 #include "core/components_ng/render/paragraph.h"
30 #include "core/pipeline/pipeline_context.h"
31 
32 namespace OHOS::Ace::NG {
33 namespace {
GetDeclaration(const std::optional<Color> & color,const std::optional<TextDecoration> & textDecoration)34 std::string GetDeclaration(const std::optional<Color>& color, const std::optional<TextDecoration>& textDecoration)
35 {
36     auto jsonSpanDeclaration = JsonUtil::Create(true);
37     jsonSpanDeclaration->Put(
38         "type", V2::ConvertWrapTextDecorationToStirng(textDecoration.value_or(TextDecoration::NONE)).c_str());
39     jsonSpanDeclaration->Put("color", (color.value_or(Color::BLACK).ColorToString()).c_str());
40     return jsonSpanDeclaration->ToString();
41 }
42 } // namespace
43 
ToJsonValue(std::unique_ptr<JsonValue> & json) const44 void SpanItem::ToJsonValue(std::unique_ptr<JsonValue>& json) const
45 {
46     json->Put("content", content.c_str());
47     if (fontStyle) {
48         json->Put("fontSize", fontStyle->GetFontSize().value_or(Dimension()).ToString().c_str());
49         json->Put(
50             "decoration", GetDeclaration(fontStyle->GetTextDecorationColor(), fontStyle->GetTextDecoration()).c_str());
51         json->Put("letterSpacing", fontStyle->GetLetterSpacing().value_or(Dimension()).ToString().c_str());
52         json->Put(
53             "textCase", V2::ConvertWrapTextCaseToStirng(fontStyle->GetTextCase().value_or(TextCase::NORMAL)).c_str());
54         json->Put("fontColor", fontStyle->GetForegroundColor()
55             .value_or(fontStyle->GetTextColor().value_or(Color::BLACK)).ColorToString().c_str());
56         json->Put("fontStyle",
57             fontStyle->GetItalicFontStyle().value_or(Ace::FontStyle::NORMAL) == Ace::FontStyle::NORMAL
58                                 ? "FontStyle.Normal" : "FontStyle.Italic");
59         json->Put("fontWeight",
60             V2::ConvertWrapFontWeightToStirng(fontStyle->GetFontWeight().value_or(FontWeight::NORMAL)).c_str());
61         std::vector<std::string> fontFamilyVector =
62             fontStyle->GetFontFamily().value_or<std::vector<std::string>>({ "HarmonyOS Sans" });
63         if (fontFamilyVector.empty()) {
64             fontFamilyVector = std::vector<std::string>({ "HarmonyOS Sans" });
65         }
66         std::string fontFamily = fontFamilyVector.at(0);
67         for (uint32_t i = 1; i < fontFamilyVector.size(); ++i) {
68             fontFamily += ',' + fontFamilyVector.at(i);
69         }
70         json->Put("fontFamily", fontFamily.c_str());
71     }
72 }
73 
GetOrCreateSpanNode(int32_t nodeId)74 RefPtr<SpanNode> SpanNode::GetOrCreateSpanNode(int32_t nodeId)
75 {
76     auto spanNode = ElementRegister::GetInstance()->GetSpecificItemById<SpanNode>(nodeId);
77     if (spanNode) {
78         return spanNode;
79     }
80     spanNode = MakeRefPtr<SpanNode>(nodeId);
81     ElementRegister::GetInstance()->AddUINode(spanNode);
82     return spanNode;
83 }
84 
MountToParagraph()85 void SpanNode::MountToParagraph()
86 {
87     auto parent = GetParent();
88     while (parent) {
89         auto spanNode = DynamicCast<SpanNode>(parent);
90         if (spanNode) {
91             spanNode->AddChildSpanItem(Claim(this));
92             return;
93         }
94         auto textNode = DynamicCast<FrameNode>(parent);
95         if (textNode) {
96             auto textPattern = textNode->GetPattern<TextPattern>();
97             if (textPattern) {
98                 textPattern->AddChildSpanItem(Claim(this));
99                 return;
100             }
101         }
102         parent = parent->GetParent();
103     }
104     LOGE("fail to find Text or Parent Span");
105 }
106 
RequestTextFlushDirty()107 void SpanNode::RequestTextFlushDirty()
108 {
109     auto parent = GetParent();
110     while (parent) {
111         auto textNode = DynamicCast<FrameNode>(parent);
112         if (textNode) {
113             textNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
114             auto textPattern = textNode->GetPattern<TextPattern>();
115             if (textPattern) {
116                 textPattern->OnModifyDone();
117                 return;
118             }
119         }
120         parent = parent->GetParent();
121     }
122     LOGE("fail to find Text or Parent Span");
123 }
124 
UpdateParagraph(const RefPtr<Paragraph> & builder)125 void SpanItem::UpdateParagraph(const RefPtr<Paragraph>& builder)
126 {
127     CHECK_NULL_VOID(builder);
128     if (fontStyle) {
129         auto pipelineContext = PipelineContext::GetCurrentContext();
130         CHECK_NULL_VOID(pipelineContext);
131         TextStyle textStyle = CreateTextStyleUsingTheme(fontStyle, nullptr, pipelineContext->GetTheme<TextTheme>());
132         builder->PushStyle(textStyle);
133     }
134     auto displayText = content;
135     auto textCase = fontStyle ? fontStyle->GetTextCase().value_or(TextCase::NORMAL) : TextCase::NORMAL;
136     StringUtils::TransformStrCase(displayText, static_cast<int32_t>(textCase));
137     builder->AddText(StringUtils::Str8ToStr16(displayText));
138     for (const auto& child : children) {
139         if (child) {
140             child->UpdateParagraph(builder);
141         }
142     }
143     if (fontStyle) {
144         builder->PopStyle();
145     }
146 }
147 } // namespace OHOS::Ace::NG
148