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