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/clip/render_clip.h"
17
18 #include "base/log/dump_log.h"
19 #include "base/log/event_report.h"
20 #include "base/utils/utils.h"
21 #include "core/components/box/render_box.h"
22 #include "core/components/clip/clip_component.h"
23 #include "core/components/display/render_display.h"
24 #include "core/components/transform/render_transform.h"
25
26 namespace OHOS::Ace {
27
Update(const RefPtr<Component> & component)28 void RenderClip::Update(const RefPtr<Component>& component)
29 {
30 const RefPtr<ClipComponent> clip = AceType::DynamicCast<ClipComponent>(component);
31 if (!clip) {
32 return;
33 }
34 clipWithShadow_ = clip->IsClipWithShadow();
35 followChildSize_ = clip->IsFollowChild();
36 width_ = NormalizeToPx(clip->GetWidth());
37 height_ = NormalizeToPx(clip->GetHeight());
38 offsetX_ = NormalizeToPx(clip->GetOffsetX());
39 offsetY_ = NormalizeToPx(clip->GetOffsetY());
40
41 topLeftRadius_ = clip->GetTopLeftRadius();
42 topRightRadius_ = clip->GetTopRightRadius();
43 bottomLeftRadius_ = clip->GetBottomLeftRadius();
44 bottomRightRadius_ = clip->GetBottomRightRadius();
45
46 MarkNeedLayout();
47 }
48
PerformLayout()49 void RenderClip::PerformLayout()
50 {
51 if (GetChildren().empty()) {
52 LOGE("RenderClip: no child found in RenderClip!");
53 EventReport::SendRenderException(RenderExcepType::CLIP_ERR);
54 return;
55 }
56 auto child = GetChildren().front();
57 child->Layout(GetLayoutParam());
58 child->SetPosition(Offset::Zero());
59 if (followChildSize_) {
60 SetLayoutSize(child->GetLayoutSize());
61 } else {
62 SetLayoutSize(GetLayoutParam().GetMaxSize());
63 }
64 }
65
GetFloatPropertySetterMap()66 FloatPropertyAnimatable::SetterMap RenderClip::GetFloatPropertySetterMap()
67 {
68 FloatPropertyAnimatable::SetterMap map;
69 auto weak = AceType::WeakClaim(this);
70 map[PropertyAnimatableType::PROPERTY_WIDTH] = [weak](float value) {
71 auto clip = weak.Upgrade();
72 if (!clip) {
73 LOGE("set width failed. clip is null.");
74 return;
75 }
76 clip->SetWidth(value);
77 };
78 map[PropertyAnimatableType::PROPERTY_HEIGHT] = [weak](float value) {
79 auto clip = weak.Upgrade();
80 if (!clip) {
81 LOGE("set height failed. clip is null.");
82 return;
83 }
84 clip->SetHeight(value);
85 };
86 map[PropertyAnimatableType::PROPERTY_OFFSET_X] = [weak](float value) {
87 auto clip = weak.Upgrade();
88 if (!clip) {
89 LOGE("set offsetX failed. clip is null.");
90 return;
91 }
92 clip->SetOffsetX(value);
93 clip->UpdateBoxForShadowAnimation();
94 };
95 map[PropertyAnimatableType::PROPERTY_OFFSET_Y] = [weak](float value) {
96 auto clip = weak.Upgrade();
97 if (!clip) {
98 LOGE("set offsetY failed. clip is null.");
99 return;
100 }
101 clip->SetOffsetY(value);
102 clip->UpdateBoxForShadowAnimation();
103 };
104 map[PropertyAnimatableType::PROPERTY_BORDER_RADIUS] = [weak](float value) {
105 auto clip = weak.Upgrade();
106 if (!clip) {
107 LOGE("set border radius failed. clip is null.");
108 return;
109 }
110 clip->SetClipRadius(Radius(value));
111 };
112 return map;
113 };
114
GetFloatPropertyGetterMap()115 FloatPropertyAnimatable::GetterMap RenderClip::GetFloatPropertyGetterMap()
116 {
117 FloatPropertyAnimatable::GetterMap map;
118 auto weak = AceType::WeakClaim(this);
119 map[PropertyAnimatableType::PROPERTY_WIDTH] = [weak]() -> float {
120 auto clip = weak.Upgrade();
121 if (!clip) {
122 LOGE("get width failed. clip is null.");
123 return 0.0;
124 }
125 return clip->width_;
126 };
127 map[PropertyAnimatableType::PROPERTY_HEIGHT] = [weak]() -> float {
128 auto clip = weak.Upgrade();
129 if (!clip) {
130 LOGE("get height failed. clip is null.");
131 return 0.0;
132 }
133 return clip->height_;
134 };
135 map[PropertyAnimatableType::PROPERTY_OFFSET_X] = [weak]() -> float {
136 auto clip = weak.Upgrade();
137 if (!clip) {
138 LOGE("get offsetX failed. clip is null.");
139 return 0.0;
140 }
141 return clip->offsetX_;
142 };
143 map[PropertyAnimatableType::PROPERTY_OFFSET_Y] = [weak]() -> float {
144 auto clip = weak.Upgrade();
145 if (!clip) {
146 LOGE("get offsetY failed. clip is null.");
147 return 0.0;
148 }
149 return clip->offsetY_;
150 };
151
152 map[PropertyAnimatableType::PROPERTY_BORDER_RADIUS] = [weak]() -> float {
153 auto clip = weak.Upgrade();
154 if (!clip) {
155 LOGE("get borer radius failed. clip is null.");
156 return 0.0f;
157 }
158 return clip->topLeftRadius_.GetX().Value();
159 };
160 return map;
161 };
162
GetClipRect(const Offset & offset) const163 Rect RenderClip::GetClipRect(const Offset& offset) const
164 {
165 double clipWidth = 0.0;
166 if (!NearZero(width_)) {
167 clipWidth = width_;
168 } else {
169 clipWidth = GetTransitionPaintRect().Width();
170 }
171 double clipHeight = 0.0;
172 if (!NearZero(height_)) {
173 clipHeight = height_;
174 } else {
175 clipHeight = GetTransitionPaintRect().Height();
176 }
177 return Rect(offset.GetX() + offsetX_, offset.GetY() + offsetY_, clipWidth, clipHeight);
178 }
179
UpdateBoxForShadowAnimation()180 void RenderClip::UpdateBoxForShadowAnimation()
181 {
182 if (!clipWithShadow_) {
183 return;
184 }
185
186 // If clip is used for animation, then there will be existed display and transform.
187 auto renderTransform = AceType::DynamicCast<RenderTransform>(GetParent().Upgrade());
188 if (!renderTransform) {
189 return;
190 }
191 auto renderDisplay = AceType::DynamicCast<RenderDisplay>(renderTransform->GetParent().Upgrade());
192 if (!renderDisplay) {
193 return;
194 }
195 // There must be box for shadow animation.
196 auto renderBox = DynamicCast<RenderBox>(renderDisplay->GetParent().Upgrade());
197 if (renderBox) {
198 renderBox->SetPaintSize(GetLayoutSize() - Size(offsetX_, offsetY_));
199 renderBox->SetPosition(shadowBoxOffset_ + Offset(offsetX_, offsetY_));
200 renderBox->MarkNeedRender();
201 SetPosition(Offset(-offsetX_, -offsetY_));
202 }
203 }
204
Dump()205 void RenderClip::Dump()
206 {
207 DumpLog::GetInstance().AddDesc(std::string("Clip HW: ").append(Size(width_, height_).ToString()));
208 DumpLog::GetInstance().AddDesc(std::string("Clip Offset: ").append(Offset(offsetX_, offsetY_).ToString()));
209 }
210
211 } // namespace OHOS::Ace
212