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 LOGD("OnOpacityDisappearingCallback");
130 RefPtr<RenderNode> child = AceType::Claim(this);
131 while (child && !child->IsDisappearing()) {
132 child = child->GetParent().Upgrade();
133 }
134 if (!child) {
135 return;
136 }
137 auto parent = child->GetParent().Upgrade();
138 if (parent) {
139 parent->ClearDisappearingNode(child);
140 }
141 }
142
OnOpacityAnimationCallback()143 void RenderDisplay::OnOpacityAnimationCallback()
144 {
145 double value = animatableOpacity_.GetValue();
146 opacity_ = static_cast<uint8_t>(round(value * UINT8_MAX));
147 MarkNeedRender();
148 if (disableLayer_) {
149 UpdateOpacity(opacity_);
150 }
151 }
152
HasDisappearingTransition(int32_t nodeId)153 bool RenderDisplay::HasDisappearingTransition(int32_t nodeId)
154 {
155 return hasDisappearTransition_ || RenderNode::HasDisappearingTransition(nodeId);
156 }
157
OnTransition(TransitionType type,int32_t id)158 void RenderDisplay::OnTransition(TransitionType type, int32_t id)
159 {
160 LOGD("OnTransition. type: %{public}d, id: %{public}d", type, id);
161 if (type == TransitionType::APPEARING) {
162 pendingAppearing_ = true;
163 MarkNeedLayout();
164 } else if (type == TransitionType::DISAPPEARING) {
165 animatableOpacity_.SetAnimationStopCallback(std::bind(&RenderDisplay::OnOpacityDisappearingCallback, this));
166 animatableOpacity_ = AnimatableDouble(disappearingOpacity_);
167 }
168 }
169
ClearRenderObject()170 void RenderDisplay::ClearRenderObject()
171 {
172 RenderNode::ClearRenderObject();
173 animatableOpacity_ = 1.0;
174 appearingOpacity_ = 0.0;
175 disappearingOpacity_ = 0.0;
176 }
177
GetCardAppearingDuration()178 int32_t RenderDisplay::GetCardAppearingDuration()
179 {
180 auto pipeline = context_.Upgrade();
181 if (!pipeline) {
182 LOGE("pipeline context is nullptr");
183 return 0;
184 }
185 auto limitDuration = pipeline->GetAppearingDuration();
186 return limitDuration;
187 }
188
ResetAppearingAnimation()189 void RenderDisplay::ResetAppearingAnimation()
190 {
191 if (animator_->GetStatus() != Animator::Status::STOPPED) {
192 animator_->Stop();
193 }
194 animator_->ClearInterpolators();
195 }
196
CreateAppearingAnimation(uint8_t opacity,int32_t limit)197 void RenderDisplay::CreateAppearingAnimation(uint8_t opacity, int32_t limit)
198 {
199 if (!animator_) {
200 animator_ = AceType::MakeRefPtr<Animator>(context_);
201 }
202 ResetAppearingAnimation();
203 if (!appearingAnimation_) {
204 appearingAnimation_ = AceType::MakeRefPtr<CurveAnimation<uint8_t>>(0, opacity, Curves::FRICTION);
205 }
206 appearingAnimation_->AddListener([weak = WeakClaim(this)](const uint8_t value) {
207 auto display = weak.Upgrade();
208 if (display) {
209 display->UpdateOpacity(value);
210 }
211 });
212 animator_->AddInterpolator(appearingAnimation_);
213 animator_->SetDuration(std::min(duration_, limit));
214 }
215
OnStatusStyleChanged(VisualState componentState)216 void RenderDisplay::OnStatusStyleChanged(VisualState componentState)
217 {
218 RenderNode::OnStatusStyleChanged(componentState);
219 if (stateAttributeList_ == nullptr) {
220 return;
221 }
222
223 bool updated = false;
224 for (auto& attribute : stateAttributeList_->GetAttributesForState(componentState)) {
225 updated = true;
226 switch (attribute->id_) {
227 case DisplayStateAttribute::OPACITY: {
228 auto opacityState =
229 AceType::DynamicCast<StateAttributeValue<DisplayStateAttribute, AnimatableDouble>>(attribute);
230 if (!pendingAppearing_) {
231 animatableOpacity_ = opacityState->value_;
232 }
233 opacity_ = static_cast<uint8_t>(round(animatableOpacity_.GetValue() * UINT8_MAX));
234 } break;
235 default:
236 break;
237 }
238 }
239 if (updated) {
240 MarkNeedLayout();
241 }
242 }
243
OnVisibleChange(VisibleType type)244 void RenderDisplay::OnVisibleChange(VisibleType type)
245 {
246 auto display = displayComponent_.Upgrade();
247 if (display && !display->GetVisibleChangeEvent().IsEmpty()) {
248 auto event = AceSyncEvent<void(const std::shared_ptr<BaseEventInfo>&)>::Create(
249 display->GetVisibleChangeEvent(), context_);
250 switch (type) {
251 case VisibleType::VISIBLE:
252 event(std::make_shared<BaseEventInfo>("0"));
253 break;
254 case VisibleType::INVISIBLE:
255 event(std::make_shared<BaseEventInfo>("1"));
256 break;
257 case VisibleType::GONE:
258 event(std::make_shared<BaseEventInfo>("2"));
259 break;
260 default:
261 break;
262 }
263 }
264 auto accessibilityNode = GetAccessibilityNode().Upgrade();
265 if (accessibilityNode) {
266 accessibilityNode->SetVisible(GetVisible());
267 }
268 }
269
UpdateVisibleType(VisibleType type)270 void RenderDisplay::UpdateVisibleType(VisibleType type)
271 {
272 if (visible_ != type) {
273 visible_ = type;
274 SetVisible(visible_ == VisibleType::VISIBLE);
275 MarkNeedLayout();
276 OnVisibleChange(type);
277 }
278 }
279
SetVisible(bool visible,bool inRecursion)280 void RenderDisplay::SetVisible(bool visible, bool inRecursion)
281 {
282 RenderNode::SetVisible(visible, inRecursion);
283 }
284
285 } // namespace OHOS::Ace
286