• 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/pattern/patternlock/patternlock_modifier.h"
17 
18 #include <algorithm>
19 #include <string>
20 #include <vector>
21 
22 #include "base/geometry/dimension.h"
23 #include "base/geometry/ng/offset_t.h"
24 #include "base/geometry/ng/size_t.h"
25 #include "base/log/log_wrapper.h"
26 #include "base/memory/ace_type.h"
27 #include "base/utils/utils.h"
28 #include "core/components/common/properties/color.h"
29 #include "core/components_ng/base/modifier.h"
30 #include "core/components_ng/pattern/patternlock/patternlock_paint_property.h"
31 #include "core/components_ng/render/drawing.h"
32 #include "core/components_ng/render/drawing_prop_convertor.h"
33 
34 namespace OHOS::Ace::NG {
35 namespace {
36 constexpr int32_t PATTERN_LOCK_COL_COUNT = 3;
37 constexpr int32_t PATTERN_LOCK_POINT_COUNT = 9;
38 constexpr int32_t RADIUS_TO_DIAMETER = 2;
39 constexpr float FLASH_POINT_OPACITY = 0.5f;
40 constexpr int32_t ACTIVE_RADIUS_ANIMATION_DURATION = 200;
41 constexpr int32_t LIGHT_RING_RADIUS_ANIMATION_DURATION = 500;
42 constexpr int32_t LIGHT_RING_ALPHAF_ANIMATION_DURATION_FIRST = 200;
43 constexpr int32_t LIGHT_RING_ALPHAF_ANIMATION_DURATION_SECOND = 300;
44 constexpr int32_t CONNECT_ANIMATION_DURATION_FIRST = 100;
45 constexpr int32_t WRONG_ANIMATION_DURATION_DIMMING = 150;
46 constexpr int32_t WRONG_ANIMATION_DURATION_BRIGHTENING = 200;
47 constexpr int32_t WRONG_ANIMATION_DURATION_FLASH_ONCE =
48     WRONG_ANIMATION_DURATION_DIMMING + WRONG_ANIMATION_DURATION_BRIGHTENING;
49 constexpr int32_t WRONG_ANIMATION_DURATION_FLASH_TWICE =
50     WRONG_ANIMATION_DURATION_FLASH_ONCE + WRONG_ANIMATION_DURATION_FLASH_ONCE;
51 constexpr float BACKGROUND_RADIUS_SPRING_RESPONSE = 0.347f;
52 constexpr float BACKGROUND_RADIUS_SPRING_DAMPING = 0.55f;
53 constexpr Dimension LIGHT_RING_LINE_WIDTH = 2.5_vp;
54 constexpr Dimension LIGHT_RING_MASK_RADIUS = 10.0_vp;
55 constexpr float LIGHT_RING_ALPHAF_START = 0.0f;
56 constexpr float LIGHT_RING_ALPHAF_END = 0.5f;
57 constexpr float CONNECTED_LINE_SPRING_RESPONSE = 0.22f;
58 constexpr float CONNECTED_LINE_SPRING_DAMPING = 0.88f;
59 constexpr float CANCELED_LINE_SPRING_RESPONSE = 0.22f;
60 constexpr float CANCELED_LINE_SPRING_DAMPING = 0.88f;
61 constexpr int32_t ANIMATABLE_POINT_COUNT = 2;
62 constexpr float DIAMETER_TO_RADIUS = 0.5f;
63 constexpr float GRADUAL_CHANGE_POINT = 0.5;
64 constexpr int32_t MAX_ALPHA = 255;
65 } // namespace
66 
PatternLockCell(int32_t column,int32_t row)67 PatternLockCell::PatternLockCell(int32_t column, int32_t row)
68 {
69     column_ = column;
70     row_ = row;
71     code_ = PATTERN_LOCK_COL_COUNT * (row - 1) + (column - 1);
72 }
73 
CreateProperties()74 void PatternLockModifier::CreateProperties()
75 {
76     sideLength_ = AceType::MakeRefPtr<PropertyFloat>(0.0f);
77     circleRadius_ = AceType::MakeRefPtr<PropertyFloat>(0.0f);
78     regularColor_ = AceType::MakeRefPtr<PropertyColor>(Color::BLACK);
79     selectedColor_ = AceType::MakeRefPtr<PropertyColor>(Color::BLACK);
80     activeColor_ = AceType::MakeRefPtr<PropertyColor>(Color::BLACK);
81     hoverColor_ = AceType::MakeRefPtr<PropertyColor>(Color::BLACK);
82     wrongColor_ = AceType::MakeRefPtr<PropertyColor>(Color::RED);
83     correctColor_ = AceType::MakeRefPtr<PropertyColor>(Color::BLUE);
84     pathColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(Color::BLUE));
85     pointAnimateColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(Color::BLACK));
86     pathStrokeWidth_ = AceType::MakeRefPtr<PropertyFloat>(0.0f);
87     offset_ = AceType::MakeRefPtr<PropertyOffsetF>(OffsetF());
88     cellCenter_ = AceType::MakeRefPtr<PropertyOffsetF>(OffsetF());
89     isMoveEventValid_ = AceType::MakeRefPtr<PropertyBool>(false);
90     isHover_ = AceType::MakeRefPtr<PropertyBool>(false);
91     hoverIndex_ = AceType::MakeRefPtr<PropertyInt>(-1);
92     connectedLineTailPoint_ = AceType::MakeRefPtr<AnimatablePropertyOffsetF>(OffsetF());
93     canceledLineTailPoint_ = AceType::MakeRefPtr<AnimatablePropertyOffsetF>(OffsetF());
94 }
95 
AttachProperties()96 void PatternLockModifier::AttachProperties()
97 {
98     AttachProperty(sideLength_);
99     AttachProperty(circleRadius_);
100     AttachProperty(regularColor_);
101     AttachProperty(selectedColor_);
102     AttachProperty(activeColor_);
103     AttachProperty(hoverColor_);
104     AttachProperty(wrongColor_);
105     AttachProperty(correctColor_);
106     AttachProperty(pathColor_);
107     AttachProperty(pointAnimateColor_);
108     AttachProperty(pathStrokeWidth_);
109     AttachProperty(cellCenter_);
110     AttachProperty(offset_);
111     AttachProperty(isMoveEventValid_);
112     AttachProperty(isHover_);
113     AttachProperty(hoverIndex_);
114     AttachProperty(connectedLineTailPoint_);
115     AttachProperty(canceledLineTailPoint_);
116 }
117 
PatternLockModifier()118 PatternLockModifier::PatternLockModifier()
119 {
120     CreateProperties();
121     AttachProperties();
122     for (size_t count = 0; count < PATTERN_LOCK_POINT_COUNT; count++) {
123         auto backgroundRadius = AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0f);
124         AttachProperty(backgroundRadius);
125         backgroundCircleRadius_.emplace_back(backgroundRadius);
126 
127         auto activeRadius = AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0f);
128         AttachProperty(activeRadius);
129         activeCircleRadius_.emplace_back(activeRadius);
130 
131         auto lightRingRadius = AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0f);
132         AttachProperty(lightRingRadius);
133         lightRingRadius_.emplace_back(lightRingRadius);
134 
135         auto lightRingAlphaF = AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0f);
136         AttachProperty(lightRingAlphaF);
137         lightRingAlphaF_.emplace_back(lightRingAlphaF);
138     }
139 }
140 
onDraw(DrawingContext & context)141 void PatternLockModifier::onDraw(DrawingContext& context)
142 {
143     auto pipeline = PipelineBase::GetCurrentContext();
144     CHECK_NULL_VOID(pipeline);
145     if (pipeline->GetMinPlatformVersion() < static_cast<int32_t>(PlatformVersion::VERSION_TEN)) {
146         DrawForApiNine(context);
147         return;
148     }
149     auto& canvas = context.canvas;
150     PaintLockLine(canvas, offset_->Get());
151     canvas.Save();
152     for (int i = 0; i < PATTERN_LOCK_COL_COUNT; i++) {
153         for (int j = 0; j < PATTERN_LOCK_COL_COUNT; j++) {
154             PaintLockCircle(canvas, offset_->Get(), i + 1, j + 1);
155         }
156     }
157     canvas.Restore();
158 }
159 
DrawForApiNine(DrawingContext & context)160 void PatternLockModifier::DrawForApiNine(DrawingContext& context)
161 {
162     auto& canvas = context.canvas;
163     PaintLockLineForApiNine(canvas, offset_->Get());
164     canvas.Save();
165     for (int i = 0; i < PATTERN_LOCK_COL_COUNT; i++) {
166         for (int j = 0; j < PATTERN_LOCK_COL_COUNT; j++) {
167             PaintLockCircleForApiNine(canvas, offset_->Get(), i + 1, j + 1);
168         }
169     }
170     canvas.Restore();
171 }
172 
PaintLockLineForApiNine(RSCanvas & canvas,const OffsetF & offset)173 void PatternLockModifier::PaintLockLineForApiNine(RSCanvas& canvas, const OffsetF& offset)
174 {
175     size_t count = choosePoint_.size();
176     if (count == 0) {
177         return;
178     }
179 
180     float sideLength = sideLength_->Get();
181     float pathStrokeWidth = pathStrokeWidth_->Get();
182     if (LessOrEqual(pathStrokeWidth, 0.0)) {
183         return;
184     }
185     float handleStrokeWidth = std::min(pathStrokeWidth, sideLength / PATTERN_LOCK_COL_COUNT);
186     pathStrokeWidth = std::max(handleStrokeWidth, 0.0f);
187 
188     auto pathColor = pathColor_->Get();
189     auto cellCenter = cellCenter_->Get();
190     RSPen pen;
191     pen.SetAntiAlias(true);
192     pen.SetColor(ToRSColor(pathColor));
193     pen.SetWidth(pathStrokeWidth);
194     pen.SetCapStyle(RSPen::CapStyle::ROUND_CAP);
195 
196     Color pathColorAlpha255 = pathColor.ToColor().ChangeAlpha(MAX_ALPHA);
197     pen.SetColor(pathColorAlpha255.GetValue());
198     canvas.AttachPen(pen);
199     for (size_t i = 0; i < count - 1; i++) {
200         OffsetF pointBegin = GetCircleCenterByXY(offset, choosePoint_[i].GetColumn(), choosePoint_[i].GetRow());
201         OffsetF pointEnd = GetCircleCenterByXY(offset, choosePoint_[i + 1].GetColumn(), choosePoint_[i + 1].GetRow());
202         canvas.DrawLine(RSPoint(pointBegin.GetX(), pointBegin.GetY()), RSPoint(pointEnd.GetX(), pointEnd.GetY()));
203     }
204     if (isMoveEventValid_->Get()) {
205         OffsetF pointBegin =
206             GetCircleCenterByXY(offset, choosePoint_[count - 1].GetColumn(), choosePoint_[count - 1].GetRow());
207         float x1 = pointBegin.GetX();
208         float y1 = pointBegin.GetY();
209         float x2 = cellCenter.GetX();
210         float y2 = cellCenter.GetY();
211         x2 = x2 > offset.GetX() + sideLength ? offset.GetX() + sideLength : x2;
212         x2 = x2 < offset.GetX() ? offset.GetX() : x2;
213         y2 = y2 > offset.GetY() + sideLength ? offset.GetY() + sideLength : y2;
214         y2 = y2 < offset.GetY() ? offset.GetY() : y2;
215 
216         std::vector<RSColorQuad> colors = { pathColorAlpha255.GetValue(), pathColorAlpha255.GetValue(),
217             pathColorAlpha255.ChangeOpacity(0.0).GetValue() };
218         std::vector<RSScalar> pos = { 0.0, GRADUAL_CHANGE_POINT, 1.0 };
219         auto shader = pen.GetShaderEffect();
220         shader->CreateLinearGradient(RSPoint(x1, y1), RSPoint(x2, y2), colors, pos, RSTileMode::CLAMP);
221         pen.SetShaderEffect(shader);
222         canvas.DrawLine(RSPoint(x1, y1), RSPoint(x2, y2));
223     }
224     canvas.DetachPen();
225     canvas.Restore();
226 }
227 
PaintLockCircleForApiNine(RSCanvas & canvas,const OffsetF & offset,int32_t x,int32_t y)228 void PatternLockModifier::PaintLockCircleForApiNine(RSCanvas& canvas, const OffsetF& offset, int32_t x, int32_t y)
229 {
230     auto activeColor = activeColor_->Get();
231     auto regularColor = regularColor_->Get();
232     auto selectedColor = selectedColor_->Get();
233     auto sideLength = sideLength_->Get();
234     auto circleRadius = circleRadius_->Get();
235 
236     RSBrush brush;
237     brush.SetAntiAlias(true);
238     brush.SetColor(ToRSColor(regularColor));
239     OffsetF cellcenter = GetCircleCenterByXY(offset, x, y);
240     OffsetF firstCellcenter = GetCircleCenterByXY(offset, 1, 1);
241     float offsetX = cellcenter.GetX();
242     float offsetY = cellcenter.GetY();
243     const int32_t radiusCount = RADIUS_TO_DIAMETER * PATTERN_LOCK_COL_COUNT;
244     float handleCircleRadius = std::min(circleRadius, sideLength / scaleBackgroundCircleRadius_ / radiusCount);
245     circleRadius = std::max(handleCircleRadius, 0.0f);
246     if (CheckChoosePoint(x, y)) {
247         const int32_t lastIndexFir = 1;
248         if (CheckChoosePointIsLastIndex(x, y, lastIndexFir)) {
249             if (isMoveEventValid_->Get()) {
250                 brush.SetColor(ToRSColor(activeColor));
251                 canvas.AttachBrush(brush);
252                 auto radius = circleRadius * scaleBackgroundCircleRadius_;
253                 canvas.DrawCircle(
254                     RSPoint(offsetX, offsetY), std::min(static_cast<float>(radius), firstCellcenter.GetX()));
255             } else {
256                 brush.SetColor(ToRSColor(selectedColor));
257                 canvas.AttachBrush(brush);
258                 canvas.DrawCircle(RSPoint(offsetX, offsetY), circleRadius * scaleActiveCircleRadius_);
259             }
260         } else {
261             brush.SetColor(ToRSColor(selectedColor));
262             canvas.AttachBrush(brush);
263             canvas.DrawCircle(RSPoint(offsetX, offsetY), circleRadius * scaleActiveCircleRadius_);
264         }
265     } else {
266         canvas.AttachBrush(brush);
267         canvas.DrawCircle(RSPoint(offsetX, offsetY), circleRadius);
268     }
269     canvas.DetachBrush();
270 }
271 
PaintLockLine(RSCanvas & canvas,const OffsetF & offset)272 void PatternLockModifier::PaintLockLine(RSCanvas& canvas, const OffsetF& offset)
273 {
274     size_t count = choosePoint_.size();
275     if (count < 1) {
276         return;
277     }
278 
279     float sideLength = sideLength_->Get();
280     float pathStrokeWidth = pathStrokeWidth_->Get();
281     if (LessOrEqual(pathStrokeWidth, 0.0)) {
282         return;
283     }
284     float handleStrokeWidth = std::min(pathStrokeWidth, sideLength / PATTERN_LOCK_COL_COUNT);
285     pathStrokeWidth = std::max(handleStrokeWidth, 0.0f);
286 
287     auto pathColor = pathColor_->Get();
288     RSPen pen;
289     pen.SetAntiAlias(true);
290     pen.SetWidth(pathStrokeWidth);
291     pen.SetCapStyle(RSPen::CapStyle::ROUND_CAP);
292 
293     pen.SetColor(pathColor.GetValue());
294     canvas.Save();
295     SetCircleClip(canvas);
296     canvas.AttachPen(pen);
297     RSPath path;
298     if (count > ANIMATABLE_POINT_COUNT) {
299         for (size_t i = 0; i < count - ANIMATABLE_POINT_COUNT; i++) {
300             OffsetF pointBegin = GetCircleCenterByXY(offset, choosePoint_[i].GetColumn(), choosePoint_[i].GetRow());
301             OffsetF pointEnd =
302                 GetCircleCenterByXY(offset, choosePoint_[i + 1].GetColumn(), choosePoint_[i + 1].GetRow());
303             path.MoveTo(pointBegin.GetX(), pointBegin.GetY());
304             path.LineTo(pointEnd.GetX(), pointEnd.GetY());
305         }
306     }
307     AddConnectedLineToPath(path, offset);
308     if (isMoveEventValid_->Get()) {
309         OffsetF pointBegin =
310             GetCircleCenterByXY(offset, choosePoint_[count - 1].GetColumn(), choosePoint_[count - 1].GetRow());
311         OffsetF pointEnd = GetPointEndByCellCenter();
312         if (pointEnd != pointBegin) {
313             path.MoveTo(pointBegin.GetX(), pointBegin.GetY());
314             path.LineTo(pointEnd.GetX(), pointEnd.GetY());
315         }
316     }
317     AddCanceledLineToPath(path, offset);
318     canvas.DrawPath(path);
319     canvas.DetachPen();
320     canvas.Restore();
321 }
322 
AddConnectedLineToPath(RSPath & path,const OffsetF & offset)323 void PatternLockModifier::AddConnectedLineToPath(RSPath& path, const OffsetF& offset)
324 {
325     size_t count = choosePoint_.size();
326     if (count < ANIMATABLE_POINT_COUNT) {
327         return;
328     }
329     OffsetF pointBegin = GetCircleCenterByXY(offset, choosePoint_[count - ANIMATABLE_POINT_COUNT].GetColumn(),
330         choosePoint_[count - ANIMATABLE_POINT_COUNT].GetRow());
331     OffsetF pointEnd = GetConnectedLineTailPoint();
332     if (pointEnd != pointBegin) {
333         path.MoveTo(pointBegin.GetX(), pointBegin.GetY());
334         path.LineTo(pointEnd.GetX(), pointEnd.GetY());
335     }
336 }
337 
AddCanceledLineToPath(RSPath & path,const OffsetF & offset)338 void PatternLockModifier::AddCanceledLineToPath(RSPath& path, const OffsetF& offset)
339 {
340     if (!needCanceledLine_) {
341         return;
342     }
343     size_t count = choosePoint_.size();
344     OffsetF pointBegin =
345         GetCircleCenterByXY(offset, choosePoint_[count - 1].GetColumn(), choosePoint_[count - 1].GetRow());
346     OffsetF pointEnd = GetCanceledLineTailPoint();
347     if (pointEnd != pointBegin) {
348         path.MoveTo(pointBegin.GetX(), pointBegin.GetY());
349         path.LineTo(pointEnd.GetX(), pointEnd.GetY());
350     }
351 }
352 
PaintLockCircle(RSCanvas & canvas,const OffsetF & offset,int32_t x,int32_t y)353 void PatternLockModifier::PaintLockCircle(RSCanvas& canvas, const OffsetF& offset, int32_t x, int32_t y)
354 {
355     auto activeColor = activeColor_->Get();
356     auto regularColor = regularColor_->Get();
357     auto selectedColor = selectedColor_->Get();
358     auto circleRadius = circleRadius_->Get();
359     auto pointAnimateColor = pointAnimateColor_->Get();
360     auto pathColor = pathColor_->Get();
361 
362     OffsetF cellcenter = GetCircleCenterByXY(offset, x, y);
363     float offsetX = cellcenter.GetX();
364     float offsetY = cellcenter.GetY();
365 
366     auto index = (x - 1) * PATTERN_LOCK_COL_COUNT + y - 1;
367     if (CheckChoosePoint(x, y)) {
368         PaintCircle(canvas, offsetX, offsetY, GetBackgroundCircleRadius(index), ToRSColor(pathColor));
369         PaintLightRing(canvas, offsetX, offsetY, GetLightRingCircleRadius(index), GetLightRingAlphaF(index));
370         const int32_t lastIndexFir = 1;
371         CheckIsHoverAndPaint(canvas, offsetX, offsetY, GetActiveCircleRadius(index), index);
372         if (isMoveEventValid_->Get() && CheckChoosePointIsLastIndex(x, y, lastIndexFir)) {
373             PaintCircle(canvas, offsetX, offsetY, GetActiveCircleRadius(index), ToRSColor(activeColor));
374         } else {
375             if (challengeResult_.has_value()) {
376                 PaintCircle(canvas, offsetX, offsetY, GetActiveCircleRadius(index), ToRSColor(pointAnimateColor));
377             } else {
378                 PaintCircle(canvas, offsetX, offsetY, GetActiveCircleRadius(index), ToRSColor(selectedColor));
379             }
380         }
381     } else {
382         CheckIsHoverAndPaint(canvas, offsetX, offsetY, circleRadius, index);
383         PaintCircle(canvas, offsetX, offsetY, circleRadius, ToRSColor(regularColor));
384     }
385 }
386 
CheckIsHoverAndPaint(RSCanvas & canvas,float offsetX,float offsetY,float radius,int32_t index)387 void PatternLockModifier::CheckIsHoverAndPaint(
388     RSCanvas& canvas, float offsetX, float offsetY, float radius, int32_t index)
389 {
390     if (isHover_->Get() && hoverIndex_->Get() == index) {
391         PaintCircle(canvas, offsetX, offsetY, radius * hoverRadiusScale_, ToRSColor(hoverColor_->Get()));
392     }
393 }
394 
PaintCircle(RSCanvas & canvas,float offsetX,float offsetY,float radius,const RSColor & circleColor)395 void PatternLockModifier::PaintCircle(
396     RSCanvas& canvas, float offsetX, float offsetY, float radius, const RSColor& circleColor)
397 {
398     RSBrush brush;
399     brush.SetAntiAlias(true);
400     brush.SetColor(circleColor);
401     canvas.AttachBrush(brush);
402     canvas.DrawCircle(RSPoint(offsetX, offsetY), radius);
403     canvas.DetachBrush();
404 }
405 
PaintLightRing(RSCanvas & canvas,float offsetX,float offsetY,float radius,float alphaF)406 void PatternLockModifier::PaintLightRing(RSCanvas& canvas, float offsetX, float offsetY, float radius, float alphaF)
407 {
408     if (NearZero(alphaF)) {
409         return;
410     }
411     RSPen pen;
412     pen.SetWidth(LIGHT_RING_LINE_WIDTH.ConvertToPx());
413     pen.SetAntiAlias(true);
414     pen.SetColor(ToRSColor(activeColor_->Get()));
415     pen.SetAlphaF(alphaF);
416     RSFilter filter;
417     filter.SetMaskFilter(RSMaskFilter::CreateBlurMaskFilter(
418         RSBlurType::NORMAL, RSDrawing::ConvertRadiusToSigma(LIGHT_RING_MASK_RADIUS.ConvertToPx())));
419     pen.SetFilter(filter);
420 
421     canvas.AttachPen(pen);
422     RSPath path;
423     path.AddCircle(offsetX, offsetY, radius);
424     canvas.DrawPath(path);
425     canvas.DetachPen();
426 }
427 
CheckChoosePoint(int32_t x,int32_t y) const428 bool PatternLockModifier::CheckChoosePoint(int32_t x, int32_t y) const
429 {
430     for (auto it : choosePoint_) {
431         if (it.GetColumn() == x && it.GetRow() == y) {
432             return true;
433         }
434     }
435     return false;
436 }
437 
CheckChoosePointIsLastIndex(int32_t x,int32_t y,int32_t index) const438 bool PatternLockModifier::CheckChoosePointIsLastIndex(int32_t x, int32_t y, int32_t index) const
439 {
440     if (!choosePoint_.empty() && static_cast<int32_t>(choosePoint_.size()) >= index) {
441         if (choosePoint_.at(choosePoint_.size() - static_cast<uint32_t>(index)).GetColumn() == x &&
442             choosePoint_.at(choosePoint_.size() - static_cast<uint32_t>(index)).GetRow() == y) {
443             return true;
444         }
445     }
446     return false;
447 }
448 
GetCircleCenterByXY(const OffsetF & offset,int32_t x,int32_t y)449 OffsetF PatternLockModifier::GetCircleCenterByXY(const OffsetF& offset, int32_t x, int32_t y)
450 {
451     float sideLength = sideLength_->Get();
452     OffsetF cellCenter;
453     int32_t scale = RADIUS_TO_DIAMETER;
454     cellCenter.SetX(offset.GetX() + sideLength / PATTERN_LOCK_COL_COUNT / scale * (x * scale - 1));
455     cellCenter.SetY(offset.GetY() + sideLength / PATTERN_LOCK_COL_COUNT / scale * (y * scale - 1));
456     return cellCenter;
457 }
458 
SetSideLength(float sideLength)459 void PatternLockModifier::SetSideLength(float sideLength)
460 {
461     CHECK_NULL_VOID(sideLength_);
462     if (!NearEqual(sideLength_->Get(), sideLength)) {
463         sideLength_->Set(sideLength);
464         size_t count = choosePoint_.size();
465         if (count > 0) {
466             OffsetF lastPoint = GetCircleCenterByXY(
467                 offset_->Get(), choosePoint_[count - 1].GetColumn(), choosePoint_[count - 1].GetRow());
468             connectedLineTailPoint_->Set(lastPoint);
469             canceledLineTailPoint_->Set(lastPoint);
470         }
471     }
472 }
473 
SetCircleRadius(float circleRadius)474 void PatternLockModifier::SetCircleRadius(float circleRadius)
475 {
476     CHECK_NULL_VOID(circleRadius_);
477     auto sideLength = sideLength_->Get();
478     if (NearZero(scaleBackgroundCircleRadius_)) {
479         return;
480     }
481     float handleCircleRadius =
482         std::min(circleRadius, sideLength / scaleBackgroundCircleRadius_ / PATTERN_LOCK_COL_COUNT * DIAMETER_TO_RADIUS);
483     circleRadius = std::max(handleCircleRadius, 0.0f);
484     if (!NearEqual(circleRadius_->Get(), circleRadius)) {
485         circleRadius_->Set(circleRadius);
486         for (const auto& cell : choosePoint_) {
487             auto index = (cell.GetColumn() - 1) * PATTERN_LOCK_COL_COUNT + cell.GetRow() - 1;
488             if (index < PATTERN_LOCK_POINT_COUNT && index >= 0) {
489                 backgroundCircleRadius_.at(index)->Set(circleRadius * scaleBackgroundCircleRadius_);
490                 activeCircleRadius_.at(index)->Set(circleRadius * scaleActiveCircleRadius_);
491                 lightRingRadius_.at(index)->Set(circleRadius * scaleLightRingRadiusStart_);
492             }
493         }
494     }
495 }
496 
SetRegularColor(const Color & regularColor)497 void PatternLockModifier::SetRegularColor(const Color& regularColor)
498 {
499     CHECK_NULL_VOID(regularColor_);
500     regularColor_->Set(regularColor);
501 }
502 
SetSelectColor(const Color & selectedColor)503 void PatternLockModifier::SetSelectColor(const Color& selectedColor)
504 {
505     CHECK_NULL_VOID(selectedColor_);
506     if (selectedColor_->Get() != selectedColor) {
507         selectedColor_->Set(selectedColor);
508     }
509 }
510 
SetActiveColor(const Color & activeColor)511 void PatternLockModifier::SetActiveColor(const Color& activeColor)
512 {
513     CHECK_NULL_VOID(activeColor_);
514     activeColor_->Set(activeColor);
515 }
516 
SetPathColor(const LinearColor & pathColor)517 void PatternLockModifier::SetPathColor(const LinearColor& pathColor)
518 {
519     CHECK_NULL_VOID(pathColor_);
520     pathColor_->Set(pathColor);
521 }
522 
SetHoverColor(const Color & hoverColor)523 void PatternLockModifier::SetHoverColor(const Color& hoverColor)
524 {
525     CHECK_NULL_VOID(hoverColor_);
526     if (hoverColor_->Get() != hoverColor) {
527         hoverColor_->Set(hoverColor);
528     }
529 }
530 
SetWrongColor(const Color & wrongColor)531 void PatternLockModifier::SetWrongColor(const Color& wrongColor)
532 {
533     CHECK_NULL_VOID(wrongColor_);
534     if (wrongColor_->Get() != wrongColor) {
535         wrongColor_->Set(wrongColor);
536     }
537 }
538 
SetCorrectColor(const Color & correctColor)539 void PatternLockModifier::SetCorrectColor(const Color& correctColor)
540 {
541     CHECK_NULL_VOID(correctColor_);
542     correctColor_->Set(correctColor);
543 }
544 
SetPathStrokeWidth(float pathStrokeWidth)545 void PatternLockModifier::SetPathStrokeWidth(float pathStrokeWidth)
546 {
547     CHECK_NULL_VOID(pathStrokeWidth_);
548     pathStrokeWidth_->Set(pathStrokeWidth);
549 }
550 
SetContentOffset(const OffsetF & offset)551 void PatternLockModifier::SetContentOffset(const OffsetF& offset)
552 {
553     CHECK_NULL_VOID(offset_);
554     if (!NearEqual(offset_->Get(), offset)) {
555         offset_->Set(offset);
556         size_t count = choosePoint_.size();
557         if (count > 0) {
558             OffsetF lastPoint =
559                 GetCircleCenterByXY(offset, choosePoint_[count - 1].GetColumn(), choosePoint_[count - 1].GetRow());
560             connectedLineTailPoint_->Set(lastPoint);
561             canceledLineTailPoint_->Set(lastPoint);
562         }
563     }
564 }
565 
SetIsMoveEventValid(bool isMoveEventValid)566 void PatternLockModifier::SetIsMoveEventValid(bool isMoveEventValid)
567 {
568     isMoveEventValid_->Set(isMoveEventValid);
569 }
570 
SetIsHover(bool isHover)571 void PatternLockModifier::SetIsHover(bool isHover)
572 {
573     isHover_->Set(isHover);
574 }
575 
SetHoverIndex(int32_t hoverIndex)576 void PatternLockModifier::SetHoverIndex(int32_t hoverIndex)
577 {
578     hoverIndex_->Set(hoverIndex);
579 }
580 
StartChallengeResultAnimate()581 void PatternLockModifier::StartChallengeResultAnimate()
582 {
583     if (!challengeResult_.has_value()) {
584         return;
585     }
586     if (challengeResult_.value() == NG::PatternLockChallengeResult::CORRECT) {
587         pointAnimateColor_->Set(LinearColor(selectedColor_->Get()));
588         AnimationOption option = AnimationOption();
589         option.SetDuration(CONNECT_ANIMATION_DURATION_FIRST);
590         option.SetCurve(Curves::SHARP);
591         AnimationUtils::Animate(option, [&]() { pointAnimateColor_->Set(LinearColor(correctColor_->Get())); });
592     } else if (challengeResult_.value() == NG::PatternLockChallengeResult::WRONG) {
593         pointAnimateColor_->Set(LinearColor(wrongColor_->Get()));
594         auto pathColor = pathColor_->Get();
595         AnimationOption option = AnimationOption();
596         option.SetDuration(WRONG_ANIMATION_DURATION_FLASH_TWICE);
597         option.SetCurve(Curves::SHARP);
598         auto dimmingAnimation = [weak = WeakClaim(this)]() {
599             auto modifier = weak.Upgrade();
600             CHECK_NULL_VOID(modifier);
601             modifier->pointAnimateColor_->Set(
602                 LinearColor(modifier->wrongColor_->Get().BlendOpacity(FLASH_POINT_OPACITY)));
603             modifier->SetPathColor(LinearColor(modifier->pathColor_->Get().BlendOpacity(FLASH_POINT_OPACITY)));
604         };
605         auto brighteningAnimation = [weak = WeakClaim(this), pathColor]() {
606             auto modifier = weak.Upgrade();
607             CHECK_NULL_VOID(modifier);
608             modifier->pointAnimateColor_->Set(LinearColor(modifier->wrongColor_->Get()));
609             modifier->SetPathColor(pathColor);
610         };
611         AnimationUtils::OpenImplicitAnimation(option, Curves::SHARP, nullptr);
612         AnimationUtils::AddKeyFrame(((float)WRONG_ANIMATION_DURATION_DIMMING / WRONG_ANIMATION_DURATION_FLASH_TWICE),
613             Curves::SHARP, dimmingAnimation);
614         AnimationUtils::AddKeyFrame(((float)WRONG_ANIMATION_DURATION_FLASH_ONCE / WRONG_ANIMATION_DURATION_FLASH_TWICE),
615             Curves::SHARP, brighteningAnimation);
616         AnimationUtils::AddKeyFrame(((float)(WRONG_ANIMATION_DURATION_FLASH_ONCE + WRONG_ANIMATION_DURATION_DIMMING) /
617                                         WRONG_ANIMATION_DURATION_FLASH_TWICE),
618             Curves::SHARP, dimmingAnimation);
619         AnimationUtils::AddKeyFrame(1.0f, Curves::SHARP, brighteningAnimation);
620         AnimationUtils::CloseImplicitAnimation();
621     }
622 }
623 
SetChallengeResult(std::optional<NG::PatternLockChallengeResult> & challengeResult)624 void PatternLockModifier::SetChallengeResult(std::optional<NG::PatternLockChallengeResult>& challengeResult)
625 {
626     if (challengeResult_ != challengeResult) {
627         challengeResult_ = challengeResult;
628         StartChallengeResultAnimate();
629     }
630 }
631 
SetCellCenterOffset(const OffsetF & cellcenter)632 void PatternLockModifier::SetCellCenterOffset(const OffsetF& cellcenter)
633 {
634     CHECK_NULL_VOID(cellCenter_);
635     cellCenter_->Set(cellcenter);
636 }
637 
SetChoosePoint(const std::vector<PatternLockCell> & choosePoint)638 void PatternLockModifier::SetChoosePoint(const std::vector<PatternLockCell>& choosePoint)
639 {
640     choosePoint_ = choosePoint;
641 }
642 
SetActiveCircleRadiusScale(float scale)643 void PatternLockModifier::SetActiveCircleRadiusScale(float scale)
644 {
645     scaleActiveCircleRadius_ = scale;
646 }
647 
SetBackgroundCircleRadiusScale(float scale)648 void PatternLockModifier::SetBackgroundCircleRadiusScale(float scale)
649 {
650     scaleBackgroundCircleRadius_ = scale;
651 }
652 
SetLightRingRadiusStartScale(float scale)653 void PatternLockModifier::SetLightRingRadiusStartScale(float scale)
654 {
655     scaleLightRingRadiusStart_ = scale;
656 }
657 
SetLightRingRadiusEndScale(float scale)658 void PatternLockModifier::SetLightRingRadiusEndScale(float scale)
659 {
660     scaleLightRingRadiusEnd_ = scale;
661 }
662 
SetHoverRadiusScale(float scale)663 void PatternLockModifier::SetHoverRadiusScale(float scale)
664 {
665     hoverRadiusScale_ = scale;
666 }
667 
SetBackgroundCircleRadius(int32_t index)668 void PatternLockModifier::SetBackgroundCircleRadius(int32_t index)
669 {
670     if (index < static_cast<int32_t>(backgroundCircleRadius_.size()) && index >= 0) {
671         backgroundCircleRadius_.at(index)->Set(0.0f);
672         AnimationOption option = AnimationOption();
673         auto curve = AceType::MakeRefPtr<ResponsiveSpringMotion>(
674             BACKGROUND_RADIUS_SPRING_RESPONSE, BACKGROUND_RADIUS_SPRING_DAMPING);
675         option.SetCurve(curve);
676         AnimationUtils::Animate(option,
677             [&]() { backgroundCircleRadius_.at(index)->Set(circleRadius_->Get() * scaleBackgroundCircleRadius_); });
678     }
679 }
680 
GetBackgroundCircleRadius(int32_t index) const681 float PatternLockModifier::GetBackgroundCircleRadius(int32_t index) const
682 {
683     if ((index >= PATTERN_LOCK_POINT_COUNT || index < 0)) {
684         return 0;
685     }
686     return backgroundCircleRadius_.at(index)->Get();
687 }
688 
SetActiveCircleRadius(int32_t index)689 void PatternLockModifier::SetActiveCircleRadius(int32_t index)
690 {
691     if (index < static_cast<int32_t>(activeCircleRadius_.size()) && index >= 0) {
692         activeCircleRadius_.at(index)->Set(circleRadius_->Get());
693         AnimationOption option = AnimationOption();
694         option.SetDuration(ACTIVE_RADIUS_ANIMATION_DURATION);
695         option.SetCurve(Curves::FRICTION);
696         AnimationUtils::Animate(
697             option, [&]() { activeCircleRadius_.at(index)->Set(circleRadius_->Get() * scaleActiveCircleRadius_); });
698     }
699 }
700 
GetActiveCircleRadius(int32_t index) const701 float PatternLockModifier::GetActiveCircleRadius(int32_t index) const
702 {
703     if ((index >= PATTERN_LOCK_POINT_COUNT || index < 0)) {
704         return 0;
705     }
706     return activeCircleRadius_.at(index)->Get();
707 }
708 
SetLightRingCircleRadius(int32_t index)709 void PatternLockModifier::SetLightRingCircleRadius(int32_t index)
710 {
711     if (index < static_cast<int32_t>(lightRingRadius_.size()) && index >= 0) {
712         auto circleRadius = circleRadius_->Get();
713         lightRingRadius_.at(index)->Set(circleRadius * scaleLightRingRadiusStart_);
714         AnimationOption option = AnimationOption();
715         option.SetDuration(LIGHT_RING_RADIUS_ANIMATION_DURATION);
716         option.SetCurve(Curves::LINEAR);
717         AnimationUtils::Animate(
718             option, [&]() { lightRingRadius_.at(index)->Set(circleRadius * scaleLightRingRadiusEnd_); });
719     }
720 }
721 
GetLightRingCircleRadius(int32_t index) const722 float PatternLockModifier::GetLightRingCircleRadius(int32_t index) const
723 {
724     if ((index >= PATTERN_LOCK_POINT_COUNT || index < 0)) {
725         return 0;
726     }
727     return lightRingRadius_.at(index)->Get();
728 }
729 
SetLightRingAlphaF(int32_t index)730 void PatternLockModifier::SetLightRingAlphaF(int32_t index)
731 {
732     if (index < static_cast<int32_t>(lightRingAlphaF_.size()) && index >= 0) {
733         auto singleLightRingAlphaF = lightRingAlphaF_.at(index);
734         singleLightRingAlphaF->Set(LIGHT_RING_ALPHAF_START);
735         AnimationOption optionFirst = AnimationOption();
736         optionFirst.SetDuration(LIGHT_RING_ALPHAF_ANIMATION_DURATION_FIRST);
737         optionFirst.SetCurve(Curves::SHARP);
738         optionFirst.SetOnFinishEvent([=] {
739             AnimationOption optionSecond = AnimationOption();
740             optionSecond.SetDuration(LIGHT_RING_ALPHAF_ANIMATION_DURATION_SECOND);
741             optionSecond.SetCurve(Curves::SHARP);
742             AnimationUtils::Animate(optionSecond, [=]() { singleLightRingAlphaF->Set(LIGHT_RING_ALPHAF_START); });
743         });
744         AnimationUtils::Animate(
745             optionFirst, [&]() { singleLightRingAlphaF->Set(LIGHT_RING_ALPHAF_END); }, optionFirst.GetOnFinishEvent());
746     }
747 }
748 
GetLightRingAlphaF(int32_t index) const749 float PatternLockModifier::GetLightRingAlphaF(int32_t index) const
750 {
751     if ((index >= PATTERN_LOCK_POINT_COUNT || index < 0)) {
752         return 0;
753     }
754     return lightRingAlphaF_.at(index)->Get();
755 }
756 
SetConnectedLineTailPoint(int32_t x,int32_t y)757 void PatternLockModifier::SetConnectedLineTailPoint(int32_t x, int32_t y)
758 {
759     size_t count = choosePoint_.size();
760     if (count < 1) {
761         return;
762     }
763     OffsetF lastPoint = GetCircleCenterByXY(offset_->Get(), x, y);
764     if (isTouchDown_ && isMoveEventValid_) {
765         connectedLineTailPoint_->Set(cellCenter_->Get());
766         AnimationOption option = AnimationOption();
767         auto curve =
768             AceType::MakeRefPtr<ResponsiveSpringMotion>(CONNECTED_LINE_SPRING_RESPONSE, CONNECTED_LINE_SPRING_DAMPING);
769         option.SetCurve(curve);
770         AnimationUtils::Animate(option, [&]() { connectedLineTailPoint_->Set(lastPoint); });
771     } else {
772         connectedLineTailPoint_->Set(lastPoint);
773     }
774 }
775 
GetConnectedLineTailPoint() const776 OffsetF PatternLockModifier::GetConnectedLineTailPoint() const
777 {
778     return connectedLineTailPoint_->Get();
779 }
780 
SetCanceledLineTailPoint()781 void PatternLockModifier::SetCanceledLineTailPoint()
782 {
783     size_t count = choosePoint_.size();
784     if (count < 1) {
785         return;
786     }
787 
788     canceledLineTailPoint_->Set(GetPointEndByCellCenter());
789     OffsetF pointEnd =
790         GetCircleCenterByXY(offset_->Get(), choosePoint_[count - 1].GetColumn(), choosePoint_[count - 1].GetRow());
791     AnimationOption option = AnimationOption();
792     auto curve =
793         AceType::MakeRefPtr<ResponsiveSpringMotion>(CANCELED_LINE_SPRING_RESPONSE, CANCELED_LINE_SPRING_DAMPING);
794     option.SetCurve(curve);
795     AnimationUtils::Animate(option, [&]() { canceledLineTailPoint_->Set(pointEnd); });
796 }
797 
GetCanceledLineTailPoint() const798 OffsetF PatternLockModifier::GetCanceledLineTailPoint() const
799 {
800     return canceledLineTailPoint_->Get();
801 }
802 
StartConnectedCircleAnimate(int32_t x,int32_t y)803 void PatternLockModifier::StartConnectedCircleAnimate(int32_t x, int32_t y)
804 {
805     auto index = (x - 1) * PATTERN_LOCK_COL_COUNT + y - 1;
806     SetBackgroundCircleRadius(index);
807     SetActiveCircleRadius(index);
808     SetLightRingCircleRadius(index);
809     SetLightRingAlphaF(index);
810 }
811 
StartConnectedLineAnimate(int32_t x,int32_t y)812 void PatternLockModifier::StartConnectedLineAnimate(int32_t x, int32_t y)
813 {
814     SetConnectedLineTailPoint(x, y);
815 }
816 
StartCanceledAnimate()817 void PatternLockModifier::StartCanceledAnimate()
818 {
819     SetCanceledLineTailPoint();
820 }
821 
Reset()822 void PatternLockModifier::Reset()
823 {
824     SetIsTouchDown(false);
825     needCanceledLine_ = false;
826     challengeResult_.reset();
827     connectedLineTailPoint_->Set(OffsetF());
828     canceledLineTailPoint_->Set(OffsetF());
829     for (auto& radius : backgroundCircleRadius_) {
830         radius->Set(0.0f);
831     }
832     for (auto& radius : activeCircleRadius_) {
833         radius->Set(circleRadius_->Get());
834     }
835     for (auto& radius : lightRingRadius_) {
836         radius->Set(circleRadius_->Get() * scaleLightRingRadiusStart_);
837     }
838     for (auto& alphaF : lightRingAlphaF_) {
839         alphaF->Set(LIGHT_RING_ALPHAF_START);
840     }
841 }
842 
SetIsTouchDown(bool isTouchDown)843 void PatternLockModifier::SetIsTouchDown(bool isTouchDown)
844 {
845     if (isTouchDown_ && (!isTouchDown)) {
846         needCanceledLine_ = true;
847     } else if ((!isTouchDown_) && isTouchDown) {
848         needCanceledLine_ = false;
849     }
850     isTouchDown_ = isTouchDown;
851 }
852 
GetPointEndByCellCenter() const853 OffsetF PatternLockModifier::GetPointEndByCellCenter() const
854 {
855     auto offset = offset_->Get();
856     float sideLength = sideLength_->Get();
857     auto cellCenter = cellCenter_->Get();
858     float x = cellCenter.GetX();
859     float y = cellCenter.GetY();
860     x = x > offset.GetX() + sideLength ? offset.GetX() + sideLength : x;
861     x = x < offset.GetX() ? offset.GetX() : x;
862     y = y > offset.GetY() + sideLength ? offset.GetY() + sideLength : y;
863     y = y < offset.GetY() ? offset.GetY() : y;
864     return OffsetF(x, y);
865 }
866 
SetCircleClip(RSCanvas & canvas)867 void PatternLockModifier::SetCircleClip(RSCanvas& canvas)
868 {
869     int32_t x = 0;
870     int32_t y = 0;
871     int32_t index = 0;
872     OffsetF center;
873     float backgroundCircleRadius = 0.0f;
874     float activeCircleRadius = 0.0f;
875     float clipRadius = 0.0f;
876     RSPath path;
877     for (const auto& point : choosePoint_) {
878         x = point.GetColumn();
879         y = point.GetRow();
880         center = GetCircleCenterByXY(offset_->Get(), x, y);
881         index = (x - 1) * PATTERN_LOCK_COL_COUNT + y - 1;
882         backgroundCircleRadius = GetBackgroundCircleRadius(index);
883         activeCircleRadius = GetActiveCircleRadius(index);
884         clipRadius = backgroundCircleRadius > activeCircleRadius ? backgroundCircleRadius : activeCircleRadius;
885         path.AddCircle(center.GetX(), center.GetY(), clipRadius);
886     }
887     canvas.ClipPath(path, RSClipOp::DIFFERENCE, true);
888 }
889 } // namespace OHOS::Ace::NG
890