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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TEXT_SPAN_NODE_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_TEXT_SPAN_NODE_H 18 19 #include <list> 20 #include <memory> 21 #include <string> 22 23 #include "base/memory/referenced.h" 24 #include "core/components_ng/base/ui_node.h" 25 #include "core/components_ng/pattern/text/text_styles.h" 26 #include "core/components_v2/inspector/inspector_constants.h" 27 #include "core/components_v2/inspector/utils.h" 28 #include "core/gestures/gesture_info.h" 29 30 #define DEFINE_SPAN_FONT_STYLE_ITEM(name, type) \ 31 public: \ 32 std::optional<type> Get##name() const \ 33 { \ 34 if (spanItem_->fontStyle) { \ 35 return spanItem_->fontStyle->Get##name(); \ 36 } \ 37 return std::nullopt; \ 38 } \ 39 bool Has##name() const \ 40 { \ 41 if (spanItem_->fontStyle) { \ 42 return spanItem_->fontStyle->Has##name(); \ 43 } \ 44 return false; \ 45 } \ 46 type Get##name##Value(const type& defaultValue) const \ 47 { \ 48 if (spanItem_->fontStyle) { \ 49 return spanItem_->fontStyle->Get##name().value_or(defaultValue); \ 50 } \ 51 return defaultValue; \ 52 } \ 53 void Update##name(const type& value) \ 54 { \ 55 if (!spanItem_->fontStyle) { \ 56 spanItem_->fontStyle = std::make_unique<FontStyle>(); \ 57 } \ 58 if (spanItem_->fontStyle->Check##name(value)) { \ 59 LOGD("the %{public}s is same, just ignore", #name); \ 60 return; \ 61 } \ 62 spanItem_->fontStyle->Update##name(value); \ 63 RequestTextFlushDirty(); \ 64 } \ 65 void Reset##name() \ 66 { \ 67 if (spanItem_->fontStyle) { \ 68 return spanItem_->fontStyle->Reset##name(); \ 69 } \ 70 } \ 71 void Update##name##WithoutFlushDirty(const type& value) \ 72 { \ 73 if (!spanItem_->fontStyle) { \ 74 spanItem_->fontStyle = std::make_unique<FontStyle>(); \ 75 } \ 76 if (spanItem_->fontStyle->Check##name(value)) { \ 77 LOGD("the %{public}s is same, just ignore", #name); \ 78 return; \ 79 } \ 80 spanItem_->fontStyle->Update##name(value); \ 81 } \ 82 83 84 #define DEFINE_SPAN_TEXT_LINE_STYLE_ITEM(name, type) \ 85 public: \ 86 std::optional<type> Get##name() const \ 87 { \ 88 if (spanItem_->textLineStyle) { \ 89 return spanItem_->textLineStyle->Get##name(); \ 90 } \ 91 return std::nullopt; \ 92 } \ 93 bool Has##name() const \ 94 { \ 95 if (spanItem_->textLineStyle) { \ 96 return spanItem_->textLineStyle->Has##name(); \ 97 } \ 98 return false; \ 99 } \ 100 type Get##name##Value(const type& defaultValue) const \ 101 { \ 102 if (spanItem_->textLineStyle) { \ 103 return spanItem_->textLineStyle->Get##name().value_or(defaultValue); \ 104 } \ 105 return defaultValue; \ 106 } \ 107 void Update##name(const type& value) \ 108 { \ 109 if (!spanItem_->textLineStyle) { \ 110 spanItem_->textLineStyle = std::make_unique<TextLineStyle>(); \ 111 } \ 112 if (spanItem_->textLineStyle->Check##name(value)) { \ 113 LOGD("the %{public}s is same, just ignore", #name); \ 114 return; \ 115 } \ 116 spanItem_->textLineStyle->Update##name(value); \ 117 RequestTextFlushDirty(); \ 118 } \ 119 void Reset##name() \ 120 { \ 121 if (spanItem_->textLineStyle) { \ 122 return spanItem_->textLineStyle->Reset##name(); \ 123 } \ 124 } \ 125 void Update##name##WithoutFlushDirty(const type& value) \ 126 { \ 127 if (!spanItem_->textLineStyle) { \ 128 spanItem_->textLineStyle = std::make_unique<TextLineStyle>(); \ 129 } \ 130 if (spanItem_->textLineStyle->Check##name(value)) { \ 131 LOGD("the %{public}s is same, just ignore", #name); \ 132 return; \ 133 } \ 134 spanItem_->textLineStyle->Update##name(value); \ 135 } 136 137 namespace OHOS::Ace::NG { 138 139 class Paragraph; 140 141 struct SpanItem : public AceType { 142 DECLARE_ACE_TYPE(SpanItem, AceType); 143 144 public: 145 SpanItem() = default; ~SpanItemSpanItem146 virtual ~SpanItem() 147 { 148 children.clear(); 149 } 150 int32_t position = -1; 151 std::string content; 152 std::unique_ptr<FontStyle> fontStyle; 153 std::unique_ptr<TextLineStyle> textLineStyle; 154 GestureEventFunc onClick; 155 std::list<RefPtr<SpanItem>> children; 156 int32_t placeHolderIndex = -1; 157 #ifdef ENABLE_DRAG_FRAMEWORK 158 int32_t selectedStart = -1; 159 int32_t selectedEnd = -1; 160 #endif // ENABLE_DRAG_FRAMEWORK 161 virtual int32_t UpdateParagraph(const RefPtr<FrameNode>& frameNode, const RefPtr<Paragraph>& builder, 162 double width = 0.0f, double height = 0.0f, VerticalAlign verticalAlign = VerticalAlign::BASELINE); 163 virtual void UpdateTextStyle(const RefPtr<Paragraph>& builder, const std::optional<TextStyle>& textStyle); 164 virtual void FontRegisterCallback(const RefPtr<FrameNode>& frameNode, const TextStyle& textStyle); 165 virtual void ToJsonValue(std::unique_ptr<JsonValue>& json) const; 166 std::string GetFont() const; 167 #ifdef ENABLE_DRAG_FRAMEWORK 168 virtual void StartDrag(int32_t start, int32_t end); 169 virtual void EndDrag(); 170 virtual bool IsDragging(); 171 #endif // ENABLE_DRAG_FRAMEWORK GetTextStyleSpanItem172 std::optional<TextStyle> GetTextStyle() const 173 { 174 return textStyle_; 175 } SetTextStyleSpanItem176 void SetTextStyle(const std::optional<TextStyle>& textStyle) 177 { 178 textStyle_ = textStyle; 179 } 180 private: 181 std::optional<TextStyle> textStyle_; 182 }; 183 184 struct ImageSpanItem : public SpanItem { 185 DECLARE_ACE_TYPE(ImageSpanItem, SpanItem); 186 187 public: 188 ImageSpanItem() = default; 189 ~ImageSpanItem() override = default; 190 int32_t UpdateParagraph(const RefPtr<FrameNode>& frameNode, 191 const RefPtr<Paragraph>& builder, double width, double height, VerticalAlign verticalAlign) override; ToJsonValueImageSpanItem192 void ToJsonValue(std::unique_ptr<JsonValue>& json) const override {}; 193 194 TextStyle textStyle; 195 196 ACE_DISALLOW_COPY_AND_MOVE(ImageSpanItem); 197 }; 198 199 enum class PropertyInfo { 200 FONTSIZE = 0, 201 FONTCOLOR, 202 FONTSTYLE, 203 FONTWEIGHT, 204 FONTFAMILY, 205 TEXTDECORATION, 206 TEXTCASE, 207 LETTERSPACE, 208 LINEHEIGHT, 209 NONE, 210 }; 211 212 class ACE_EXPORT SpanNode : public UINode { 213 DECLARE_ACE_TYPE(SpanNode, UINode); 214 215 public: 216 static RefPtr<SpanNode> GetOrCreateSpanNode(int32_t nodeId); 217 SpanNode(int32_t nodeId)218 explicit SpanNode(int32_t nodeId) : UINode(V2::SPAN_ETS_TAG, nodeId) {} 219 ~SpanNode() override = default; 220 IsAtomicNode()221 bool IsAtomicNode() const override 222 { 223 return true; 224 } 225 GetSpanItem()226 const RefPtr<SpanItem>& GetSpanItem() const 227 { 228 return spanItem_; 229 } 230 UpdateContent(const std::string & content)231 void UpdateContent(const std::string& content) 232 { 233 if (spanItem_->content == content) { 234 LOGD("the content is same, just ignore"); 235 return; 236 } 237 spanItem_->content = content; 238 RequestTextFlushDirty(); 239 } 240 UpdateOnClickEvent(GestureEventFunc && onClick)241 void UpdateOnClickEvent(GestureEventFunc&& onClick) 242 { 243 spanItem_->onClick = std::move(onClick); 244 } 245 246 DEFINE_SPAN_FONT_STYLE_ITEM(FontSize, Dimension); 247 DEFINE_SPAN_FONT_STYLE_ITEM(TextColor, Color); 248 DEFINE_SPAN_FONT_STYLE_ITEM(ItalicFontStyle, Ace::FontStyle); 249 DEFINE_SPAN_FONT_STYLE_ITEM(FontWeight, FontWeight); 250 DEFINE_SPAN_FONT_STYLE_ITEM(FontFamily, std::vector<std::string>); 251 DEFINE_SPAN_FONT_STYLE_ITEM(TextDecoration, TextDecoration); 252 DEFINE_SPAN_FONT_STYLE_ITEM(TextDecorationColor, Color); 253 DEFINE_SPAN_FONT_STYLE_ITEM(TextCase, TextCase); 254 DEFINE_SPAN_FONT_STYLE_ITEM(LetterSpacing, Dimension); 255 DEFINE_SPAN_TEXT_LINE_STYLE_ITEM(LineHeight, Dimension); 256 257 // Mount to the previous Span node or Text node. 258 void MountToParagraph(); 259 AddChildSpanItem(const RefPtr<SpanNode> & child)260 void AddChildSpanItem(const RefPtr<SpanNode>& child) 261 { 262 spanItem_->children.emplace_back(child->GetSpanItem()); 263 } 264 CleanSpanItemChildren()265 void CleanSpanItemChildren() 266 { 267 spanItem_->children.clear(); 268 } 269 ToJsonValue(std::unique_ptr<JsonValue> & json)270 void ToJsonValue(std::unique_ptr<JsonValue>& json) const override 271 { 272 spanItem_->ToJsonValue(json); 273 } 274 275 void RequestTextFlushDirty(); 276 // The function is only used for fast preview. FastPreviewUpdateChildDone()277 void FastPreviewUpdateChildDone() override 278 { 279 RequestTextFlushDirty(); 280 } 281 AddPropertyInfo(PropertyInfo value)282 void AddPropertyInfo(PropertyInfo value) 283 { 284 propertyInfo_.insert(value); 285 } 286 CleanPropertyInfo()287 void CleanPropertyInfo() 288 { 289 propertyInfo_.clear(); 290 } 291 CaculateInheritPropertyInfo()292 std::set<PropertyInfo> CaculateInheritPropertyInfo() 293 { 294 std::set<PropertyInfo> inheritPropertyInfo; 295 const std::set<PropertyInfo> propertyInfoContainer = { PropertyInfo::FONTSIZE, 296 PropertyInfo::FONTCOLOR, 297 PropertyInfo::FONTSTYLE, 298 PropertyInfo::FONTWEIGHT, 299 PropertyInfo::FONTFAMILY, 300 PropertyInfo::TEXTDECORATION, 301 PropertyInfo::TEXTCASE, 302 PropertyInfo::LETTERSPACE, 303 PropertyInfo::LINEHEIGHT }; 304 set_difference(propertyInfoContainer.begin(), propertyInfoContainer.end(), 305 propertyInfo_.begin(), propertyInfo_.end(), 306 inserter(inheritPropertyInfo, inheritPropertyInfo.begin())); 307 return inheritPropertyInfo; 308 } 309 310 private: 311 std::list<RefPtr<SpanNode>> spanChildren_; 312 std::set<PropertyInfo> propertyInfo_; 313 314 RefPtr<SpanItem> spanItem_ = MakeRefPtr<SpanItem>(); 315 316 ACE_DISALLOW_COPY_AND_MOVE(SpanNode); 317 }; 318 319 } // namespace OHOS::Ace::NG 320 321 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_SYNTAX_FOR_EACH_NODE_H 322