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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BASE_RENDER_NODE_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BASE_RENDER_NODE_H
18 
19 #include <list>
20 
21 #include "base/geometry/dimension.h"
22 #include "base/geometry/matrix4.h"
23 #include "base/geometry/rect.h"
24 #include "base/memory/ace_type.h"
25 #include "base/utils/macros.h"
26 #include "base/utils/system_properties.h"
27 #include "core/accessibility/accessibility_manager.h"
28 #include "core/animation/animatable_properties.h"
29 #include "core/animation/keyframe_animation.h"
30 #include "core/animation/property_animatable.h"
31 #include "core/common/draw_delegate.h"
32 #include "core/components/common/layout/align_declaration.h"
33 #include "core/components/common/layout/constants.h"
34 #include "core/components/common/layout/layout_param.h"
35 #include "core/components/common/properties/motion_path_option.h"
36 #include "core/components/common/properties/state_attributes.h"
37 #include "core/components/common/properties/text_style.h"
38 #include "core/components_v2/extensions/events/event_extensions.h"
39 #include "core/components_v2/inspector/inspector_node.h"
40 #include "core/event/axis_event.h"
41 #include "core/event/mouse_raw_recognizer.h"
42 #include "core/event/touch_event.h"
43 #include "core/gestures/click_recognizer.h"
44 #include "core/gestures/drag_recognizer.h"
45 #include "core/pipeline/base/render_context.h"
46 #include "core/pipeline/base/render_layer.h"
47 #include "core/pipeline/pipeline_context.h"
48 
49 namespace OHOS::Ace {
50 
51 extern const Dimension FOCUS_BOUNDARY;
52 
53 class Component;
54 
55 // If no insertion location is specified, new child will be added to the end of children list by default.
56 constexpr int32_t DEFAULT_RENDER_NODE_SLOT = -1;
57 constexpr int32_t PRESS_DURATION = 100;
58 constexpr int32_t HOVER_DURATION = 250;
59 constexpr uint32_t FIND_MAX_COUNT = 64;
60 
61 using HoverAndPressCallback = std::function<void(const Color&)>;
62 using Rosen::RSNode;
63 
64 // RenderNode is the base class for different render backend, represent a render unit for render pipeline.
65 class ACE_EXPORT RenderNode : public PropertyAnimatable, public AnimatableProperties, public virtual AceType {
66     DECLARE_ACE_TYPE(RenderNode, PropertyAnimatable, AceType);
67 
68 public:
69     using OpacityCallback = std::function<void(uint8_t)>;
70     using SlipFactorSetting = std::function<void(double)>;
71     ~RenderNode() override = default;
72 
73     static void MarkTreeRender(const RefPtr<RenderNode>& root, bool& meetHole, bool needFlush);
74 
75     static void MarkWholeRender(const WeakPtr<RenderNode>& nodeWeak, bool needFlush);
76 
SetZIndex(int32_t zIndex)77     void SetZIndex(int32_t zIndex)
78     {
79         zIndex_ = zIndex;
80     }
81 
GetZIndex()82     int32_t GetZIndex() const
83     {
84         return zIndex_;
85     }
86 
SetIsPercentSize(bool isPercentSize)87     void SetIsPercentSize(bool isPercentSize)
88     {
89         isPercentSize_ = isPercentSize;
90     }
91 
GetIsPercentSize()92     bool GetIsPercentSize() const
93     {
94         return isPercentSize_;
95     }
96 
97     void AddChild(const RefPtr<RenderNode>& child, int32_t slot = DEFAULT_RENDER_NODE_SLOT);
98 
99     void RemoveChild(const RefPtr<RenderNode>& child);
100 
101     void MovePosition(int32_t slot);
102 
103     void ClearChildren();
104 
105     virtual void MoveWhenOutOfViewPort(bool hasEffect);
106 
107     bool IsPointInBox(const TouchEvent& point);
108     void Attach(const WeakPtr<PipelineContext>& context);
109 
110     // unmount from render tree
Unmount()111     void Unmount()
112     {
113         RefPtr<RenderNode> parent = parent_.Upgrade();
114         if (parent) {
115             parent->MarkNeedLayout();
116             parent->RemoveChild(AceType::Claim(this));
117         }
118         parent_ = nullptr;
119     }
120 
121     // Update node with attr, style, event, method and so on.
122     // This method will call Update virtual function.
123     void UpdateAll(const RefPtr<Component>& component);
124 
AddToScene()125     virtual void AddToScene() {}
126 
127     virtual void Update(const RefPtr<Component>& component) = 0;
128 
129     // Called when page context attached, subclass can initialize object which needs page context.
OnAttachContext()130     virtual void OnAttachContext() {}
131 
FinishRender(const std::unique_ptr<DrawDelegate> & delegate,const Rect & dirty)132     virtual void FinishRender(const std::unique_ptr<DrawDelegate>& delegate, const Rect& dirty) {}
133 
134     virtual void UpdateTouchRect();
135 
136     void SetTouchRectList(std::vector<Rect>& touchRectList);
137     bool CompareTouchRect(const Rect& parentTouchRect, const Rect& childTouchRect);
138     void CompareTouchRectList(std::vector<Rect>& touchRectList,
139         const std::vector<Rect>& childTouchRectList, const std::vector<Rect>& parentTouchRectList);
140 
NeedLayout()141     bool NeedLayout() const
142     {
143         return needLayout_;
144     }
145 
SetNeedLayout(bool needLayout)146     void SetNeedLayout(bool needLayout)
147     {
148         needLayout_ = needLayout;
149     }
150 
151     void MarkNeedLayout(bool selfOnly = false, bool forceParent = false);
152 
153     /**
154      * \brief check in mark need layout progress if parent need layout again.
155      * \return true if need layout again.
156      */
CheckIfNeedLayoutAgain()157     virtual bool CheckIfNeedLayoutAgain()
158     {
159         return true;
160     }
161 
162     void MarkNeedPredictLayout();
163 
164     void OnLayout();
165 
166     // deadline : The remaining time until the next vsync. (unit: microsecond)
OnPredictLayout(int64_t deadline)167     virtual void OnPredictLayout(int64_t deadline) {}
168 
GetChildViewPort()169     virtual Size GetChildViewPort()
170     {
171         return viewPort_;
172     }
173 
174     // Called by parent to perform layout.
Layout(const LayoutParam & layoutParam)175     void Layout(const LayoutParam& layoutParam)
176     {
177         auto pipeline = context_.Upgrade();
178         if (!pipeline) {
179             LOGE("pipeline is null when layout");
180             return;
181         }
182 
183         bool dipScaleChange = !NearEqual(pipeline->GetDipScale(), dipScale_);
184         dipScale_ = pipeline->GetDipScale();
185         if (dipScaleChange || layoutParam_ != layoutParam) {
186             layoutParam_ = layoutParam;
187             layoutParamChanged_ = true;
188             SetNeedLayout(true);
189         }
190 
191         if (onChangeCallback_) {
192             onChangeCallback_();
193         }
194         OnLayout();
195     }
196 
197     // Called by parent to update layout param without PerformLayout.
SetLayoutParam(const LayoutParam & layoutParam)198     void SetLayoutParam(const LayoutParam& layoutParam)
199     {
200         if (layoutParam_ != layoutParam) {
201             layoutParam_ = layoutParam;
202             layoutParamChanged_ = true;
203             MarkNeedLayout();
204         }
205     }
206 
GetLayoutParam()207     const LayoutParam& GetLayoutParam() const
208     {
209         return layoutParam_;
210     }
211 
212     // Each subclass should override this function for actual layout operation.
213     virtual void PerformLayout() = 0;
214 
GetPosition()215     Offset GetPosition() const
216     {
217         return paintRect_.GetOffset();
218     }
219 
220     void SetPosition(const Offset& offset);
221 
SetAbsolutePosition(const Offset & offset)222     void SetAbsolutePosition(const Offset& offset)
223     {
224         SetPositionInternal(offset);
225     }
226 
GetLayoutSize()227     Size GetLayoutSize() const
228     {
229         return paintRect_.GetSize();
230     }
231 
232     Rect GetRectWithShadow() const;
233 
SetShadow(const Shadow & shadow)234     void SetShadow(const Shadow& shadow)
235     {
236         shadow_ = shadow;
237         hasShadow_ = true;
238     }
239 
240     void SetLayoutSize(const Size& size);
241 
GetRectBasedWindowTopLeft()242     Rect GetRectBasedWindowTopLeft()
243     {
244         return Rect(GetGlobalOffset(), paintRect_.GetSize());
245     }
246 
GetTouchRect()247     virtual const Rect& GetTouchRect()
248     {
249         if (needUpdateTouchRect_) {
250             needUpdateTouchRect_ = false;
251             UpdateTouchRect();
252         }
253         return touchRect_;
254     }
255 
GetTouchRectList()256     virtual const std::vector<Rect>& GetTouchRectList()
257     {
258         if (needUpdateTouchRect_) {
259             needUpdateTouchRect_ = false;
260             touchRectList_.clear();
261             UpdateTouchRect();
262         }
263         return touchRectList_;
264     }
265 
ChangeTouchRectList(std::vector<Rect> & touchRectList)266     void ChangeTouchRectList(std::vector<Rect>& touchRectList)
267     {
268         touchRectList_ = touchRectList;
269     }
270 
InTouchRectList(const Point & parentLocalPoint,const std::vector<Rect> & touchRectList)271     bool InTouchRectList(const Point& parentLocalPoint, const std::vector<Rect>& touchRectList) const
272     {
273         for (auto& rect : touchRectList) {
274             if (rect.IsInRegion(parentLocalPoint)) {
275                 return true;
276             }
277         }
278         return false;
279     }
280 
IsUseOnly()281     virtual bool IsUseOnly()
282     {
283         return false;
284     }
285 
IsNotSiblingAddRecognizerToResult()286     virtual bool IsNotSiblingAddRecognizerToResult()
287     {
288         return isNotSiblingAddRecognizerToResult_;
289     }
290 
MarkIsNotSiblingAddRecognizerToResult(bool isNotSiblingAddRecognizerToResult)291     void MarkIsNotSiblingAddRecognizerToResult(bool isNotSiblingAddRecognizerToResult)
292     {
293         isNotSiblingAddRecognizerToResult_ = isNotSiblingAddRecognizerToResult;
294     }
295 
GetTransformPoint(const Point & point)296     virtual Point GetTransformPoint(const Point& point)
297     {
298         return point;
299     }
300 
GetTransformRect(const Rect & rect)301     virtual Rect GetTransformRect(const Rect& rect)
302     {
303         return rect;
304     }
305 
306     const Rect& GetPaintRect() const;
307 
308     Rect GetTransitionPaintRect() const;
309 
310     Offset GetTransitionGlobalOffset() const;
311 
312     void SetPaintRect(const Rect& rect);
313 
SetTouchRect(const Rect & rect)314     void SetTouchRect(const Rect& rect)
315     {
316         touchRect_ = rect;
317         needUpdateTouchRect_ = false;
318     }
319 
MarkNeedUpdateTouchRect(bool needUpdateTouchRect)320     void MarkNeedUpdateTouchRect(bool needUpdateTouchRect)
321     {
322         needUpdateTouchRect_ = needUpdateTouchRect;
323     }
324 
OnChildAdded(const RefPtr<RenderNode> & child)325     virtual void OnChildAdded(const RefPtr<RenderNode>& child)
326     {
327         if (slipFactorSetting_) {
328             child->SetSlipFactorSetting(slipFactorSetting_);
329         }
330     }
331 
OnChildRemoved(const RefPtr<RenderNode> & child)332     virtual void OnChildRemoved(const RefPtr<RenderNode>& child) {}
333 
OnRemove()334     virtual void OnRemove() {}
335 
GetAccessibilityText()336     const std::string& GetAccessibilityText() const
337     {
338         return accessibilityText_;
339     }
340 
SetAccessibilityText(const std::string & accessibilityText)341     void SetAccessibilityText(const std::string& accessibilityText)
342     {
343         accessibilityText_ = accessibilityText;
344     }
345 
346     virtual void DumpTree(int32_t depth);
347 
348     virtual void Dump();
349 
350     enum class BridgeType { NONE, ROSEN, FLUTTER };
351 
GetBridgeType()352     virtual BridgeType GetBridgeType() const
353     {
354         return BridgeType::NONE;
355     }
356 
SetNeedRender(bool needRender)357     void SetNeedRender(bool needRender)
358     {
359         needRender_ = needRender;
360     }
361 
362     void MarkNeedRender(bool overlay = false);
363 
NeedRender()364     bool NeedRender() const
365     {
366         return needRender_;
367     }
368 
369     void SetDepth(int32_t depth);
370 
SetPositionType(PositionType type)371     void SetPositionType(PositionType type)
372     {
373         positionParam_.type = type;
374     }
375 
GetDepth()376     int32_t GetDepth() const
377     {
378         return depth_;
379     }
380 
GetPositionType()381     PositionType GetPositionType() const
382     {
383         return positionParam_.type;
384     }
385 
GetLeft()386     virtual const Dimension& GetLeft() const
387     {
388         return positionParam_.left.first;
389     }
390 
GetRight()391     virtual const Dimension& GetRight() const
392     {
393         return positionParam_.right.first;
394     }
395 
GetTop()396     virtual const Dimension& GetTop() const
397     {
398         return positionParam_.top.first;
399     }
400 
GetBottom()401     virtual const Dimension& GetBottom() const
402     {
403         return positionParam_.bottom.first;
404     }
405 
GetAnchorX()406     const Dimension& GetAnchorX() const
407     {
408         return positionParam_.anchor.first;
409     }
410 
GetAnchorY()411     const Dimension& GetAnchorY() const
412     {
413         return positionParam_.anchor.second;
414     }
415 
HasLeft()416     virtual bool HasLeft() const
417     {
418         return positionParam_.left.second;
419     }
420 
HasRight()421     virtual bool HasRight() const
422     {
423         return positionParam_.right.second;
424     }
425 
HasTop()426     virtual bool HasTop() const
427     {
428         return positionParam_.top.second;
429     }
430 
HasBottom()431     virtual bool HasBottom() const
432     {
433         return positionParam_.bottom.second;
434     }
435 
SetLeft(const Dimension & left)436     virtual void SetLeft(const Dimension& left) // add for animation
437     {
438         if (positionParam_.left.first != left) {
439             positionParam_.left = std::make_pair(left, true);
440             MarkNeedLayout();
441         }
442     }
443 
SetTop(const Dimension & top)444     virtual void SetTop(const Dimension& top) // add for animation
445     {
446         if (positionParam_.top.first != top) {
447             positionParam_.top = std::make_pair(top, true);
448             MarkNeedLayout();
449         }
450     }
451 
SetRight(const Dimension & right)452     virtual void SetRight(const Dimension& right) // add for animation
453     {
454         if (positionParam_.right.first != right) {
455             positionParam_.top = std::make_pair(right, true);
456             MarkNeedLayout();
457         }
458     }
459 
SetBottom(const Dimension & bottom)460     virtual void SetBottom(const Dimension& bottom) // add for animation
461     {
462         if (positionParam_.bottom.first != bottom) {
463             positionParam_.bottom = std::make_pair(bottom, true);
464             MarkNeedLayout();
465         }
466     }
467 
GetParent()468     WeakPtr<RenderNode> GetParent() const
469     {
470         return parent_;
471     }
472 
GetContext()473     WeakPtr<PipelineContext> GetContext() const
474     {
475         return context_;
476     }
477 
GetRenderLayer()478     virtual RenderLayer GetRenderLayer()
479     {
480         return nullptr;
481     }
482 
483     virtual void SetVisible(bool visible, bool inRecursion = false);
484 
GetVisible()485     virtual bool GetVisible() const
486     {
487         return visible_;
488     }
489 
490     virtual void SetHidden(bool hidden, bool inRecursion = false)
491     {
492         if (hidden_ != hidden) {
493             hidden_ = hidden;
494             AddDirtyRenderBoundaryNode();
495             OnHiddenChanged(hidden);
496             if (!inRecursion && SystemProperties::GetRosenBackendEnabled()) {
497                 MarkParentNeedRender();
498             }
499             if (hidden_) {
500                 disableTouchEvent_ = true;
501             } else {
502                 disableTouchEvent_ = false;
503             }
504         }
505         for (auto& child : children_) {
506             child->SetHidden(hidden, true);
507         }
508     }
509 
SetSelfHidden(bool hidden)510     void SetSelfHidden(bool hidden)
511     {
512         if (hidden_ != hidden) {
513             hidden_ = hidden;
514             AddDirtyRenderBoundaryNode();
515             OnHiddenChanged(hidden);
516             if (SystemProperties::GetRosenBackendEnabled()) {
517                 MarkParentNeedRender();
518             }
519         }
520     }
521 
GetHidden()522     bool GetHidden() const
523     {
524         return hidden_;
525     }
526 
IsTakenBoundary()527     bool IsTakenBoundary() const
528     {
529         return takeBoundary_;
530     }
531 
IsRepaintBoundary()532     virtual bool IsRepaintBoundary() const
533     {
534         return IsHeadRenderNode();
535     }
536 
GetChildren()537     virtual const std::list<RefPtr<RenderNode>>& GetChildren() const
538     {
539         return children_;
540     }
541 
542     virtual void NotifyPaintFinish();
543 
544     virtual void RenderWithContext(RenderContext& context, const Offset& offset);
545     virtual void Paint(RenderContext& context, const Offset& offset);
546     void PaintChildList(const std::list<RefPtr<RenderNode>>& childList, RenderContext& context, const Offset& offset);
547     virtual void PaintChild(const RefPtr<RenderNode>& child, RenderContext& context, const Offset& offset);
548 
OnPaintFinish()549     virtual void OnPaintFinish() {}
550 
551     virtual bool TouchTest(const Point& globalPoint, const Point& parentLocalPoint, const TouchRestrict& touchRestrict,
552         TouchTestResult& result);
553 
554     virtual void MouseTest(const Point& globalPoint, const Point& parentLocalPoint, MouseRawResult& result);
555 
556     virtual bool MouseHoverTest(const Point& parentLocalPoint);
557 
558     virtual bool MouseDetect(const Point& globalPoint, const Point& parentLocalPoint, MouseHoverTestList& result,
559         WeakPtr<RenderNode>& hoverNode);
560 
561     virtual bool AxisDetect(const Point& globalPoint, const Point& parentLocalPoint, WeakPtr<RenderNode>& axisNode,
562         const AxisDirection direction);
563 
HandleMouseHoverEvent(const MouseState mouseState)564     virtual void HandleMouseHoverEvent(const MouseState mouseState) {}
565 
HandleMouseEvent(const MouseEvent & event)566     virtual bool HandleMouseEvent(const MouseEvent& event)
567     {
568         return false;
569     }
570 
HandleAxisEvent(const AxisEvent & event)571     virtual void HandleAxisEvent(const AxisEvent& event) {}
572 
573     virtual bool RotationMatchTest(const RefPtr<RenderNode>& requestRenderNode);
574 
575     virtual bool RotationTest(const RotationEvent& event);
576 
577     virtual bool RotationTestForward(const RotationEvent& event);
578 
579     virtual double GetBaselineDistance(TextBaseline textBaseline);
580 
581     virtual Size GetContentSize();
582 
583     virtual bool ScrollPageByChild(Offset& delta, int32_t source);
584 
585     // Change render nodes' status
ChangeStatus(RenderStatus renderStatus)586     void ChangeStatus(RenderStatus renderStatus)
587     {
588         // Myself status should be changed and function achieved by derived class which is component
589         OnStatusChanged(renderStatus);
590 
591         // Deep traversal
592         for (auto& child : children_) {
593             child->ChangeStatus(renderStatus);
594         }
595     }
596 
597     virtual void OnStatusStyleChanged(VisualState state);
598 
599     Offset GetOffsetFromOrigin(const Offset& offset) const;
600 
601     virtual Offset GetGlobalOffset() const;
602 
603     virtual Offset GetGlobalOffsetExternal() const;
604 
605     RefPtr<RenderNode> GetHeadRenderNode();
606 
607     // Whether |rect| is in the paint rect of render tree recursively.
608     bool IsVisible(const Rect& rect, bool totally = false) const;
609 
SetOnChangeCallback(std::function<void ()> && onChangeCallback)610     void SetOnChangeCallback(std::function<void()>&& onChangeCallback)
611     {
612         onChangeCallback_ = std::move(onChangeCallback);
613     }
614 
SetDisableTouchEvent(bool disableTouchEvent)615     void SetDisableTouchEvent(bool disableTouchEvent)
616     {
617         disableTouchEvent_ = disableTouchEvent;
618     }
619 
GetDisableTouchEvent()620     bool GetDisableTouchEvent() const
621     {
622         return disableTouchEvent_;
623     }
624 
IsChildrenTouchEnable()625     virtual bool IsChildrenTouchEnable()
626     {
627         return true;
628     }
629 
SetTextDirection(TextDirection textDirection)630     void SetTextDirection(TextDirection textDirection)
631     {
632         textDirection_ = textDirection;
633     }
634 
GetTextDirection()635     TextDirection GetTextDirection() const
636     {
637         return textDirection_;
638     }
639 
640     // Transfer any other dimension unit to logical px.
641     // NOTE: context_ MUST be initialized before call this method.
642     double NormalizeToPx(Dimension dimension) const;
643 
644     // Mainly use this function to convert Percent to Px. Do not call this function in Update().
645     double NormalizePercentToPx(const Dimension& dimension, bool isVertical, bool referSelf = false) const;
646 
647     // for accessibility
SetAccessibilityNode(const WeakPtr<AccessibilityNode> & accessibilityNode)648     void SetAccessibilityNode(const WeakPtr<AccessibilityNode>& accessibilityNode)
649     {
650         accessibilityNode_ = accessibilityNode;
651     }
652 
GetAccessibilityNode()653     const WeakPtr<AccessibilityNode>& GetAccessibilityNode() const
654     {
655         return accessibilityNode_;
656     }
657 
GetAccessibilityNodeId()658     int32_t GetAccessibilityNodeId() const
659     {
660         auto accessibilityNode = accessibilityNode_.Upgrade();
661         if (accessibilityNode) {
662             return accessibilityNode->GetNodeId();
663         }
664         return 0;
665     }
666 
ClearAccessibilityRect()667     void ClearAccessibilityRect()
668     {
669         auto node = accessibilityNode_.Upgrade();
670         if (node) {
671             node->ClearRect();
672         }
673         for (auto& child : children_) {
674             child->ClearAccessibilityRect();
675         }
676     }
677     void SetAccessibilityRect(const Rect& rect);
678 
SetNeedUpdateAccessibility(bool needUpdate)679     void SetNeedUpdateAccessibility(bool needUpdate)
680     {
681         needUpdateAccessibility_ = needUpdate;
682         for (auto& child : children_) {
683             child->SetNeedUpdateAccessibility(needUpdate);
684         }
685     }
686 
SetAccessibilityVisible(bool visible)687     void SetAccessibilityVisible(bool visible)
688     {
689         auto node = accessibilityNode_.Upgrade();
690         if (node) {
691             node->SetVisible(visible);
692         }
693         for (auto& child : children_) {
694             child->SetAccessibilityVisible(visible);
695         }
696     }
697 
698     RefPtr<RenderNode> GetLastChild() const;
699 
700     RefPtr<RenderNode> GetFirstChild() const;
701 
GetOffsetToStage()702     Offset GetOffsetToStage() const
703     {
704         auto offset = GetGlobalOffset();
705         auto context = GetContext().Upgrade();
706         if (context) {
707             offset = offset - context->GetStageRect().GetOffset();
708         }
709         return offset;
710     }
711 
712     Offset GetOffsetToPage() const;
713 
GetFlexWeight()714     double GetFlexWeight() const
715     {
716         return flexWeight_;
717     }
718 
GetDisplayIndex()719     int32_t GetDisplayIndex() const
720     {
721         return displayIndex_;
722     }
723 
GetDisplayIndexSetted()724     bool GetDisplayIndexSetted() const
725     {
726         return displayIndexSetted_;
727     }
728 
729     OpacityCallback GetOpacityCallback(int32_t domId);
730 
731     virtual bool SupportOpacity();
732 
733     void GetDomOpacityCallbacks(int32_t domId, std::list<OpacityCallback>& result);
734 
735     int32_t GetNodeId() const;
736 
737     uint8_t GetOpacity() const;
738 
739     virtual void UpdateOpacity(uint8_t opacity);
740 
InterceptTouchEvent()741     bool InterceptTouchEvent() const
742     {
743         return interceptTouchEvent_;
744     }
745 
SetInterceptTouchEvent(bool interceptTouchEvent)746     void SetInterceptTouchEvent(bool interceptTouchEvent)
747     {
748         interceptTouchEvent_ = interceptTouchEvent;
749     }
750 
DispatchCancelPressAnimation()751     void DispatchCancelPressAnimation()
752     {
753         OnCancelPressAnimation();
754         for (const auto& child : children_) {
755             child->DispatchCancelPressAnimation();
756         }
757     }
758 
CheckAxisNode()759     virtual WeakPtr<RenderNode> CheckAxisNode()
760     {
761         return nullptr;
762     }
MouseHoverEnterTest()763     virtual void MouseHoverEnterTest() {}
MouseHoverExitTest()764     virtual void MouseHoverExitTest() {}
AnimateMouseHoverEnter()765     virtual void AnimateMouseHoverEnter() {}
AnimateMouseHoverExit()766     virtual void AnimateMouseHoverExit() {}
OnCancelPressAnimation()767     virtual void OnCancelPressAnimation() {}
OnMouseHoverEnterAnimation()768     virtual void OnMouseHoverEnterAnimation() {}
OnMouseHoverExitAnimation()769     virtual void OnMouseHoverExitAnimation() {}
OnMouseClickDownAnimation()770     virtual void OnMouseClickDownAnimation() {}
OnMouseClickUpAnimation()771     virtual void OnMouseClickUpAnimation() {}
StopMouseHoverAnimation()772     virtual void StopMouseHoverAnimation() {}
IsAxisScrollable(AxisDirection direction)773     virtual bool IsAxisScrollable(AxisDirection direction)
774     {
775         return false;
776     }
777 
OnVisibleChanged()778     virtual void OnVisibleChanged() {}
779 
780     void CreateMouseAnimation(RefPtr<KeyframeAnimation<Color>>& animation, const Color& from, const Color& to);
SetHoverAndPressCallback(const HoverAndPressCallback & callback)781     void SetHoverAndPressCallback(const HoverAndPressCallback& callback)
782     {
783         hoveAndPressCallback_ = callback;
784     }
785 
GetEventEffectColor()786     Color GetEventEffectColor() const
787     {
788         return eventEffectColor_;
789     }
790 
791     void UpdateWindowBlurRRect(bool clear = false);
792 
793     void WindowBlurTest();
794 
GetWindowBlurRRect()795     virtual RRect GetWindowBlurRRect() const
796     {
797         return RRect::MakeRRect(Rect(Offset::Zero(), GetLayoutSize()), Radius(0.0));
798     }
799 
800     RRect GetGlobalWindowBlurRRect(std::vector<RRect>& coords) const;
801 
MarkNeedWindowBlur(bool flag)802     void MarkNeedWindowBlur(bool flag)
803     {
804         if (needWindowBlur_ != flag) {
805             needWindowBlur_ = flag;
806             if (!needWindowBlur_) {
807                 UpdateWindowBlurProgress(0.0f);
808                 SetWindowBlurStyle(WindowBlurStyle::STYLE_BACKGROUND_SMALL_LIGHT);
809             }
810             OnWindowBlurChanged();
811         }
812     }
813 
NeedWindowBlur()814     bool NeedWindowBlur() const
815     {
816         return needWindowBlur_;
817     }
818 
UpdateWindowBlurProgress(float progress)819     void UpdateWindowBlurProgress(float progress)
820     {
821         windowBlurProgress_ = progress;
822     }
823 
GetWindowBlurProgress()824     float GetWindowBlurProgress() const
825     {
826         return windowBlurProgress_;
827     }
828 
SetWindowBlurStyle(WindowBlurStyle style)829     void SetWindowBlurStyle(WindowBlurStyle style)
830     {
831         windowBlurStyle_ = style;
832     }
833 
GetWindowBlurStyle()834     WindowBlurStyle GetWindowBlurStyle() const
835     {
836         return windowBlurStyle_;
837     }
838 
SetSlipFactorSetting(const SlipFactorSetting & slipFactorSetting)839     void SetSlipFactorSetting(const SlipFactorSetting& slipFactorSetting)
840     {
841         slipFactorSetting_ = slipFactorSetting;
842     }
843 
IsInfiniteLayout()844     bool IsInfiniteLayout() const
845     {
846         return GetLayoutSize().Width() > INT32_MAX || GetLayoutSize().Height() > INT32_MAX;
847     }
848 
IsIgnored()849     bool IsIgnored() const
850     {
851         return isIgnored_;
852     }
853 
SetIsIgnored(bool ignore)854     void SetIsIgnored(bool ignore)
855     {
856         isIgnored_ = ignore;
857     }
858 
SetGlobalPoint(const Point & point)859     void SetGlobalPoint(const Point& point)
860     {
861         globalPoint_ = point;
862     }
863 
GetGlobalPoint()864     const Point& GetGlobalPoint()
865     {
866         return globalPoint_;
867     }
868 
SetCoordinatePoint(const Point & point)869     void SetCoordinatePoint(const Point& point)
870     {
871         coordinatePoint_ = point;
872     }
873 
GetCoordinatePoint()874     const Point& GetCoordinatePoint()
875     {
876         return coordinatePoint_;
877     }
878 
IsTouchable()879     bool IsTouchable() const
880     {
881         return touchable_;
882     }
883 
GetHitTestMode()884     HitTestMode GetHitTestMode() const
885     {
886         return hitTestMode_;
887     }
888 
IsDisabled()889     bool IsDisabled() const
890     {
891         return disabled_;
892     }
893 
OnAppShow()894     virtual void OnAppShow()
895     {
896         isAppOnShow_ = true;
897         for (const auto& child : children_) {
898             child->OnAppShow();
899         }
900     }
901 
OnAppHide()902     virtual void OnAppHide()
903     {
904         isAppOnShow_ = false;
905         for (const auto& child : children_) {
906             child->OnAppHide();
907         }
908     }
909 
IsAppShow()910     bool IsAppShow()
911     {
912         return isAppOnShow_;
913     }
914 
915     template<typename T>
GetTheme()916     RefPtr<T> GetTheme() const
917     {
918         auto context = context_.Upgrade();
919         if (!context) {
920             return nullptr;
921         }
922         auto themeManager = context->GetThemeManager();
923         if (!themeManager) {
924             return nullptr;
925         }
926         return themeManager->GetTheme<T>();
927     }
928 
929     virtual bool HasEffectiveTransform() const;
930 
OnTransition(TransitionType type,int32_t id)931     virtual void OnTransition(TransitionType type, int32_t id) {}
932 
933     bool IsDisappearing();
934     virtual bool HasDisappearingTransition(int32_t nodeId);
935     void NotifyTransition(TransitionType type, int32_t nodeId);
SetPendingAppearingTransition()936     virtual void SetPendingAppearingTransition() {}
937 
938     Rect GetDirtyRect() const;
939     std::function<void(const DragUpdateInfo&)> onDomDragEnter_ = nullptr;
940     std::function<void(const DragUpdateInfo&)> onDomDragOver_ = nullptr;
941     std::function<void(const DragUpdateInfo&)> onDomDragLeave_ = nullptr;
942     std::function<void(const DragEndInfo&)> onDomDragDrop_ = nullptr;
943     virtual bool GetAlignDeclarationOffset(AlignDeclarationPtr alignDeclarationPtr, Offset& offset) const;
944 
945     // Each subclass override this to return touch target object which is used to receive touch event.
946     // For convenience, it is recommended to return directly to the corresponding gesture recognizer.
947     // Sees gestures directory.
948     // Uses coordinateOffset for recognizer to calculate the local location of the touch point.
949     // Uses touchRestrict for restrict gesture recognition in some sense.
OnTouchTestHit(const Offset & coordinateOffset,const TouchRestrict & touchRestrict,TouchTestResult & result)950     virtual void OnTouchTestHit(
951         const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result)
952     {}
OnPreDraw()953     virtual void OnPreDraw() {}
954 
955     template<typename T>
FindChildNodeOfClass(const Point & globalPoint,const Point & parentLocalPoint)956     RefPtr<T> FindChildNodeOfClass(const Point& globalPoint, const Point& parentLocalPoint)
957     {
958         Point transformPoint = GetTransformPoint(parentLocalPoint);
959         if (!InTouchRectList(transformPoint, GetTouchRectList())) {
960             return nullptr;
961         }
962 
963         // Calculates the local point location in this node.
964         const auto localPoint = transformPoint - GetPaintRect().GetOffset();
965         const auto& children = GetChildren();
966         for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
967             auto& child = *iter;
968             if (!child->GetVisible()) {
969                 continue;
970             }
971 
972             if (child->InterceptTouchEvent()) {
973                 continue;
974             }
975 
976             auto target = child->FindChildNodeOfClass<T>(globalPoint, localPoint);
977             if (target) {
978                 return target;
979             }
980         }
981 
982         for (auto& rect : GetTouchRectList()) {
983             if (touchable_ && rect.IsInRegion(transformPoint)) {
984                 RefPtr<RenderNode> renderNode = AceType::Claim<RenderNode>(this);
985                 if (AceType::InstanceOf<T>(renderNode)) {
986                     return AceType::DynamicCast<T>(renderNode);
987                 }
988             }
989         }
990         return nullptr;
991     }
992 
993     template<typename T>
FindTargetRenderNode(const RefPtr<PipelineContext> context,const GestureEvent & info)994     RefPtr<T> FindTargetRenderNode(const RefPtr<PipelineContext> context, const GestureEvent& info)
995     {
996         if (!context) {
997             return nullptr;
998         }
999 
1000         auto pageRenderNode = context->GetLastPageRender();
1001         if (!pageRenderNode) {
1002             return nullptr;
1003         }
1004 
1005         return pageRenderNode->FindChildNodeOfClass<T>(info.GetGlobalPoint(), info.GetGlobalPoint());
1006     }
1007 
1008     template<class T>
FindChildOfClass(const RefPtr<RenderNode> & parent)1009     RefPtr<T> FindChildOfClass(const RefPtr<RenderNode>& parent)
1010     {
1011         // BFS to find child in tree.
1012         uint32_t findCount = 0;
1013         auto searchQueue = parent->GetChildren(); // copy children to a queue
1014         while (++findCount <= FIND_MAX_COUNT && !searchQueue.empty()) {
1015             const auto child = searchQueue.front();
1016             searchQueue.pop_front();
1017             if (!child) {
1018                 continue;
1019             }
1020             if (AceType::InstanceOf<T>(child)) {
1021                 return AceType::DynamicCast<T>(child);
1022             }
1023             searchQueue.insert(searchQueue.end(), child->GetChildren().begin(), child->GetChildren().end());
1024         }
1025         return RefPtr<T>();
1026     }
1027 
1028     void SaveExplicitAnimationOption(const AnimationOption& option);
1029 
1030     const AnimationOption& GetExplicitAnimationOption() const;
1031 
1032     void ClearExplicitAnimationOption();
1033 
1034     void ClearDisappearingNode(RefPtr<RenderNode> child);
1035 
1036     void CreateLayoutTransition();
1037 
1038     void CreatePathAnimation();
1039 
IsExclusiveEventForChild()1040     bool IsExclusiveEventForChild() const
1041     {
1042         return exclusiveEventForChild_;
1043     }
SetExclusiveEventForChild(bool exclusiveEventForChild)1044     void SetExclusiveEventForChild(bool exclusiveEventForChild)
1045     {
1046         exclusiveEventForChild_ = exclusiveEventForChild;
1047     }
1048 
1049     void MarkUpdateType(const RefPtr<Component>& component);
1050 
GetComponent()1051     virtual RefPtr<Component> GetComponent()
1052     {
1053         return nullptr;
1054     }
1055 
1056     virtual void NotifySizeTransition(const AnimationOption& option, Size fromSize, Size toSize, int32_t nodeId);
1057     void CreateGeometryTransitionFrom(const RefPtr<RenderNode>& targetNode, AnimationOption& sharedOption);
1058     void CreateGeometryTransitionTo(const RefPtr<RenderNode>& targetNode, AnimationOption& sharedOption);
1059     void SetIsPaintGeometryTransition(bool isPaintGeometryTransition);
1060     void SetPaintOutOfParent(bool isPaintOutOfParent);
1061     bool IsPaintOutOfParent();
1062     void UpdatePosition();
1063 
SetHasSubWindow(bool hasSubWindow)1064     void SetHasSubWindow(bool hasSubWindow)
1065     {
1066         hasSubWindow_ = hasSubWindow;
1067     }
1068 
GetHasSubWindow()1069     bool GetHasSubWindow() const
1070     {
1071         return hasSubWindow_;
1072     }
1073 
1074     // mark JSview boundary, create/destroy RSNode if need
1075     void SyncRSNodeBoundary(bool isHead, bool isTail, const RefPtr<Component>& component = nullptr);
1076     bool ProcessExternalRSNode(const RefPtr<Component>& component);
1077     void SyncRSNode(const std::shared_ptr<RSNode>& rsNode);
GetRSNode()1078     const std::shared_ptr<RSNode>& GetRSNode() const
1079     {
1080         return rsNode_;
1081     }
1082     // sync geometry properties to ROSEN backend
1083     virtual void SyncGeometryProperties();
1084 
IsResponseRegion()1085     bool IsResponseRegion() const
1086     {
1087         return isResponseRegion_;
1088     }
1089 
1090     double GetPxValue(double standard, const Dimension& value);
1091 
GetResponseRegionList()1092     const std::vector<Rect>& GetResponseRegionList() const
1093     {
1094         return responseRegionList_;
1095     }
1096 
GetInspectorNode()1097     const WeakPtr<V2::InspectorNode>& GetInspectorNode() const
1098     {
1099         return inspector_;
1100     }
1101 
SetInspectorNode(const RefPtr<V2::InspectorNode> & inspectorNode)1102     void SetInspectorNode(const RefPtr<V2::InspectorNode>& inspectorNode)
1103     {
1104         inspector_ = inspectorNode;
1105     }
1106 
SetNeedClip(bool needClip)1107     virtual void SetNeedClip(bool needClip)
1108     {
1109         needClip_ = needClip;
1110     }
1111 
GetNeedClip()1112     bool GetNeedClip()
1113     {
1114         return needClip_;
1115     }
1116 
1117     RefPtr<RenderNode> FindDropChild(const Point& globalPoint, const Point& parentLocalPoint);
1118     static constexpr size_t DEFAULT_INDEX = -1;
1119 
ProvideRestoreInfo()1120     virtual std::string ProvideRestoreInfo()
1121     {
1122         return "";
1123     }
1124 
SetRestoreInfo(const std::string & restoreInfo)1125     void SetRestoreInfo(const std::string& restoreInfo)
1126     {
1127         restoreInfo_ = restoreInfo;
1128     }
1129 
GetRestoreInfo()1130     const std::string& GetRestoreInfo() const
1131     {
1132         return restoreInfo_;
1133     }
1134 
1135     // JSview boundary, all nodes in [head, tail] share the same RSNode
IsHeadRenderNode()1136     bool IsHeadRenderNode() const
1137     {
1138 #ifdef ENABLE_ROSEN_BACKEND
1139         return SystemProperties::GetRosenBackendEnabled() ? isHeadRenderNode_ : false;
1140 #else
1141         return false;
1142 #endif
1143     }
1144 
1145 protected:
1146     explicit RenderNode(bool takeBoundary = false);
1147     virtual void ClearRenderObject();
1148 
OnMouseTestHit(const Offset & coordinateOffset,MouseRawResult & result)1149     virtual void OnMouseTestHit(const Offset& coordinateOffset, MouseRawResult& result) {}
OnMouseHoverEnterTest()1150     virtual void OnMouseHoverEnterTest() {}
OnMouseHoverExitTest()1151     virtual void OnMouseHoverExitTest() {}
1152     void SendAccessibilityEvent(const std::string& eventType);
1153     void SetAccessibilityClick(RefPtr<ClickRecognizer> clickRecognizer);
1154     bool DispatchTouchTestToChildren(const Point& localPoint, const Point& globalPoint,
1155         const TouchRestrict& touchRestrict, TouchTestResult& result);
1156 
1157     void PrepareLayout();
1158 
SetParent(const WeakPtr<RenderNode> & parent)1159     void SetParent(const WeakPtr<RenderNode>& parent)
1160     {
1161         parent_ = parent;
1162     }
1163 
1164     void TakeBoundary(bool taken = true)
1165     {
1166         takeBoundary_ = taken;
1167     }
1168 
IsLayoutParamChanged()1169     bool IsLayoutParamChanged() const
1170     {
1171         return layoutParamChanged_;
1172     }
1173 
OnGlobalPositionChanged()1174     virtual void OnGlobalPositionChanged()
1175     {
1176         MarkNeedSyncGeometryProperties();
1177         if (IsTailRenderNode()) {
1178             return;
1179         }
1180         for (const auto& child : children_) {
1181             if (child) {
1182                 child->OnGlobalPositionChanged();
1183             }
1184         }
1185     };
OnPositionChanged()1186     virtual void OnPositionChanged() {}
OnSizeChanged()1187     virtual void OnSizeChanged() {}
OnRenderFinish(RenderContext & context)1188     virtual void OnRenderFinish(RenderContext& context) {}
OnStatusChanged(RenderStatus renderStatus)1189     virtual void OnStatusChanged(RenderStatus renderStatus) {}
OnHiddenChanged(bool hidden)1190     virtual void OnHiddenChanged(bool hidden) {}
OnWindowBlurChanged()1191     virtual void OnWindowBlurChanged() {}
1192     virtual bool MarkNeedRenderSpecial();
1193 
1194     double GetHighestChildBaseline(TextBaseline baseline);
1195     double GetFirstChildBaseline(TextBaseline baseline);
1196     Size GetLargestChildContentSize();
1197     void UpdateAccessibilityPosition();
1198     void UpdateAccessibilityEnable(bool isEnabled);
1199     void CheckIfNeedUpdateTouchRect();
1200 
GetThemeManager()1201     RefPtr<ThemeManager> GetThemeManager() const
1202     {
1203         auto context = context_.Upgrade();
1204         if (!context) {
1205             return nullptr;
1206         }
1207         return context->GetThemeManager();
1208     }
1209 
GetUpdateType()1210     uint32_t GetUpdateType()
1211     {
1212         return updateType_;
1213     }
1214 
1215     virtual std::shared_ptr<RSNode> CreateRSNode() const;
OnRSTransition(TransitionType type)1216     virtual void OnRSTransition(TransitionType type) {}
IsTailRenderNode()1217     bool IsTailRenderNode() const
1218     {
1219         return isTailRenderNode_;
1220     }
1221     Offset GetPaintOffset() const;
HasGeometryProperties()1222     virtual bool HasGeometryProperties() const
1223     {
1224         return IsTailRenderNode();
1225     }
1226     void MarkNeedSyncGeometryProperties();
1227 
1228     bool hasSubWindow_ = false;
1229     bool needClip_ = false;
1230     WeakPtr<PipelineContext> context_;
1231     Size viewPort_;
1232     Point globalPoint_;
1233     Point coordinatePoint_;
1234     WeakPtr<V2::InspectorNode> inspector_;
1235     WeakPtr<AccessibilityNode> accessibilityNode_;
1236 
1237     // Used for RS extra case.
1238     bool isFirstNode_ = false;
1239 
1240     Rect touchRect_;                  // Self touch rect
1241     std::vector<Rect> touchRectList_; // Self and all children touch rect
1242     std::vector<DimensionRect> responseRegion_;
1243     std::vector<Rect> responseRegionList_;
1244     PositionParam positionParam_;
1245     uint8_t opacity_ = 255;
1246     Shadow shadow_;
1247 
1248     float windowBlurProgress_ = 0.0f;
1249     WindowBlurStyle windowBlurStyle_ = WindowBlurStyle::STYLE_BACKGROUND_SMALL_LIGHT;
1250     bool touchable_ = true;
1251     bool interceptTouchEvent_ = false;
1252     bool needWindowBlur_ = false;
1253     bool needUpdateAccessibility_ = true;
1254     bool disabled_ = false;
1255     bool isResponseRegion_ = false;
1256     HoverAnimationType hoverAnimationType_ = HoverAnimationType::UNKNOWN;
1257     int32_t minPlatformVersion_ = 0;
1258 
1259     MouseState mouseState_ = MouseState::NONE;
1260     SlipFactorSetting slipFactorSetting_;
1261 
1262     HoverAndPressCallback hoveAndPressCallback_;
1263 
1264     // hover or press color
1265     Color eventEffectColor_ = Color::TRANSPARENT;
1266     std::function<void(const std::string&)> onLayoutReady_;
1267 
1268     bool isAppOnShow_ = true;
1269     AnimationOption nonStrictOption_; // clear after transition done
1270     MotionPathOption motionPathOption_;
1271     RefPtr<V2::EventExtensions> eventExtensions_;
1272 
1273     // Compute multiSelect zone
1274     Rect ComputeSelectedZone(const Offset& startOffset, const Offset& endOffset);
1275 
1276 private:
AddDirtyRenderBoundaryNode()1277     void AddDirtyRenderBoundaryNode()
1278     {
1279         if (visible_ && !hidden_ && IsRepaintBoundary()) {
1280             auto pipelineContext = context_.Upgrade();
1281             if (pipelineContext == nullptr) {
1282                 return;
1283             }
1284             pipelineContext->AddDirtyRenderNode(AceType::Claim(this));
1285         }
1286     }
1287 
1288     void SetPositionInternal(const Offset& offset);
1289     bool InLayoutTransition() const;
1290     // Sync view hierarchy to RSNode
1291     void RSNodeAddChild(const RefPtr<RenderNode>& child);
1292     void MarkParentNeedRender() const;
1293     static std::shared_ptr<RSNode> ExtractExternalRSNode(const RefPtr<Component>& component);
1294 
1295     std::list<RefPtr<RenderNode>> hoverChildren_;
1296     std::list<RefPtr<RenderNode>> children_;
1297     std::string accessibilityText_;
1298     LayoutParam layoutParam_;
1299     Rect paintRect_;
1300     WeakPtr<RenderNode> parent_;
1301     int32_t depth_ = 0;
1302     bool needRender_ = false;
1303     bool needLayout_ = false;
1304     bool visible_ = true;
1305     bool takeBoundary_ = false;
1306     bool layoutParamChanged_ = false;
1307     bool pendingDispatchLayoutReady_ = false;
1308     bool disableTouchEvent_ = false;
1309     bool needUpdateTouchRect_ = false;
1310     bool hasShadow_ = false;
1311 
1312     double flexWeight_ = 0.0;
1313     int32_t displayIndex_ = 1;
1314     bool displayIndexSetted_ = false;
1315 
1316     double dipScale_ = 0.0;
1317 
1318     TextDirection textDirection_ { TextDirection::LTR };
1319     Offset selfOffset_ { 0, 0 };
1320 
1321     bool hidden_ = false;
1322     bool isIgnored_ = false;
1323     std::function<void()> onChangeCallback_;
1324     std::list<RefPtr<RenderNode>> disappearingNodes_;
1325     AnimatableDimension paintX_;
1326     AnimatableDimension paintY_;
1327     AnimatableDimension paintW_;
1328     AnimatableDimension paintH_;
1329     Size transitionPaintRectSize_;
1330     Rect nonStrictPaintRect_;
1331     bool isFirstSizeAssign_ = true;
1332     bool isFirstPositionAssign_ = true;
1333 
1334     // for container, this flag controls only the last child in touch area is consuming event.
1335     bool exclusiveEventForChild_ = false;
1336     int32_t zIndex_ = 0;
1337     bool isPercentSize_ = false;
1338     uint32_t updateType_ = 0;
1339 
1340     std::shared_ptr<RSNode> rsNode_ = nullptr;
1341     bool isHeadRenderNode_ = false;
1342     bool isTailRenderNode_ = false;
1343 
1344     bool isPaintGeometryTransition_ = false;
1345     bool isPaintOutOfParent_ = false;
1346 
1347     std::string restoreInfo_;
1348     bool isNotSiblingAddRecognizerToResult_ = true;
1349     HitTestMode hitTestMode_ = HitTestMode::HTMDEFAULT;
1350 
1351     ACE_DISALLOW_COPY_AND_MOVE(RenderNode);
1352 };
1353 
1354 } // namespace OHOS::Ace
1355 
1356 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BASE_RENDER_NODE_H
1357