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