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