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