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