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