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