1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components/display/render_display.h"
17 
18 #include "base/log/dump_log.h"
19 #include "base/log/event_report.h"
20 
21 namespace OHOS::Ace {
22 
Update(const RefPtr<Component> & component)23 void RenderDisplay::Update(const RefPtr<Component>& component)
24 {
25     const RefPtr<DisplayComponent> display = AceType::DynamicCast<DisplayComponent>(component);
26     if (!display) {
27         LOGE("RenderDisplay update with nullptr");
28         EventReport::SendRenderException(RenderExcepType::RENDER_COMPONENT_ERR);
29         return;
30     }
31     displayComponent_ = display;
32     bool needAppearingCard = false;
33     if ((visible_ == VisibleType::GONE) && (display->GetVisible() != VisibleType::GONE)) {
34         needAppearingCard = true;
35     }
36     UpdateVisibleType(display->GetVisible());
37     duration_ = display->GetAppearingDuration();
38     transitionOpacity_ = display->GetOpacity();
39     disappearingOpacity_ = display->GetDisappearingOpacity();
40     appearingOpacity_ = display->GetAppearingOpacity();
41     hasDisappearTransition_ = display->HasDisappearTransition();
42     hasAppearTransition_ = display->HasAppearTransition();
43     backgroundMask_ = display->GetBackgroundMask();
44     if (!hasDisappearTransition_) {
45         pendingAppearing_ = false;
46     }
47     if (!pendingAppearing_) {
48         animatableOpacity_ = AnimatableDouble(display->GetOpacity(), display->GetOpacityAnimationOption());
49     }
50     double opacity = std::min(std::max(animatableOpacity_.GetValue(), 0.0), 1.0);
51     if (disableLayer_ != display->IsDisableLayer()) {
52         // recover opacity in child
53         UpdateOpacity(UINT8_MAX);
54         disableLayer_ = display->IsDisableLayer();
55     }
56     opacity_ = static_cast<uint8_t>(round(opacity * UINT8_MAX));
57     auto limitDuration = GetCardAppearingDuration();
58     if (duration_ > 0 && limitDuration > 0 && needAppearingCard) {
59         CreateAppearingAnimation(opacity_, limitDuration);
60         opacity_ = 0;
61         animator_->Play();
62     }
63 
64     if (display->HasStateAttributes()) {
65         stateAttributeList_ = display->GetStateAttributes();
66     }
67     OnStatusStyleChanged(VisualState::NORMAL);
68     SetShadow(display->GetShadow());
69     MarkNeedLayout();
70 }
71 
PerformLayout()72 void RenderDisplay::PerformLayout()
73 {
74     if (pendingAppearing_) {
75         if (animatableOpacity_.GetAnimationStatus() != Animator::Status::RUNNING) {
76             animatableOpacity_.MoveTo(appearingOpacity_);
77         }
78         // appearing transition do not need stop callback anymore.
79         animatableOpacity_.SetAnimationStopCallback(nullptr);
80         animatableOpacity_ = AnimatableDouble(opacity_ / (1.0 * UINT8_MAX));
81         pendingAppearing_ = false;
82     }
83     LayoutParam layoutParam = GetLayoutParam();
84     if (visible_ == VisibleType::GONE) {
85         layoutParam.SetMinSize(Size());
86         layoutParam.SetMaxSize(Size());
87         SetVisible(false);
88     } else if (visible_ == VisibleType::INVISIBLE) {
89         SetVisible(false);
90     }
91     Size childSize;
92     if (!GetChildren().empty()) {
93         const auto& child = GetChildren().front();
94         child->Layout(layoutParam);
95         childSize = child->GetLayoutSize();
96         child->SetPosition(Offset());
97     }
98     SetLayoutSize(childSize);
99 }
100 
GetOpacityCallbacks()101 void RenderDisplay::GetOpacityCallbacks()
102 {
103     opacityCallbacks_.clear();
104     if (!disableLayer_) {
105         return;
106     }
107     GetDomOpacityCallbacks(GetNodeId(), opacityCallbacks_);
108 }
109 
Dump()110 void RenderDisplay::Dump()
111 {
112     DumpLog::GetInstance().AddDesc(
113         std::string("Display: ")
114             .append(visible_ == VisibleType::VISIBLE ? "visible"
115                                                         : visible_ == VisibleType::INVISIBLE ? "invisible" : "gone"));
116     DumpLog::GetInstance().AddDesc(std::string("Opacity: ").append(std::to_string(animatableOpacity_.GetValue())));
117 }
118 
GetVisible() const119 bool RenderDisplay::GetVisible() const
120 {
121     return RenderNode::GetVisible() && (visible_ == VisibleType::VISIBLE);
122 }
123 
OnOpacityDisappearingCallback()124 void RenderDisplay::OnOpacityDisappearingCallback()
125 {
126     RefPtr<RenderNode> child = AceType::Claim(this);
127     while (child && !child->IsDisappearing()) {
128         child = child->GetParent().Upgrade();
129     }
130     if (!child) {
131         return;
132     }
133     auto parent = child->GetParent().Upgrade();
134     if (parent) {
135         parent->ClearDisappearingNode(child);
136     }
137 }
138 
OnOpacityAnimationCallback()139 void RenderDisplay::OnOpacityAnimationCallback()
140 {
141     double value = animatableOpacity_.GetValue();
142     opacity_ = static_cast<uint8_t>(round(value * UINT8_MAX));
143     MarkNeedRender();
144     if (disableLayer_) {
145         UpdateOpacity(opacity_);
146     }
147 }
148 
HasDisappearingTransition(int32_t nodeId)149 bool RenderDisplay::HasDisappearingTransition(int32_t nodeId)
150 {
151     return hasDisappearTransition_ || RenderNode::HasDisappearingTransition(nodeId);
152 }
153 
OnTransition(TransitionType type,int32_t id)154 void RenderDisplay::OnTransition(TransitionType type, int32_t id)
155 {
156     if (type == TransitionType::APPEARING) {
157         pendingAppearing_ = true;
158         MarkNeedLayout();
159     } else if (type == TransitionType::DISAPPEARING) {
160         animatableOpacity_.SetAnimationStopCallback(std::bind(&RenderDisplay::OnOpacityDisappearingCallback, this));
161         animatableOpacity_ = AnimatableDouble(disappearingOpacity_);
162     }
163 }
164 
ClearRenderObject()165 void RenderDisplay::ClearRenderObject()
166 {
167     RenderNode::ClearRenderObject();
168     animatableOpacity_ = 1.0;
169     appearingOpacity_ = 0.0;
170     disappearingOpacity_ = 0.0;
171 }
172 
GetCardAppearingDuration()173 int32_t RenderDisplay::GetCardAppearingDuration()
174 {
175     auto pipeline = context_.Upgrade();
176     if (!pipeline) {
177         LOGE("pipeline context is nullptr");
178         return 0;
179     }
180     auto limitDuration = pipeline->GetAppearingDuration();
181     return limitDuration;
182 }
183 
ResetAppearingAnimation()184 void RenderDisplay::ResetAppearingAnimation()
185 {
186     if (animator_->GetStatus() != Animator::Status::STOPPED) {
187         animator_->Stop();
188     }
189     animator_->ClearInterpolators();
190 }
191 
CreateAppearingAnimation(uint8_t opacity,int32_t limit)192 void RenderDisplay::CreateAppearingAnimation(uint8_t opacity, int32_t limit)
193 {
194     if (!animator_) {
195         animator_ = CREATE_ANIMATOR(context_);
196     }
197     ResetAppearingAnimation();
198     if (!appearingAnimation_) {
199         appearingAnimation_ = AceType::MakeRefPtr<CurveAnimation<uint8_t>>(0, opacity, Curves::FRICTION);
200     }
201     appearingAnimation_->AddListener([weak = WeakClaim(this)](const uint8_t value) {
202         auto display = weak.Upgrade();
203         if (display) {
204             display->UpdateOpacity(value);
205         }
206     });
207     animator_->AddInterpolator(appearingAnimation_);
208     animator_->SetDuration(std::min(duration_, limit));
209 }
210 
OnStatusStyleChanged(VisualState componentState)211 void RenderDisplay::OnStatusStyleChanged(VisualState componentState)
212 {
213     RenderNode::OnStatusStyleChanged(componentState);
214     if (stateAttributeList_ == nullptr) {
215         return;
216     }
217 
218     bool updated = false;
219     for (auto& attribute : stateAttributeList_->GetAttributesForState(componentState)) {
220         updated = true;
221         switch (attribute->id_) {
222             case DisplayStateAttribute::OPACITY: {
223                 auto opacityState =
224                     AceType::DynamicCast<StateAttributeValue<DisplayStateAttribute, AnimatableDouble>>(attribute);
225                 if (!pendingAppearing_) {
226                     animatableOpacity_ = opacityState->value_;
227                 }
228                 opacity_ = static_cast<uint8_t>(round(animatableOpacity_.GetValue() * UINT8_MAX));
229             } break;
230             default:
231                 break;
232         }
233     }
234     if (updated) {
235         MarkNeedLayout();
236     }
237 }
238 
OnVisibleChange(VisibleType type)239 void RenderDisplay::OnVisibleChange(VisibleType type)
240 {
241     auto display = displayComponent_.Upgrade();
242     if (display && !display->GetVisibleChangeEvent().IsEmpty()) {
243         auto event = AceSyncEvent<void(const std::shared_ptr<BaseEventInfo>&)>::Create(
244             display->GetVisibleChangeEvent(), context_);
245         switch (type) {
246             case VisibleType::VISIBLE:
247                 event(std::make_shared<BaseEventInfo>("0"));
248                 break;
249             case VisibleType::INVISIBLE:
250                 event(std::make_shared<BaseEventInfo>("1"));
251                 break;
252             case VisibleType::GONE:
253                 event(std::make_shared<BaseEventInfo>("2"));
254                 break;
255             default:
256                 break;
257         }
258     }
259     auto accessibilityNode = GetAccessibilityNode().Upgrade();
260     if (accessibilityNode) {
261         accessibilityNode->SetVisible(GetVisible());
262     }
263 }
264 
UpdateVisibleType(VisibleType type)265 void RenderDisplay::UpdateVisibleType(VisibleType type)
266 {
267     if (visible_ != type) {
268         visible_ = type;
269         SetVisible(visible_ == VisibleType::VISIBLE);
270         MarkNeedLayout();
271         OnVisibleChange(type);
272     }
273 }
274 
SetVisible(bool visible,bool inRecursion)275 void RenderDisplay::SetVisible(bool visible, bool inRecursion)
276 {
277     RenderNode::SetVisible(visible, inRecursion);
278 }
279 
280 } // namespace OHOS::Ace
281