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