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