• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "frameworks/bridge/common/dom/dom_node.h"
17 
18 #include <sstream>
19 #include <unordered_set>
20 
21 #include "base/json/json_util.h"
22 #include "base/log/ace_trace.h"
23 #include "base/utils/string_utils.h"
24 #include "core/animation/animatable_data.h"
25 #include "core/common/ace_application_info.h"
26 #include "core/common/frontend.h"
27 #include "core/components/declaration/common/declaration_creator_manager.h"
28 #include "core/components/scroll/scroll_bar_theme.h"
29 #include "core/components/scroll/scroll_fade_effect.h"
30 #include "core/components/scroll/scroll_spring_effect.h"
31 #include "core/components/text_field/text_field_component.h"
32 #include "core/components/video/texture_component.h"
33 #include "core/components/web/web_component.h"
34 #include "core/components/xcomponent/xcomponent_component.h"
35 #include "frameworks/bridge/common/dom/dom_document.h"
36 #include "frameworks/bridge/common/dom/dom_div.h"
37 #include "frameworks/bridge/common/utils/utils.h"
38 
39 namespace OHOS::Ace::Framework {
40 namespace {
41 
42 constexpr uint32_t TRANSFORM_SINGLE = 1;
43 constexpr uint32_t TRANSFORM_DUAL = 2;
44 constexpr uint32_t TRANSFORM_SIX = 6;
45 constexpr uint32_t TRANSFORM_SIXTEEN = 16;
46 constexpr uint32_t COMMON_METHOD_FOCUS_ARGS_SIZE = 1;
47 constexpr uint32_t THREE_VALUES = 3;
48 constexpr uint32_t FOUR_VALUES = 4;
49 constexpr int32_t MS_TO_S = 1000;
50 const char COMMON_METHOD_FOCUS[] = "focus";
51 
52 // focusable support list, this list should be updated after the other nodes(checkbox/radio/switch/
53 // grid/dialog/button/input) implemented in frontend.
54 std::unordered_set<std::string> g_focusableNode;
55 
56 // unsupported focusable list.
57 const std::unordered_set<std::string> UNFOCUSABLED_NODE = {
58     DOM_NODE_TAG_SPAN,
59 };
60 
61 static const std::unordered_set<std::string> TRANSITION_PROPERTIES = {
62     DOM_WIDTH,
63     DOM_HEIGHT,
64     DOM_PADDING_TOP,
65     DOM_PADDING_RIGHT,
66     DOM_PADDING_BOTTOM,
67     DOM_PADDING_LEFT,
68     DOM_MARGIN_TOP,
69     DOM_MARGIN_RIGHT,
70     DOM_MARGIN_BOTTOM,
71     DOM_MARGIN_LEFT,
72     DOM_BACKGROUND_COLOR,
73     DOM_OPACITY,
74     DOM_BORDER_LEFT_WIDTH,
75     DOM_BORDER_TOP_WIDTH,
76     DOM_BORDER_RIGHT_WIDTH,
77     DOM_BORDER_BOTTOM_WIDTH,
78     DOM_BORDER_LEFT_COLOR,
79     DOM_BORDER_TOP_COLOR,
80     DOM_BORDER_RIGHT_COLOR,
81     DOM_BORDER_BOTTOM_COLOR
82 };
83 
84 // default flex value
85 constexpr double DEFAULT_FLEX_GROW = 0.0;
86 constexpr double DEFAULT_FLEX_SHRINK = 1.0;
87 constexpr double DEFAULT_FLEX_BASIS = -1.0;
88 constexpr int32_t TRANSITION_NAME_LENGTH = 4;
89 
90 // prefix id of TweenComponent, for differentiation from id of ComposedComponent
91 constexpr char COMPONENT_PREFIX[] = "FrontendTween";
92 constexpr char TRANSITION_COMPONENT_PREFIX[] = "FrontendTransition";
93 
94 } // namespace
95 
DOMNode(NodeId nodeId,const std::string & nodeName)96 DOMNode::DOMNode(NodeId nodeId, const std::string& nodeName) : nodeId_(nodeId), tag_(nodeName)
97 {
98     rootComponent_ = AceType::MakeRefPtr<ComposedComponent>(std::to_string(nodeId), nodeName);
99     boxComponent_ = AceType::MakeRefPtr<BoxComponent>();
100     boxComponent_->SetEnableDebugBoundary(true);
101     CreateDeclaration(nodeName);
102 }
103 
~DOMNode()104 DOMNode::~DOMNode()
105 {
106     if (declaration_) {
107         auto& focusEvent = static_cast<CommonFocusEvent&>(declaration_->GetEvent(EventTag::COMMON_FOCUS_EVENT));
108         if (focusEvent.IsValid()) {
109             if (!focusEvent.focus.eventMarker.IsEmpty()) {
110                 BackEndEventManager<void()>::GetInstance().RemoveBackEndEvent(focusEvent.focus.eventMarker);
111             }
112             if (!focusEvent.blur.eventMarker.IsEmpty()) {
113                 BackEndEventManager<void()>::GetInstance().RemoveBackEndEvent(focusEvent.blur.eventMarker);
114             }
115         }
116         auto& mouseEvent = static_cast<CommonMouseEvent&>(declaration_->GetEvent(EventTag::COMMON_MOUSE_EVENT));
117         if (mouseEvent.IsValid()) {
118             if (!mouseEvent.mouseHover.eventMarker.IsEmpty()) {
119                 BackEndEventManager<void()>::GetInstance().RemoveBackEndEvent(mouseEvent.mouseHover.eventMarker);
120             }
121             if (!mouseEvent.mouseHoverExit.eventMarker.IsEmpty()) {
122                 BackEndEventManager<void()>::GetInstance().RemoveBackEndEvent(mouseEvent.mouseHoverExit.eventMarker);
123             }
124         }
125 
126         for (uint32_t eventAction = 0; eventAction < EventAction::SIZE; eventAction++) {
127             for (uint32_t eventStage = 0; eventStage < EventStage::SIZE; eventStage++) {
128                 for (uint32_t touchEventType = 0; touchEventType < EventType::SIZE; touchEventType++) {
129                     const auto& eventMarker = GetTouchId(eventAction, eventStage, touchEventType);
130                     if (!eventMarker.IsEmpty()) {
131                         BackEndEventManager<void()>::GetInstance().RemoveBackEndEvent(eventMarker);
132                     }
133                 }
134             }
135         }
136     }
137 }
138 
Mount(int32_t slot)139 void DOMNode::Mount(int32_t slot)
140 {
141     auto parentNode = parentNode_.Upgrade();
142     if (!parentNode) {
143         return;
144     }
145     // flex-item could be used in div, list-item, tabs
146     static const std::unordered_set<std::string> flexItemParents = {
147         DOM_NODE_TAG_DIV,
148         DOM_NODE_TAG_GRID_COLUMN,
149         DOM_NODE_TAG_LIST_ITEM,
150         DOM_NODE_TAG_LIST_ITEM_GROUP,
151         DOM_NODE_TAG_TABS,
152         DOM_NODE_TAG_REFRESH,
153         DOM_NODE_TAG_STEPPER_ITEM,
154     };
155     if (flexItemParents.count(parentTag_) > 0) {
156         flexItemComponent_ =
157             AceType::MakeRefPtr<FlexItemComponent>(DEFAULT_FLEX_GROW, DEFAULT_FLEX_SHRINK, DEFAULT_FLEX_BASIS);
158         if (boxComponent_) {
159             // span has no box component.
160             boxComponent_->SetDeliverMinToChild(false);
161         }
162     }
163     GenerateComponentNode();
164     if (parentNode->IsRootNode()) {
165         // When parent is root node, parent contains scroll component,
166         // box could handle percent with viewport size.
167         if (boxComponent_) {
168             // span has no box component.
169             boxComponent_->SetPercentFlag(PERCENT_FLAG_USE_VIEW_PORT);
170         }
171     }
172     parentNode->AddNode(AceType::Claim(this), slot);
173     OnMounted(parentNode);
174 }
175 
AddEvent(int32_t pageId,const std::vector<std::string> & events)176 void DOMNode::AddEvent(int32_t pageId, const std::vector<std::string>& events)
177 {
178     std::vector<std::string> tempEvents;
179     for (const auto& event : events) {
180         if (!AddSpecializedEvent(pageId, event)) {
181             tempEvents.emplace_back(event);
182         }
183         if (event == "dragstart") {
184             auto onDragStartId = [](const RefPtr<DragEvent>& info, const std::string &extraParams) -> DragItemInfo {
185                 DragItemInfo itemInfo;
186                 itemInfo.pixelMap = DOMDocument::pixelMap_;
187                 return itemInfo;
188             };
189             boxComponent_->SetOnDragStartId(onDragStartId);
190         }
191 
192     }
193     if (declaration_) {
194         declaration_->AddEvent(pageId, GetNodeIdForEvent(), tempEvents);
195     }
196 }
197 
SetAttr(const std::vector<std::pair<std::string,std::string>> & attrs)198 void DOMNode::SetAttr(const std::vector<std::pair<std::string, std::string>>& attrs)
199 {
200     attributesCache_ = attrs;
201     SetAttrInternal(attrs);
202 }
203 
SetAttrInternal(const std::vector<std::pair<std::string,std::string>> & attrs)204 void DOMNode::SetAttrInternal(const std::vector<std::pair<std::string, std::string>>& attrs)
205 {
206     std::vector<std::pair<std::string, std::string>> tempAttrs;
207     for (const auto& attr : attrs) {
208         if (SetSpecializedAttr(attr)) {
209             continue;
210         } else {
211             tempAttrs.emplace_back(attr);
212         }
213     }
214     if (declaration_) {
215         IsSubscriptEnable();
216         declaration_->SetAttr(tempAttrs);
217     }
218 }
219 
CallMethod(const std::string & method,const std::string & args)220 void DOMNode::CallMethod(const std::string& method, const std::string& args)
221 {
222     if (method == COMMON_METHOD_FOCUS) {
223         if (!focusableEventComponent_) {
224             return;
225         }
226 
227         bool shouldFocus = true;
228         std::unique_ptr<JsonValue> argsValue = JsonUtil::ParseJsonString(args);
229         if (argsValue && argsValue->IsArray() && argsValue->GetArraySize() == COMMON_METHOD_FOCUS_ARGS_SIZE) {
230             std::unique_ptr<JsonValue> focusValue = argsValue->GetArrayItem(0)->GetValue(COMMON_METHOD_FOCUS);
231             if (focusValue && focusValue->IsBool()) {
232                 shouldFocus = focusValue->GetBool();
233             }
234         }
235         OnRequestFocus(shouldFocus);
236     } else if (method == DOM_LIST_METHOD_SCROLL_BY) {
237         std::unique_ptr<JsonValue> argsValue = JsonUtil::ParseJsonString(args);
238         if (!argsValue || !argsValue->IsArray() || argsValue->GetArraySize() != 1) {
239             LOGW("Dom Node parse args error");
240             return;
241         }
242         std::unique_ptr<JsonValue> scrollByPara = argsValue->GetArrayItem(0);
243         double x = scrollByPara->GetDouble("dx", 0.0);
244         double y = scrollByPara->GetDouble("dy", 0.0);
245         bool isSmooth = scrollByPara->GetBool("smooth", true);
246         OnScrollBy(x, y, isSmooth);
247     } else {
248         CallSpecializedMethod(method, args);
249     }
250 }
251 
OnRequestFocus(bool shouldFocus)252 void DOMNode::OnRequestFocus(bool shouldFocus)
253 {
254     auto controller = focusableEventComponent_->GetFocusableController();
255     if (!controller) {
256         return;
257     }
258     controller->RequestFocus(shouldFocus);
259 }
260 
OnScrollBy(double dx,double dy,bool isSmooth)261 void DOMNode::OnScrollBy(double dx, double dy, bool isSmooth)
262 {
263     auto scrollComponent = GetScrollComponent();
264     if (!scrollComponent) {
265         return;
266     }
267     auto positionController = scrollComponent->GetScrollPositionController();
268     if (!positionController) {
269         return;
270     }
271     positionController->ScrollBy(dx, dy, isSmooth);
272 }
273 
SetShowAttr(const std::string & showValue)274 void DOMNode::SetShowAttr(const std::string& showValue)
275 {
276     if (!declaration_) {
277         return;
278     }
279 
280     auto& renderAttr = declaration_->MaybeResetAttribute<CommonRenderAttribute>(AttributeTag::COMMON_RENDER_ATTR);
281     if (renderAttr.IsValid()) {
282         renderAttr.show = showValue;
283     }
284     if (showValue == "false") {
285         SetDisplay(DisplayType::NONE);
286     } else {
287         SetDisplay(DisplayType::NO_SETTING);
288     }
289 }
290 
ParseTransitionPropertyStyle(const std::string & transitionProperty)291 bool DOMNode::ParseTransitionPropertyStyle(const std::string& transitionProperty)
292 {
293     if (TRANSITION_PROPERTIES.find(transitionProperty) == TRANSITION_PROPERTIES.end()) {
294         return false;
295     }
296     transitionPropertyName_ = transitionProperty;
297     CreatePropertyAnimation(transitionPropertyName_);
298     return true;
299 }
300 
ParseTransitionNameStyle(const std::string & transitionName)301 bool DOMNode::ParseTransitionNameStyle(const std::string& transitionName)
302 {
303     std::vector<std::string> transitions;
304     StringUtils::StringSplitter(transitionName, ' ', transitions);
305     if (transitions.size() != TRANSITION_NAME_LENGTH) {
306         return false;
307     }
308     transitionPropertyName_ = transitions[0];
309     transitionDuration_ = StringUtils::StringToDouble(transitions[1]) * MS_TO_S;
310     transitionTimeFunction_ = transitions[2];
311     transitionDelay_ = StringUtils::StringToDouble(transitions[3]) * MS_TO_S;
312 
313     CreatePropertyAnimation(transitionPropertyName_);
314     return true;
315 }
316 
CreatePropertyAnimation(const std::string & property)317 void DOMNode::CreatePropertyAnimation(const std::string& property)
318 {
319     propertyWidthAnimation_ = AceType::MakeRefPtr<KeyframeAnimation<float>>();
320     propertyHeightAnimation_ = AceType::MakeRefPtr<KeyframeAnimation<float>>();
321     propertyColorAnimation_ = AceType::MakeRefPtr<KeyframeAnimation<Color>>();
322     static const std::unordered_map<std::string, void (*)(DOMNode&)> propertyAnimationMap = {
323         { DOM_WIDTH, [](DOMNode& node) {
324             float widthBegin = 0.0f;
325             float widthEnd = node.GetWidth().Value();
326             node.propertyWidthAnimation_ = node.SetPropertyFloatAnimationKeyframe(widthBegin, widthEnd);
327         } },
328         { DOM_HEIGHT, [](DOMNode& node) {
329             float heightBegin = 0.0f;
330             float heightEnd = node.GetHeight().Value();
331             node.propertyHeightAnimation_ = node.SetPropertyFloatAnimationKeyframe(heightBegin, heightEnd);
332         } },
333         { DOM_TRANSITION_BACKGROUND_COLOR, [](DOMNode& node) {
334             Color backgroundColorBegin = Color::TRANSPARENT;
335             Color backgroundColorEnd = node.GetBackGroundColor();
336             node.propertyColorAnimation_ =
337                     node.SetPropertyColorAnimationKeyframe(backgroundColorBegin, backgroundColorEnd);
338         } },
339     };
340 
341     auto animationIter = propertyAnimationMap.find(property);
342     if (animationIter != propertyAnimationMap.end()) {
343         animationIter->second(*this);
344     }
345     if (property == "all") {
346         for (auto propertyAnimation : propertyAnimationMap) {
347             propertyAnimation.second(*this);
348         }
349     }
350 }
351 
SetPropertyFloatAnimationKeyframe(float begin,float end)352 RefPtr<KeyframeAnimation<float>> DOMNode::SetPropertyFloatAnimationKeyframe(float begin, float end)
353 {
354     auto propertyDimensionAnimation = AceType::MakeRefPtr<KeyframeAnimation<float>>();
355     auto keyframeBegin = AceType::MakeRefPtr<Keyframe<float>>(0.0f, begin);
356     auto keyframeEnd = AceType::MakeRefPtr<Keyframe<float>>(1.0f, end);
357     propertyDimensionAnimation->AddKeyframe(keyframeBegin);
358     propertyDimensionAnimation->AddKeyframe(keyframeEnd);
359     return propertyDimensionAnimation;
360 }
361 
SetPropertyColorAnimationKeyframe(const Color & begin,const Color & end)362 RefPtr<KeyframeAnimation<Color>> DOMNode::SetPropertyColorAnimationKeyframe(const Color& begin, const Color& end)
363 {
364     auto propertyColorAnimation = AceType::MakeRefPtr<KeyframeAnimation<Color>>();
365     auto keyframeBegin = AceType::MakeRefPtr<Keyframe<Color>>(0.0f, begin);
366     auto keyframeEnd = AceType::MakeRefPtr<Keyframe<Color>>(1.0f, end);
367     propertyColorAnimation->AddKeyframe(keyframeBegin);
368     propertyColorAnimation->AddKeyframe(keyframeEnd);
369     return propertyColorAnimation;
370 }
371 
TransitionOptionSetKeyframes(TweenOption & transitionOption)372 void DOMNode::TransitionOptionSetKeyframes(TweenOption& transitionOption)
373 {
374     transitionOption.SetDuration(transitionDuration_);
375     transitionOption.SetFillMode(FillMode::FORWARDS);
376     transitionOption.SetCurve(CreateCurve(transitionTimeFunction_));
377     transitionOption.SetDelay(transitionDelay_);
378     if (propertyWidthAnimation_ && !propertyWidthAnimation_->GetKeyframes().empty()) {
379         transitionOption.SetPropertyAnimationFloat(PropertyAnimatableType::PROPERTY_WIDTH, propertyWidthAnimation_);
380     }
381     if (propertyHeightAnimation_ && !propertyHeightAnimation_->GetKeyframes().empty()) {
382         transitionOption.SetPropertyAnimationFloat(PropertyAnimatableType::PROPERTY_HEIGHT,
383             propertyHeightAnimation_);
384     }
385     if (propertyColorAnimation_ && !propertyColorAnimation_->GetKeyframes().empty()) {
386         transitionOption.SetColorAnimation(propertyColorAnimation_);
387     }
388 }
389 
SetStyle(const std::vector<std::pair<std::string,std::string>> & styles)390 void DOMNode::SetStyle(const std::vector<std::pair<std::string, std::string>>& styles)
391 {
392     std::vector<std::pair<std::string, std::string>> tempStyles;
393     for (const auto& style : styles) {
394         if ((style.first == DOM_TRANSITION_NAME) || (style.first == DOM_TRANSITION_PROPERTY_DURATION)) {
395             transitionStyleUpdated_ = true;
396         }
397         if (style.first == DOM_BACKGROUND_COLOR) {
398             isTransitionColor_ = true;
399         }
400         CachePseudoClassStyle(style);
401         if (style.first.find(DOM_PSEUDO_CLASS_SYMBOL) == std::string::npos) {
402             if (!SetCurrentStyle(style)) {
403                 tempStyles.emplace_back(style);
404             }
405         } else {
406             tempStyles.emplace_back(style);
407         }
408     }
409     if (declaration_) {
410         declaration_->SetStyle(tempStyles);
411     }
412     OnSetStyleFinished();
413 }
414 
SetCurrentStyle(const std::pair<std::string,std::string> & style)415 bool DOMNode::SetCurrentStyle(const std::pair<std::string, std::string>& style)
416 {
417     if (SetSpecializedStyle(style)) {
418         // If the subclass consumes this property, it will no longer look in the general property.
419         return true;
420     }
421     // Operator map for styles
422     static const std::unordered_map<std::string, void (*)(const std::string&, DOMNode&)> styleOperators = {
423         // Set width and height
424         { DOM_TRANSFORM, &DOMNode::SetTransform },
425         { DOM_TRANSITION_PROPERTY,
426             [](const std::string& val, DOMNode& node) {
427                 node.ParseTransitionPropertyStyle(val);
428             } },
429         { DOM_TRANSITION_PROPERTY_DURATION,
430             [](const std::string& val, DOMNode& node) {
431                 node.transitionDuration_ = StringUtils::StringToInt(val) * MS_TO_S;
432             } },
433         { DOM_TRANSITION_PROPERTY_TIMING_FUNCTION,
434             [](const std::string& val, DOMNode& node) {
435                 node.transitionTimeFunction_ = val;
436             } },
437         { DOM_TRANSITION_PROPERTY_DELAY,
438             [](const std::string& val, DOMNode& node) {
439                 node.transitionDelay_ = StringUtils::StringToInt(val) * MS_TO_S;
440             } },
441     };
442     auto operatorIter = styleOperators.find(style.first);
443     if (operatorIter != styleOperators.end()) {
444         operatorIter->second(style.second, *this);
445         return true;
446     }
447     return false;
448 }
449 
OnActive(bool isActive)450 void DOMNode::OnActive(bool isActive)
451 {
452     isActive_ = isActive;
453     UpdatePseudoStyle(true);
454 }
455 
OnFocus(bool isFocus)456 void DOMNode::OnFocus(bool isFocus)
457 {
458     isFocus_ = isFocus;
459     UpdatePseudoStyle(true);
460 }
461 
OnChecked(bool isChecked)462 void DOMNode::OnChecked(bool isChecked)
463 {
464     if (declaration_) {
465         declaration_->SetIsChecked(isChecked);
466     }
467     UpdatePseudoStyle(true);
468 }
469 
OnHover(bool isHover)470 void DOMNode::OnHover(bool isHover)
471 {
472     if (declaration_) {
473         declaration_->SetIsHover(isHover);
474     }
475     UpdatePseudoStyle(true);
476 }
477 
MarkNeedUpdate()478 void DOMNode::MarkNeedUpdate()
479 {
480     auto pipelineContext = pipelineContext_.Upgrade();
481     if (!pipelineContext) {
482         return;
483     }
484     rootComponent_->MarkNeedUpdate();
485     rootComponent_->SetUpdateType(UpdateType::ALL);
486     pipelineContext->ScheduleUpdate(rootComponent_);
487 }
488 
SetOnFocusClick(const EventMarker & eventMarker)489 void DOMNode::SetOnFocusClick(const EventMarker& eventMarker)
490 {
491     if (!focusableEventComponent_) {
492         return;
493     }
494     focusableEventComponent_->SetOnClickId(eventMarker);
495 }
496 
IsNodeDisabled() const497 bool DOMNode::IsNodeDisabled() const
498 {
499     return declaration_ ? declaration_->IsDisabled() : false;
500 }
501 
ResetDefaultStyles()502 void DOMNode::ResetDefaultStyles()
503 {
504     if (declaration_) {
505         declaration_->ResetDefaultStyles();
506     }
507 
508     displayComponent_.Reset();
509     if (transformComponent_) {
510         transformComponent_->ResetTransform();
511     }
512 }
513 
UpdatePseudoStyleByStatus(int32_t status,bool isBackendChange)514 void DOMNode::UpdatePseudoStyleByStatus(int32_t status, bool isBackendChange)
515 {
516     std::unordered_map<std::string, std::string> matchedStyleMap;
517     do {
518         if (pseudoClassStyleMap_.empty()) {
519             break;
520         }
521         // first:use status as the key, search the complete matched;
522         // second:if first do not matched any, calculate the max value of key & status, select the max value one.
523         auto matchedStyle = pseudoClassStyleMap_.find(status);
524         if (matchedStyle != pseudoClassStyleMap_.end()) {
525             matchedStyleMap = matchedStyle->second;
526         } else {
527             uint32_t maxAndResult = 0;
528             uint32_t maxValueKey = pseudoClassStyleMap_.begin()->first;
529             // status & map key, select the max result one
530             for (const auto& pseudoClass : pseudoClassStyleMap_) {
531                 uint32_t key = pseudoClass.first;
532                 uint32_t andResult = key & static_cast<uint32_t>(status);
533                 if (andResult > maxAndResult) {
534                     maxAndResult = andResult;
535                     maxValueKey = key;
536                 }
537             }
538             // if matched style except none pseudo style
539             auto iter = pseudoClassStyleMap_.find(maxValueKey);
540             if (maxAndResult > 0 && iter != pseudoClassStyleMap_.end()) {
541                 matchedStyleMap = iter->second;
542             }
543         }
544     } while (0);
545 
546     ResetDefaultStyles();
547     ResetInitializedStyle();
548 
549     // if not none pseudo style, need set none pseudo style first.
550     auto nonePseudoStylesIter = pseudoClassStyleMap_.find(STATE_NORMAL);
551     if (status != STATE_NORMAL && nonePseudoStylesIter != pseudoClassStyleMap_.end()) {
552         for (const auto& noneTypeStyle : nonePseudoStylesIter->second) {
553             if (!SetCurrentStyle(noneTypeStyle)) {
554                 declaration_->SetCurrentStyle(noneTypeStyle);
555             }
556         }
557     }
558     for (const auto& style : matchedStyleMap) {
559         if (!SetCurrentStyle(style)) {
560             declaration_->SetCurrentStyle(style);
561         }
562     }
563 
564     // do not move this for block into the up one
565     for (const auto& style : matchedStyleMap) {
566         if (style.first == DOM_TRANSITION_NAME) {
567             if (isTransitionNameUpdateFirst_) {
568                 isTransitionNameUpdateFirst_ = false;
569             } else {
570                 ParseTransitionNameStyle(style.second);
571                 propTransitionOption_ = TweenOption();
572                 TransitionOptionSetKeyframes(propTransitionOption_);
573                 transitionStyleUpdated_ = true;
574             }
575         }
576         if (style.first == DOM_TRANSITION_PROPERTY_DURATION) {
577             if (isTransitionDurationUpdateFirst_) {
578                 isTransitionDurationUpdateFirst_ = false;
579             } else {
580                 CreatePropertyAnimation(transitionPropertyName_);
581                 propTransitionOption_ = TweenOption();
582                 TransitionOptionSetKeyframes(propTransitionOption_);
583                 transitionStyleUpdated_ = true;
584             }
585         }
586     }
587     if (isBackendChange) {
588         auto pipelineContext = pipelineContext_.Upgrade();
589         if (!pipelineContext) {
590             return;
591         }
592         if (GetTag() != DOM_NODE_TAG_SPAN) {
593             UpdateUiComponents();
594         }
595         UpdateSpecializedComponentWithDeclaration();
596         PrepareSpecializedComponent();
597         CompositeComponents();
598         rootComponent_->MarkNeedUpdate();
599         rootComponent_->SetUpdateType(UpdateType::STYLE);
600         pipelineContext->ScheduleUpdate(rootComponent_);
601     }
602 }
603 
CalculatePseudoStatus() const604 uint32_t DOMNode::CalculatePseudoStatus() const
605 {
606     uint32_t status = STATE_NORMAL;
607     if (!declaration_) {
608         return STATE_NORMAL;
609     }
610     if (isActive_) {
611         status |= STATE_ACTIVE;
612     }
613     if (declaration_->IsDisabled()) {
614         status |= STATE_DISABLED;
615     }
616     if (isFocus_) {
617         status |= STATE_FOCUS;
618     }
619     if (declaration_->IsChecked()) {
620         status |= STATE_CHECKED;
621     }
622     if (declaration_->IsWaiting()) {
623         status |= STATE_WAITING;
624     }
625     if (declaration_->IsHover()) {
626         status |= STATE_HOVERED;
627     }
628     return status;
629 }
630 
UpdateStyleWithChildren()631 void DOMNode::UpdateStyleWithChildren()
632 {
633     auto status = CalculatePseudoStatus();
634     UpdatePseudoStyleByStatus(status, true);
635     SetAttrInternal(attributesCache_);
636 
637     for (const auto& child : children_) {
638         if (child) {
639             child->UpdateStyleWithChildren();
640         }
641     }
642 }
643 
UpdatePseudoStyle(bool isBackendChange)644 void DOMNode::UpdatePseudoStyle(bool isBackendChange)
645 {
646     if (!HasPseudo()) {
647         return;
648     }
649     auto status = CalculatePseudoStatus();
650     if (!isBackendChange) {
651         UpdatePseudoStyleByStatus(status, false);
652         return;
653     }
654     // Triggered by backend, elements may processing build or layout now. So post a new task to UI thread.
655     auto context = GetPipelineContext().Upgrade();
656     if (!context || !context->GetTaskExecutor()) {
657         return;
658     }
659     context->GetTaskExecutor()->PostTask(
660         [weak = AceType::WeakClaim(this), status = status]() {
661             auto node = weak.Upgrade();
662             if (!node) {
663                 return;
664             }
665             node->UpdatePseudoStyleByStatus(status, true);
666         },
667         TaskExecutor::TaskType::UI);
668 }
669 
CachePseudoClassStyle(const std::pair<std::string,std::string> & pseudoClassStyle)670 void DOMNode::CachePseudoClassStyle(const std::pair<std::string, std::string>& pseudoClassStyle)
671 {
672     uint32_t pseudoClassType = STATE_NORMAL;
673     const auto& styleKey = pseudoClassStyle.first;
674 
675     if (styleKey.find(DOM_ACTIVE_PSEUDO_CLASS) != std::string::npos) {
676         pseudoClassType |= STATE_ACTIVE;
677     }
678 
679     if (styleKey.find(DOM_DISABLED_PSEUDO_CLASS) != std::string::npos) {
680         pseudoClassType |= STATE_DISABLED;
681     }
682 
683     if (styleKey.find(DOM_FOCUS_PSEUDO_CLASS) != std::string::npos) {
684         pseudoClassType |= STATE_FOCUS;
685     }
686 
687     if (styleKey.find(DOM_CHECKED_PSEUDO_CLASS) != std::string::npos) {
688         pseudoClassType |= STATE_CHECKED;
689     }
690 
691     if (styleKey.find(DOM_WAITING_PSEUDO_CLASS) != std::string::npos) {
692         pseudoClassType |= STATE_WAITING;
693     }
694 
695     if (styleKey.find(DOM_HOVER_PSEUDO_CLASS) != std::string::npos) {
696         pseudoClassType |= STATE_HOVERED;
697     }
698 
699     cachedPseudoType_ |= pseudoClassType;
700 
701     auto pseudoSymbolLocation = styleKey.find(DOM_PSEUDO_CLASS_SYMBOL);
702     auto dealedStyleKey =
703         ((pseudoSymbolLocation != std::string::npos) ? styleKey.substr(0, pseudoSymbolLocation) : styleKey);
704 
705     auto styleMapIter = pseudoClassStyleMap_.find(pseudoClassType);
706 
707     if (styleMapIter != pseudoClassStyleMap_.end()) {
708         auto result = styleMapIter->second.try_emplace(dealedStyleKey, pseudoClassStyle.second);
709         if (!result.second) {
710             result.first->second = pseudoClassStyle.second;
711         }
712         return;
713     }
714     std::unordered_map<std::string, std::string> newPseudoMap;
715     newPseudoMap.emplace(dealedStyleKey, pseudoClassStyle.second);
716     pseudoClassStyleMap_.emplace(pseudoClassType, newPseudoMap);
717 }
718 
GenerateComponentNode()719 void DOMNode::GenerateComponentNode()
720 {
721     UpdatePseudoStyle(false);
722     if (GetTag() != DOM_NODE_TAG_SPAN) {
723         UpdateUiComponents();
724         UpdateTouchEventComponent();
725         UpdateGestureEventComponent();
726         UpdateMouseEventComponent();
727         UpdateFocusableEventComponents();
728         // Prepare for fixed position
729         UpdatePositionComponent();
730 #ifndef WEARABLE_PRODUCT
731         UpdateMultimodalComponent();
732         PrepareScrollComponent();
733 #endif
734     }
735     UpdateSpecializedComponentWithDeclaration();
736     PrepareSpecializedComponent();
737     CompositeComponents();
738     // Relative and absolute position needs to update the top component props.
739     UpdatePositionProps();
740     auto rootChild = AceType::DynamicCast<RenderComponent>(rootComponent_->GetChild());
741     if (isCustomComponent_) {
742         if (rootChild) {
743             rootChild->SetIsCustomComponent(isCustomComponent_);
744             rootChild->SetOnLayoutReadyMarker(EventMarker(GetNodeIdForEvent(), ""));
745         }
746     }
747     if (rootChild) {
748         int32_t zIndex = 0;
749         if (declaration_) {
750             auto& commonStyle = static_cast<CommonStyle&>(declaration_->GetStyle(StyleTag::COMMON_STYLE));
751             if (commonStyle.IsValid()) {
752                 zIndex = commonStyle.zIndex;
753             }
754         }
755         rootChild->SetZIndex(zIndex);
756     }
757     rootComponent_->MarkNeedUpdate();
758 }
759 
AddNode(const RefPtr<DOMNode> & node,int32_t slot)760 void DOMNode::AddNode(const RefPtr<DOMNode>& node, int32_t slot)
761 {
762     if (!node) {
763         return;
764     }
765     auto isExist = std::find_if(children_.begin(), children_.end(),
766         [node](const RefPtr<DOMNode>& child) { return child->GetNodeId() == node->GetNodeId(); });
767     if (isExist != children_.end()) {
768         LOGW("the node[%{public}d] has already in the children", node->GetNodeId());
769         return;
770     }
771     auto pos = children_.begin();
772     std::advance(pos, slot);
773     children_.insert(pos, node);
774     if (node->GetPosition() != PositionType::PTFIXED) {
775         if (!node->IsProxy() && GetDisplay() == DisplayType::NONE) {
776             node->GenerateComponentNode();
777         }
778         OnChildNodeAdded(node, slot);
779     }
780 }
781 
RemoveNode(const RefPtr<DOMNode> & node)782 void DOMNode::RemoveNode(const RefPtr<DOMNode>& node)
783 {
784     if (!node) {
785         return;
786     }
787     children_.remove_if([node](const RefPtr<DOMNode>& child) { return node->GetNodeId() == child->GetNodeId(); });
788     if (node->GetPosition() != PositionType::PTFIXED) {
789         OnChildNodeRemoved(node);
790     }
791 }
792 
SetDisplayStyle()793 void DOMNode::SetDisplayStyle()
794 {
795     switch (GetDisplay()) {
796         case DisplayType::NONE:
797             visible_ = VisibleType::GONE;
798             break;
799         case DisplayType::GRID:
800         case DisplayType::FLEX:
801         default:
802             VisibilityType visibility = VisibilityType::NO_SETTING;
803             if (declaration_) {
804                 auto& visibilityStyle =
805                     static_cast<CommonVisibilityStyle&>(declaration_->GetStyle(StyleTag::COMMON_VISIBILITY_STYLE));
806                 if (visibilityStyle.IsValid()) {
807                     visibility = visibilityStyle.visibility;
808                 }
809             }
810             visible_ = (visibility == VisibilityType::HIDDEN) ? VisibleType::INVISIBLE : VisibleType::VISIBLE;
811             break;
812     }
813 }
814 
BuildTransitionComponent()815 const RefPtr<PageTransitionComponent>& DOMNode::BuildTransitionComponent()
816 {
817     transitionComponent_ = AceType::MakeRefPtr<PageTransitionComponent>();
818     if (!declaration_) {
819         return transitionComponent_;
820     }
821 
822     transitionComponent_->SetTextDirection(declaration_->IsRightToLeft() ? TextDirection::RTL : TextDirection::LTR);
823     auto& pageTransitionStyle =
824         declaration_->MaybeResetStyle<CommonPageTransitionStyle>(StyleTag::COMMON_PAGE_TRANSITION_STYLE);
825     if (!pageTransitionStyle.IsValid()) {
826         return transitionComponent_;
827     }
828     if (pageTransitionStyle.transitionEnterOption.IsValid() || pageTransitionStyle.transitionExitOption.IsValid()) {
829         if (!pageTransitionStyle.transitionEnterOption.GetCurve()) {
830             // use FRICTION as transition default curve.
831             pageTransitionStyle.transitionEnterOption.SetCurve(Curves::FRICTION);
832             pageTransitionStyle.transitionExitOption.SetCurve(Curves::FRICTION);
833         }
834         transitionComponent_->SetContentTransitionOption(
835             pageTransitionStyle.transitionEnterOption, pageTransitionStyle.transitionExitOption);
836     }
837     return transitionComponent_;
838 }
839 
GetTransformType(const std::unique_ptr<JsonValue> & transformJson)840 std::string DOMNode::GetTransformType(const std::unique_ptr<JsonValue>& transformJson)
841 {
842     if (transformJson->IsNull()) {
843         return "";
844     }
845     return transformJson->GetKey();
846 }
847 
GetTransformTypeValue(const std::unique_ptr<JsonValue> & transformJson)848 std::string DOMNode::GetTransformTypeValue(const std::unique_ptr<JsonValue>& transformJson)
849 {
850     if (transformJson->IsNull()) {
851         return "";
852     }
853     std::string jsonValue = transformJson->GetString();
854     if (jsonValue.empty()) {
855         double jsonDouble = transformJson->GetDouble();
856         return std::to_string(jsonDouble);
857     }
858     return jsonValue;
859 }
860 
SetTransform(const std::string & value,DOMNode & node)861 void DOMNode::SetTransform(const std::string& value, DOMNode& node)
862 {
863     if (!node.transformComponent_) {
864         node.transformComponent_ = AceType::MakeRefPtr<TransformComponent>();
865     }
866     node.transformComponent_->ResetTransform(); // Avoid transform effect overlay.
867     auto jsonValue = node.GetTransformJsonValue(value);
868     std::unique_ptr<JsonValue> transformJson = JsonUtil::ParseJsonString(jsonValue);
869     for (int32_t index = 0; index < transformJson->GetArraySize(); ++index) {
870         std::string typeKey = node.GetTransformType(transformJson->GetArrayItem(index));
871         std::string typeValue = node.GetTransformTypeValue(transformJson->GetArrayItem(index));
872         if ((!typeKey.empty()) && (!typeValue.empty())) {
873             // Operator map for transform
874             static const std::unordered_map<std::string, void (*)(const std::string&, DOMNode&)> transformOperators = {
875                 { DOM_ROTATE,
876                     [](const std::string& typeValue, DOMNode& node) {
877                         node.transformComponent_->RotateZ(StringUtils::StringToDegree(typeValue));
878                     } },
879                 { DOM_ROTATE_3D,
880                     [](const std::string& typeValue, DOMNode& node) {
881                         std::vector<std::string> offsets;
882                         StringUtils::StringSplitter(typeValue, ' ', offsets);
883                         if (offsets.size() == FOUR_VALUES) {
884                             auto dx = StringToDouble(offsets[0]);
885                             auto dy = StringToDouble(offsets[1]);
886                             auto dz = StringToDouble(offsets[2]);
887                             auto degree = StringUtils::StringToDegree(offsets[3]);
888                             node.transformComponent_->Rotate(dx, dy, dz, degree);
889                         }
890                     } },
891                 { DOM_ROTATE_X,
892                     [](const std::string& typeValue, DOMNode& node) {
893                         node.transformComponent_->RotateX(StringUtils::StringToDegree(typeValue));
894                     } },
895                 { DOM_ROTATE_Y,
896                     [](const std::string& typeValue, DOMNode& node) {
897                         node.transformComponent_->RotateY(StringUtils::StringToDegree(typeValue));
898                     } },
899                 { DOM_ROTATE_Z,
900                     [](const std::string& typeValue, DOMNode& node) {
901                         node.transformComponent_->RotateZ(StringUtils::StringToDegree(typeValue));
902                     } },
903                 { SCALE,
904                     [](const std::string& typeValue, DOMNode& node) {
905                         if (typeValue.find(' ', 0) != std::string::npos) {
906                             Offset offset = ConvertStrToOffset(typeValue);
907                             node.transformComponent_->Scale(offset.GetX(), offset.GetY());
908                         } else {
909                             auto scaleValue = StringToDouble(typeValue);
910                             node.transformComponent_->Scale(scaleValue, scaleValue);
911                         }
912                     } },
913                 { DOM_SCALE_3D,
914                     [](const std::string& typeValue, DOMNode& node) {
915                         std::vector<std::string> offsets;
916                         StringUtils::StringSplitter(typeValue, ' ', offsets);
917                         if (offsets.size() == THREE_VALUES) {
918                             auto scaleX = StringToDouble(offsets[0]);
919                             auto scaleY = StringToDouble(offsets[1]);
920                             auto scaleZ = StringToDouble(offsets[2]);
921                             node.transformComponent_->Scale(scaleX, scaleY, scaleZ);
922                         }
923                     } },
924                 { DOM_SCALE_X, [](const std::string& typeValue,
925                                    DOMNode& node) { node.transformComponent_->ScaleX(StringToDouble(typeValue)); } },
926                 { DOM_SCALE_Y, [](const std::string& typeValue,
927                                    DOMNode& node) { node.transformComponent_->ScaleY(StringToDouble(typeValue)); } },
928                 { DOM_SCALE_Z, [](const std::string& typeValue,
929                                    DOMNode& node) { node.transformComponent_->ScaleZ(StringToDouble(typeValue)); } },
930                 { DOM_TRANSLATE,
931                     [](const std::string& typeValue, DOMNode& node) {
932                         std::vector<std::string> offsets;
933                         StringUtils::StringSplitter(typeValue, ' ', offsets);
934                         if (offsets.size() == TRANSFORM_DUAL) {
935                             node.transformComponent_->Translate(
936                                 node.ParseDimension(offsets[0]), node.ParseDimension(offsets[1]));
937                         } else if (offsets.size() == TRANSFORM_SINGLE) {
938                             node.transformComponent_->TranslateX(node.ParseDimension(offsets[0]));
939                         }
940                     } },
941                 { DOM_TRANSLATE_3D,
942                     [](const std::string& typeValue, DOMNode& node) {
943                         std::vector<std::string> offsets;
944                         StringUtils::StringSplitter(typeValue, ' ', offsets);
945                         if (offsets.size() == THREE_VALUES) {
946                             auto dx = node.ParseDimension(offsets[0]);
947                             auto dy = node.ParseDimension(offsets[1]);
948                             auto dz = node.ParseDimension(offsets[2]);
949                             node.transformComponent_->Translate(dx, dy, dz);
950                         }
951                     } },
952                 { DOM_TRANSLATE_X,
953                     [](const std::string& typeValue, DOMNode& node) {
954                         node.transformComponent_->TranslateX(node.ParseDimension(typeValue));
955                     } },
956                 { DOM_TRANSLATE_Y,
957                     [](const std::string& typeValue, DOMNode& node) {
958                         node.transformComponent_->TranslateY(node.ParseDimension(typeValue));
959                     } },
960                 { DOM_TRANSLATE_Z,
961                     [](const std::string& typeValue, DOMNode& node) {
962                         node.transformComponent_->TranslateZ(node.ParseDimension(typeValue));
963                     } },
964                 { DOM_SKEW,
965                     [](const std::string& typeValue, DOMNode& node) {
966                         std::vector<std::string> offsets;
967                         StringUtils::StringSplitter(typeValue, ' ', offsets);
968                         if (offsets.size() == TRANSFORM_DUAL) {
969                             auto degreeX = StringUtils::StringToDegree(offsets[0]);
970                             auto degreeY = StringUtils::StringToDegree(offsets[1]);
971                             node.transformComponent_->Skew(degreeX, degreeY);
972                         } else if (offsets.size() == TRANSFORM_SINGLE) {
973                             auto degree = StringUtils::StringToDegree(typeValue);
974                             node.transformComponent_->Skew(degree, 0.0f);
975                         }
976                     } },
977                 { DOM_SKEW_X,
978                     [](const std::string& typeValue, DOMNode& node) {
979                         node.transformComponent_->SkewX(StringUtils::StringToDegree(typeValue));
980                     } },
981                 { DOM_SKEW_Y,
982                     [](const std::string& typeValue, DOMNode& node) {
983                         node.transformComponent_->SkewY(StringUtils::StringToDegree(typeValue));
984                     } },
985                 { DOM_MATRIX,
986                     [](const std::string& typeValue, DOMNode& node) {
987                         std::vector<std::string> offsets;
988                         StringUtils::StringSplitter(typeValue, ' ', offsets);
989                         if (offsets.size() == TRANSFORM_SIX) {
990                             double scaleX = StringToDouble(offsets[0]);
991                             double skewY = StringToDouble(offsets[1]);
992                             double skewX = StringToDouble(offsets[2]);
993                             double scaleY = StringToDouble(offsets[3]);
994                             double translateX = StringToDouble(offsets[4]);
995                             double translateY = StringToDouble(offsets[5]);
996                             node.transformComponent_->Matrix(scaleX, skewY, skewX, scaleY, translateX, translateY);
997                         }
998                     } },
999                 { DOM_MATRIX_3D,
1000                     [](const std::string& typeValue, DOMNode& node) {
1001                         std::vector<std::string> offsets;
1002                         StringUtils::StringSplitter(typeValue, ' ', offsets);
1003                         if (offsets.size() == TRANSFORM_SIXTEEN) {
1004                             std::vector<double> matrix;
1005                             for (const auto& offset : offsets) {
1006                                 matrix.push_back(StringToDouble(offset));
1007                             }
1008                             node.transformComponent_->Matrix3d(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4],
1009                                 matrix[5], matrix[6], matrix[7], matrix[8], matrix[9], matrix[10], matrix[11],
1010                                 matrix[12], matrix[13], matrix[14], matrix[15]);
1011                         }
1012                     } },
1013                 { DOM_PERSPECTIVE,
1014                     [](const std::string& typeValue, DOMNode& node) {
1015                         node.transformComponent_->Perspective(node.ParseDimension(typeValue));
1016                     } },
1017             };
1018 
1019             auto operatorIter = transformOperators.find(typeKey);
1020             if (operatorIter != transformOperators.end()) {
1021                 operatorIter->second(typeValue, node);
1022             }
1023         }
1024     }
1025 }
1026 
1027 // Convert transform style to json format, such as rotate(50deg) to {"rotate":"50deg"}
GetTransformJsonValue(const std::string & value)1028 std::string DOMNode::GetTransformJsonValue(const std::string& value)
1029 {
1030     auto jsonValue = JsonUtil::Create(true);
1031     std::vector<std::string> subValues;
1032     StringUtils::StringSplitter(value, ' ', subValues);
1033     for (const auto& subValue : subValues) {
1034         auto rightIndex = subValue.find('(');
1035         auto leftIndex = subValue.find(')');
1036 
1037         if (rightIndex != std::string::npos && leftIndex != std::string::npos && (leftIndex - 1 - rightIndex > 0)) {
1038             std::string transformType = subValue.substr(0, rightIndex);
1039             std::string transformValue = subValue.substr(rightIndex + 1, leftIndex - 1 - rightIndex);
1040             jsonValue->Put(transformType.c_str(), transformValue.c_str());
1041         } else {
1042             return value;
1043         }
1044     }
1045 
1046     return jsonValue->ToString();
1047 }
1048 
AddKeyframe(double time,double typeValue,RefPtr<KeyframeAnimation<float>> & transformKeyframes)1049 void DOMNode::AddKeyframe(double time, double typeValue, RefPtr<KeyframeAnimation<float>>& transformKeyframes)
1050 {
1051     auto keyframe = AceType::MakeRefPtr<Keyframe<float>>(time, typeValue);
1052     transformKeyframes->AddKeyframe(keyframe);
1053 }
1054 
AddKeyframe(double time,const std::string & typeValue,RefPtr<KeyframeAnimation<float>> & transformKeyframes)1055 void DOMNode::AddKeyframe(
1056     double time, const std::string& typeValue, RefPtr<KeyframeAnimation<float>>& transformKeyframes)
1057 {
1058     DOMNode::AddKeyframe(time, StringToDouble(typeValue), transformKeyframes);
1059 }
1060 
SetSharedTransitionStyle(const std::vector<std::unordered_map<std::string,std::string>> & animationKeyframes)1061 void DOMNode::SetSharedTransitionStyle(
1062     const std::vector<std::unordered_map<std::string, std::string>>& animationKeyframes)
1063 {
1064     if (!declaration_) {
1065         return;
1066     }
1067     auto& shareTransitionStyle =
1068         declaration_->MaybeResetStyle<CommonShareTransitionStyle>(StyleTag::COMMON_SHARE_TRANSITION_STYLE);
1069     if (!shareTransitionStyle.IsValid()) {
1070         return;
1071     }
1072     if (!ParseAnimationStyle(animationKeyframes)) {
1073         return;
1074     }
1075     shareTransitionStyle.sharedTransitionOption = TweenOption();
1076     TweenOptionSetKeyframes(shareTransitionStyle.sharedTransitionOption);
1077 }
1078 
ParseAnimationStyle(const std::vector<std::unordered_map<std::string,std::string>> & animationKeyframes)1079 bool DOMNode::ParseAnimationStyle(const std::vector<std::unordered_map<std::string, std::string>>& animationKeyframes)
1080 {
1081     if (animationKeyframes.empty()) {
1082         return false;
1083     }
1084     animationUtil_.ParseAnimationStyle(animationKeyframes, declaration_, GetThemeConstants());
1085     propAnimations_ = animationUtil_.GetPropAnimationMap();
1086     animationName_ = animationUtil_.GetAnimationName();
1087 
1088     if (propAnimations_.find(AnimatableType::PROPERTY_OPACITY) != propAnimations_.end()) {
1089         if (declaration_) {
1090             declaration_->SetHasDisplayStyle(true);
1091         }
1092     }
1093     return true;
1094 }
1095 
SetAnimationStyle(const std::vector<std::unordered_map<std::string,std::string>> & animationKeyframes)1096 void DOMNode::SetAnimationStyle(const std::vector<std::unordered_map<std::string, std::string>>& animationKeyframes)
1097 {
1098     if (!declaration_ || !ParseAnimationStyle(animationKeyframes)) {
1099         return;
1100     }
1101     if (isTransition_) {
1102         auto& pageTransitionStyle =
1103             declaration_->MaybeResetStyle<CommonPageTransitionStyle>(StyleTag::COMMON_PAGE_TRANSITION_STYLE);
1104         if (pageTransitionStyle.IsValid()) {
1105             if (isEnter_) {
1106                 TweenOptionSetKeyframes(pageTransitionStyle.transitionEnterOption);
1107             } else {
1108                 TweenOptionSetKeyframes(pageTransitionStyle.transitionExitOption);
1109             }
1110         }
1111     } else {
1112         auto& animationStyle = declaration_->MaybeResetStyle<CommonAnimationStyle>(StyleTag::COMMON_ANIMATION_STYLE);
1113         if (animationStyle.IsValid()) {
1114             animationStyle.tweenOption = TweenOption();
1115             TweenOptionSetKeyframes(animationStyle.tweenOption);
1116             animationStyleUpdated_ = true;
1117         }
1118     }
1119 }
1120 
UpdatePropAnimations(const PropAnimationMap & animations)1121 void DOMNode::UpdatePropAnimations(const PropAnimationMap& animations)
1122 {
1123     if (boxComponent_ != nullptr) {
1124         boxComponent_->ClearAnimatables();
1125     }
1126     if (displayComponent_ != nullptr) {
1127         displayComponent_->ClearAnimatables();
1128     }
1129     for (const auto& [type, animation] : animations) {
1130         switch (type) {
1131             case AnimatableType::PROPERTY_WIDTH:
1132             case AnimatableType::PROPERTY_HEIGHT:
1133             case AnimatableType::PROPERTY_BG_COLOR:
1134             case AnimatableType::PROPERTY_MARGIN_LEFT:
1135             case AnimatableType::PROPERTY_MARGIN_TOP:
1136             case AnimatableType::PROPERTY_MARGIN_RIGHT:
1137             case AnimatableType::PROPERTY_MARGIN_BOTTOM:
1138             case AnimatableType::PROPERTY_PADDING_LEFT:
1139             case AnimatableType::PROPERTY_PADDING_TOP:
1140             case AnimatableType::PROPERTY_PADDING_RIGHT:
1141             case AnimatableType::PROPERTY_PADDING_BOTTOM:
1142             case AnimatableType::PROPERTY_BACKGROUND_POSITION:
1143             case AnimatableType::PROPERTY_BACKGROUND_SIZE:
1144             case AnimatableType::PROPERTY_BORDER_LEFT_WIDTH:
1145             case AnimatableType::PROPERTY_BORDER_TOP_WIDTH:
1146             case AnimatableType::PROPERTY_BORDER_RIGHT_WIDTH:
1147             case AnimatableType::PROPERTY_BORDER_BOTTOM_WIDTH:
1148             case AnimatableType::PROPERTY_BORDER_LEFT_COLOR:
1149             case AnimatableType::PROPERTY_BORDER_TOP_COLOR:
1150             case AnimatableType::PROPERTY_BORDER_RIGHT_COLOR:
1151             case AnimatableType::PROPERTY_BORDER_BOTTOM_COLOR:
1152             case AnimatableType::PROPERTY_BORDER_TOP_LEFT_RADIUS:
1153             case AnimatableType::PROPERTY_BORDER_TOP_RIGHT_RADIUS:
1154             case AnimatableType::PROPERTY_BORDER_BOTTOM_LEFT_RADIUS:
1155             case AnimatableType::PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS:
1156             case AnimatableType::PROPERTY_BORDER_LEFT_STYLE:
1157             case AnimatableType::PROPERTY_BORDER_RIGHT_STYLE:
1158             case AnimatableType::PROPERTY_BORDER_TOP_STYLE:
1159             case AnimatableType::PROPERTY_BORDER_BOTTOM_STYLE:
1160             case AnimatableType::PROPERTY_FILTER_BLUR:
1161             case AnimatableType::PROPERTY_BACKDROP_FILTER_BLUR:
1162             case AnimatableType::PROPERTY_WINDOW_FILTER_BLUR:
1163             case AnimatableType::PROPERTY_BOX_SHADOW: {
1164                 if (boxComponent_ != nullptr) {
1165                     boxComponent_->AddAnimatable(type, animation);
1166                 }
1167                 break;
1168             }
1169             case AnimatableType::PROPERTY_OPACITY: {
1170                 if (displayComponent_ != nullptr) {
1171                     displayComponent_->AddAnimatable(type, animation);
1172                 }
1173                 break;
1174             }
1175             default:
1176                 break;
1177         }
1178     }
1179 }
1180 
UpdatePositionAnimations(const RefPtr<Component> component)1181 void DOMNode::UpdatePositionAnimations(const RefPtr<Component> component)
1182 {
1183     if (component != nullptr) {
1184         static const AnimatableType positionAnimatableType[] = {
1185             AnimatableType::PROPERTY_POSITION_LEFT,
1186             AnimatableType::PROPERTY_POSITION_TOP,
1187             AnimatableType::PROPERTY_POSITION_RIGHT,
1188             AnimatableType::PROPERTY_POSITION_BOTTOM,
1189         };
1190 
1191         for (const auto& type : positionAnimatableType) {
1192             const auto& animation = propAnimations_[type];
1193             if (animation) {
1194                 component->AddAnimatable(type, animation);
1195             }
1196         }
1197     }
1198 }
1199 
TweenOptionSetKeyframes(TweenOption & tweenOption)1200 void DOMNode::TweenOptionSetKeyframes(TweenOption& tweenOption)
1201 {
1202     auto pos = propAnimations_.find(AnimatableType::PROPERTY_OPACITY);
1203     if (pos != propAnimations_.end()) {
1204         auto opacityAnimation = AceType::MakeRefPtr<KeyframeAnimation<float>>();
1205         for (auto& item : pos->second->GetAnimatable()) {
1206             auto opacityAnimatable = AceType::DynamicCast<AnimatableData<float>>(item);
1207             if (opacityAnimatable) {
1208                 opacityAnimation->AddKeyframe(
1209                     AceType::MakeRefPtr<Keyframe<float>>(item->GetTimePoint(), opacityAnimatable->GetValue()));
1210             }
1211         }
1212         tweenOption.SetOpacityAnimation(opacityAnimation);
1213         propAnimations_.erase(pos);
1214     }
1215     if (!propAnimations_.empty()) {
1216         tweenOption.SetAnimatables(propAnimations_);
1217     }
1218     animationUtil_.GetTransformConvertor().AddAnimationToTweenOption(tweenOption);
1219 }
1220 
SetCustomAnimationStyleUpdate(bool enable)1221 void DOMNode::SetCustomAnimationStyleUpdate(bool enable)
1222 {
1223     customAnimationStyleUpdated_ = enable;
1224 }
1225 
CompositeComponents()1226 void DOMNode::CompositeComponents()
1227 {
1228     std::vector<RefPtr<SingleChild>> components;
1229     if (flexItemComponent_) {
1230         // Update flex item after PrepareSpecializedComponent to make sure sub class has finished prepare.
1231         UpdateFlexItemComponent();
1232         components.emplace_back(flexItemComponent_);
1233     }
1234     if (tweenComponent_) {
1235         tweenComponent_->SetLeafNode(IsLeafNode());
1236         components.emplace_back(tweenComponent_);
1237     }
1238     if (displayComponent_) {
1239         displayComponent_->DisableLayer(IsLeafNode());
1240         components.emplace_back(displayComponent_);
1241         if (focusableEventComponent_) {
1242             focusableEventComponent_->SetShow(GetDisplay() != DisplayType::NONE);
1243         }
1244     }
1245     if (transformComponent_) {
1246         components.emplace_back(transformComponent_);
1247     }
1248     if (focusableEventComponent_) {
1249         components.emplace_back(focusableEventComponent_);
1250     }
1251     if (touchEventComponent_) {
1252         touchEventComponent_->SetIsVisible(visible_ == VisibleType::VISIBLE);
1253         components.emplace_back(touchEventComponent_);
1254     }
1255     if (gestureEventComponent_) {
1256         gestureEventComponent_->SetIsVisible(visible_ == VisibleType::VISIBLE);
1257         components.emplace_back(gestureEventComponent_);
1258     }
1259 #ifndef WEARABLE_PRODUCT
1260     if (multimodalComponent_) {
1261         components.emplace_back(multimodalComponent_);
1262     }
1263 #endif
1264     if (mouseEventComponent_) {
1265         components.emplace_back(mouseEventComponent_);
1266     }
1267     if (propTransitionComponent_) {
1268         components.emplace_back(propTransitionComponent_);
1269     }
1270     if (boxComponent_) {
1271         components.emplace_back(boxComponent_);
1272     }
1273     if (scrollComponent_) {
1274         components.emplace_back(scrollComponent_);
1275     }
1276     if (sharedTransitionComponent_) {
1277         components.emplace_back(sharedTransitionComponent_);
1278     }
1279 
1280     auto mainComponent = GetSpecializedComponent();
1281     if (!components.empty() &&
1282         (AceType::InstanceOf<TextureComponent>(mainComponent) ||
1283         AceType::InstanceOf<TextFieldComponent>(mainComponent) ||
1284         AceType::InstanceOf<ListComponent>(mainComponent) ||
1285         AceType::InstanceOf<ListItemComponent>(mainComponent) ||
1286         AceType::InstanceOf<WebComponent>(mainComponent) ||
1287         AceType::InstanceOf<XComponentComponent>(mainComponent))) {
1288         Component::MergeRSNode(components);
1289         Component::MergeRSNode(mainComponent);
1290     } else {
1291         Component::MergeRSNode(components, mainComponent);
1292     }
1293     // Only fixed position has position component
1294     if (positionComponent_ && GetPosition() == PositionType::PTFIXED) {
1295         components.emplace(components.begin(), positionComponent_);
1296         Component::MergeRSNode(positionComponent_);
1297     }
1298 
1299     // First, composite all common components.
1300     for (int32_t idx = static_cast<int32_t>(components.size()) - 1; idx - 1 >= 0; --idx) {
1301         components[idx - 1]->SetChild(DynamicCast<Component>(components[idx]));
1302     }
1303     // Then composite specialized components.
1304     auto compositeComponent = CompositeSpecializedComponent(components);
1305     // At last add to composite component.
1306     rootComponent_->SetChild(compositeComponent);
1307     // final set disabled status.
1308     if (declaration_ && declaration_->IsDisabled() != rootComponent_->IsDisabledStatus()) {
1309         rootComponent_->SetDisabledStatus(declaration_->IsDisabled());
1310     }
1311 }
1312 
SetDisplayType()1313 void DOMNode::SetDisplayType()
1314 {
1315     static std::unordered_map<std::string, DisplayType> types = {
1316         { DOM_NODE_TAG_DIV, DisplayType::FLEX },
1317         { DOM_NODE_TAG_BADGE, DisplayType::BLOCK },
1318         { DOM_NODE_TAG_DIALOG, DisplayType::BLOCK },
1319         { DOM_NODE_TAG_FORM, DisplayType::BLOCK },
1320         { DOM_NODE_TAG_LIST, DisplayType::BLOCK },
1321         { DOM_NODE_TAG_LIST_ITEM, DisplayType::BLOCK },
1322         { DOM_NODE_TAG_LIST_ITEM_GROUP, DisplayType::BLOCK },
1323         { DOM_NODE_TAG_PANEL, DisplayType::BLOCK },
1324         { DOM_NODE_TAG_POPUP, DisplayType::BLOCK },
1325         { DOM_NODE_TAG_REFRESH, DisplayType::BLOCK },
1326         { DOM_NODE_TAG_STACK, DisplayType::BLOCK },
1327         { DOM_NODE_TAG_STEPPER, DisplayType::BLOCK },
1328         { DOM_NODE_TAG_STEPPER_ITEM, DisplayType::BLOCK },
1329         { DOM_NODE_TAG_SWIPER, DisplayType::BLOCK },
1330         { DOM_NODE_TAG_TABS, DisplayType::BLOCK },
1331         { DOM_NODE_TAG_TAB_BAR, DisplayType::BLOCK },
1332         { DOM_NODE_TAG_TAB_CONTENT, DisplayType::BLOCK },
1333 
1334         { DOM_NODE_TAG_BUTTON, DisplayType::INLINE_BLOCK },
1335         { DOM_NODE_TAG_CHART, DisplayType::INLINE_BLOCK },
1336         { DOM_NODE_TAG_DIVIDER, DisplayType::INLINE_BLOCK },
1337         { DOM_NODE_TAG_IMAGE, DisplayType::INLINE_BLOCK },
1338         { DOM_NODE_TAG_IMAGE_ANIMATOR, DisplayType::INLINE_BLOCK },
1339         { DOM_NODE_TAG_INPUT, DisplayType::INLINE_BLOCK },
1340         { DOM_NODE_TAG_LABEL, DisplayType::INLINE_BLOCK },
1341         { DOM_NODE_TAG_MARQUEE, DisplayType::INLINE_BLOCK },
1342         { DOM_NODE_TAG_MENU, DisplayType::INLINE_BLOCK },
1343         { DOM_NODE_TAG_OPTION, DisplayType::INLINE_BLOCK },
1344         { DOM_NODE_TAG_PICKER_DIALOG, DisplayType::INLINE_BLOCK },
1345         { DOM_NODE_TAG_PICKER_VIEW, DisplayType::INLINE_BLOCK },
1346         { DOM_NODE_TAG_PIECE, DisplayType::INLINE_BLOCK },
1347         { DOM_NODE_TAG_PROGRESS, DisplayType::INLINE_BLOCK },
1348         { DOM_NODE_TAG_QRCODE, DisplayType::INLINE_BLOCK },
1349         { DOM_NODE_TAG_RATING, DisplayType::INLINE_BLOCK },
1350         { DOM_NODE_TAG_RICH_TEXT, DisplayType::INLINE_BLOCK },
1351         { DOM_NODE_TAG_SEARCH, DisplayType::INLINE_BLOCK },
1352         { DOM_NODE_TAG_SELECT, DisplayType::INLINE_BLOCK },
1353         { DOM_NODE_TAG_SLIDER, DisplayType::INLINE_BLOCK },
1354         { DOM_NODE_TAG_SPAN, DisplayType::INLINE_BLOCK },
1355         { DOM_NODE_TAG_SWITCH, DisplayType::INLINE_BLOCK },
1356         { DOM_NODE_TAG_TEXT, DisplayType::INLINE_BLOCK },
1357         { DOM_NODE_TAG_TEXTAREA, DisplayType::INLINE_BLOCK },
1358         { DOM_NODE_TAG_TOOL_BAR, DisplayType::INLINE_BLOCK },
1359         { DOM_NODE_TAG_TOOL_BAR_ITEM, DisplayType::INLINE_BLOCK },
1360         { DOM_NODE_TAG_TOGGLE, DisplayType::INLINE_BLOCK },
1361         { DOM_NODE_TAG_WEB, DisplayType::INLINE_BLOCK },
1362     };
1363     DisplayType displayType = GetDisplay();
1364     if (displayType == DisplayType::NO_SETTING) {
1365         auto item = types.find(GetTag());
1366         if (item != types.end()) {
1367             displayType = item->second;
1368         }
1369     }
1370     if (flexItemComponent_) {
1371         flexItemComponent_->SetDisplayType(displayType);
1372     }
1373     if (boxComponent_) {
1374         boxComponent_->SetDisplayType(displayType);
1375     }
1376 }
1377 
UpdateFlexItemComponent()1378 void DOMNode::UpdateFlexItemComponent()
1379 {
1380     if (!declaration_ || !flexItemComponent_) {
1381         return;
1382     }
1383 
1384     auto& flexStyle = static_cast<CommonFlexStyle&>(declaration_->GetStyle(StyleTag::COMMON_FLEX_STYLE));
1385     if (flexStyle.IsValid()) {
1386         flexItemComponent_->SetFlexGrow(flexStyle.flexGrow);
1387         flexItemComponent_->SetFlexShrink(flexStyle.flexShrink);
1388         flexItemComponent_->SetFlexBasis(flexStyle.flexBasis);
1389         flexItemComponent_->SetFlexWeight(flexStyle.flexWeight);
1390         flexItemComponent_->SetDisplayIndex(flexStyle.displayIndex);
1391     }
1392     const LinearMapNode<FlexAlign> ALIGN_SELF_TABLE[] = {
1393         { DOM_ALIGN_ITEMS_BASELINE, FlexAlign::BASELINE },
1394         { DOM_ALIGN_ITEMS_CENTER, FlexAlign::CENTER },
1395         { DOM_ALIGN_ITEMS_END, FlexAlign::FLEX_END },
1396         { DOM_ALIGN_ITEMS_START, FlexAlign::FLEX_START },
1397         { DOM_ALIGN_ITEMS_STRETCH, FlexAlign::STRETCH },
1398     };
1399     auto& commonStyle = static_cast<CommonStyle&>(declaration_->GetStyle(StyleTag::COMMON_STYLE));
1400     int64_t index = -1;
1401     if (commonStyle.IsValid()) {
1402         index = BinarySearchFindIndex(ALIGN_SELF_TABLE, ArraySize(ALIGN_SELF_TABLE), commonStyle.alignSelf.c_str());
1403     }
1404     if (index != -1) {
1405         flexItemComponent_->SetAlignSelf(ALIGN_SELF_TABLE[index].value);
1406     } else {
1407         flexItemComponent_->SetAlignSelf(FlexAlign::AUTO);
1408     }
1409     auto parentNode = parentNode_.Upgrade();
1410     if ((parentNode) &&
1411         (parentNode->GetTag() == DOM_NODE_TAG_DIV || parentNode->GetTag() == DOM_NODE_TAG_GRID_COLUMN)) {
1412         auto parent = AceType::DynamicCast<DOMDiv>(parentNode);
1413         // Stretch flag means that if the child's main size is determined, it can not be stretched.
1414         if (((parent->GetFlexDirection() == FlexDirection::ROW ||
1415                  parent->GetFlexDirection() == FlexDirection::ROW_REVERSE) &&
1416                  (GreatOrEqual(GetHeight().Value(), 0.0) || GetHeight().Unit() == DimensionUnit::CALC)) ||
1417             ((parent->GetFlexDirection() == FlexDirection::COLUMN ||
1418                  parent->GetFlexDirection() == FlexDirection::COLUMN_REVERSE) &&
1419                  (GreatOrEqual(GetWidth().Value(), 0.0) || GetWidth().Unit() == DimensionUnit::CALC))) {
1420             flexItemComponent_->SetStretchFlag(false);
1421         } else {
1422             flexItemComponent_->SetStretchFlag(true);
1423         }
1424     }
1425     auto& sizeStyle = static_cast<CommonSizeStyle&>(declaration_->GetStyle(StyleTag::COMMON_SIZE_STYLE));
1426     if (sizeStyle.IsValid()) {
1427         // Make sure input layout constraint is valid
1428         flexItemComponent_->SetMaxHeight(sizeStyle.maxHeight);
1429         flexItemComponent_->SetMaxWidth(sizeStyle.maxWidth);
1430         flexItemComponent_->SetMinHeight(sizeStyle.minHeight);
1431         flexItemComponent_->SetMinWidth(sizeStyle.minWidth);
1432         // If set aspect Ratio, it cannot be stretch
1433         if (GreatNotEqual(sizeStyle.aspectRatio, 0.0)) {
1434             flexItemComponent_->SetStretchFlag(false);
1435         }
1436     }
1437     // If set display, this flexItem is ignored.
1438     if (GetDisplay() == DisplayType::NONE) {
1439         flexItemComponent_->SetIsHidden(GetDisplay() == DisplayType::NONE);
1440     }
1441     SetDisplayType();
1442 }
1443 
UpdateUiComponents()1444 void DOMNode::UpdateUiComponents()
1445 {
1446     UpdateBoxComponent();
1447     UpdateDisplayComponent();
1448     UpdateTweenComponent();
1449 }
1450 
UpdateBoxSize(const CalcDimension & width,const CalcDimension & height)1451 void DOMNode::UpdateBoxSize(const CalcDimension& width, const CalcDimension& height)
1452 {
1453     if (height.Unit() == DimensionUnit::CALC) {
1454         boxComponent_->SetHeight(height.CalcValue(), height.Unit());
1455     } else {
1456         boxComponent_->SetHeight(height.Value(), height.Unit());
1457     }
1458     if (width.Unit() == DimensionUnit::CALC) {
1459         boxComponent_->SetWidth(width.CalcValue(), width.Unit());
1460     } else {
1461         boxComponent_->SetWidth(width.Value(), width.Unit());
1462     }
1463 }
1464 
UpdateBoxPadding(const Edge & padding)1465 void DOMNode::UpdateBoxPadding(const Edge& padding)
1466 {
1467     boxComponent_->SetPadding(padding);
1468 }
1469 
UpdateBoxBorder(const Border & border)1470 void DOMNode::UpdateBoxBorder(const Border& border)
1471 {
1472     if (declaration_ && declaration_->GetBackDecoration()) {
1473         declaration_->GetBackDecoration()->SetBorder(border);
1474     }
1475 }
1476 
UpdateBoxComponent()1477 void DOMNode::UpdateBoxComponent()
1478 {
1479     if (!declaration_) {
1480         return;
1481     }
1482 
1483     if (declaration_->HasBoxStyle()) {
1484         if (GetWidth().Unit() != DimensionUnit::CALC && GetHeight().Unit() != DimensionUnit::CALC) {
1485             UpdateBoxSize(GetWidth(), GetHeight());
1486         } else if (GetWidth().Unit() == DimensionUnit::CALC && GetHeight().Unit() != DimensionUnit::CALC) {
1487             UpdateBoxSize(GetCalcWidth(), GetHeight());
1488         } else if (GetWidth().Unit() != DimensionUnit::CALC && GetHeight().Unit() == DimensionUnit::CALC) {
1489             UpdateBoxSize(GetWidth(), GetCalcHeight());
1490         } else {
1491             UpdateBoxSize(GetCalcWidth(), GetCalcHeight());
1492         }
1493         auto& paddingStyle = static_cast<CommonPaddingStyle&>(declaration_->GetStyle(StyleTag::COMMON_PADDING_STYLE));
1494         if (paddingStyle.IsValid()) {
1495             UpdateBoxPadding(paddingStyle.padding);
1496         }
1497         auto& marginStyle = static_cast<CommonMarginStyle&>(declaration_->GetStyle(StyleTag::COMMON_MARGIN_STYLE));
1498         if (marginStyle.IsValid()) {
1499             boxComponent_->SetMargin(marginStyle.margin);
1500         }
1501         auto& commonStyle = static_cast<CommonStyle&>(declaration_->GetStyle(StyleTag::COMMON_STYLE));
1502         if (commonStyle.IsValid()) {
1503             boxComponent_->SetLayoutInBoxFlag(commonStyle.layoutInBox);
1504         }
1505     }
1506     SetDisplayType();
1507     auto& sizeStyle = static_cast<CommonSizeStyle&>(declaration_->GetStyle(StyleTag::COMMON_SIZE_STYLE));
1508     if (sizeStyle.IsValid()) {
1509         boxComponent_->SetAspectRatio(sizeStyle.aspectRatio);
1510     }
1511     if (flexItemComponent_) {
1512         boxComponent_->SetDeliverMinToChild(false);
1513         if (sizeStyle.IsValid()) {
1514             boxComponent_->SetMinWidth(sizeStyle.minWidth);
1515             boxComponent_->SetMinHeight(sizeStyle.minHeight);
1516             boxComponent_->SetMaxWidth(sizeStyle.maxWidth);
1517             boxComponent_->SetMaxHeight(sizeStyle.maxHeight);
1518             boxComponent_->SetBoxSizing(sizeStyle.boxSizing);
1519         }
1520     }
1521 
1522     if (declaration_->HasDecorationStyle()) {
1523         auto& borderStyle = declaration_->MaybeResetStyle<CommonBorderStyle>(StyleTag::COMMON_BORDER_STYLE);
1524         if (borderStyle.IsValid()) {
1525             UpdateBoxBorder(borderStyle.border);
1526         }
1527         auto& backDecoration = declaration_->GetBackDecoration();
1528         if (!declaration_->HasBackGroundColor() && boxComponent_->GetBackDecoration() &&
1529             boxComponent_->HasBackgroundColor()) {
1530             backDecoration->SetBackgroundColor(boxComponent_->GetBackDecoration()->GetBackgroundColor());
1531         }
1532 
1533         auto& backgroundStyle =
1534             static_cast<CommonBackgroundStyle&>(declaration_->GetStyle(StyleTag::COMMON_BACKGROUND_STYLE));
1535         if (backgroundStyle.IsValid() && backgroundStyle.gradient.IsValid()) {
1536             backDecoration->SetGradient(backgroundStyle.gradient);
1537         }
1538         if (backgroundStyle.IsValid() && backgroundStyle.gradientBorderImage.IsValid()) {
1539             backDecoration->SetBorderImageGradient(backgroundStyle.gradientBorderImage);
1540         }
1541 
1542         if (declaration_->HasShadowStyle()) {
1543             auto& shadowStyle = static_cast<CommonShadowStyle&>(declaration_->GetStyle(StyleTag::COMMON_SHADOW_STYLE));
1544             if (shadowStyle.IsValid()) {
1545                 backDecoration->ClearAllShadow();
1546                 backDecoration->AddShadow(shadowStyle.shadow);
1547             }
1548         }
1549         boxComponent_->SetBackDecoration(backDecoration);
1550     }
1551 
1552     if (declaration_->HasFrontDecorationStyle()) {
1553         boxComponent_->SetFrontDecoration(declaration_->GetFrontDecoration());
1554     }
1555     auto& overflowStyle = static_cast<CommonOverflowStyle&>(declaration_->GetStyle(StyleTag::COMMON_OVERFLOW_STYLE));
1556     if (overflowStyle.IsValid()) {
1557         boxComponent_->SetOverflow(overflowStyle.overflow);
1558     }
1559 
1560     boxComponent_->SetOnDomDragEnter(GetDragEnterId());
1561     boxComponent_->SetOnDomDragOver(GetDragOverId());
1562     boxComponent_->SetOnDomDragLeave(GetDragLeaveId());
1563     boxComponent_->SetOnDomDragDrop(GetDragDropId());
1564 
1565     auto& clipPathStyle = static_cast<CommonClipPathStyle&>(declaration_->GetStyle(StyleTag::COMMON_CLIP_PATH_STYLE));
1566     if (clipPathStyle.IsValid() && clipPathStyle.clipPath != nullptr) {
1567         boxComponent_->SetClipPath(clipPathStyle.clipPath);
1568     }
1569 
1570     auto& maskStyle = static_cast<CommonMaskStyle&>(declaration_->GetStyle(StyleTag::COMMON_MASK_STYLE));
1571     if (maskStyle.IsValid() && !maskStyle.maskImage.empty()) {
1572         BackgroundImagePosition position;
1573         if (!maskStyle.maskPosition.empty()) {
1574             ParseBackgroundImagePosition(maskStyle.maskPosition, position);
1575         }
1576 
1577         BackgroundImageSize size;
1578         if (!maskStyle.maskSize.empty()) {
1579             ParseBackgroundImageSize(maskStyle.maskSize, size);
1580         }
1581         boxComponent_->SetMask(maskStyle.maskImage, size, position);
1582     }
1583 }
1584 
PrepareScrollComponent()1585 void DOMNode::PrepareScrollComponent()
1586 {
1587     if (!declaration_) {
1588         return;
1589     }
1590 
1591     // div is specially handled.
1592     if (GetTag() == DOM_NODE_TAG_DIV) {
1593         return;
1594     }
1595     auto& overflowStyle = static_cast<CommonOverflowStyle&>(declaration_->GetStyle(StyleTag::COMMON_OVERFLOW_STYLE));
1596     if (!declaration_->HasOverflowStyle() || !overflowStyle.IsValid() || overflowStyle.overflow != Overflow::SCROLL) {
1597         return;
1598     }
1599     if (boxComponent_->GetWidthDimension().IsValid() && boxComponent_->GetHeightDimension().IsValid()) {
1600         if (!scrollComponent_) {
1601             scrollComponent_ = AceType::MakeRefPtr<ScrollComponent>(nullptr);
1602         }
1603         scrollComponent_->InitScrollBar(GetTheme<ScrollBarTheme>(), overflowStyle.scrollBarColor,
1604             overflowStyle.scrollBarWidth, overflowStyle.edgeEffect);
1605         declaration_->SetPositionController(scrollComponent_->GetScrollPositionController());
1606     }
1607 }
1608 
UpdateDisplayComponent()1609 void DOMNode::UpdateDisplayComponent()
1610 {
1611     if (!declaration_ || !declaration_->HasDisplayStyle()) {
1612         return;
1613     }
1614 
1615     if (!displayComponent_) {
1616         displayComponent_ = AceType::MakeRefPtr<DisplayComponent>(rootComponent_->GetChild());
1617     }
1618     auto& opacityStyle = static_cast<CommonOpacityStyle&>(declaration_->GetStyle(StyleTag::COMMON_OPACITY_STYLE));
1619     if (opacityStyle.IsValid()) {
1620         displayComponent_->SetOpacity(opacityStyle.opacity);
1621         displayComponent_->SetAppearingDuration(opacityStyle.appearingDuration);
1622     }
1623     auto context = pipelineContext_.Upgrade();
1624     if (!context) {
1625         return;
1626     }
1627     SetDisplayStyle();
1628     displayComponent_->SetVisible(visible_);
1629     bool show = (GetDisplay() != DisplayType::NONE);
1630     if (!focusableEventComponent_ && !show && !context->IsJsCard()) {
1631         focusableEventComponent_ = AceType::MakeRefPtr<FocusableComponent>();
1632         focusableEventComponent_->SetFocusable(true);
1633         declaration_->SetFocusableController(focusableEventComponent_->GetFocusableController());
1634     }
1635     if (focusableEventComponent_) {
1636         focusableEventComponent_->SetShow(show);
1637     }
1638     if (declaration_->HasShadowStyle()) {
1639         auto& shadowStyle = static_cast<CommonShadowStyle&>(declaration_->GetStyle(StyleTag::COMMON_SHADOW_STYLE));
1640         if (shadowStyle.IsValid()) {
1641             displayComponent_->SetShadow(shadowStyle.shadow);
1642         }
1643     }
1644 }
1645 
UpdateTweenComponent()1646 void DOMNode::UpdateTweenComponent()
1647 {
1648     if (transitionStyleUpdated_) {
1649         if (!propTransitionComponent_) {
1650             propTransitionComponent_ = AceType::MakeRefPtr<TransitionComponent>(TRANSITION_COMPONENT_PREFIX
1651                 + std::to_string(nodeId_), tag_);
1652         }
1653         propTransitionComponent_->SetTransitionOption(propTransitionOption_);
1654         transitionStyleUpdated_ = false;
1655     }
1656     if (!declaration_) {
1657         return;
1658     }
1659     if (declaration_->HasTransformStyle() && !transformComponent_) {
1660         transformComponent_ = AceType::MakeRefPtr<TransformComponent>();
1661     }
1662     auto& animationStyle = static_cast<CommonAnimationStyle&>(declaration_->GetStyle(StyleTag::COMMON_ANIMATION_STYLE));
1663     auto& shadowStyle = static_cast<CommonShadowStyle&>(declaration_->GetStyle(StyleTag::COMMON_SHADOW_STYLE));
1664     auto& clickEffectAttr =
1665         static_cast<CommonClickEffectAttribute&>(declaration_->GetAttribute(AttributeTag::COMMON_CLICK_EFFECT_ATTR));
1666     if (transformComponent_) {
1667         if (clickEffectAttr.IsValid()) {
1668             transformComponent_->SetClickSpringEffectType(clickEffectAttr.clickEffect);
1669         }
1670         if (animationStyle.IsValid()) {
1671             // Set transform style.
1672             if (declaration_->HasTransformOriginStyle()) {
1673                 transformComponent_->SetOriginDimension(
1674                     DimensionOffset(animationStyle.transformOriginX, animationStyle.transformOriginY));
1675             }
1676         }
1677 
1678         if (declaration_->HasShadowStyle() && shadowStyle.IsValid()) {
1679             transformComponent_->SetShadow(shadowStyle.shadow);
1680         }
1681 
1682         auto& cardTransitionStyle =
1683             static_cast<CommonCardTransitionStyle&>(declaration_->GetStyle(StyleTag::COMMON_CARD_TRANSITION_STYLE));
1684         if (cardTransitionStyle.IsValid()) {
1685             transformComponent_->SetTransitionEffect(cardTransitionStyle.transitionEffect);
1686         }
1687     }
1688 
1689     // Only check animation style here.
1690     if (animationStyle.IsValid() && animationStyle.tweenOption.IsValid() && animationStyleUpdated_) {
1691         if (!tweenComponent_) {
1692             tweenComponent_ = AceType::MakeRefPtr<TweenComponent>(COMPONENT_PREFIX + std::to_string(nodeId_), tag_);
1693         }
1694         tweenComponent_->SetTweenOption(animationStyle.tweenOption);
1695         tweenComponent_->UpdateAnimationName(animationName_);
1696         tweenComponent_->SetAnimationOperation(animationStyle.animationOperation);
1697         if (declaration_->HasShadowStyle() && shadowStyle.IsValid()) {
1698             tweenComponent_->SetShadow(shadowStyle.shadow);
1699         }
1700         UpdatePropAnimations(propAnimations_);
1701         animationStyleUpdated_ = false;
1702     }
1703     // for custom animation
1704     if (customAnimationStyleUpdated_) {
1705         UpdatePropAnimations(propAnimations_);
1706         customAnimationStyleUpdated_ = false;
1707     }
1708     if (!shareId_.empty()) {
1709         if (!sharedTransitionComponent_) {
1710             sharedTransitionComponent_ = AceType::MakeRefPtr<SharedTransitionComponent>(
1711                 "FrontendShared" + std::to_string(nodeId_), tag_, shareId_);
1712             auto& sharedTransitionStyle = static_cast<CommonShareTransitionStyle&>(
1713                 declaration_->GetStyle(StyleTag::COMMON_SHARE_TRANSITION_STYLE));
1714             if (sharedTransitionStyle.IsValid()) {
1715                 sharedTransitionComponent_->SetOption(sharedTransitionStyle.sharedTransitionOption);
1716                 sharedTransitionComponent_->SetEffect(sharedTransitionStyle.sharedEffect);
1717             }
1718         } else {
1719             sharedTransitionComponent_->SetShareId(shareId_);
1720         }
1721     }
1722 }
1723 
IsTabbarSubNode() const1724 bool DOMNode::IsTabbarSubNode() const
1725 {
1726     if (isRootNode_) {
1727         return GetTag() == DOM_NODE_TAG_TAB_BAR;
1728     }
1729     RefPtr<DOMNode> parent = parentNode_.Upgrade();
1730     if (!parent) {
1731         return false;
1732     }
1733 
1734     if (parent->GetTag() == DOM_NODE_TAG_TAB_BAR) {
1735         return true;
1736     }
1737 
1738     while (!parent->IsRootNode()) {
1739         if (parent->GetTag() == DOM_NODE_TAG_TAB_BAR) {
1740             return true;
1741         }
1742         parent = parent->GetParentNode();
1743         if (!parent) {
1744             return false;
1745         }
1746     }
1747     return false;
1748 }
1749 
PrepareTouchEvent(EventMarker & eventMarker,uint32_t type)1750 void DOMNode::PrepareTouchEvent(EventMarker& eventMarker, uint32_t type)
1751 {
1752     bool isTababrSubNode = IsTabbarSubNode();
1753     if (isTababrSubNode) {
1754         return;
1755     }
1756 
1757     auto weak = AceType::WeakClaim(this);
1758     if (eventMarker.IsEmpty()) {
1759         eventMarker = BackEndEventManager<void(const TouchEventInfo&)>::GetInstance().GetAvailableMarker();
1760         BackEndEventManager<void(const TouchEventInfo&)>::GetInstance().BindBackendEvent(
1761             eventMarker, [](const TouchEventInfo&) {});
1762     }
1763     eventMarker.SetPreFunction([weak, type]() {
1764         auto domNode = weak.Upgrade();
1765         if (!domNode) {
1766             return;
1767         }
1768         domNode->OnActive(type != EventType::TOUCH_UP && type != EventType::TOUCH_CANCEL);
1769     });
1770 }
1771 
PrepareMouseHoverEvent()1772 void DOMNode::PrepareMouseHoverEvent()
1773 {
1774     if (!declaration_) {
1775         return;
1776     }
1777     auto& mouseEvent = declaration_->MaybeResetEvent<CommonMouseEvent>(EventTag::COMMON_MOUSE_EVENT);
1778     if (!mouseEvent.IsValid()) {
1779         return;
1780     }
1781     auto weak = AceType::WeakClaim(this);
1782     if (mouseEvent.mouseHover.eventMarker.IsEmpty()) {
1783         mouseEvent.mouseHover.eventMarker = BackEndEventManager<void()>::GetInstance().GetAvailableMarker();
1784         mouseEvent.mouseHover.isRefreshed = true;
1785         BackEndEventManager<void()>::GetInstance().BindBackendEvent(mouseEvent.mouseHover.eventMarker, []() {});
1786     }
1787     mouseEvent.mouseHover.eventMarker.SetPreFunction([weak]() {
1788         auto domNode = weak.Upgrade();
1789         if (!domNode) {
1790             return;
1791         }
1792         domNode->OnHover(true);
1793     });
1794 
1795     if (mouseEvent.mouseHoverExit.eventMarker.IsEmpty()) {
1796         mouseEvent.mouseHoverExit.eventMarker = BackEndEventManager<void()>::GetInstance().GetAvailableMarker();
1797         mouseEvent.mouseHoverExit.isRefreshed = true;
1798         BackEndEventManager<void()>::GetInstance().BindBackendEvent(mouseEvent.mouseHoverExit.eventMarker, []() {});
1799     }
1800     mouseEvent.mouseHoverExit.eventMarker.SetPreFunction([weak]() {
1801         auto domNode = weak.Upgrade();
1802         if (!domNode) {
1803             return;
1804         }
1805         domNode->OnHover(false);
1806     });
1807 }
1808 
PrepareFocusableEventId()1809 void DOMNode::PrepareFocusableEventId()
1810 {
1811     if (!declaration_) {
1812         return;
1813     }
1814     auto& focusEvent = declaration_->MaybeResetEvent<CommonFocusEvent>(EventTag::COMMON_FOCUS_EVENT);
1815     if (!focusEvent.IsValid()) {
1816         return;
1817     }
1818 
1819     auto weak = AceType::WeakClaim(this);
1820     if (focusEvent.focus.eventMarker.IsEmpty()) {
1821         focusEvent.focus.eventMarker = BackEndEventManager<void()>::GetInstance().GetAvailableMarker();
1822         focusEvent.focus.isRefreshed = true;
1823         BackEndEventManager<void()>::GetInstance().BindBackendEvent(focusEvent.focus.eventMarker, []() {});
1824     }
1825 
1826     focusEvent.focus.eventMarker.SetPreFunction([weak]() {
1827         auto domNode = weak.Upgrade();
1828         if (!domNode) {
1829             return;
1830         }
1831         domNode->OnFocus(true);
1832     });
1833 
1834     if (focusEvent.blur.eventMarker.IsEmpty()) {
1835         focusEvent.blur.eventMarker = BackEndEventManager<void()>::GetInstance().GetAvailableMarker();
1836         focusEvent.blur.isRefreshed = true;
1837         BackEndEventManager<void()>::GetInstance().BindBackendEvent(focusEvent.blur.eventMarker, []() {});
1838     }
1839 
1840     focusEvent.blur.eventMarker.SetPreFunction([weak]() {
1841         auto domNode = weak.Upgrade();
1842         if (!domNode) {
1843             return;
1844         }
1845         domNode->OnFocus(false);
1846     });
1847 }
1848 
UpdateTouchEventComponent()1849 void DOMNode::UpdateTouchEventComponent()
1850 {
1851     if (!declaration_) {
1852         return;
1853     }
1854 
1855     auto& swipeEvent = static_cast<CommonSwipeEvent&>(declaration_->GetEvent(EventTag::COMMON_SWIPE_EVENT));
1856     if (swipeEvent.IsValid()) {
1857         for (uint32_t eventAction = 0; eventAction < EventAction::SIZE; eventAction++) {
1858             for (uint32_t eventStage = 0; eventStage < EventStage::SIZE; eventStage++) {
1859                 EventMarker& eventMarker = GetSwipeId(eventAction, eventStage);
1860                 if (!eventMarker.IsEmpty()) {
1861                     if (!touchEventComponent_) {
1862                         touchEventComponent_ = AceType::MakeRefPtr<TouchListenerComponent>();
1863                     }
1864                     touchEventComponent_->SetSwipeEvent(eventMarker, eventAction, eventStage);
1865                 }
1866             }
1867         }
1868     }
1869 
1870     auto& touchableAttr =
1871         static_cast<CommonTouchableAttribute&>(declaration_->GetAttribute(AttributeTag::COMMON_TOUCHABLE_ATTR));
1872     if (touchableAttr.IsValid() && !touchableAttr.touchable) {
1873         if (!touchEventComponent_) {
1874             touchEventComponent_ = AceType::MakeRefPtr<TouchListenerComponent>();
1875         }
1876         touchEventComponent_->SetTouchable(touchableAttr.touchable);
1877     }
1878 
1879     auto& rawEvent = static_cast<CommonRawEvent&>(declaration_->GetEvent(EventTag::COMMON_RAW_EVENT));
1880     if (!rawEvent.IsValid()) {
1881         return;
1882     }
1883     for (uint32_t eventAction = 0; eventAction < EventAction::SIZE; eventAction++) {
1884         for (uint32_t eventStage = 0; eventStage < EventStage::SIZE; eventStage++) {
1885             for (uint32_t touchEventType = 0; touchEventType < EventType::SIZE; touchEventType++) {
1886                 EventMarker& eventMarker = GetTouchId(eventAction, eventStage, touchEventType);
1887                 if (!eventMarker.IsEmpty() || HasActivePseudo()) {
1888                     if (!touchEventComponent_) {
1889                         touchEventComponent_ = AceType::MakeRefPtr<TouchListenerComponent>();
1890                     }
1891                     if (HasActivePseudo() && touchEventType != EventType::TOUCH_MOVE &&
1892                         eventAction == EventAction::ON && eventStage == EventStage::BUBBLE) {
1893                         PrepareTouchEvent(eventMarker, touchEventType);
1894                     }
1895                     touchEventComponent_->SetEvent(eventMarker, eventAction, eventStage, touchEventType);
1896                 }
1897             }
1898         }
1899     }
1900 }
1901 
UpdateMouseEventComponent()1902 void DOMNode::UpdateMouseEventComponent()
1903 {
1904     if (!declaration_) {
1905         return;
1906     }
1907     auto& mouseEvent = declaration_->MaybeResetEvent<CommonMouseEvent>(EventTag::COMMON_MOUSE_EVENT);
1908     if (!mouseEvent.IsValid()) {
1909         return;
1910     }
1911     if (!mouseEvent.mouse.eventMarker.IsEmpty()) {
1912         if (!mouseEventComponent_) {
1913             mouseEventComponent_ = AceType::MakeRefPtr<MouseListenerComponent>();
1914         }
1915         mouseEventComponent_->SetOnMouseId(mouseEvent.mouse.eventMarker);
1916     }
1917 
1918     PrepareMouseHoverEvent();
1919     if (!mouseEvent.mouseHover.eventMarker.IsEmpty()) {
1920         if (!mouseEventComponent_) {
1921             mouseEventComponent_ = AceType::MakeRefPtr<MouseListenerComponent>();
1922         }
1923         mouseEventComponent_->SetOnMouseHoverId(mouseEvent.mouseHover.eventMarker);
1924     }
1925     if (!mouseEvent.mouseHoverExit.eventMarker.IsEmpty()) {
1926         if (!mouseEventComponent_) {
1927             mouseEventComponent_ = AceType::MakeRefPtr<MouseListenerComponent>();
1928         }
1929         mouseEventComponent_->SetOnMouseHoverExitId(mouseEvent.mouseHoverExit.eventMarker);
1930     }
1931 }
1932 
UpdateGestureEventComponent()1933 void DOMNode::UpdateGestureEventComponent()
1934 {
1935     if (!declaration_) {
1936         return;
1937     }
1938 
1939     if (!GetClickId().IsEmpty() || !GetDoubleClickId().IsEmpty() || !GetLongPressId().IsEmpty() ||
1940         !GetPinchStartId().IsEmpty() || !GetPinchUpdateId().IsEmpty() || !GetPinchEndId().IsEmpty() ||
1941         !GetPinchCancelId().IsEmpty() || declaration_->HasIdAttr() || !GetDragStartId().IsEmpty() ||
1942         !GetDragId().IsEmpty() || !GetDragEndId().IsEmpty()) {
1943         if (!gestureEventComponent_) {
1944             gestureEventComponent_ = AceType::MakeRefPtr<GestureListenerComponent>();
1945         }
1946         gestureEventComponent_->SetOnClickId(GetClickId());
1947         gestureEventComponent_->SetOnDoubleClickId(GetDoubleClickId());
1948         gestureEventComponent_->SetOnLongPressId(GetLongPressId());
1949         gestureEventComponent_->SetOnPinchStartId(GetPinchStartId());
1950         gestureEventComponent_->SetOnPinchUpdateId(GetPinchUpdateId());
1951         gestureEventComponent_->SetOnPinchEndId(GetPinchEndId());
1952         gestureEventComponent_->SetOnPinchCancelId(GetPinchCancelId());
1953         gestureEventComponent_->SetOnFreeDragStartId(GetDragStartId());
1954         gestureEventComponent_->SetOnFreeDragUpdateId(GetDragId());
1955         gestureEventComponent_->SetOnFreeDragEndId(GetDragEndId());
1956         auto onDragStartGestureId = []() -> GestureItemInfo {
1957             GestureItemInfo itemInfo;
1958             itemInfo.pixelMap = DOMDocument::pixelMap_;
1959             itemInfo.offsetX = DOMDocument::pixelMapOffsetX_;
1960             itemInfo.offsetY = DOMDocument::pixelMapOffsetY_;
1961             return itemInfo;
1962         };
1963         gestureEventComponent_->SetOnDragStartId(onDragStartGestureId);
1964     }
1965 }
1966 
UpdateFocusableEventComponents()1967 void DOMNode::UpdateFocusableEventComponents()
1968 {
1969     if (!declaration_ || (UNFOCUSABLED_NODE.find(tag_) != UNFOCUSABLED_NODE.end())) {
1970         return;
1971     }
1972 
1973     auto& focusableAttr =
1974         static_cast<CommonFocusableAttribute&>(declaration_->GetAttribute(AttributeTag::COMMON_FOCUSABLE_ATTR));
1975     auto& focusEvent = declaration_->MaybeResetEvent<CommonFocusEvent>(EventTag::COMMON_FOCUS_EVENT);
1976     auto& keyEvent = static_cast<CommonKeyEvent&>(declaration_->GetEvent(EventTag::COMMON_KEY_EVENT));
1977     bool focusable = focusableAttr.IsValid() && focusableAttr.focusable.second;
1978     bool supportFocus = focusEvent.IsValid() && !focusEvent.focus.eventMarker.IsEmpty();
1979     bool supportBlur = focusEvent.IsValid() && !focusEvent.blur.eventMarker.IsEmpty();
1980     bool supportKey = keyEvent.IsValid() && !keyEvent.key.eventMarker.IsEmpty();
1981 
1982     if (!focusable && GetClickId().IsEmpty() && !supportFocus && !supportBlur && !supportKey && !HasFocusPseudo()) {
1983         return;
1984     }
1985     if (!focusableEventComponent_) {
1986         focusableEventComponent_ = AceType::MakeRefPtr<FocusableComponent>();
1987         declaration_->SetFocusableController(focusableEventComponent_->GetFocusableController());
1988     }
1989     if (focusableAttr.IsValid() && focusableAttr.focusable.second) {
1990         focusableEventComponent_->SetFocusable(focusableAttr.focusable.first);
1991     } else {
1992         focusableEventComponent_->SetFocusable(true);
1993     }
1994 
1995     focusableEventComponent_->SetOnClickId(GetClickId());
1996 
1997     PrepareFocusableEventId();
1998 
1999     if (focusEvent.IsValid()) {
2000         focusableEventComponent_->SetOnBlurId(focusEvent.blur.eventMarker);
2001         focusableEventComponent_->SetOnFocusId(focusEvent.focus.eventMarker);
2002     }
2003     if (keyEvent.IsValid()) {
2004         focusableEventComponent_->SetOnKeyId(keyEvent.key.eventMarker);
2005     }
2006     if (g_focusableNode.empty()) {
2007         g_focusableNode = std::unordered_set<std::string>({
2008             DOM_NODE_TAG_BUTTON,
2009             DOM_NODE_TAG_DIV,
2010             DOM_NODE_TAG_FORM,
2011             DOM_NODE_TAG_LIST,
2012             DOM_NODE_TAG_LIST_ITEM,
2013             DOM_NODE_TAG_REFRESH,
2014             DOM_NODE_TAG_INPUT,
2015             DOM_NODE_TAG_OPTION,
2016             DOM_NODE_TAG_PROGRESS,
2017             DOM_NODE_TAG_POPUP,
2018             DOM_NODE_TAG_RATING,
2019             DOM_NODE_TAG_SELECT,
2020             DOM_NODE_TAG_SLIDER,
2021             DOM_NODE_TAG_STACK,
2022             DOM_NODE_TAG_STEPPER,
2023             DOM_NODE_TAG_STEPPER_ITEM,
2024             DOM_NODE_TAG_SWIPER,
2025             DOM_NODE_TAG_SWITCH,
2026             DOM_NODE_TAG_TABS,
2027             DOM_NODE_TAG_TAB_BAR,
2028             DOM_NODE_TAG_TAB_CONTENT,
2029             DOM_NODE_TAG_TEXTAREA,
2030             DOM_NODE_TAG_TOGGLE,
2031             DOM_NODE_TAG_SEARCH,
2032             DOM_NODE_TAG_VIDEO,
2033             DOM_NODE_TAG_CALENDAR,
2034             DOM_NODE_TAG_PICKER_DIALOG,
2035             DOM_NODE_TAG_PIECE,
2036         });
2037     }
2038     if (g_focusableNode.find(tag_) != g_focusableNode.end()) {
2039         focusableEventComponent_->SetFocusNode(false);
2040     } else {
2041         focusableEventComponent_->SetFocusNode(true);
2042     }
2043 }
2044 
UpdatePositionProps()2045 void DOMNode::UpdatePositionProps()
2046 {
2047     if (!declaration_ || !declaration_->HasPositionStyle() || GetPosition() == PositionType::PTFIXED) {
2048         return;
2049     }
2050 
2051     declaration_->SetHasPositionStyle(false);
2052     auto tweenComponent = AceType::DynamicCast<TweenComponent>(rootComponent_->GetChild());
2053     if (tweenComponent) {
2054         UpdateTweenPosition(tweenComponent);
2055         UpdatePositionAnimations(tweenComponent);
2056     } else {
2057         // Set position props to first RenderComponent of node
2058         auto compositeComponent = AceType::DynamicCast<RenderComponent>(rootComponent_->GetChild());
2059         if (!compositeComponent) {
2060             return;
2061         }
2062         compositeComponent->SetHasLeft(declaration_->HasLeft());
2063         compositeComponent->SetHasTop(declaration_->HasTop());
2064         compositeComponent->SetHasBottom(declaration_->HasBottom());
2065         compositeComponent->SetHasRight(declaration_->HasRight());
2066         auto& positionStyle =
2067             static_cast<CommonPositionStyle&>(declaration_->GetStyle(StyleTag::COMMON_POSITION_STYLE));
2068         if (positionStyle.IsValid()) {
2069             if (declaration_->HasLeft()) {
2070                 compositeComponent->SetLeft(positionStyle.left);
2071                 // reset value
2072                 declaration_->SetHasLeft(false);
2073             }
2074             if (declaration_->HasRight()) {
2075                 compositeComponent->SetRight(positionStyle.right);
2076                 declaration_->SetHasRight(false);
2077             }
2078             if (declaration_->HasTop()) {
2079                 compositeComponent->SetTop(positionStyle.top);
2080                 declaration_->SetHasTop(false);
2081             }
2082             if (declaration_->HasBottom()) {
2083                 compositeComponent->SetBottom(positionStyle.bottom);
2084                 declaration_->SetHasBottom(false);
2085             }
2086             compositeComponent->SetPositionType(positionStyle.position);
2087         }
2088         UpdatePositionAnimations(compositeComponent);
2089     }
2090 }
2091 
UpdateTweenPosition(const RefPtr<TweenComponent> tweenComponent)2092 void DOMNode::UpdateTweenPosition(const RefPtr<TweenComponent> tweenComponent)
2093 {
2094     if (!declaration_ || !tweenComponent) {
2095         return;
2096     }
2097     tweenComponent->SetHasLeft(declaration_->HasLeft());
2098     tweenComponent->SetHasTop(declaration_->HasTop());
2099     tweenComponent->SetHasBottom(declaration_->HasBottom());
2100     tweenComponent->SetHasRight(declaration_->HasRight());
2101 
2102     auto& positionStyle = static_cast<CommonPositionStyle&>(declaration_->GetStyle(StyleTag::COMMON_POSITION_STYLE));
2103     if (!positionStyle.IsValid()) {
2104         return;
2105     }
2106     if (declaration_->HasLeft()) {
2107         tweenComponent->SetLeft(positionStyle.left);
2108         // reset value
2109         declaration_->SetHasLeft(false);
2110     }
2111     if (declaration_->HasRight()) {
2112         tweenComponent->SetRight(positionStyle.right);
2113         declaration_->SetHasRight(false);
2114     }
2115     if (declaration_->HasTop()) {
2116         tweenComponent->SetTop(positionStyle.top);
2117         declaration_->SetHasTop(false);
2118     }
2119     if (declaration_->HasBottom()) {
2120         tweenComponent->SetBottom(positionStyle.bottom);
2121         declaration_->SetHasBottom(false);
2122     }
2123     tweenComponent->SetPositionType(positionStyle.position);
2124 }
2125 
UpdatePositionComponent()2126 void DOMNode::UpdatePositionComponent()
2127 {
2128     if (!declaration_ || !declaration_->HasPositionStyle() || GetPosition() != PositionType::PTFIXED) {
2129         return;
2130     }
2131     if (!positionComponent_) {
2132         positionComponent_ = AceType::MakeRefPtr<PositionedComponent>();
2133     }
2134     auto& positionStyle = static_cast<CommonPositionStyle&>(declaration_->GetStyle(StyleTag::COMMON_POSITION_STYLE));
2135     if (positionStyle.IsValid()) {
2136         positionComponent_->SetTop(positionStyle.top);
2137         positionComponent_->SetRight(positionStyle.right);
2138         positionComponent_->SetBottom(positionStyle.bottom);
2139         positionComponent_->SetLeft(positionStyle.left);
2140         positionComponent_->SetHasLeft(declaration_->HasLeft());
2141         positionComponent_->SetHasRight(declaration_->HasRight());
2142         positionComponent_->SetHasBottom(declaration_->HasBottom());
2143         positionComponent_->SetHasTop(declaration_->HasTop());
2144     }
2145     UpdatePositionAnimations(positionComponent_);
2146 }
2147 
CompositeSpecializedComponent(const std::vector<RefPtr<SingleChild>> & components)2148 RefPtr<Component> DOMNode::CompositeSpecializedComponent(const std::vector<RefPtr<SingleChild>>& components)
2149 {
2150     const auto& specializedComponent = GetSpecializedComponent();
2151     if (specializedComponent) {
2152         bool touchable = true;
2153         if (declaration_) {
2154             auto& touchableAttr =
2155                 static_cast<CommonTouchableAttribute&>(declaration_->GetAttribute(AttributeTag::COMMON_TOUCHABLE_ATTR));
2156             if (touchableAttr.IsValid()) {
2157                 touchable = touchableAttr.touchable;
2158             }
2159         }
2160         specializedComponent->SetTouchable(touchable);
2161     }
2162     if (components.empty()) {
2163         return specializedComponent;
2164     } else {
2165         const auto& parent = components.back();
2166         if (parent) {
2167             parent->SetChild(specializedComponent);
2168         }
2169         return AceType::DynamicCast<Component>(components.front());
2170     }
2171 }
2172 
2173 #ifndef WEARABLE_PRODUCT
UpdateMultimodalComponent()2174 void DOMNode::UpdateMultimodalComponent()
2175 {
2176     if (!declaration_ || GetClickId().IsEmpty()) {
2177         return;
2178     }
2179     auto& multimodalAttr =
2180         static_cast<CommonMultimodalAttribute&>(declaration_->GetAttribute(AttributeTag::COMMON_MULTIMODAL_ATTR));
2181     if (!multimodalAttr.IsValid() || multimodalAttr.IsUnavailable() || multimodalAttr.scene == SceneLabel::SWITCH) {
2182         return;
2183     }
2184     if (!multimodalComponent_) {
2185         multimodalComponent_ = AceType::MakeRefPtr<MultimodalComponent>(pageId_);
2186     }
2187     multimodalComponent_->SetMultimodalProperties(multimodalAttr);
2188     multimodalComponent_->SetOnClickId(GetClickId());
2189 }
2190 #endif
2191 
GetThemeConstants() const2192 RefPtr<ThemeConstants> DOMNode::GetThemeConstants() const
2193 {
2194     auto themeManager = GetThemeManager();
2195     if (!themeManager) {
2196         return nullptr;
2197     }
2198     return themeManager->GetThemeConstants();
2199 }
2200 
ParseColor(const std::string & value,uint32_t maskAlpha) const2201 Color DOMNode::ParseColor(const std::string& value, uint32_t maskAlpha) const
2202 {
2203     auto themeConstants = GetThemeConstants();
2204     if (!themeConstants) {
2205         return Color::TRANSPARENT;
2206     }
2207     auto&& noRefFunc = [&value, maskAlpha = maskAlpha]() { return Color::FromString(value, maskAlpha); };
2208     auto&& idRefFunc = [constants = themeConstants](uint32_t refId) { return constants->GetColor(refId); };
2209     return ParseThemeReference<Color>(value, noRefFunc, idRefFunc, Color::TRANSPARENT);
2210 }
2211 
ParseDouble(const std::string & value) const2212 double DOMNode::ParseDouble(const std::string& value) const
2213 {
2214     auto themeConstants = GetThemeConstants();
2215     if (!themeConstants) {
2216         return 0.0;
2217     }
2218     auto&& noRefFunc = [&value]() { return StringUtils::StringToDouble(value); };
2219     auto&& idRefFunc = [constants = themeConstants](uint32_t refId) { return constants->GetDouble(refId); };
2220     return ParseThemeReference<double>(value, noRefFunc, idRefFunc, 0.0);
2221 }
2222 
ParseDimension(const std::string & value) const2223 CalcDimension DOMNode::ParseDimension(const std::string& value) const
2224 {
2225     auto themeConstants = GetThemeConstants();
2226     if (!themeConstants) {
2227         return Dimension();
2228     }
2229     auto&& noRefFunc = [&value]() { return StringUtils::StringToDimension(value); };
2230     auto&& idRefFunc = [constants = themeConstants](uint32_t refId) { return constants->GetDimension(refId); };
2231     if (value.find("calc") != std::string::npos) {
2232         return CalcDimension(value, DimensionUnit::CALC);
2233     } else {
2234         return ParseThemeReference<Dimension>(value, noRefFunc, idRefFunc, Dimension());
2235     }
2236 }
2237 
ParseLineHeight(const std::string & value) const2238 Dimension DOMNode::ParseLineHeight(const std::string& value) const
2239 {
2240     auto themeConstants = GetThemeConstants();
2241     if (!themeConstants) {
2242         return Dimension();
2243     }
2244     const auto& parseResult = ThemeUtils::ParseThemeIdReference(value, GetThemeConstants());
2245     if (!parseResult.parseSuccess) {
2246         return StringUtils::StringToDimension(value);
2247     }
2248     auto&& noRefFunc = [&value]() { return StringUtils::StringToDouble(value); };
2249     auto&& idRefFunc = [constants = themeConstants](uint32_t refId) { return constants->GetDouble(refId); };
2250     auto lineHeightScale = ParseThemeReference<double>(value, noRefFunc, idRefFunc, 1.0);
2251     // If got 0.0 from ThemeConstants, use default 1.0
2252     lineHeightScale = NearZero(lineHeightScale) ? 1.0 : lineHeightScale;
2253     return Dimension(lineHeightScale, DimensionUnit::PERCENT);
2254 }
2255 
ParseFontFamilies(const std::string & value) const2256 std::vector<std::string> DOMNode::ParseFontFamilies(const std::string& value) const
2257 {
2258     std::vector<std::string> fontFamilies;
2259     std::stringstream stream(value);
2260     std::string fontFamily;
2261 
2262     auto themeConstants = GetThemeConstants();
2263     if (!themeConstants) {
2264         return fontFamilies;
2265     }
2266     auto&& idRefFunc = [constants = themeConstants](uint32_t refId) { return constants->GetString(refId); };
2267 
2268     while (getline(stream, fontFamily, ',')) {
2269         auto&& noRefFunc = [&fontFamily]() { return fontFamily; };
2270         fontFamilies.emplace_back(ParseThemeReference<std::string>(fontFamily, noRefFunc, idRefFunc, fontFamily));
2271     }
2272     return fontFamilies;
2273 }
2274 
ParsePreferFontSizes(const std::string & value) const2275 std::vector<Dimension> DOMNode::ParsePreferFontSizes(const std::string& value) const
2276 {
2277     std::vector<Dimension> prefers;
2278     std::stringstream stream(value);
2279     std::string fontSize;
2280     while (getline(stream, fontSize, ',')) {
2281         prefers.emplace_back(ParseDimension(fontSize));
2282     }
2283     std::sort(prefers.begin(), prefers.end(),
2284         [](const Dimension& left, const Dimension& right) { return left.Value() > right.Value(); });
2285     return prefers;
2286 }
2287 
ParseImageSrc(const std::string & imgSrc) const2288 std::string DOMNode::ParseImageSrc(const std::string& imgSrc) const
2289 {
2290     return ThemeUtils::ProcessImageSource(imgSrc, GetThemeConstants());
2291 }
2292 
AdjustParamInLiteMode()2293 void DOMNode::AdjustParamInLiteMode()
2294 {
2295     if (!declaration_) {
2296         return;
2297     }
2298 
2299     declaration_->SetUseLiteStyle(true);
2300     // Change default value
2301     if (boxComponent_) {
2302         boxComponent_->SetUseLiteStyle(true);
2303         boxComponent_->SetAlignment(Alignment::TOP_CENTER);
2304     }
2305     auto& flexStyle = declaration_->MaybeResetStyle<CommonFlexStyle>(StyleTag::COMMON_FLEX_STYLE);
2306     if (flexStyle.IsValid()) {
2307         flexStyle.flexShrink = 0.0;
2308     }
2309     AdjustSpecialParamInLiteMode();
2310 }
2311 
CreateDeclaration(const std::string & tag)2312 void DOMNode::CreateDeclaration(const std::string& tag)
2313 {
2314     declaration_ = DeclarationCreatorManager::GetInstance().CreateDeclaration(tag);
2315     if (!declaration_) {
2316         return;
2317     }
2318     declaration_->SetCachePseudoClassStyle(
2319         [weak = WeakClaim(this)](const std::pair<std::string, std::string>& pseudoClassStyle) {
2320             auto node = weak.Upgrade();
2321             if (node) {
2322                 node->CachePseudoClassStyle(pseudoClassStyle);
2323             }
2324         });
2325     declaration_->SetOnSetStyleFinished([weak = WeakClaim(this)]() {
2326         auto node = weak.Upgrade();
2327         if (node) {
2328             node->OnSetStyleFinished();
2329         }
2330     });
2331     declaration_->SetOnSetAttribute([weakComponent = WeakPtr<ComposedComponent>(rootComponent_)]() {
2332         auto rootComponent = weakComponent.Upgrade();
2333         if (rootComponent) {
2334             rootComponent->SetUpdateType(UpdateType::ALL);
2335         }
2336     });
2337 }
2338 
2339 } // namespace OHOS::Ace::Framework
2340