1 /*
2 * Copyright (c) 2021 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/animation/curve_animation.h"
21
22 namespace OHOS::Ace {
23
Update(const RefPtr<Component> & component)24 void RenderDisplay::Update(const RefPtr<Component>& component)
25 {
26 const RefPtr<DisplayComponent> display = AceType::DynamicCast<DisplayComponent>(component);
27 if (!display) {
28 LOGE("RenderDisplay update with nullptr");
29 EventReport::SendRenderException(RenderExcepType::RENDER_COMPONENT_ERR);
30 return;
31 }
32 displayComponent_ = display;
33 bool needAppearingCard = false;
34 if ((visible_ == VisibleType::GONE) && (display->GetVisible() != VisibleType::GONE)) {
35 needAppearingCard = true;
36 }
37 UpdateVisibleType(display->GetVisible());
38 duration_ = display->GetAppearingDuration();
39 transitionOpacity_ = display->GetOpacity();
40 disappearingOpacity_ = display->GetDisappearingOpacity();
41 appearingOpacity_ = display->GetAppearingOpacity();
42 hasDisappearTransition_ = display->HasDisappearTransition();
43 hasAppearTransition_ = display->HasAppearTransition();
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 }
89 Size childSize;
90 if (!GetChildren().empty()) {
91 const auto& child = GetChildren().front();
92 child->Layout(layoutParam);
93 childSize = child->GetLayoutSize();
94 child->SetPosition(Offset());
95 }
96 SetLayoutSize(childSize);
97 }
98
GetOpacityCallbacks()99 void RenderDisplay::GetOpacityCallbacks()
100 {
101 opacityCallbacks_.clear();
102 if (!disableLayer_) {
103 return;
104 }
105 GetDomOpacityCallbacks(GetNodeId(), opacityCallbacks_);
106 }
107
Dump()108 void RenderDisplay::Dump()
109 {
110 DumpLog::GetInstance().AddDesc(
111 std::string("Display: ")
112 .append(visible_ == VisibleType::VISIBLE ? "visible"
113 : visible_ == VisibleType::INVISIBLE ? "invisible" : "gone"));
114 DumpLog::GetInstance().AddDesc(std::string("Opacity: ").append(std::to_string(animatableOpacity_.GetValue())));
115 }
116
GetVisible() const117 bool RenderDisplay::GetVisible() const
118 {
119 return RenderNode::GetVisible() && (visible_ == VisibleType::VISIBLE);
120 }
121
OnOpacityDisappearingCallback()122 void RenderDisplay::OnOpacityDisappearingCallback()
123 {
124 LOGD("OnOpacityDisappearingCallback");
125 RefPtr<RenderNode> child = AceType::Claim(this);
126 while (child && !child->IsDisappearing()) {
127 child = child->GetParent().Upgrade();
128 }
129 if (!child) {
130 return;
131 }
132 auto parent = child->GetParent().Upgrade();
133 if (parent) {
134 parent->ClearDisappearingNode(child);
135 }
136 }
137
OnOpacityAnimationCallback()138 void RenderDisplay::OnOpacityAnimationCallback()
139 {
140 double value = animatableOpacity_.GetValue();
141 opacity_ = static_cast<uint8_t>(round(value * UINT8_MAX));
142 MarkNeedRender();
143 if (disableLayer_) {
144 UpdateOpacity(opacity_);
145 }
146 }
147
HasDisappearingTransition(int32_t nodeId)148 bool RenderDisplay::HasDisappearingTransition(int32_t nodeId)
149 {
150 return hasDisappearTransition_ || RenderNode::HasDisappearingTransition(nodeId);
151 }
152
OnTransition(TransitionType type,int32_t id)153 void RenderDisplay::OnTransition(TransitionType type, int32_t id)
154 {
155 LOGD("OnTransition. type: %{public}d, id: %{public}d", type, id);
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_ = AceType::MakeRefPtr<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 }
231 }
232 if (updated) {
233 MarkNeedLayout();
234 }
235 }
236
237 } // namespace OHOS::Ace
238