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