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