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