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