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->topLeftRadius_ = Radius(value);
111 clip->topRightRadius_ = Radius(value);
112 clip->bottomLeftRadius_ = Radius(value);
113 clip->bottomRightRadius_ = Radius(value);
114 clip->SetClipRadius(Radius(value));
115 };
116 return map;
117 };
118
GetFloatPropertyGetterMap()119 FloatPropertyAnimatable::GetterMap RenderClip::GetFloatPropertyGetterMap()
120 {
121 FloatPropertyAnimatable::GetterMap map;
122 auto weak = AceType::WeakClaim(this);
123 map[PropertyAnimatableType::PROPERTY_WIDTH] = [weak]() -> float {
124 auto clip = weak.Upgrade();
125 if (!clip) {
126 LOGE("get width failed. clip is null.");
127 return 0.0;
128 }
129 return clip->width_;
130 };
131 map[PropertyAnimatableType::PROPERTY_HEIGHT] = [weak]() -> float {
132 auto clip = weak.Upgrade();
133 if (!clip) {
134 LOGE("get height failed. clip is null.");
135 return 0.0;
136 }
137 return clip->height_;
138 };
139 map[PropertyAnimatableType::PROPERTY_OFFSET_X] = [weak]() -> float {
140 auto clip = weak.Upgrade();
141 if (!clip) {
142 LOGE("get offsetX failed. clip is null.");
143 return 0.0;
144 }
145 return clip->offsetX_;
146 };
147 map[PropertyAnimatableType::PROPERTY_OFFSET_Y] = [weak]() -> float {
148 auto clip = weak.Upgrade();
149 if (!clip) {
150 LOGE("get offsetY failed. clip is null.");
151 return 0.0;
152 }
153 return clip->offsetY_;
154 };
155
156 map[PropertyAnimatableType::PROPERTY_BORDER_RADIUS] = [weak]() -> float {
157 auto clip = weak.Upgrade();
158 if (!clip) {
159 LOGE("get borer radius failed. clip is null.");
160 return 0.0f;
161 }
162 return clip->topLeftRadius_.GetX().Value();
163 };
164 return map;
165 };
166
GetClipRect(const Offset & offset) const167 Rect RenderClip::GetClipRect(const Offset& offset) const
168 {
169 double clipWidth = 0.0;
170 if (!NearZero(width_)) {
171 clipWidth = width_;
172 } else {
173 clipWidth = GetTransitionPaintRect().Width();
174 }
175 double clipHeight = 0.0;
176 if (!NearZero(height_)) {
177 clipHeight = height_;
178 } else {
179 clipHeight = GetTransitionPaintRect().Height();
180 }
181 return Rect(offset.GetX() + offsetX_, offset.GetY() + offsetY_, clipWidth, clipHeight);
182 }
183
UpdateBoxForShadowAnimation()184 void RenderClip::UpdateBoxForShadowAnimation()
185 {
186 if (!clipWithShadow_) {
187 return;
188 }
189
190 // If clip if used for animation, then there will be exist display and transform.
191 auto renderTransform = AceType::DynamicCast<RenderTransform>(GetParent().Upgrade());
192 if (!renderTransform) {
193 return;
194 }
195 auto renderDisplay = AceType::DynamicCast<RenderDisplay>(renderTransform->GetParent().Upgrade());
196 if (!renderDisplay) {
197 return;
198 }
199 // There must be box for shadow animation.
200 auto renderBox = DynamicCast<RenderBox>(renderDisplay->GetParent().Upgrade());
201 if (renderBox) {
202 renderBox->SetPaintSize(GetLayoutSize() - Size(offsetX_, offsetY_));
203 renderBox->SetPosition(shadowBoxOffset_ + Offset(offsetX_, offsetY_));
204 renderBox->MarkNeedRender();
205 SetPosition(Offset(-offsetX_, -offsetY_));
206 }
207 }
208
Dump()209 void RenderClip::Dump()
210 {
211 DumpLog::GetInstance().AddDesc(std::string("Clip HW: ").append(Size(width_, height_).ToString()));
212 DumpLog::GetInstance().AddDesc(std::string("Clip Offset: ").append(Offset(offsetX_, offsetY_).ToString()));
213 }
214
215 } // namespace OHOS::Ace
216