• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/pipeline/base/render_node.h"
17 
18 #include <algorithm>
19 #include <set>
20 #include <sstream>
21 #include <string>
22 #include <unistd.h>
23 
24 #include "base/memory/ace_type.h"
25 #include "base/utils/utils.h"
26 #include "core/components/common/layout/constants.h"
27 
28 #ifdef ENABLE_ROSEN_BACKEND
29 #include "render_service_client/core/ui/rs_canvas_node.h"
30 
31 #include "core/animation/native_curve_helper.h"
32 #include "core/components/remote_window/rosen_render_remote_window.h"
33 #endif
34 
35 #include "base/log/dump_log.h"
36 #include "base/log/event_report.h"
37 #include "base/log/log.h"
38 #include "core/components/box/drag_drop_event.h"
39 #include "core/components/box/render_box.h"
40 #include "core/components/common/properties/motion_path_evaluator.h"
41 #include "core/components/common/properties/motion_path_option.h"
42 #include "core/components/common/rotation/rotation_node.h"
43 #include "core/components/container_modal/container_modal_constants.h"
44 #include "core/components/focus_animation/render_focus_animation.h"
45 #include "core/components/grid_layout/render_grid_layout.h"
46 #include "core/components/root/render_root.h"
47 #include "core/components/scroll/render_single_child_scroll.h"
48 #include "core/components/transform/render_transform.h"
49 #include "core/components_v2/list/render_list.h"
50 #include "core/event/ace_event_helper.h"
51 #include "core/event/axis_event.h"
52 #include "core/pipeline/base/component.h"
53 
54 namespace OHOS::Ace {
55 namespace {
56 
57 constexpr float PRESS_KEYFRAME_START = 0.0f;
58 constexpr float PRESS_KEYFRAME_END = 1.0f;
59 
60 struct ZIndexComparator {
operator ()OHOS::Ace::__anon5c8176d40111::ZIndexComparator61     bool operator()(const RefPtr<RenderNode>& left, const RefPtr<RenderNode>& right) const
62     {
63         if (left && right) {
64             return (left->GetZIndex() < right->GetZIndex());
65         }
66         return false;
67     }
68 };
69 
SortChildrenByZIndex(const std::list<RefPtr<RenderNode>> & children)70 inline std::multiset<RefPtr<RenderNode>, ZIndexComparator> SortChildrenByZIndex(
71     const std::list<RefPtr<RenderNode>>& children)
72 {
73     return std::multiset<RefPtr<RenderNode>, ZIndexComparator>(children.begin(), children.end());
74 }
75 
76 } // namespace
77 
78 constexpr Dimension FOCUS_BOUNDARY = 4.0_vp; // focus padding + effect boundary, VP
79 
RenderNode(bool takeBoundary)80 RenderNode::RenderNode(bool takeBoundary) : takeBoundary_(takeBoundary) {}
81 
MarkTreeRender(const RefPtr<RenderNode> & root,bool & meetHole,bool needFlush)82 void RenderNode::MarkTreeRender(const RefPtr<RenderNode>& root, bool& meetHole, bool needFlush)
83 {
84     if (root->GetHasSubWindow()) {
85         meetHole = true;
86     }
87 
88     if (meetHole) {
89         root->SetNeedClip(false);
90     } else {
91         root->SetNeedClip(true);
92     }
93 
94     if (needFlush) {
95         root->MarkNeedRender();
96     }
97 
98     bool subMeetHole = meetHole;
99     for (auto child : root->GetChildren()) {
100         MarkTreeRender(child, subMeetHole, needFlush);
101     }
102     meetHole = subMeetHole;
103 }
104 
MarkWholeRender(const WeakPtr<RenderNode> & nodeWeak,bool needFlush)105 void RenderNode::MarkWholeRender(const WeakPtr<RenderNode>& nodeWeak, bool needFlush)
106 {
107     auto node = nodeWeak.Upgrade();
108     if (!node) {
109         LOGE("Hole: MarkWholeRender node is null");
110         return;
111     }
112 
113     auto parentWeak = node->GetParent();
114     auto parent = parentWeak.Upgrade();
115     while (parent) {
116         node = parent;
117         parentWeak = node->GetParent();
118         parent = parentWeak.Upgrade();
119     }
120 
121     bool meetHole = false;
122     MarkTreeRender(node, meetHole, needFlush);
123 }
124 
AddChild(const RefPtr<RenderNode> & child,int32_t slot)125 void RenderNode::AddChild(const RefPtr<RenderNode>& child, int32_t slot)
126 {
127     if (!child) {
128         LOGW("Child MUST NOT be nullptr");
129         return;
130     }
131 
132     auto it = std::find(children_.begin(), children_.end(), child);
133     if (it != children_.end()) {
134         LOGW("RenderNode exist AddChild failed");
135         return;
136     }
137 
138     auto pos = children_.begin();
139     std::advance(pos, slot);
140     children_.insert(pos, child);
141     child->SetParent(AceType::WeakClaim(this));
142     auto context = context_.Upgrade();
143     if (context && context->GetTransparentHole().IsValid()) {
144         MarkWholeRender(AceType::WeakClaim(this), true);
145     }
146     child->SetDepth(GetDepth() + 1);
147     OnChildAdded(child);
148     disappearingNodes_.remove(child);
149     if (SystemProperties::GetRosenBackendEnabled()) {
150         RSNodeAddChild(child);
151         // we don't know transition parameters until Update() is called, so we set pending flag here
152         child->SetPendingAppearingTransition();
153     } else {
154         child->NotifyTransition(TransitionType::APPEARING, child->GetNodeId());
155     }
156 }
157 
RemoveChild(const RefPtr<RenderNode> & child)158 void RenderNode::RemoveChild(const RefPtr<RenderNode>& child)
159 {
160     if (!child) {
161         LOGW("Child MUST NOT be nullptr");
162         return;
163     }
164 
165     // ClearChildren() before RemoveChild() also need to NotifyTransition().
166     if (!children_.empty()) {
167         auto it = std::find(children_.begin(), children_.end(), child);
168         if (it == children_.end()) {
169             LOGW("Child is not in this render node");
170             return;
171         } else {
172             children_.erase(it);
173         }
174     }
175 
176     OnChildRemoved(child);
177     disappearingNodes_.remove(child);
178     // check whether child has config transition or will cause child memory leak.
179     auto context = context_.Upgrade();
180     if (context && context->GetExplicitAnimationOption().IsValid() &&
181         child->HasDisappearingTransition(child->GetNodeId())) {
182         LOGD("RemoveChild with transition. [child]: tag: %s, nodeId: %d", child->GetTypeName(), child->GetNodeId());
183         disappearingNodes_.emplace_back(child);
184         child->SetParent(AceType::WeakClaim(this));
185         child->NotifyTransition(TransitionType::DISAPPEARING, child->GetNodeId());
186     }
187 #ifdef ENABLE_ROSEN_BACKEND
188     // To avoid redundant transition animation, only trigger transition when head render node is removed
189     else if (child->IsHeadRenderNode() && child->HasDisappearingTransition(child->GetNodeId())) {
190         // kick off a disappearing transition
191         child->NotifyTransition(TransitionType::DISAPPEARING, child->GetNodeId());
192     }
193     if (rsNode_ && rsNode_ == child->rsNode_) {
194         child->OnRemove();
195     }
196 #endif
197     LOGD("RenderNode RemoveChild %{public}zu", children_.size());
198 }
199 
MovePosition(int32_t slot)200 void RenderNode::MovePosition(int32_t slot)
201 {
202     auto parentNode = GetParent().Upgrade();
203     if (!parentNode) {
204         LOGW("Invalid parent");
205         return;
206     }
207 
208     auto self = AceType::Claim(this);
209     auto& children = parentNode->children_;
210     auto it = children.end();
211     if (slot >= 0 && static_cast<size_t>(slot) < children.size()) {
212         it = children.begin();
213         std::advance(it, slot);
214         if (*it == this) {
215             // Already at the right place
216             return;
217         }
218 
219         auto itSelf = std::find(it, children.end(), self);
220         if (itSelf != children.end()) {
221             children.erase(itSelf);
222         } else {
223             LOGW("Should NOT be here");
224             children.remove(self);
225             ++it;
226         }
227     } else {
228         children.remove(self);
229     }
230     children.insert(it, self);
231 }
232 
ClearChildren()233 void RenderNode::ClearChildren()
234 {
235     children_.clear();
236 }
237 
UpdateTouchRect()238 void RenderNode::UpdateTouchRect()
239 {
240     if (!isResponseRegion_) {
241         touchRect_ = GetPaintRect();
242         auto box = AceType::DynamicCast<RenderBox>(this);
243         if (box && box->GetTouchArea().GetOffset().IsPositiveOffset()) {
244             touchRect_.SetOffset(box->GetTouchArea().GetOffset() + touchRect_.GetOffset());
245             touchRect_.SetSize(box->GetTouchArea().GetSize());
246         }
247         touchRect_ = GetTransformRect(touchRect_);
248         touchRectList_.emplace_back(touchRect_);
249         SetTouchRectList(touchRectList_);
250         return;
251     }
252 
253     responseRegionList_.clear();
254     touchRect_ = GetTransformRect(GetPaintRect());
255 
256     for (auto& region : responseRegion_) {
257         double x = GetPxValue(touchRect_.Width(), region.GetOffset().GetX());
258         double y = GetPxValue(touchRect_.Height(), region.GetOffset().GetY());
259         double width = GetPxValue(touchRect_.Width(), region.GetWidth());
260         double height = GetPxValue(touchRect_.Height(), region.GetHeight());
261         Rect responseRegion(touchRect_.GetOffset().GetX() + x, touchRect_.GetOffset().GetY() + y, width, height);
262         responseRegionList_.emplace_back(responseRegion);
263     }
264 
265     touchRectList_ = responseRegionList_;
266     SetTouchRectList(touchRectList_);
267 }
268 
SetTouchRectList(std::vector<Rect> & touchRectList)269 void RenderNode::SetTouchRectList(std::vector<Rect>& touchRectList)
270 {
271     if (IsUseOnly()) {
272         return;
273     }
274     std::vector<Rect> parentTouchRectList = touchRectList;
275     const auto& children = GetChildren();
276     if (!children.empty()) {
277         for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
278             auto& child = *iter;
279             auto childTouchRectList = child->GetTouchRectList();
280             CompareTouchRectList(touchRectList, childTouchRectList, parentTouchRectList);
281         }
282     }
283 }
284 
CompareTouchRectList(std::vector<Rect> & touchRectList,const std::vector<Rect> & childTouchRectList,const std::vector<Rect> & parentTouchRectList)285 void RenderNode::CompareTouchRectList(std::vector<Rect>& touchRectList,
286     const std::vector<Rect>& childTouchRectList, const std::vector<Rect>& parentTouchRectList)
287 {
288     for (auto& childRect : childTouchRectList) {
289         bool isInRegion = false;
290         auto rect = childRect;
291         for (auto& parentRect : parentTouchRectList) {
292             // unified coordinate system
293             rect.SetOffset(childRect.GetOffset() + GetPaintRect().GetOffset());
294             if (CompareTouchRect(parentRect, rect)) {
295                 isInRegion = true;
296                 break;
297             }
298         }
299         if (!isInRegion && !IsResponseRegion()) {
300             touchRectList.emplace_back(rect);
301         }
302     }
303 }
304 
GetPxValue(double standard,const Dimension & value)305 double RenderNode::GetPxValue(double standard, const Dimension& value)
306 {
307     auto context = context_.Upgrade();
308     if (!context) {
309         return value.Value();
310     }
311 
312     double result = 0.0;
313     if (value.Unit() == DimensionUnit::PERCENT) {
314         result = standard * value.Value();
315     } else {
316         result = context->NormalizeToPx(value);
317     }
318     return result;
319 }
320 
CompareTouchRect(const Rect & parentTouchRect,const Rect & childTouchRect)321 bool RenderNode::CompareTouchRect(const Rect& parentTouchRect, const Rect& childTouchRect)
322 {
323     if (childTouchRect.IsWrappedBy(parentTouchRect)) {
324         return true;
325     }
326     return false;
327 }
328 
MoveWhenOutOfViewPort(bool hasEffect)329 void RenderNode::MoveWhenOutOfViewPort(bool hasEffect)
330 {
331     if (SystemProperties::GetDeviceType() != DeviceType::TV) {
332         return;
333     }
334 
335     Offset effectOffset;
336     if (hasEffect) {
337         effectOffset = Offset(NormalizeToPx(FOCUS_BOUNDARY), NormalizeToPx(FOCUS_BOUNDARY));
338     }
339     auto parentNode = GetParent().Upgrade();
340     while (parentNode) {
341         auto scroll = AceType::DynamicCast<RenderSingleChildScroll>(parentNode);
342         if (scroll) {
343             // do move then break
344             scroll->MoveChildToViewPort(GetLayoutSize(), GetGlobalOffset(), effectOffset);
345             break;
346         } else {
347             parentNode = parentNode->GetParent().Upgrade();
348         }
349     }
350 }
351 
DumpTree(int32_t depth)352 void RenderNode::DumpTree(int32_t depth)
353 {
354     auto accessibilityNode = GetAccessibilityNode().Upgrade();
355     int32_t nodeId = 0;
356     if (accessibilityNode) {
357         nodeId = accessibilityNode->GetNodeId();
358     }
359     const auto& children = GetChildren();
360     if (DumpLog::GetInstance().GetDumpFile()) {
361         auto dirtyRect = context_.Upgrade()->GetDirtyRect();
362         std::string touchRectList = "[";
363         for (auto& rect : touchRectList_) {
364             touchRectList.append("{").append(rect.ToString()).append("}");
365         }
366         touchRectList.append("]");
367 
368         DumpLog::GetInstance().AddDesc(std::string("AccessibilityNodeID: ").append(std::to_string(nodeId)));
369         DumpLog::GetInstance().AddDesc(std::string("Depth: ").append(std::to_string(depth)));
370         DumpLog::GetInstance().AddDesc(
371             std::string("DisappearingNodes: ").append(std::to_string(disappearingNodes_.size())));
372         DumpLog::GetInstance().AddDesc(std::string("GlobalOffset: ").append(GetGlobalOffset().ToString()));
373         DumpLog::GetInstance().AddDesc(std::string("PaintRect: ").append(paintRect_.ToString()));
374         DumpLog::GetInstance().AddDesc(std::string("TouchRect: ").append(touchRect_.ToString()));
375         DumpLog::GetInstance().AddDesc(std::string("TouchRectList: ").append(touchRectList));
376         DumpLog::GetInstance().AddDesc(std::string("DirtyRect: ").append(dirtyRect.ToString()));
377         DumpLog::GetInstance().AddDesc(std::string("LayoutParam: ").append(layoutParam_.ToString()));
378 #ifdef ENABLE_ROSEN_BACKEND
379         if (rsNode_) {
380             DumpLog::GetInstance().AddDesc(rsNode_->DumpNode(depth));
381         }
382 #endif
383         Dump();
384         DumpLog::GetInstance().Print(depth, AceType::TypeName(this), children.size());
385     }
386 
387     for (const auto& item : children) {
388         item->DumpTree(depth + 1);
389     }
390 }
391 
Dump()392 void RenderNode::Dump() {}
393 
RenderWithContext(RenderContext & context,const Offset & offset)394 void RenderNode::RenderWithContext(RenderContext& context, const Offset& offset)
395 {
396     MarkNeedWindowBlur(false);
397     if (onLayoutReady_ && pendingDispatchLayoutReady_) {
398         onLayoutReady_(std::string("\"layoutReady\",null,null"));
399     }
400     pendingDispatchLayoutReady_ = false;
401     if (GetHasSubWindow() || !GetNeedClip()) {
402         if (context.GetNeedRestoreHole()) {
403             context.Restore();
404             context.SetNeedRestoreHole(false);
405             context.SetClipHole(Rect());
406         }
407     } else {
408         context.SetClipHole(context_.Upgrade()->GetTransparentHole());
409     }
410     Paint(context, offset);
411     for (const auto& item : SortChildrenByZIndex(disappearingNodes_)) {
412         PaintChild(item, context, offset);
413     }
414     auto hasOnAreaChangeCallback = eventExtensions_ ? eventExtensions_->HasOnAreaChangeExtension() : false;
415     if (needUpdateAccessibility_ || hasOnAreaChangeCallback) {
416         auto pipelineContext = context_.Upgrade();
417         if (pipelineContext != nullptr) {
418             pipelineContext->AddNeedRenderFinishNode(AceType::Claim(this));
419         }
420     }
421     CheckIfNeedUpdateTouchRect();
422     SetNeedRender(false);
423 }
424 
NotifyPaintFinish()425 void RenderNode::NotifyPaintFinish()
426 {
427     bool hasObserver = false;
428     auto accessNode = accessibilityNode_.Upgrade();
429     if (accessNode) {
430         auto index = accessNode->GetNodeId();
431         auto pipeline = context_.Upgrade();
432         hasObserver = pipeline ? pipeline->IsVisibleChangeNodeExists(index) : false;
433     }
434     if (needUpdateAccessibility_ || hasObserver) {
435         for (auto& child : children_) {
436             child->NotifyPaintFinish();
437         }
438         auto pipelineContext = context_.Upgrade();
439         if (pipelineContext != nullptr) {
440             pipelineContext->AddNeedRenderFinishNode(AceType::Claim(this));
441         }
442     }
443 }
444 
Paint(RenderContext & context,const Offset & offset)445 void RenderNode::Paint(RenderContext& context, const Offset& offset)
446 {
447     const auto& children = GetChildren();
448     for (const auto& item : SortChildrenByZIndex(children)) {
449         PaintChild(item, context, offset);
450     }
451 }
452 
PaintChild(const RefPtr<RenderNode> & child,RenderContext & context,const Offset & offset)453 void RenderNode::PaintChild(const RefPtr<RenderNode>& child, RenderContext& context, const Offset& offset)
454 {
455     if (child && child->GetVisible()) {
456         context.PaintChild(child, offset);
457     }
458 }
459 
PaintChildList(const std::list<RefPtr<RenderNode>> & childList,RenderContext & context,const Offset & offset)460 void RenderNode::PaintChildList(
461     const std::list<RefPtr<RenderNode>>& childList, RenderContext& context, const Offset& offset)
462 {
463     for (const auto& item : SortChildrenByZIndex(childList)) {
464         PaintChild(item, context, offset);
465     }
466 }
467 
MarkNeedLayout(bool selfOnly,bool forceParent)468 void RenderNode::MarkNeedLayout(bool selfOnly, bool forceParent)
469 {
470     bool addSelf = false;
471     auto context = context_.Upgrade();
472     if (context != nullptr) {
473         context->ForceLayoutForImplicitAnimation();
474     }
475 
476     bool forceSelf = forceParent && AceType::InstanceOf<RenderRoot>(this);
477     if (forceSelf) {
478         // This is root and child need force parent layout.
479         SetNeedLayout(true);
480         addSelf = true;
481     } else if (forceParent) {
482         // Force mark self and all ancestors need layout.
483         SetNeedLayout(true);
484         auto parent = parent_.Upgrade();
485         if (parent && (parent->CheckIfNeedLayoutAgain() || forceParent)) {
486             parent->MarkNeedLayout(false, forceParent);
487         } else {
488             addSelf = true;
489         }
490     } else if (!needLayout_) {
491         SetNeedLayout(true);
492         if ((IsTakenBoundary() || selfOnly) && !MarkNeedRenderSpecial()) {
493             addSelf = true;
494         } else {
495             auto parent = parent_.Upgrade();
496             if (parent && parent->CheckIfNeedLayoutAgain()) {
497                 parent->MarkNeedLayout();
498             } else {
499                 addSelf = true;
500             }
501         }
502     }
503     if (addSelf) {
504         auto pipelineContext = context_.Upgrade();
505         if (pipelineContext != nullptr) {
506             pipelineContext->AddDirtyLayoutNode(AceType::Claim(this));
507         }
508     }
509 }
510 
MarkNeedPredictLayout()511 void RenderNode::MarkNeedPredictLayout()
512 {
513     auto pipelineContext = context_.Upgrade();
514     if (pipelineContext) {
515         pipelineContext->AddPredictLayoutNode(AceType::Claim(this));
516     }
517 }
518 
OnLayout()519 void RenderNode::OnLayout()
520 {
521     auto parent = parent_.Upgrade();
522     if (parent) {
523         Size parentViewPort = parent->GetChildViewPort();
524         if (viewPort_ != parentViewPort) {
525             viewPort_ = parentViewPort;
526             needLayout_ = true;
527         }
528     }
529     if (NeedLayout()) {
530         PrepareLayout();
531         PerformLayout();
532         layoutParamChanged_ = false;
533         SetNeedLayout(false);
534         pendingDispatchLayoutReady_ = true;
535         MarkNeedRender();
536     }
537 }
538 
PrepareLayout()539 void RenderNode::PrepareLayout() {}
540 
SetPosition(const Offset & offset)541 void RenderNode::SetPosition(const Offset& offset)
542 {
543     Offset selfOffset;
544     if (positionParam_.left.second) {
545         selfOffset.SetX(NormalizePercentToPx(positionParam_.left.first, false));
546     } else if (positionParam_.right.second) {
547         selfOffset.SetX(-NormalizePercentToPx(positionParam_.right.first, false));
548     } else {
549         selfOffset.SetX(0);
550     }
551     selfOffset.SetX(selfOffset.GetX() - NormalizePercentToPx(positionParam_.anchor.first, false, true));
552     if (positionParam_.top.second) {
553         selfOffset.SetY(NormalizePercentToPx(positionParam_.top.first, true));
554     } else if (positionParam_.bottom.second) {
555         selfOffset.SetY(-NormalizePercentToPx(positionParam_.bottom.first, true));
556     } else {
557         selfOffset.SetY(0);
558     }
559     selfOffset.SetY(selfOffset.GetY() - NormalizePercentToPx(positionParam_.anchor.second, true, true));
560     selfOffset_ = selfOffset;
561     SetPositionInternal(selfOffset + offset);
562 }
563 
Attach(const WeakPtr<PipelineContext> & context)564 void RenderNode::Attach(const WeakPtr<PipelineContext>& context)
565 {
566     context_ = context;
567     OnAttachContext();
568     paintX_.SetContextAndCallback(context_, [weak = WeakClaim(this)] {
569         auto render = weak.Upgrade();
570         if (!render) {
571             return;
572         }
573         auto parent = render->GetParent().Upgrade();
574         if (!parent) {
575             return;
576         }
577         parent->MarkNeedRender();
578         render->needUpdateTouchRect_ = true;
579         render->nonStrictPaintRect_.SetLeft(render->paintX_.Value());
580         render->OnGlobalPositionChanged();
581     });
582 
583     paintY_.SetContextAndCallback(context_, [weak = WeakClaim(this)] {
584         auto render = weak.Upgrade();
585         if (!render) {
586             return;
587         }
588         auto parent = render->GetParent().Upgrade();
589         if (!parent) {
590             return;
591         }
592         parent->MarkNeedRender();
593         render->needUpdateTouchRect_ = true;
594         render->nonStrictPaintRect_.SetTop(render->paintY_.Value());
595         render->OnGlobalPositionChanged();
596     });
597 
598     paintW_.SetContextAndCallback(context_, [weak = WeakClaim(this)] {
599         auto render = weak.Upgrade();
600         if (!render) {
601             return;
602         }
603         render->MarkNeedRender();
604         render->needUpdateTouchRect_ = true;
605         render->nonStrictPaintRect_.SetWidth(render->paintW_.Value());
606         render->transitionPaintRectSize_.SetWidth(render->paintW_.Value());
607         render->MarkNeedSyncGeometryProperties();
608     });
609 
610     paintH_.SetContextAndCallback(context_, [weak = WeakClaim(this)] {
611         auto render = weak.Upgrade();
612         if (!render) {
613             return;
614         }
615         render->MarkNeedRender();
616         render->needUpdateTouchRect_ = true;
617         render->nonStrictPaintRect_.SetHeight(render->paintH_.Value());
618         render->transitionPaintRectSize_.SetHeight(render->paintH_.Value());
619         render->MarkNeedSyncGeometryProperties();
620     });
621 }
622 
SetPositionInternal(const Offset & offset)623 void RenderNode::SetPositionInternal(const Offset& offset)
624 {
625     auto context = context_.Upgrade();
626     if (!context) {
627         LOGE("Set position internal failed. context is null.");
628         return;
629     }
630     if (paintRect_.GetOffset() != offset) {
631         isFirstPositionAssign_ = false;
632         nonStrictOption_ = context->GetExplicitAnimationOption();
633         context->AddLayoutTransitionNode(AceType::Claim(this));
634         paintRect_.SetOffset(offset);
635         needUpdateTouchRect_ = true;
636         OnPositionChanged();
637         OnGlobalPositionChanged();
638         MarkNeedSyncGeometryProperties();
639     }
640     if (isFirstPositionAssign_) {
641         isFirstPositionAssign_ = false;
642         nonStrictOption_ = context->GetExplicitAnimationOption();
643         context->AddLayoutTransitionNode(AceType::Claim(this));
644     }
645 }
646 
CheckIfNeedUpdateTouchRect()647 void RenderNode::CheckIfNeedUpdateTouchRect()
648 {
649     auto parent = parent_.Upgrade();
650     if (!parent) {
651         return;
652     }
653     parent->MarkNeedUpdateTouchRect(true);
654     parent->CheckIfNeedUpdateTouchRect();
655 }
656 
CreateMouseAnimation(RefPtr<KeyframeAnimation<Color>> & animation,const Color & from,const Color & to)657 void RenderNode::CreateMouseAnimation(RefPtr<KeyframeAnimation<Color>>& animation, const Color& from, const Color& to)
658 {
659     if (!animation) {
660         return;
661     }
662     auto colorFrameStart = AceType::MakeRefPtr<Keyframe<Color>>(PRESS_KEYFRAME_START, from);
663     auto colorFrameEnd = AceType::MakeRefPtr<Keyframe<Color>>(PRESS_KEYFRAME_END, to);
664     colorFrameEnd->SetCurve(Curves::SHARP);
665     animation->AddKeyframe(colorFrameStart);
666     animation->AddKeyframe(colorFrameEnd);
667     animation->AddListener([weakNode = AceType::WeakClaim(this)](const Color& value) {
668         auto node = weakNode.Upgrade();
669         if (node) {
670             node->eventEffectColor_ = value;
671             if (node->hoveAndPressCallback_) {
672                 node->hoveAndPressCallback_(value);
673             }
674             node->MarkNeedRender();
675         }
676     });
677 }
678 
MarkNeedRenderSpecial()679 bool RenderNode::MarkNeedRenderSpecial()
680 {
681     return false;
682 }
683 
MarkNeedRender(bool overlay)684 void RenderNode::MarkNeedRender(bool overlay)
685 {
686     if (!needRender_) {
687         SetNeedRender(true);
688         if (IsRepaintBoundary()) {
689             auto pipelineContext = context_.Upgrade();
690             if (pipelineContext) {
691                 pipelineContext->AddDirtyRenderNode(AceType::Claim(this), overlay);
692             }
693         } else {
694             auto parent = parent_.Upgrade();
695             if (parent) {
696                 parent->MarkNeedRender();
697             }
698         }
699     }
700 }
701 
SetVisible(bool visible,bool inRecursion)702 void RenderNode::SetVisible(bool visible, bool inRecursion)
703 {
704     if (visible_ != visible) {
705         visible_ = visible;
706         AddDirtyRenderBoundaryNode();
707         OnVisibleChanged();
708         CheckIfNeedUpdateTouchRect();
709         if (!inRecursion && SystemProperties::GetRosenBackendEnabled()) {
710             MarkParentNeedRender();
711         }
712     }
713     for (auto& child : children_) {
714         child->SetVisible(visible, true);
715     }
716 }
717 
TouchTest(const Point & globalPoint,const Point & parentLocalPoint,const TouchRestrict & touchRestrict,TouchTestResult & result)718 bool RenderNode::TouchTest(const Point& globalPoint, const Point& parentLocalPoint, const TouchRestrict& touchRestrict,
719     TouchTestResult& result)
720 {
721     LOGD("OnTouchTest: type is %{public}s, the region is %{public}lf, %{public}lf, %{public}lf, %{public}lf",
722         GetTypeName(), GetTouchRect().Left(), GetTouchRect().Top(), GetTouchRect().Width(), GetTouchRect().Height());
723     LOGD("OnTouchTest: the local point refer to parent is %{public}lf, %{public}lf, ", parentLocalPoint.GetX(),
724         parentLocalPoint.GetY());
725     if (disableTouchEvent_ || disabled_) {
726         return false;
727     }
728 
729     Point transformPoint = GetTransformPoint(parentLocalPoint);
730     if (!InTouchRectList(transformPoint, GetTouchRectList())) {
731         return false;
732     }
733 
734     const auto localPoint = transformPoint - GetPaintRect().GetOffset();
735     bool dispatchSuccess = DispatchTouchTestToChildren(localPoint, globalPoint, touchRestrict, result);
736     auto beforeSize = result.size();
737     std::vector<Rect> vrect;
738     if (IsResponseRegion()) {
739         vrect = responseRegionList_;
740     }
741     vrect.emplace_back(paintRect_);
742     for (const auto& rect : vrect) {
743         if (touchable_ && rect.IsInRegion(transformPoint)) {
744             // Calculates the coordinate offset in this node.
745             globalPoint_ = globalPoint;
746             const auto coordinateOffset = globalPoint - localPoint;
747             coordinatePoint_ = Point(coordinateOffset.GetX(), coordinateOffset.GetY());
748             OnTouchTestHit(coordinateOffset, touchRestrict, result);
749             break;
750         }
751     }
752     auto endSize = result.size();
753     return dispatchSuccess || (beforeSize != endSize && IsNotSiblingAddRecognizerToResult());
754 }
755 
DispatchTouchTestToChildren(const Point & localPoint,const Point & globalPoint,const TouchRestrict & touchRestrict,TouchTestResult & result)756 bool RenderNode::DispatchTouchTestToChildren(const Point& localPoint, const Point& globalPoint,
757     const TouchRestrict& touchRestrict, TouchTestResult& result)
758 {
759     bool dispatchSuccess = false;
760     if (!IsChildrenTouchEnable() || GetHitTestMode() == HitTestMode::HTMBLOCK) {
761         return dispatchSuccess;
762     }
763 
764     const auto& sortedChildren = SortChildrenByZIndex(GetChildren());
765     for (auto iter = sortedChildren.rbegin(); iter != sortedChildren.rend(); ++iter) {
766         const auto& child = *iter;
767         if (!child->GetVisible() || child->disabled_ || child->disableTouchEvent_) {
768             continue;
769         }
770         if (child->TouchTest(globalPoint, localPoint, touchRestrict, result)) {
771             dispatchSuccess = true;
772             if (child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) {
773                 break;
774             }
775         }
776         auto interceptTouchEvent = (child->IsTouchable() &&
777             (child->InterceptTouchEvent() || IsExclusiveEventForChild()) &&
778             child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT);
779         if (child->GetHitTestMode() == HitTestMode::HTMBLOCK || interceptTouchEvent) {
780             auto localTransformPoint = child->GetTransformPoint(localPoint);
781             bool isInRegion = false;
782             for (const auto& rect : child->GetTouchRectList()) {
783                 if (rect.IsInRegion(localTransformPoint)) {
784                     dispatchSuccess = true;
785                     isInRegion = true;
786                     break;
787                 }
788             }
789             if (isInRegion && child->GetHitTestMode() != HitTestMode::HTMDEFAULT) {
790                 break;
791             }
792         }
793     }
794     return dispatchSuccess;
795 }
796 
FindDropChild(const Point & globalPoint,const Point & parentLocalPoint)797 RefPtr<RenderNode> RenderNode::FindDropChild(const Point& globalPoint, const Point& parentLocalPoint)
798 {
799     Point transformPoint = GetTransformPoint(parentLocalPoint);
800     if (!InTouchRectList(transformPoint, GetTouchRectList())) {
801         return nullptr;
802     }
803 
804     const auto localPoint = transformPoint - GetPaintRect().GetOffset();
805     const auto& children = GetChildren();
806     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
807         auto& child = *iter;
808         if (!child->GetVisible()) {
809             continue;
810         }
811         if (child->InterceptTouchEvent()) {
812             continue;
813         }
814 
815         auto target = child->FindDropChild(globalPoint, localPoint);
816         if (target) {
817             return target;
818         }
819     }
820 
821     for (auto& rect : GetTouchRectList()) {
822         if (touchable_ && rect.IsInRegion(transformPoint)) {
823             RefPtr<RenderNode> renderNode = AceType::Claim<RenderNode>(this);
824             auto targetDropNode = AceType::DynamicCast<DragDropEvent>(renderNode);
825             if (targetDropNode && targetDropNode->GetOnDrop()) {
826                 return renderNode;
827             }
828         }
829     }
830 
831     return nullptr;
832 }
833 
MouseTest(const Point & globalPoint,const Point & parentLocalPoint,MouseRawResult & result)834 void RenderNode::MouseTest(const Point& globalPoint, const Point& parentLocalPoint, MouseRawResult& result)
835 {
836     LOGD("MouseTest: type is %{public}s, the region is %{public}lf, %{public}lf, %{public}lf, %{public}lf",
837         GetTypeName(), GetTouchRect().Left(), GetTouchRect().Top(), GetTouchRect().Width(), GetTouchRect().Height());
838     LOGD("MouseTest: the local point refer to parent is %{public}lf, %{public}lf, ", parentLocalPoint.GetX(),
839         parentLocalPoint.GetY());
840 
841     if (!InTouchRectList(parentLocalPoint, GetTouchRectList())) {
842         return;
843     }
844 
845     // Calculates the local point location in this node.
846     const auto localPoint = parentLocalPoint - paintRect_.GetOffset();
847     const auto& children = GetChildren();
848     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
849         auto& child = *iter;
850         child->MouseTest(globalPoint, localPoint, result);
851     }
852 
853     // Calculates the coordinate offset in this node.
854     const auto coordinatePoint = globalPoint - localPoint;
855     globalPoint_ = globalPoint;
856     OnMouseTestHit(coordinatePoint, result);
857 }
858 
MouseDetect(const Point & globalPoint,const Point & parentLocalPoint,MouseHoverTestList & hoverList,WeakPtr<RenderNode> & hoverNode)859 bool RenderNode::MouseDetect(const Point& globalPoint, const Point& parentLocalPoint, MouseHoverTestList& hoverList,
860     WeakPtr<RenderNode>& hoverNode)
861 {
862     LOGD("MouseDetect: type is %{public}s, the region is %{public}lf, %{public}lf, %{public}lf, %{public}lf",
863         GetTypeName(), GetTouchRect().Left(), GetTouchRect().Top(), GetTouchRect().Width(), GetTouchRect().Height());
864     if (disableTouchEvent_ || disabled_) {
865         return false;
866     }
867 
868     Point transformPoint = GetTransformPoint(parentLocalPoint);
869     if (!InTouchRectList(transformPoint, GetTouchRectList())) {
870         return false;
871     }
872 
873     const auto localPoint = transformPoint - GetPaintRect().GetOffset();
874     const auto& sortedChildren = SortChildrenByZIndex(GetChildren());
875     for (auto iter = sortedChildren.rbegin(); iter != sortedChildren.rend(); ++iter) {
876         auto& child = *iter;
877         if (!child->GetVisible() || child->disabled_ || child->disableTouchEvent_) {
878             continue;
879         }
880         child->MouseDetect(globalPoint, localPoint, hoverList, hoverNode);
881     }
882 
883     auto beforeSize = hoverList.size();
884     for (auto& rect : GetTouchRectList()) {
885         if (touchable_ && rect.IsInRegion(transformPoint)) {
886             if (!hoverNode.Upgrade()) {
887                 if (hoverAnimationType_ != HoverAnimationType::UNKNOWN) {
888                     hoverNode = AceType::WeakClaim<RenderNode>(this);
889                     LOGI("Got hoverEffect node: %{public}s", AceType::TypeName(this));
890                 }
891             }
892             hoverList.emplace_back(AceType::WeakClaim<RenderNode>(this));
893             // Calculates the coordinate offset in this node.
894             globalPoint_ = globalPoint;
895             auto offset = globalPoint - localPoint;
896             coordinatePoint_ = Point(offset.GetX(), offset.GetY());
897             break;
898         }
899     }
900     auto endSize = hoverList.size();
901     return beforeSize != endSize;
902 }
903 
AxisDetect(const Point & globalPoint,const Point & parentLocalPoint,WeakPtr<RenderNode> & axisNode,const AxisDirection direction)904 bool RenderNode::AxisDetect(const Point& globalPoint, const Point& parentLocalPoint, WeakPtr<RenderNode>& axisNode,
905     const AxisDirection direction)
906 {
907     LOGD("AxisDetect: type is %{public}s, the region is %{public}lf, %{public}lf, %{public}lf, %{public}lf",
908         GetTypeName(), GetTouchRect().Left(), GetTouchRect().Top(), GetTouchRect().Width(), GetTouchRect().Height());
909     if (disabled_) {
910         return false;
911     }
912 
913     Point transformPoint = GetTransformPoint(parentLocalPoint);
914     if (!InTouchRectList(transformPoint, GetTouchRectList())) {
915         return false;
916     }
917 
918     const auto localPoint = transformPoint - GetPaintRect().GetOffset();
919     const auto& sortedChildren = SortChildrenByZIndex(GetChildren());
920     for (auto iter = sortedChildren.rbegin(); iter != sortedChildren.rend(); ++iter) {
921         auto& child = *iter;
922         if (!child->GetVisible() || child->disabled_) {
923             continue;
924         }
925         child->AxisDetect(globalPoint, localPoint, axisNode, direction);
926     }
927 
928     for (auto& rect : GetTouchRectList()) {
929         if (touchable_ && rect.IsInRegion(transformPoint)) {
930             if (!axisNode.Upgrade()) {
931                 axisNode = CheckAxisNode();
932                 if (axisNode.Upgrade() && !(axisNode.Upgrade()->IsAxisScrollable(direction))) {
933                     axisNode = nullptr;
934                 }
935             }
936             // Calculates the coordinate offset in this node.
937             globalPoint_ = globalPoint;
938             auto offset = globalPoint - localPoint;
939             coordinatePoint_ = Point(offset.GetX(), offset.GetY());
940             break;
941         }
942     }
943     return true;
944 }
945 
MouseHoverTest(const Point & parentLocalPoint)946 bool RenderNode::MouseHoverTest(const Point& parentLocalPoint)
947 {
948     LOGD("OnMouseHoverTest: type is %{public}s, the region is %{public}lf, %{public}lf, %{public}lf, %{public}lf",
949         GetTypeName(), GetTouchRect().Left(), GetTouchRect().Top(), GetTouchRect().Width(), GetTouchRect().Height());
950     LOGD("OnMouseHoverTest: the local point refer to parent is %{public}lf, %{public}lf, ", parentLocalPoint.GetX(),
951         parentLocalPoint.GetY());
952     if (disabled_) {
953         return false;
954     }
955 
956     Point transformPoint = GetTransformPoint(parentLocalPoint);
957     const auto localPoint = transformPoint - GetPaintRect().GetOffset();
958 
959     if (!InTouchRectList(transformPoint, GetTouchRectList())) {
960         for (const auto& child : hoverChildren_) {
961             child->MouseHoverTest(localPoint);
962         }
963         // mouse state of the node is from HOVER to NONE, the callback of hover exit is triggered.
964         if (mouseState_ == MouseState::HOVER) {
965             if (hoverAnimationType_ == HoverAnimationType::AUTO) {
966                 OnMouseHoverExitTest();
967             } else {
968                 MouseHoverExitTest();
969             }
970             mouseState_ = MouseState::NONE;
971         }
972         return false;
973     }
974 
975     // Since the paintRect is relative to parent, use parent local point to perform touch test.
976     auto context = context_.Upgrade();
977     if (!context) {
978         return false;
979     }
980     hoverChildren_.clear();
981     context->AddToHoverList(AceType::WeakClaim(this).Upgrade());
982     const auto& children = GetChildren();
983     for (auto iter = children.begin(); iter != children.end(); ++iter) {
984         auto& child = *iter;
985         if (child->MouseHoverTest(localPoint)) {
986             hoverChildren_.emplace_back(child);
987         }
988     }
989     // mouse state of the node is from NONE to HOVER, the callback of hover enter is triggered.
990     if (mouseState_ == MouseState::NONE) {
991         if (hoverAnimationType_ == HoverAnimationType::AUTO) {
992             OnMouseHoverEnterTest();
993         } else {
994             MouseHoverEnterTest();
995         }
996         mouseState_ = MouseState::HOVER;
997     }
998     return true;
999 }
1000 
1001 #if defined(PREVIEW)
SetAccessibilityRect(const Rect & rect)1002 void RenderNode::SetAccessibilityRect(const Rect& rect)
1003 {
1004     Rect parentRect = rect;
1005     if (!selfOffset_.IsZero()) {
1006         parentRect.SetOffset(parentRect.GetOffset() + selfOffset_);
1007     }
1008     auto node = accessibilityNode_.Upgrade();
1009     auto content = context_.Upgrade();
1010     Rect currentRect = Rect(GetGlobalOffset(), GetLayoutSize());
1011     Rect clampRect = currentRect.Constrain(parentRect);
1012     if (node && content) {
1013         if (clampRect.IsValid()) {
1014             auto size = Size(clampRect.Width(), clampRect.Height()) * content->GetViewScale();
1015             node->SetGlobalRect(currentRect * content->GetViewScale());
1016             if (size.Width() > node->GetWidth() || size.Height() > node->GetHeight()) {
1017                 // Same AccessibilityNode update the largest size.
1018                 node->SetWidth(size.Width());
1019                 node->SetHeight(size.Height());
1020                 node->SetLeft(clampRect.Left() * content->GetViewScale());
1021                 node->SetTop(clampRect.Top() * content->GetViewScale());
1022             } else if (NearEqual(size.Width(), node->GetWidth()) && NearEqual(size.Height(), node->GetHeight())) {
1023                 // Update the offset when same size.
1024                 node->SetLeft(clampRect.Left() * content->GetViewScale());
1025                 node->SetTop(clampRect.Top() * content->GetViewScale());
1026             }
1027             if (node->GetTag() == "tab-bar") {
1028                 return;
1029             }
1030         } else {
1031             SetAccessibilityVisible(false);
1032         }
1033     }
1034 }
1035 #else
SetAccessibilityRect(const Rect & rect)1036 void RenderNode::SetAccessibilityRect(const Rect& rect)
1037 {
1038     auto pipelineContext = context_.Upgrade();
1039     if (!pipelineContext) {
1040         return;
1041     }
1042     if (!pipelineContext->IsAccessibilityEnabled()) {
1043         return;
1044     }
1045     Rect parentRect = rect;
1046     if (!selfOffset_.IsZero()) {
1047         parentRect.SetOffset(parentRect.GetOffset() + selfOffset_);
1048     }
1049     auto node = accessibilityNode_.Upgrade();
1050     auto content = context_.Upgrade();
1051     Rect currentRect = Rect(GetGlobalOffset(), GetLayoutSize());
1052     Rect clampRect = currentRect.Constrain(parentRect);
1053     if (node && content) {
1054         node->SetGlobalRect(currentRect * content->GetViewScale());
1055         if (clampRect.IsValid()) {
1056             node->SetRect(clampRect * content->GetViewScale());
1057         } else {
1058             SetAccessibilityVisible(false);
1059         }
1060     }
1061     if (clampRect.IsValid()) {
1062         for (auto& child : children_) {
1063             // Fix case: child size is empty but access node is not empty.
1064             auto childAccessNode = child->GetAccessibilityNode().Upgrade();
1065             if (childAccessNode) {
1066                 auto childAccessGlobalRect = childAccessNode->GetGlobalRect();
1067                 if (childAccessGlobalRect.IsValid() && !child->GetPaintRect().IsValid()) {
1068                     continue;
1069                 }
1070             }
1071             child->SetAccessibilityRect(clampRect);
1072         }
1073     }
1074 }
1075 #endif
1076 
RotationMatchTest(const RefPtr<RenderNode> & requestRenderNode)1077 bool RenderNode::RotationMatchTest(const RefPtr<RenderNode>& requestRenderNode)
1078 {
1079     RotationNode* rotationNode = AceType::DynamicCast<RotationNode>(this);
1080     if ((rotationNode != nullptr) && requestRenderNode == this) {
1081         LOGD("RotationMatchTest: match rotation focus node %{public}s.", GetTypeName());
1082         return true;
1083     }
1084     const auto& children = GetChildren();
1085     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
1086         const auto& child = *iter;
1087         if (child && child->RotationMatchTest(requestRenderNode)) {
1088             return true;
1089         }
1090     }
1091 
1092     return false;
1093 }
1094 
RotationTest(const RotationEvent & event)1095 bool RenderNode::RotationTest(const RotationEvent& event)
1096 {
1097     if (disabled_) {
1098         return false;
1099     }
1100 
1101     const auto& children = GetChildren();
1102     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
1103         const auto& child = *iter;
1104         if (child && child->RotationTest(event)) {
1105             return true;
1106         }
1107     }
1108 
1109     RotationNode* rotationNode = AceType::DynamicCast<RotationNode>(this);
1110     if ((rotationNode != nullptr) && rotationNode->OnRotation(event)) {
1111         LOGD("RotationTest: type is %{public}s accept", GetTypeName());
1112         return true;
1113     }
1114 
1115     return false;
1116 }
1117 
RotationTestForward(const RotationEvent & event)1118 bool RenderNode::RotationTestForward(const RotationEvent& event)
1119 {
1120     RotationNode* rotationNode = AceType::DynamicCast<RotationNode>(this);
1121     if ((rotationNode != nullptr) && rotationNode->OnRotation(event)) {
1122         LOGD("RotationTestForward: type is %{public}s accept", GetTypeName());
1123         return true;
1124     }
1125     const auto& children = GetChildren();
1126     for (auto iter = children.begin(); iter != children.end(); ++iter) {
1127         const auto& child = *iter;
1128         if (child && child->RotationTestForward(event)) {
1129             return true;
1130         }
1131     }
1132 
1133     return false;
1134 }
1135 
GetBaselineDistance(TextBaseline textBaseline)1136 double RenderNode::GetBaselineDistance(TextBaseline textBaseline)
1137 {
1138     if (GetChildren().empty()) {
1139         return GetLayoutSize().Height();
1140     }
1141     return GetHighestChildBaseline(textBaseline);
1142 }
1143 
GetContentSize()1144 Size RenderNode::GetContentSize()
1145 {
1146     if (GetChildren().empty()) {
1147         return Size();
1148     }
1149     return GetLargestChildContentSize();
1150 }
1151 
ScrollPageByChild(Offset & delta,int32_t source)1152 bool RenderNode::ScrollPageByChild(Offset& delta, int32_t source)
1153 {
1154     RefPtr<RenderNode> parent = GetParent().Upgrade();
1155     if (parent) {
1156         return parent->ScrollPageByChild(delta, source);
1157     }
1158     return true;
1159 }
1160 
GetHighestChildBaseline(TextBaseline baseline)1161 double RenderNode::GetHighestChildBaseline(TextBaseline baseline)
1162 {
1163     double distance = 0.0;
1164     for (const auto& child : children_) {
1165         double childBaseline = child->GetBaselineDistance(baseline);
1166         childBaseline += child->GetPosition().GetY();
1167         distance = NearZero(distance) ? childBaseline : std::min(distance, childBaseline);
1168     }
1169     return distance;
1170 }
1171 
GetLargestChildContentSize()1172 Size RenderNode::GetLargestChildContentSize()
1173 {
1174     Size maxSize;
1175     for (const auto& child : children_) {
1176         Size childSize = child->GetContentSize();
1177         if (!childSize.IsValid()) {
1178             continue;
1179         }
1180         maxSize.SetWidth(maxSize.Width() > childSize.Width() ? maxSize.Width() : childSize.Width());
1181         maxSize.SetHeight(maxSize.Height() > childSize.Height() ? maxSize.Height() : childSize.Height());
1182     }
1183     return maxSize;
1184 }
1185 
GetFirstChildBaseline(TextBaseline baseline)1186 double RenderNode::GetFirstChildBaseline(TextBaseline baseline)
1187 {
1188     double distance = GetLayoutSize().Height();
1189     if (!GetChildren().empty()) {
1190         auto firstChild = GetChildren().front();
1191         distance = firstChild->GetBaselineDistance(baseline);
1192         distance += firstChild->GetPosition().GetY();
1193     }
1194     return distance;
1195 }
1196 
NormalizeToPx(Dimension dimension) const1197 double RenderNode::NormalizeToPx(Dimension dimension) const
1198 {
1199     if (dimension.Unit() == DimensionUnit::PX) {
1200         return dimension.Value();
1201     }
1202     auto context = context_.Upgrade();
1203     ACE_DCHECK(context);
1204     if (!context) {
1205         return dimension.Value();
1206     }
1207     return context->NormalizeToPx(dimension);
1208 }
1209 
NormalizePercentToPx(const Dimension & dimension,bool isVertical,bool referSelf) const1210 double RenderNode::NormalizePercentToPx(const Dimension& dimension, bool isVertical, bool referSelf) const
1211 {
1212     if (dimension.Unit() != DimensionUnit::PERCENT) {
1213         return NormalizeToPx(dimension);
1214     }
1215     Size referSize;
1216     if (referSelf) {
1217         referSize = GetLayoutSize();
1218     } else {
1219         auto parent = parent_.Upgrade();
1220         if (!parent) {
1221             referSize = GetLayoutParam().GetMaxSize();
1222         } else {
1223             if (positionParam_.type == PositionType::PTOFFSET) {
1224                 referSize = parent->GetLayoutSize();
1225             } else {
1226                 referSize = parent->GetLayoutParam().GetMaxSize();
1227             }
1228             if (referSize > viewPort_) {
1229                 referSize = viewPort_;
1230             }
1231         }
1232     }
1233     auto limit = isVertical ? referSize.Height() : referSize.Width();
1234     return limit * dimension.Value();
1235 }
1236 
GetOffsetFromOrigin(const Offset & offset) const1237 Offset RenderNode::GetOffsetFromOrigin(const Offset& offset) const
1238 {
1239     auto parent = parent_.Upgrade();
1240     if (!parent) {
1241         return offset;
1242     }
1243     Offset nowOffset = GetPosition();
1244     return parent->GetOffsetFromOrigin(offset + nowOffset);
1245 }
1246 
GetGlobalOffset() const1247 Offset RenderNode::GetGlobalOffset() const
1248 {
1249     Offset globalOffset = GetPosition();
1250     auto renderNode = parent_.Upgrade();
1251     while (renderNode) {
1252         globalOffset += renderNode->GetPosition();
1253         auto parentWeak = renderNode->GetParent();
1254         renderNode = parentWeak.Upgrade();
1255     }
1256     auto context = context_.Upgrade();
1257     if (!context) {
1258         return globalOffset;
1259     }
1260     auto isContainerModal = context->GetWindowModal() == WindowModal::CONTAINER_MODAL &&
1261         context->GetWindowManager()->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
1262     if (isContainerModal) {
1263         globalOffset = globalOffset + Offset(-(CONTAINER_BORDER_WIDTH.ConvertToPx() + CONTENT_PADDING.ConvertToPx()),
1264             -CONTAINER_TITLE_HEIGHT.ConvertToPx());
1265     }
1266     return globalOffset;
1267 }
1268 
GetPaintOffset() const1269 Offset RenderNode::GetPaintOffset() const
1270 {
1271     auto renderNode = parent_.Upgrade();
1272     bool isNotHead = !IsHeadRenderNode() || (renderNode ? (renderNode->rsNode_ == rsNode_) : false);
1273     return (renderNode && isNotHead) ? GetPosition() + renderNode->GetPaintOffset() : GetPosition();
1274 }
1275 
GetGlobalOffsetExternal() const1276 Offset RenderNode::GetGlobalOffsetExternal() const
1277 {
1278     auto renderNode = parent_.Upgrade();
1279     return renderNode ? GetPosition() + renderNode->GetGlobalOffsetExternal() : GetPosition();
1280 }
1281 
GetHeadRenderNode()1282 RefPtr<RenderNode> RenderNode::GetHeadRenderNode()
1283 {
1284     if (IsHeadRenderNode()) {
1285         return AceType::Claim(this);
1286     }
1287     auto renderNode = parent_.Upgrade();
1288     if (!renderNode) {
1289         return nullptr;
1290     }
1291     return renderNode->GetHeadRenderNode();
1292 }
1293 
IsVisible(const Rect & rect,bool totally) const1294 bool RenderNode::IsVisible(const Rect& rect, bool totally) const
1295 {
1296     Rect intersectRect = Rect(Offset(), GetLayoutSize());
1297     bool visible = totally ? rect.IsWrappedBy(intersectRect) : rect.IsIntersectWith(intersectRect);
1298     if (!visible) {
1299         return false;
1300     }
1301     auto parent = parent_.Upgrade();
1302     if (!parent) {
1303         return true;
1304     }
1305     return parent->IsVisible(rect + GetPosition());
1306 }
1307 
GetLastChild() const1308 RefPtr<RenderNode> RenderNode::GetLastChild() const
1309 {
1310     if (children_.empty()) {
1311         return nullptr;
1312     }
1313     return children_.back();
1314 }
1315 
GetFirstChild() const1316 RefPtr<RenderNode> RenderNode::GetFirstChild() const
1317 {
1318     if (children_.empty()) {
1319         return nullptr;
1320     }
1321     return children_.front();
1322 }
1323 
UpdateAccessibilityPosition()1324 void RenderNode::UpdateAccessibilityPosition()
1325 {
1326     const auto& context = context_.Upgrade();
1327     if (!context) {
1328         return;
1329     }
1330     auto viewScale = context->GetViewScale();
1331     if (NearZero(viewScale)) {
1332         return;
1333     }
1334 
1335     auto accessibilityNode = GetAccessibilityNode().Upgrade();
1336     if (!accessibilityNode) {
1337         return;
1338     }
1339 
1340     Size size = GetLayoutSize();
1341     Offset globalOffset = GetGlobalOffsetExternal();
1342     PositionInfo positionInfo = { (size.Width()) * viewScale, (size.Height()) * viewScale,
1343         (globalOffset.GetX()) * viewScale, (globalOffset.GetY()) * viewScale };
1344     accessibilityNode->SetPositionInfo(positionInfo);
1345 }
1346 
UpdateAccessibilityEnable(bool isEnabled)1347 void RenderNode::UpdateAccessibilityEnable(bool isEnabled)
1348 {
1349     auto accessibilityNode = accessibilityNode_.Upgrade();
1350     if (accessibilityNode) {
1351         accessibilityNode->SetEnabledState(isEnabled);
1352     }
1353 }
1354 
UpdateAll(const RefPtr<Component> & component)1355 void RenderNode::UpdateAll(const RefPtr<Component>& component)
1356 {
1357     if (!component) {
1358         LOGE("fail to update all due to component is null");
1359         return;
1360     }
1361     hitTestMode_ = component->GetHitTestMode();
1362     touchable_ = component->IsTouchable();
1363     disabled_ = component->IsDisabledStatus();
1364     UpdateAccessibilityEnable(!disabled_);
1365     isFirstNode_ = component->IsFirstNode();
1366     auto renderComponent = AceType::DynamicCast<RenderComponent>(component);
1367     CHECK_NULL_VOID(renderComponent);
1368     positionParam_ = renderComponent->GetPositionParam();
1369     motionPathOption_ = renderComponent->GetMotionPathOption();
1370 #ifdef ENABLE_ROSEN_BACKEND
1371     if (SystemProperties::GetRosenBackendEnabled() && motionPathOption_.IsValid()) {
1372         if (auto rsNode = GetRSNode()) {
1373             auto nativeMotionOption =
1374                 std::make_shared<Rosen::RSMotionPathOption>(NativeCurveHelper::ToNativeMotionPathOption(
1375                     motionPathOption_, positionParam_.type == PositionType::PTOFFSET));
1376             rsNode->SetMotionPathOption(nativeMotionOption);
1377         }
1378     }
1379 #endif
1380 
1381     if (!NearEqual(flexWeight_, renderComponent->GetFlexWeight())) {
1382         auto parentFlex = GetParent().Upgrade();
1383         if (parentFlex) {
1384             parentFlex->MarkNeedLayout();
1385         }
1386     }
1387     flexWeight_ = renderComponent->GetFlexWeight();
1388     displayIndex_ = renderComponent->GetDisplayIndex();
1389     displayIndexSetted_ = renderComponent->GetDisplayIndexSetted();
1390     isIgnored_ = renderComponent->IsIgnored();
1391     interceptTouchEvent_ = renderComponent->InterceptEvent();
1392     if (renderComponent->IsCustomComponent()) {
1393         onLayoutReady_ =
1394             AceAsyncEvent<void(const std::string&)>::Create(renderComponent->GetOnLayoutReadyMarker(), context_);
1395     }
1396     auto context = context_.Upgrade();
1397     if (context != nullptr) {
1398         minPlatformVersion_ = context->GetMinPlatformVersion();
1399     }
1400     SetZIndex(renderComponent->GetZIndex());
1401     isPercentSize_ = renderComponent->GetIsPercentSize();
1402     responseRegion_ = renderComponent->GetResponseRegion();
1403     isResponseRegion_ = renderComponent->IsResponseRegion();
1404     if (component->HasEventExtensions()) {
1405         eventExtensions_ = component->GetEventExtensions();
1406     }
1407     UpdatePropAnimation(component->GetAnimatables());
1408     Update(component);
1409     MarkNeedLayout();
1410 }
1411 
UpdateOpacity(uint8_t opacity)1412 void RenderNode::UpdateOpacity(uint8_t opacity)
1413 {
1414     if (!SupportOpacity()) {
1415         return;
1416     }
1417     if (opacity_ != opacity) {
1418         opacity_ = opacity;
1419         if (auto rsNode = GetRSNode()) {
1420 #ifdef ENABLE_ROSEN_BACKEND
1421             rsNode->SetAlpha(opacity_ / 255.0);
1422 #endif
1423         } else {
1424             MarkNeedRender();
1425         }
1426     }
1427 }
1428 
GetOpacityCallback(int32_t domId)1429 RenderNode::OpacityCallback RenderNode::GetOpacityCallback(int32_t domId)
1430 {
1431     if (domId != GetNodeId()) {
1432         return nullptr;
1433     }
1434     if (!SupportOpacity()) {
1435         return nullptr;
1436     }
1437     return [weak = AceType::WeakClaim(this)](uint8_t opacity) {
1438         auto render = weak.Upgrade();
1439         if (render) {
1440             render->UpdateOpacity(opacity);
1441         }
1442     };
1443 }
1444 
GetDomOpacityCallbacks(int32_t domId,std::list<OpacityCallback> & result)1445 void RenderNode::GetDomOpacityCallbacks(int32_t domId, std::list<OpacityCallback>& result)
1446 {
1447     if (domId != GetNodeId()) {
1448         return;
1449     }
1450     auto callback = GetOpacityCallback(domId);
1451     if (callback) {
1452         result.emplace_back(callback);
1453     }
1454     for (auto& child : children_) {
1455         child->GetDomOpacityCallbacks(domId, result);
1456     }
1457 }
1458 
GetNodeId() const1459 int32_t RenderNode::GetNodeId() const
1460 {
1461     return GetAccessibilityNodeId();
1462 }
1463 
GetOpacity() const1464 uint8_t RenderNode::GetOpacity() const
1465 {
1466     return opacity_;
1467 }
1468 
SupportOpacity()1469 bool RenderNode::SupportOpacity()
1470 {
1471     return false;
1472 }
1473 
GetOffsetToPage() const1474 Offset RenderNode::GetOffsetToPage() const
1475 {
1476     auto offset = GetGlobalOffset();
1477     auto context = GetContext().Upgrade();
1478     if (context) {
1479         offset = offset - context->GetPageRect().GetOffset();
1480     }
1481     return offset;
1482 }
1483 
ClearRenderObject()1484 void RenderNode::ClearRenderObject()
1485 {
1486     context_ = nullptr;
1487     viewPort_ = Size();
1488     globalPoint_ = Point();
1489     touchRect_ = Rect();
1490     accessibilityNode_ = nullptr;
1491     needUpdateAccessibility_ = true;
1492     disabled_ = false;
1493     positionParam_ = PositionParam();
1494     opacity_ = 255;
1495     interceptTouchEvent_ = false;
1496     mouseState_ = MouseState::NONE;
1497 
1498     ClearChildren();
1499     rsNode_ = nullptr;
1500     isHeadRenderNode_ = false;
1501     isTailRenderNode_ = false;
1502     isFirstNode_ = false;
1503     accessibilityText_ = "";
1504     layoutParam_ = LayoutParam();
1505     paintRect_ = Rect();
1506     paintX_ = Dimension();
1507     paintY_ = Dimension();
1508     paintW_ = Dimension();
1509     paintH_ = Dimension();
1510     nonStrictPaintRect_ = Rect();
1511     transitionPaintRectSize_ = Size();
1512     isFirstSizeAssign_ = true;
1513     isFirstPositionAssign_ = true;
1514     disappearingNodes_.clear();
1515     parent_ = nullptr;
1516     depth_ = 0;
1517     needRender_ = false;
1518     needLayout_ = false;
1519     visible_ = true;
1520     hidden_ = false;
1521     takeBoundary_ = false;
1522     layoutParamChanged_ = false;
1523     disableTouchEvent_ = false;
1524     needUpdateTouchRect_ = false;
1525     flexWeight_ = 0.0;
1526     displayIndex_ = 1;
1527     textDirection_ = TextDirection::LTR;
1528     onChangeCallback_ = nullptr;
1529     isPaintGeometryTransition_ = false;
1530     displayIndexSetted_ = false;
1531 }
1532 
GetGlobalWindowBlurRRect(std::vector<RRect> & coords) const1533 RRect RenderNode::GetGlobalWindowBlurRRect(std::vector<RRect>& coords) const
1534 {
1535     RRect windowBlurRRect = GetWindowBlurRRect();
1536     Rect innerRect = windowBlurRRect.GetRect();
1537     if (!innerRect.IsValid()) {
1538         return RRect {};
1539     } else {
1540         innerRect += GetPosition();
1541         windowBlurRRect += GetPosition();
1542         coords.push_back(windowBlurRRect);
1543         auto parent = GetParent().Upgrade();
1544         while (parent) {
1545             auto parentBlurRRect = parent->GetWindowBlurRRect();
1546             const Corner& corner = parentBlurRRect.GetCorner();
1547             // intersect with parent or set border radius should clip by java
1548             if (!innerRect.IsWrappedBy(parentBlurRRect.GetRect()) ||
1549                 (corner.topLeftRadius.GetX().IsValid() && corner.topLeftRadius.GetY().IsValid())) {
1550                 coords.push_back(parentBlurRRect);
1551             }
1552             innerRect = innerRect.Constrain(parentBlurRRect.GetRect());
1553             auto offset = parent->GetPosition();
1554             innerRect += offset;
1555             // out of view port
1556             if (!innerRect.IsValid()) {
1557                 coords.clear();
1558                 return RRect {};
1559             }
1560             for (auto& coord : coords) {
1561                 coord += offset;
1562             }
1563             parent = parent->GetParent().Upgrade();
1564         }
1565         return RRect::MakeRRect(innerRect, windowBlurRRect.GetCorner().topLeftRadius);
1566     }
1567 }
1568 
GetRectWithShadow() const1569 Rect RenderNode::GetRectWithShadow() const
1570 {
1571     Rect paintRect(paintRect_);
1572     if (InLayoutTransition()) {
1573         paintRect = nonStrictPaintRect_;
1574     }
1575     if (!hasShadow_ || !shadow_.IsValid()) {
1576         return Rect(Offset::Zero(), paintRect.GetSize());
1577     }
1578     auto blurRadius = shadow_.GetBlurRadius();
1579     auto elevation = shadow_.GetElevation();
1580     if (elevation > 0.0f && elevation < shadow_.GetLightHeight()) {
1581         // Conversion between blurRadius and elevation.
1582         blurRadius = elevation / (shadow_.GetLightHeight() - elevation) * shadow_.GetLightRadius();
1583     }
1584     auto radius = 2.0 * blurRadius + shadow_.GetSpreadRadius();
1585 
1586     Rect shadowRect = paintRect + (shadow_.GetOffset() - Offset(radius, radius));
1587     shadowRect += Size(2.0 * radius, 2.0 * radius);
1588     shadowRect = shadowRect.CombineRect(paintRect);
1589 
1590     Offset paintOffset = paintRect.GetOffset();
1591     Offset shadowOffset = shadowRect.GetOffset();
1592     Offset offset = Offset(std::min(0.0, shadowOffset.GetX() - paintOffset.GetX()),
1593         std::min(0.0, shadowOffset.GetY() - paintOffset.GetY()));
1594     return Rect(offset, shadowRect.GetSize());
1595 }
1596 
UpdateWindowBlurRRect(bool clear)1597 void RenderNode::UpdateWindowBlurRRect(bool clear)
1598 {
1599     auto pipelineContext = context_.Upgrade();
1600     if (!pipelineContext) {
1601         LOGE("pipelineContext is null");
1602         return;
1603     }
1604     if (clear) {
1605         pipelineContext->ClearWindowBlurRegion(GetNodeId());
1606     } else {
1607         std::vector<RRect> coords;
1608         auto blurRect = GetGlobalWindowBlurRRect(coords);
1609         pipelineContext->UpdateWindowBlurRegion(
1610             GetNodeId(), blurRect, GetWindowBlurProgress(), GetWindowBlurStyle(), coords);
1611     }
1612 }
1613 
WindowBlurTest()1614 void RenderNode::WindowBlurTest()
1615 {
1616     if (GetHidden() || !GetVisible()) {
1617         return;
1618     }
1619 
1620     if (NeedWindowBlur()) {
1621         UpdateWindowBlurRRect();
1622     }
1623     const auto& children = GetChildren();
1624     for (const auto& child : children) {
1625         child->WindowBlurTest();
1626     }
1627 }
1628 
HasEffectiveTransform() const1629 bool RenderNode::HasEffectiveTransform() const
1630 {
1631     return false;
1632 }
1633 
IsDisappearing()1634 bool RenderNode::IsDisappearing()
1635 {
1636     auto parentNode = parent_.Upgrade();
1637     if (!parentNode) {
1638         return false;
1639     }
1640     const auto& disappearingList = parentNode->disappearingNodes_;
1641     auto iter = std::find(disappearingList.begin(), disappearingList.end(), AceType::Claim(this));
1642     if (iter != disappearingList.end()) {
1643         return true;
1644     } else {
1645         return false;
1646     }
1647 }
HasDisappearingTransition(int32_t nodeId)1648 bool RenderNode::HasDisappearingTransition(int32_t nodeId)
1649 {
1650 #ifdef ENABLE_ROSEN_BACKEND
1651     if (SystemProperties::GetRosenBackendEnabled()) {
1652         if (isTailRenderNode_) {
1653             return false;
1654         }
1655         for (auto& child : children_) {
1656             if (child->HasDisappearingTransition(nodeId)) {
1657                 return true;
1658             }
1659         }
1660         return false;
1661     }
1662 #endif
1663     for (auto& child : children_) {
1664         if (child->GetNodeId() == nodeId) {
1665             if (child->HasDisappearingTransition(nodeId)) {
1666                 return true;
1667             }
1668         }
1669     }
1670     return false;
1671 }
1672 
NotifyTransition(TransitionType type,int32_t nodeId)1673 void RenderNode::NotifyTransition(TransitionType type, int32_t nodeId)
1674 {
1675 #ifdef ENABLE_ROSEN_BACKEND
1676     if (SystemProperties::GetRosenBackendEnabled()) {
1677         if (GetRSNode() == nullptr) {
1678             return;
1679         }
1680         // call OnRSTransition for all render_nodes sharing this RSNode
1681         OnRSTransition(type);
1682         if (isTailRenderNode_) {
1683             return;
1684         }
1685         for (auto& child : children_) {
1686             child->NotifyTransition(type, nodeId);
1687         }
1688         return;
1689     }
1690 #endif
1691     OnTransition(type, nodeId);
1692     for (auto& child : children_) {
1693         if (child->GetNodeId() == nodeId) {
1694             child->NotifyTransition(type, nodeId);
1695         }
1696     }
1697 }
1698 
NotifySizeTransition(const AnimationOption & option,Size fromSize,Size toSize,int32_t nodeId)1699 void RenderNode::NotifySizeTransition(const AnimationOption& option, Size fromSize, Size toSize, int32_t nodeId)
1700 {
1701     paintW_.MoveTo(fromSize.Width());
1702     paintH_.MoveTo(fromSize.Height());
1703     paintW_ = AnimatableDimension(toSize.Width());
1704     paintH_ = AnimatableDimension(toSize.Height());
1705     for (auto& child : children_) {
1706         if (child->GetNodeId() == nodeId) {
1707             child->NotifySizeTransition(option, fromSize, toSize, nodeId);
1708         }
1709     }
1710 }
1711 
GetDirtyRect() const1712 Rect RenderNode::GetDirtyRect() const
1713 {
1714     Rect dirty = Rect(GetGlobalOffset(), GetLayoutSize());
1715     auto context = context_.Upgrade();
1716     if (!context) {
1717         LOGE("Get dirty rect failed. context is null.");
1718         return dirty;
1719     }
1720     // check self has transform effect.
1721     if (HasEffectiveTransform()) {
1722         return context->GetRootRect();
1723     }
1724     // check parent has transform effect.
1725     auto pageRoot = context->GetLastPageRender();
1726     auto parent = GetParent().Upgrade();
1727     while (parent && parent != pageRoot) {
1728         if (parent->HasEffectiveTransform()) {
1729             return context->GetRootRect();
1730         }
1731         parent = parent->GetParent().Upgrade();
1732     }
1733     // No transform takes effect, return layoutSize.
1734     return dirty;
1735 }
1736 
IsPointInBox(const TouchEvent & point)1737 bool RenderNode::IsPointInBox(const TouchEvent& point)
1738 {
1739     double offsetX = GetGlobalOffset().GetX();
1740     double offsetY = GetGlobalOffset().GetY();
1741     double maxX = GetPaintRect().Width() + offsetX;
1742     double maxY = GetPaintRect().Height() + offsetY;
1743     if (InRegion(offsetX, maxX, point.x) && InRegion(offsetY, maxY, point.y)) {
1744         return true;
1745     }
1746     return false;
1747 }
1748 
GetAlignDeclarationOffset(AlignDeclarationPtr alignDeclarationPtr,Offset & offset) const1749 bool RenderNode::GetAlignDeclarationOffset(AlignDeclarationPtr alignDeclarationPtr, Offset& offset) const
1750 {
1751     offset = offset - GetPosition();
1752     auto renderNode = parent_.Upgrade();
1753     return renderNode ? renderNode->GetAlignDeclarationOffset(alignDeclarationPtr, offset) : false;
1754 }
1755 
SaveExplicitAnimationOption(const AnimationOption & option)1756 void RenderNode::SaveExplicitAnimationOption(const AnimationOption& option)
1757 {
1758     nonStrictOption_ = option;
1759 }
1760 
GetExplicitAnimationOption() const1761 const AnimationOption& RenderNode::GetExplicitAnimationOption() const
1762 {
1763     return nonStrictOption_;
1764 }
1765 
ClearExplicitAnimationOption()1766 void RenderNode::ClearExplicitAnimationOption()
1767 {
1768     nonStrictOption_ = AnimationOption();
1769 }
1770 
ClearDisappearingNode(RefPtr<RenderNode> child)1771 void RenderNode::ClearDisappearingNode(RefPtr<RenderNode> child)
1772 {
1773     disappearingNodes_.remove(child);
1774 }
1775 
CreateLayoutTransition()1776 void RenderNode::CreateLayoutTransition()
1777 {
1778     auto context = context_.Upgrade();
1779     if (!context) {
1780         return;
1781     }
1782     if (nonStrictOption_.IsValid()) {
1783         auto option = context->GetExplicitAnimationOption();
1784         context->SaveExplicitAnimationOption(nonStrictOption_);
1785         CreatePathAnimation();
1786         paintX_ = AnimatableDimension(paintRect_.GetOffset().GetX());
1787         paintY_ = AnimatableDimension(paintRect_.GetOffset().GetY());
1788         paintW_ = AnimatableDimension(paintRect_.GetSize().Width());
1789         paintH_ = AnimatableDimension(paintRect_.GetSize().Height());
1790         context->SaveExplicitAnimationOption(option);
1791         nonStrictOption_ = AnimationOption();
1792     } else {
1793         if (paintX_.GetAnimationStatus() != Animator::Status::RUNNING) {
1794             paintX_.MoveTo(paintRect_.GetOffset().GetX());
1795         }
1796         if (paintY_.GetAnimationStatus() != Animator::Status::RUNNING) {
1797             paintY_.MoveTo(paintRect_.GetOffset().GetY());
1798         }
1799         if (paintW_.GetAnimationStatus() != Animator::Status::RUNNING) {
1800             paintW_.MoveTo(paintRect_.GetSize().Width());
1801         }
1802         if (paintH_.GetAnimationStatus() != Animator::Status::RUNNING) {
1803             paintH_.MoveTo(paintRect_.GetSize().Height());
1804         }
1805     }
1806 
1807     nonStrictPaintRect_.SetOffset(Offset(paintX_.Value(), paintY_.Value()));
1808     nonStrictPaintRect_.SetSize(Size(paintW_.Value(), paintH_.Value()));
1809 }
1810 
CreatePathAnimation()1811 void RenderNode::CreatePathAnimation()
1812 {
1813     if (!motionPathOption_.IsValid()) {
1814         paintX_.SetEvaluator(nullptr);
1815         paintY_.SetEvaluator(nullptr);
1816         return;
1817     }
1818     if (paintX_.Value() == paintRect_.GetOffset().GetX() && paintY_.Value() == paintRect_.GetOffset().GetY()) {
1819         LOGE("CreatePathAnimation failed, target equal source");
1820         return;
1821     }
1822 
1823     auto evaluator = AceType::MakeRefPtr<MotionPathEvaluator>(
1824         motionPathOption_, Offset(paintX_.Value(), paintY_.Value()), paintRect_.GetOffset(), positionParam_.type);
1825     paintX_.SetEvaluator(evaluator->CreateXEvaluator());
1826     paintY_.SetEvaluator(evaluator->CreateYEvaluator());
1827     // find transform to create rotate Animation
1828     if (motionPathOption_.GetRotate()) {
1829         auto child = GetFirstChild();
1830         while (child) {
1831             auto transform = AceType::DynamicCast<RenderTransform>(child);
1832             if (transform) {
1833                 transform->SetMotionPathEvaluator(evaluator);
1834                 break;
1835             }
1836             child = child->GetFirstChild();
1837         }
1838     }
1839 }
1840 
CreateGeometryTransitionFrom(const RefPtr<RenderNode> & targetNode,AnimationOption & sharedOption)1841 void RenderNode::CreateGeometryTransitionFrom(const RefPtr<RenderNode>& targetNode, AnimationOption& sharedOption)
1842 {
1843     auto context = context_.Upgrade();
1844     if (!context) {
1845         return;
1846     }
1847     auto weak = AceType::WeakClaim(this);
1848     auto render = weak.Upgrade();
1849     if (!render) {
1850         return;
1851     }
1852     const Rect targetPaintRect_ = targetNode->GetPaintRect();
1853     const Offset targetOffset = targetNode->GetTransitionGlobalOffset();
1854     const Offset currentOffset = render->GetGlobalOffset();
1855     if (sharedOption.IsValid()) {
1856         auto option = context->GetExplicitAnimationOption();
1857         context->SaveExplicitAnimationOption(sharedOption);
1858         Size toSize = paintRect_.GetSize();
1859         Size fromSize = targetPaintRect_.GetSize();
1860         isPaintGeometryTransition_ = true;
1861         for (auto& child : children_) {
1862             child->SetIsPaintGeometryTransition(isPaintGeometryTransition_);
1863         }
1864         paintX_.MoveTo(targetOffset.GetX());
1865         paintY_.MoveTo(targetOffset.GetY());
1866         paintX_.SetAnimationStopCallback([weak = AceType::WeakClaim(this)] {
1867             auto render = weak.Upgrade();
1868             if (!render) {
1869                 return;
1870             }
1871             auto children = render->GetChildren();
1872             render->isPaintGeometryTransition_ = false;
1873             for (auto& child : children) {
1874                 child->SetIsPaintGeometryTransition(render->isPaintGeometryTransition_);
1875             }
1876             auto parent = render->GetParent().Upgrade();
1877             if (!parent) {
1878                 return;
1879             }
1880             render->paintX_.MoveTo(render->GetGlobalOffset().GetX() - parent->GetGlobalOffset().GetX());
1881             render->paintY_.MoveTo(render->GetGlobalOffset().GetY() - parent->GetGlobalOffset().GetY());
1882         });
1883         paintY_.SetAnimationStopCallback([weak = AceType::WeakClaim(this)] {
1884             auto render = weak.Upgrade();
1885             if (!render) {
1886                 return;
1887             }
1888             auto children = render->GetChildren();
1889             render->isPaintGeometryTransition_ = false;
1890             for (auto& child : children) {
1891                 child->SetIsPaintGeometryTransition(render->isPaintGeometryTransition_);
1892             }
1893             auto parent = render->GetParent().Upgrade();
1894             if (!parent) {
1895                 return;
1896             }
1897             render->paintX_.MoveTo(render->GetGlobalOffset().GetX() - parent->GetGlobalOffset().GetX());
1898             render->paintY_.MoveTo(render->GetGlobalOffset().GetY() - parent->GetGlobalOffset().GetY());
1899         });
1900         paintX_ = AnimatableDimension(currentOffset.GetX());
1901         paintY_ = AnimatableDimension(currentOffset.GetY());
1902         render->NotifySizeTransition(sharedOption, fromSize, toSize, render->GetNodeId());
1903         context->SaveExplicitAnimationOption(option);
1904     }
1905 }
1906 
CreateGeometryTransitionTo(const RefPtr<RenderNode> & targetNode,AnimationOption & sharedOption)1907 void RenderNode::CreateGeometryTransitionTo(const RefPtr<RenderNode>& targetNode, AnimationOption& sharedOption)
1908 {
1909     auto context = context_.Upgrade();
1910     if (!context) {
1911         return;
1912     }
1913     auto weak = AceType::WeakClaim(this);
1914     auto render = weak.Upgrade();
1915     if (!render) {
1916         return;
1917     }
1918     const Rect targetPaintRect_ = targetNode->GetPaintRect();
1919     const Offset targetOffset = targetNode->GetGlobalOffset();
1920     const Offset currentOffset = render->GetTransitionGlobalOffset();
1921     if (sharedOption.IsValid()) {
1922         auto option = context->GetExplicitAnimationOption();
1923         context->SaveExplicitAnimationOption(sharedOption);
1924         Size fromSize = paintRect_.GetSize();
1925         Size toSize = targetPaintRect_.GetSize();
1926         isPaintGeometryTransition_ = true;
1927         for (auto& child : children_) {
1928             child->SetIsPaintGeometryTransition(isPaintGeometryTransition_);
1929         }
1930         paintX_.MoveTo(currentOffset.GetX());
1931         paintY_.MoveTo(currentOffset.GetY());
1932         paintX_.SetAnimationStopCallback([weak = AceType::WeakClaim(this)] {
1933             auto render = weak.Upgrade();
1934             if (!render) {
1935                 return;
1936             }
1937             auto children = render->GetChildren();
1938             render->isPaintGeometryTransition_ = false;
1939             for (auto& child : children) {
1940                 child->SetIsPaintGeometryTransition(render->isPaintGeometryTransition_);
1941             }
1942             auto parent = render->GetParent().Upgrade();
1943             if (!parent) {
1944                 return;
1945             }
1946             render->paintX_.MoveTo(render->GetGlobalOffset().GetX() - parent->GetGlobalOffset().GetX());
1947             render->paintY_.MoveTo(render->GetGlobalOffset().GetY() - parent->GetGlobalOffset().GetY());
1948         });
1949         paintY_.SetAnimationStopCallback([weak = AceType::WeakClaim(this)] {
1950             auto render = weak.Upgrade();
1951             if (!render) {
1952                 return;
1953             }
1954             auto children = render->GetChildren();
1955             render->isPaintGeometryTransition_ = false;
1956             for (auto& child : children) {
1957                 child->SetIsPaintGeometryTransition(render->isPaintGeometryTransition_);
1958             }
1959             auto parent = render->GetParent().Upgrade();
1960             if (!parent) {
1961                 return;
1962             }
1963             render->paintX_.MoveTo(render->GetGlobalOffset().GetX() - parent->GetGlobalOffset().GetX());
1964             render->paintY_.MoveTo(render->GetGlobalOffset().GetY() - parent->GetGlobalOffset().GetY());
1965         });
1966         paintX_ = AnimatableDimension(targetOffset.GetX());
1967         paintY_ = AnimatableDimension(targetOffset.GetY());
1968         render->NotifySizeTransition(sharedOption, fromSize, toSize, render->GetNodeId());
1969         context->SaveExplicitAnimationOption(option);
1970     }
1971 }
1972 
GetPaintRect() const1973 const Rect& RenderNode::GetPaintRect() const
1974 {
1975     if (InLayoutTransition()) {
1976         return nonStrictPaintRect_;
1977     } else {
1978         return paintRect_;
1979     }
1980 }
1981 
GetTransitionGlobalOffset() const1982 Offset RenderNode::GetTransitionGlobalOffset() const
1983 {
1984     auto renderNode = parent_.Upgrade();
1985     return renderNode ? GetTransitionPaintRect().GetOffset() + renderNode->GetTransitionGlobalOffset()
1986                       : GetTransitionPaintRect().GetOffset();
1987 }
1988 
GetTransitionPaintRect() const1989 Rect RenderNode::GetTransitionPaintRect() const
1990 {
1991     if (InLayoutTransition()) {
1992         return Rect(nonStrictPaintRect_.GetOffset(), transitionPaintRectSize_);
1993     } else {
1994         return paintRect_;
1995     }
1996 }
1997 
SetLayoutSize(const Size & size)1998 void RenderNode::SetLayoutSize(const Size& size)
1999 {
2000     auto context = context_.Upgrade();
2001     if (!context) {
2002         LOGE("Set layout size failed. context is null.");
2003         return;
2004     }
2005     if (paintRect_.GetSize() != size) {
2006         isFirstSizeAssign_ = false;
2007         nonStrictOption_ = context->GetExplicitAnimationOption();
2008         context->AddLayoutTransitionNode(AceType::Claim(this));
2009         // get bigger canvas size duration transition.
2010         transitionPaintRectSize_ = Rect(Offset(), paintRect_.GetSize()).CombineRect(Rect(Offset(), size)).GetSize();
2011         paintRect_.SetSize(size);
2012         needUpdateTouchRect_ = true;
2013         OnSizeChanged();
2014         MarkNeedSyncGeometryProperties();
2015     }
2016     if (isFirstSizeAssign_) {
2017         isFirstSizeAssign_ = false;
2018         nonStrictOption_ = context->GetExplicitAnimationOption();
2019         context->AddLayoutTransitionNode(AceType::Claim(this));
2020     }
2021 }
2022 
InLayoutTransition() const2023 bool RenderNode::InLayoutTransition() const
2024 {
2025     return paintX_.GetAnimationStatus() == Animator::Status::RUNNING ||
2026            paintY_.GetAnimationStatus() == Animator::Status::RUNNING ||
2027            paintW_.GetAnimationStatus() == Animator::Status::RUNNING ||
2028            paintH_.GetAnimationStatus() == Animator::Status::RUNNING;
2029 }
2030 
MarkUpdateType(const RefPtr<Component> & component)2031 void RenderNode::MarkUpdateType(const RefPtr<Component>& component)
2032 {
2033     updateType_ = component->Compare(GetComponent());
2034     if (updateType_ & static_cast<uint32_t>(UpdateRenderType::LAYOUT)) {
2035         MarkNeedLayout();
2036         return;
2037     }
2038     if (updateType_ & static_cast<uint32_t>(UpdateRenderType::PAINT)) {
2039         MarkNeedRender();
2040         return;
2041     }
2042 }
2043 
SetIsPaintGeometryTransition(bool isPaintGeometryTransition)2044 void RenderNode::SetIsPaintGeometryTransition(bool isPaintGeometryTransition)
2045 {
2046     isPaintGeometryTransition_ = isPaintGeometryTransition;
2047 }
2048 
SetPaintOutOfParent(bool isPaintOutOfParent)2049 void RenderNode::SetPaintOutOfParent(bool isPaintOutOfParent)
2050 {
2051     isPaintOutOfParent_ = isPaintOutOfParent;
2052 }
2053 
IsPaintOutOfParent()2054 bool RenderNode::IsPaintOutOfParent()
2055 {
2056     return isPaintGeometryTransition_ || isPaintOutOfParent_;
2057 }
2058 
UpdatePosition()2059 void RenderNode::UpdatePosition()
2060 {
2061     if (isPaintGeometryTransition_) {
2062         nonStrictPaintRect_.SetLeft(paintX_.Value() - GetParent().Upgrade()->GetTransitionGlobalOffset().GetX());
2063         nonStrictPaintRect_.SetTop(paintY_.Value() - GetParent().Upgrade()->GetTransitionGlobalOffset().GetY());
2064     }
2065 }
2066 
SetDepth(int32_t depth)2067 void RenderNode::SetDepth(int32_t depth)
2068 {
2069     if (depth_ != depth) {
2070         depth_ = depth;
2071         const auto& children = GetChildren();
2072         for (const auto& item : children) {
2073             item->SetDepth(depth_ + 1);
2074         }
2075     }
2076 }
2077 
SyncRSNodeBoundary(bool isHead,bool isTail,const RefPtr<Component> & component)2078 void RenderNode::SyncRSNodeBoundary(bool isHead, bool isTail, const RefPtr<Component>& component)
2079 {
2080     isHeadRenderNode_ = isHead;
2081 #ifdef ENABLE_ROSEN_BACKEND
2082     isTailRenderNode_ = isTail;
2083 
2084     // if "UseExternalRSNode" is true, we should find tail component and extract RSNode from it.
2085     if (ProcessExternalRSNode(component)) {
2086         return;
2087     }
2088 
2089     if (isHead && !rsNode_) {
2090         // create RSNode in first node of JSview
2091         rsNode_ = CreateRSNode();
2092     } else if (!isHead && rsNode_) {
2093         // destroy unneeded RSNode
2094         rsNode_ = nullptr;
2095     }
2096 #endif
2097 }
2098 
ProcessExternalRSNode(const RefPtr<Component> & component)2099 bool RenderNode::ProcessExternalRSNode(const RefPtr<Component>& component)
2100 {
2101 #ifdef ENABLE_ROSEN_BACKEND
2102     if (!isHeadRenderNode_ || component == nullptr || !component->UseExternalRSNode()) {
2103         return false;
2104     }
2105 
2106     auto tailComponent = component;
2107     // recursively locate tail component.
2108     while (tailComponent != nullptr && !tailComponent->IsTailComponent()) {
2109         if (auto singleChild = AceType::DynamicCast<SingleChild>(tailComponent)) {
2110             tailComponent = singleChild->GetChild();
2111         } else {
2112             return false;
2113         }
2114     }
2115 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(LINUX_PLATFORM)
2116     // extract RSNode from tail component.
2117     auto rsNode = RosenRenderRemoteWindow::ExtractRSNode(tailComponent);
2118     SyncRSNode(rsNode);
2119     // avoid redundant function call.
2120     component->MarkUseExternalRSNode(false);
2121     return rsNode != nullptr;
2122 #endif
2123 #endif
2124     return false;
2125 }
2126 
SyncRSNode(const std::shared_ptr<RSNode> & rsNode)2127 void RenderNode::SyncRSNode(const std::shared_ptr<RSNode>& rsNode)
2128 {
2129 #ifdef ENABLE_ROSEN_BACKEND
2130     if (rsNode_ == rsNode) {
2131         return;
2132     }
2133     rsNode_ = rsNode;
2134     if (isTailRenderNode_) {
2135         return;
2136     }
2137     for (const auto& child : GetChildren()) {
2138         child->SyncRSNode(rsNode);
2139     }
2140 #endif
2141 }
2142 
MarkNeedSyncGeometryProperties()2143 void RenderNode::MarkNeedSyncGeometryProperties()
2144 {
2145     if (!HasGeometryProperties()) {
2146         return;
2147     }
2148     if (auto pipelineContext = context_.Upgrade()) {
2149         pipelineContext->AddGeometryChangedNode(AceType::Claim(this));
2150     }
2151 }
2152 
SyncGeometryProperties()2153 void RenderNode::SyncGeometryProperties()
2154 {
2155 #ifdef ENABLE_ROSEN_BACKEND
2156     if (!IsTailRenderNode()) {
2157         return;
2158     }
2159     auto rsNode = GetRSNode();
2160     if (!rsNode) {
2161         return;
2162     }
2163     Offset paintOffset = GetPaintOffset();
2164     Size paintSize = GetLayoutSize();
2165     rsNode->SetFrame(paintOffset.GetX(), paintOffset.GetY(), paintSize.Width(), paintSize.Height());
2166 #endif
2167 }
2168 
SetPaintRect(const Rect & rect)2169 void RenderNode::SetPaintRect(const Rect& rect)
2170 {
2171     if (paintRect_ == rect) {
2172         return;
2173     }
2174     paintRect_ = rect;
2175     needUpdateTouchRect_ = true;
2176 
2177     MarkNeedSyncGeometryProperties();
2178 }
2179 
RSNodeAddChild(const RefPtr<RenderNode> & child)2180 void RenderNode::RSNodeAddChild(const RefPtr<RenderNode>& child)
2181 {
2182 #ifdef ENABLE_ROSEN_BACKEND
2183     if (!rsNode_) {
2184         // workaround if parent have no RSNode while it should
2185         LOGD("Parent render_node has no RSNode, creating now.");
2186         SyncRSNodeBoundary(true, true);
2187     }
2188     if (IsTailRenderNode()) {
2189         if (!child->GetRSNode()) {
2190             // workaround if child have no RSNode while it should
2191             LOGD("Child render_node has no RSNode, creating now.");
2192             child->SyncRSNodeBoundary(true, true);
2193         }
2194     } else {
2195         if (child->rsNode_ && rsNode_ != child->rsNode_) {
2196             LOGE("Overwriting existing RSNode in child, this SHOULD NOT HAPPEN.");
2197         }
2198         // copy parent RSNode to child if they belong to the same JSView
2199         child->rsNode_ = rsNode_;
2200     }
2201 #endif
2202 }
2203 
MarkParentNeedRender() const2204 void RenderNode::MarkParentNeedRender() const
2205 {
2206     auto renderNode = parent_.Upgrade();
2207     if (!renderNode) {
2208         return;
2209     }
2210     if (IsHeadRenderNode()) {
2211         renderNode->MarkNeedRender();
2212     } else {
2213         renderNode->MarkParentNeedRender();
2214     }
2215 }
2216 
CreateRSNode() const2217 std::shared_ptr<RSNode> RenderNode::CreateRSNode() const
2218 {
2219 #ifdef ENABLE_ROSEN_BACKEND
2220     return Rosen::RSCanvasNode::Create();
2221 #else
2222     return nullptr;
2223 #endif
2224 }
2225 
OnStatusStyleChanged(VisualState state)2226 void RenderNode::OnStatusStyleChanged(VisualState state)
2227 {
2228     LOGD("start %{public}s", AceType::TypeName(this));
2229     if (isHeadRenderNode_) {
2230         return;
2231     }
2232     RefPtr<RenderNode> parent = parent_.Upgrade();
2233     if (parent) {
2234         parent->OnStatusStyleChanged(state);
2235     }
2236 }
2237 
ComputeSelectedZone(const Offset & startOffset,const Offset & endOffset)2238 Rect RenderNode::ComputeSelectedZone(const Offset& startOffset, const Offset& endOffset)
2239 {
2240     Rect selectedZone;
2241     if (startOffset.GetX() <= endOffset.GetX()) {
2242         if (startOffset.GetY() <= endOffset.GetY()) {
2243             // bottom right
2244             selectedZone = Rect(startOffset.GetX(), startOffset.GetY(),
2245                 endOffset.GetX() - startOffset.GetX(), endOffset.GetY() - startOffset.GetY());
2246             return selectedZone;
2247         } else {
2248             // top right
2249             selectedZone = Rect(startOffset.GetX(), endOffset.GetY(),
2250                 endOffset.GetX() - startOffset.GetX(), startOffset.GetY() - endOffset.GetY());
2251             return selectedZone;
2252         }
2253     } else {
2254         if (startOffset.GetY() <= endOffset.GetY()) {
2255             // bottom left
2256             selectedZone = Rect(endOffset.GetX(), startOffset.GetY(),
2257                 startOffset.GetX() - endOffset.GetX(), endOffset.GetY() - startOffset.GetY());
2258             return selectedZone;
2259         } else {
2260             // top left
2261             selectedZone = Rect(endOffset.GetX(), endOffset.GetY(),
2262                 startOffset.GetX() - endOffset.GetX(), startOffset.GetY() - endOffset.GetY());
2263             return selectedZone;
2264         }
2265     }
2266 }
2267 
SendAccessibilityEvent(const std::string & eventType)2268 void RenderNode::SendAccessibilityEvent(const std::string& eventType)
2269 {
2270     auto accessibilityNode = GetAccessibilityNode().Upgrade();
2271     if (!accessibilityNode) {
2272         return;
2273     }
2274     auto context = context_.Upgrade();
2275     if (context) {
2276         AccessibilityEvent event;
2277         event.nodeId = accessibilityNode->GetNodeId();
2278         event.eventType = eventType;
2279         context->SendEventToAccessibility(event);
2280     }
2281 }
2282 
SetAccessibilityClick(RefPtr<ClickRecognizer> clickRecognizer)2283 void RenderNode::SetAccessibilityClick(RefPtr<ClickRecognizer> clickRecognizer)
2284 {
2285     auto accessibilityNode = accessibilityNode_.Upgrade();
2286     if (!accessibilityNode) {
2287         return;
2288     }
2289     if (clickRecognizer) {
2290         accessibilityNode->SetClickableState(true);
2291         auto weakPtr = AceType::WeakClaim(AceType::RawPtr(clickRecognizer));
2292         accessibilityNode->SetActionClickImpl([weakPtr]() {
2293             auto click = weakPtr.Upgrade();
2294             if (click) {
2295                 click->OnAccepted();
2296             }
2297         });
2298     } else {
2299         accessibilityNode->SetClickableState(false);
2300         accessibilityNode->SetActionClickImpl(nullptr);
2301     }
2302 }
2303 
2304 } // namespace OHOS::Ace
2305