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