• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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_ng/render/adapter/moon_progress_modifier.h"
17 
18 #include "core/components_ng/render/drawing_prop_convertor.h"
19 #include "core/pipeline_ng/pipeline_context.h"
20 
21 namespace OHOS::Ace::NG {
22 namespace {
23 constexpr int32_t DIFFUSE_DURATION = 300;
24 constexpr float INITIAL_RATIO = 1.0f;
25 constexpr int32_t INT32_TWO = 2;
26 constexpr int32_t ANGLE_90 = 90;
27 constexpr int32_t ANGLE_180 = 180;
28 constexpr int32_t ANGLE_270 = 270;
29 constexpr float FLOAT_ZERO_FIVE = 0.5f;
30 constexpr float FLOAT_ZERO_SEVEN = 0.7f;
31 constexpr float FLOAT_ONE_ZERO = 1.0f;
32 constexpr float SPRING_MOTION_RESPONSE = 0.314f;
33 constexpr float SPRING_MOTION_DAMPING_FRACTION = 0.95f;
34 const float EPSLION = 1e-5;
35 const float DEFAULT_MAXVALUE = 100.0f;
36 const bool DEFAULT_ENABLE_BREATHE = true;
37 constexpr float INITIAL_OPACITY = 0.0f;
38 constexpr int32_t PICTURE_DURATION = 750;
39 } // namespace
40 
MoonProgressModifier(const WeakPtr<FrameNode> & maskNode)41 MoonProgressModifier::MoonProgressModifier(const WeakPtr<FrameNode>& maskNode)
42     : maskColor_(AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(Color::TRANSPARENT))),
43       ratio_(AceType::MakeRefPtr<AnimatablePropertyFloat>(INITIAL_RATIO)),
44       value_(AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f)),
45       opacity_(AceType::MakeRefPtr<AnimatablePropertyFloat>(INITIAL_OPACITY)),
46       maxValue_(AceType::MakeRefPtr<PropertyFloat>(DEFAULT_MAXVALUE)),
47       enableBreathe_(AceType::MakeRefPtr<PropertyBool>(DEFAULT_ENABLE_BREATHE))
48 {
49     maskNode_ = maskNode;
50     AttachProperty(maskColor_);
51     AttachProperty(ratio_);
52     AttachProperty(value_);
53     AttachProperty(opacity_);
54     AttachProperty(maxValue_);
55     AttachProperty(enableBreathe_);
56 }
57 
onDraw(DrawingContext & context)58 void MoonProgressModifier::onDraw(DrawingContext& context)
59 {
60     auto node = maskNode_.Upgrade();
61     CHECK_NULL_VOID(node);
62     auto geometryNode = node->GetGeometryNode();
63     CHECK_NULL_VOID(geometryNode);
64     auto contentSize = geometryNode->GetFrameSize();
65     frameSize_.SetWidth(contentSize.Width());
66     frameSize_.SetHeight(contentSize.Height());
67     SetBigRadius();
68     if (GreatOrEqual(ratio_->Get(), bigRadius_ / smallRadius_)) {
69         hideMask_ = true;
70         return;
71     }
72     PaintSquareMoon(context.canvas);
73 }
74 
SetMaskColor(LinearColor color)75 void MoonProgressModifier::SetMaskColor(LinearColor color)
76 {
77     maskColor_->Set(color);
78 }
79 
SetValue(float value)80 void MoonProgressModifier::SetValue(float value)
81 {
82     auto finishCallback = [weak = AceType::WeakClaim(this), bigRadius = bigRadius_, smallRadius = smallRadius_,
83                               id = Container::CurrentId()]() {
84         ContainerScope scope(id);
85         auto pipeline = PipelineContext::GetCurrentContext();
86         CHECK_NULL_VOID(pipeline);
87         auto modifier = weak.Upgrade();
88         CHECK_NULL_VOID(modifier);
89         double angle = modifier->value_->Get() / modifier->maxValue_->Get();
90         double currentAngle = modifier->value_->GetStagingValue() / modifier->maxValue_->GetStagingValue();
91 
92         // When first moon animation is interrupted by second,
93         // the second moon animation should use the staging value (the Latest updated value) for calculating.
94         if (GreatNotEqual(std::abs(angle - FLOAT_ONE_ZERO), EPSLION) ||
95             GreatNotEqual(std::abs(currentAngle - FLOAT_ONE_ZERO), EPSLION)) {
96             modifier->StopPictureAnimate();
97             return;
98         }
99         if (modifier->enableBreathe_->Get() && Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TWELVE)) {
100             modifier->StartPictureAnimate();
101         } else {
102             modifier->StopPictureAnimate();
103             modifier->SetMoonAnimate(bigRadius / smallRadius);
104         }
105         pipeline->RequestFrame();
106     };
107 
108     AnimationOption option;
109     auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(SPRING_MOTION_RESPONSE, SPRING_MOTION_DAMPING_FRACTION);
110     option.SetCurve(motion);
111     AnimationUtils::Animate(
112         option,
113         [weak = AceType::WeakClaim(AceType::RawPtr(value_)), valueTo = value]() {
114             auto value = weak.Upgrade();
115             CHECK_NULL_VOID(value);
116             value->Set(valueTo);
117         },
118         finishCallback);
119 
120     CHECK_NULL_VOID(maxValue_);
121     if (value < maxValue_->Get() && std::abs(maxValue_->Get() - value) > EPSLION &&
122         std::abs(ratio_->Get() - INITIAL_RATIO) > EPSLION) {
123         InitRatio();
124     }
125 }
126 
SetMaxValue(float value)127 void MoonProgressModifier::SetMaxValue(float value)
128 {
129     maxValue_->Set(value);
130 }
131 
GetMaxValue()132 float MoonProgressModifier::GetMaxValue()
133 {
134     if (maxValue_) {
135         return maxValue_->Get();
136     } else {
137         return DEFAULT_MAXVALUE;
138     }
139 }
140 
SetEnableBreathe(bool enableBreathe)141 void MoonProgressModifier::SetEnableBreathe(bool enableBreathe)
142 {
143     enableBreathe_->Set(enableBreathe);
144 }
145 
InitRatio()146 void MoonProgressModifier::InitRatio()
147 {
148     ratio_->Set(INITIAL_RATIO);
149     animationEnd_ = false;
150     hideMask_ = false;
151     RemoveVisibleChange();
152 }
153 
SetMoonAnimate(float value)154 void MoonProgressModifier::SetMoonAnimate(float value)
155 {
156     if (ratio_) {
157         animationEnd_ = true;
158         AnimationOption option;
159         option.SetDuration(DIFFUSE_DURATION);
160         option.SetDelay(0);
161         option.SetCurve(Curves::SHARP);
162         AnimationUtils::Animate(option, [weak = AceType::WeakClaim(AceType::RawPtr(ratio_)), value]() {
163             auto ratio = weak.Upgrade();
164             CHECK_NULL_VOID(ratio);
165             ratio->Set(value);
166         });
167     }
168 }
169 
StartPictureAnimate() const170 void MoonProgressModifier::StartPictureAnimate() const
171 {
172     if (GreatOrEqual(value_->Get(), maxValue_->Get()) && !animationEnd_) {
173         AnimationOption option;
174         option.SetDuration(PICTURE_DURATION);
175         option.SetDelay(0);
176         option.SetCurve(Curves::SHARP);
177         option.SetIteration(-1);
178         option.SetAnimationDirection(AnimationDirection::ALTERNATE);
179         AnimationUtils::Animate(option, [weak = AceType::WeakClaim(AceType::RawPtr(opacity_))]() {
180             auto opacity = weak.Upgrade();
181             CHECK_NULL_VOID(opacity);
182             opacity->Set(1.0f);
183         });
184     }
185 }
186 
StopPictureAnimate() const187 void MoonProgressModifier::StopPictureAnimate() const
188 {
189     AnimationOption option;
190     option.SetDuration(0);
191     AnimationUtils::Animate(option, [&]() { opacity_->Set(0.0f); });
192 }
193 
SetBigRadius()194 void MoonProgressModifier::SetBigRadius()
195 {
196     bigRadius_ = std::sqrt(
197         std::pow(frameSize_.Width() / INT32_TWO, INT32_TWO) + std::pow(frameSize_.Height() / INT32_TWO, INT32_TWO));
198     double radius = (std::min(frameSize_.Width() / INT32_TWO, frameSize_.Height() / INT32_TWO));
199     smallRadius_ = radius * INITIAL_RATIO * FLOAT_ZERO_SEVEN;
200 }
CalculateSquareMoonPath(RSPath & path,const PointF & centerPt,const double & angle)201 void MoonProgressModifier::CalculateSquareMoonPath(RSPath& path, const PointF& centerPt, const double& angle)
202 {
203     path.AddArc({ centerPt.GetX() - smallRadius_, centerPt.GetY() - smallRadius_, centerPt.GetX() + smallRadius_,
204                     centerPt.GetY() + smallRadius_ },
205         ANGLE_90, ANGLE_180);
206     if (LessOrEqual(angle, FLOAT_ZERO_FIVE)) {
207         double progressOffset = smallRadius_ - smallRadius_ * angle / FLOAT_ZERO_FIVE;
208         path.MoveTo(centerPt.GetX(), centerPt.GetY() - smallRadius_);
209         // startAngle:270  sweepAngle:-180
210         path.AddArc({ centerPt.GetX() - progressOffset, centerPt.GetY() - smallRadius_,
211                         centerPt.GetX() + progressOffset, centerPt.GetY() + smallRadius_ },
212             ANGLE_270, -ANGLE_180);
213     } else {
214         double progressOffset = smallRadius_ * (angle - FLOAT_ZERO_FIVE) / FLOAT_ZERO_FIVE;
215         path.MoveTo(centerPt.GetX(), centerPt.GetY() - smallRadius_);
216         // startAngle:270  sweepAngle:180
217         path.AddArc({ centerPt.GetX() - progressOffset, centerPt.GetY() - smallRadius_,
218                         centerPt.GetX() + progressOffset, centerPt.GetY() + smallRadius_ },
219             ANGLE_270, ANGLE_180);
220     }
221 }
PaintSquareMoon(RSCanvas & canvas)222 void MoonProgressModifier::PaintSquareMoon(RSCanvas& canvas)
223 {
224     PointF centerPt = PointF(frameSize_.Width() / INT32_TWO, frameSize_.Height() / INT32_TWO);
225     RSBrush brush;
226     double angle = value_->Get() / maxValue_->Get();
227 #ifndef USE_ROSEN_DRAWING
228     RSPath path;
229     RSPath clipPath;
230 #else
231     RSRecordingPath path;
232     RSRecordingPath clipPath;
233 #endif
234     brush.SetAntiAlias(true);
235     brush.SetColor(ToRSColor((maskColor_->Get())));
236     canvas.AttachBrush(brush);
237     path.SetFillStyle(RSPathFillType::EVENTODD);
238     path.AddCircle(centerPt.GetX(), centerPt.GetY(), bigRadius_, RSPathDirection::CW_DIRECTION);
239     if (NearZero(std::abs(ratio_->Get() - INITIAL_RATIO), EPSLION)) {
240         if (NearZero(angle, EPSLION)) {
241             canvas.DrawPath(path);
242             canvas.DetachBrush();
243             canvas.Restore();
244             return;
245         }
246         if (LessOrEqual(angle, FLOAT_ONE_ZERO)) {
247             CalculateSquareMoonPath(path, centerPt, angle);
248         } else {
249             clipPath.AddCircle(centerPt.GetX(), centerPt.GetY(), smallRadius_, RSPathDirection::CW_DIRECTION);
250             canvas.ClipPath(clipPath, RSClipOp::DIFFERENCE, true);
251         }
252         canvas.DrawPath(path);
253     } else {
254         path.MoveTo(centerPt.GetX(), centerPt.GetY() - smallRadius_ * ratio_->Get());
255         path.AddCircle(centerPt.GetX(), centerPt.GetY(), smallRadius_ * ratio_->Get(), RSPathDirection::CW_DIRECTION);
256         canvas.DrawPath(path);
257     }
258     canvas.DetachBrush();
259     canvas.Restore();
260     if (GreatOrEqual(angle, 1.0f)) {
261         PaintSquareMoonShadow(canvas, brush);
262     }
263 }
264 
PaintSquareMoonShadow(RSCanvas & canvas,RSBrush & brush)265 void MoonProgressModifier::PaintSquareMoonShadow(RSCanvas& canvas, RSBrush& brush)
266 {
267     RegisterVisibleChange();
268     Color color = Color::WHITE.ChangeOpacity(opacity_->Get());
269     brush.SetColor(ToRSColor(color));
270     auto radius = (std::min(frameSize_.Width() / INT32_TWO, frameSize_.Height() / INT32_TWO));
271     RSFilter filter;
272 #ifndef USE_ROSEN_DRAWING
273     RSPath path;
274     filter.SetImageFilter(
275         RSImageFilter::CreateBlurImageFilter(radius - smallRadius_, radius - smallRadius_, RSTileMode::DECAL, nullptr));
276 #else
277     RSRecordingPath path;
278     filter.SetImageFilter(RSRecordingImageFilter::CreateBlurImageFilter(
279         radius - smallRadius_, radius - smallRadius_, RSTileMode::DECAL, nullptr));
280 #endif
281     brush.SetFilter(filter);
282     canvas.AttachBrush(brush);
283     PointF centerPt = PointF(frameSize_.Width() / INT32_TWO, frameSize_.Height() / INT32_TWO);
284     path.AddCircle(centerPt.GetX(), centerPt.GetY(), smallRadius_, RSPathDirection::CW_DIRECTION);
285     canvas.ClipPath(path, RSClipOp::DIFFERENCE, true);
286     canvas.DrawPath(path);
287     canvas.DetachBrush();
288     canvas.Restore();
289 }
290 
RegisterVisibleChange()291 void MoonProgressModifier::RegisterVisibleChange()
292 {
293     if (hasVisibleChangeRegister_) {
294         return;
295     }
296     auto pipeline = PipelineContext::GetCurrentContext();
297     CHECK_NULL_VOID(pipeline);
298     auto callback = [weak = WeakClaim(this)](bool visible, double ratio) {
299         auto modifier = weak.Upgrade();
300         CHECK_NULL_VOID(modifier);
301         if (visible) {
302             modifier->StartPictureAnimate();
303         } else {
304             modifier->StopPictureAnimate();
305         }
306     };
307     std::vector<double> ratioList = { 0.0 };
308     auto node = maskNode_.Upgrade();
309     CHECK_NULL_VOID(node);
310     pipeline->AddVisibleAreaChangeNode(node, ratioList, callback, false);
311     pipeline->AddWindowStateChangedCallback(node->GetId());
312     hasVisibleChangeRegister_ = true;
313 }
314 
RemoveVisibleChange()315 void MoonProgressModifier::RemoveVisibleChange()
316 {
317     auto pipeline = PipelineContext::GetCurrentContext();
318     CHECK_NULL_VOID(pipeline);
319     auto node = maskNode_.Upgrade();
320     CHECK_NULL_VOID(node);
321     pipeline->RemoveVisibleAreaChangeNode(node->GetId());
322     pipeline->RemoveWindowStateChangedCallback(node->GetId());
323     hasVisibleChangeRegister_ = false;
324 }
325 } // namespace OHOS::Ace::NG
326