• 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/slider/slider_content_modifier.h"
17 
18 #include "base/geometry/ng/offset_t.h"
19 #include "base/utils/utils.h"
20 #include "core/animation/curves.h"
21 #include "core/components/common/properties/color.h"
22 #include "core/components/slider/slider_theme.h"
23 #include "core/components_ng/render/drawing_prop_convertor.h"
24 #include "core/components_ng/render/path_painter.h"
25 #include "core/pipeline/pipeline_base.h"
26 
27 namespace OHOS::Ace::NG {
28 namespace {
29 constexpr float HALF = 0.5f;
30 constexpr float SPRING_MOTION_RESPONSE = 0.314f;
31 constexpr float SPRING_MOTION_DAMPING_FRACTION = 0.95f;
32 } // namespace
SliderContentModifier(const Parameters & parameters,std::function<void ()> updateImageFunc)33 SliderContentModifier::SliderContentModifier(const Parameters& parameters, std::function<void()> updateImageFunc)
34     : updateImageFunc_(std::move(updateImageFunc)),
35       boardColor_(AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(Color::TRANSPARENT)))
36 {
37     // animatable property
38     selectStart_ = AceType::MakeRefPtr<AnimatablePropertyOffsetF>(parameters.selectStart - PointF());
39     selectEnd_ = AceType::MakeRefPtr<AnimatablePropertyOffsetF>(parameters.selectEnd - PointF());
40     backStart_ = AceType::MakeRefPtr<AnimatablePropertyOffsetF>(parameters.backStart - PointF());
41     backEnd_ = AceType::MakeRefPtr<AnimatablePropertyOffsetF>(parameters.backEnd - PointF());
42     blockCenterX_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(parameters.circleCenter.GetX());
43     blockCenterY_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(parameters.circleCenter.GetY());
44     trackThickness_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(parameters.trackThickness);
45     trackBackgroundColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(parameters.trackBackgroundColor));
46     selectColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(parameters.selectColor));
47     blockColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(parameters.blockColor));
48     trackBorderRadius_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(parameters.trackThickness * HALF);
49     stepSize_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(1);
50     blockBorderWidth_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(0);
51     stepColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor::TRANSPARENT);
52     blockBorderColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(parameters.blockColor));
53     blockSize_ = AceType::MakeRefPtr<AnimatablePropertySizeF>(parameters.blockSize);
54     // non-animatable property
55     stepRatio_ = AceType::MakeRefPtr<PropertyFloat>(parameters.stepRatio);
56     sliderMode_ = AceType::MakeRefPtr<PropertyInt>(static_cast<int>(SliderModelNG::SliderMode::OUTSET));
57     directionAxis_ = AceType::MakeRefPtr<PropertyInt>(static_cast<int>(Axis::HORIZONTAL));
58     isShowStep_ = AceType::MakeRefPtr<PropertyBool>(false);
59     blockType_ = AceType::MakeRefPtr<PropertyInt>(static_cast<int>(SliderModelNG::BlockStyleType::DEFAULT));
60     // others
61     UpdateData(parameters);
62     UpdateThemeColor();
63 
64     AttachProperty(selectStart_);
65     AttachProperty(selectEnd_);
66     AttachProperty(backStart_);
67     AttachProperty(backEnd_);
68     AttachProperty(blockCenterX_);
69     AttachProperty(blockCenterY_);
70     AttachProperty(trackThickness_);
71     AttachProperty(trackBackgroundColor_);
72     AttachProperty(selectColor_);
73     AttachProperty(blockColor_);
74     AttachProperty(boardColor_);
75     AttachProperty(trackBorderRadius_);
76     AttachProperty(stepSize_);
77     AttachProperty(blockBorderWidth_);
78     AttachProperty(stepColor_);
79     AttachProperty(blockBorderColor_);
80     AttachProperty(blockSize_);
81     AttachProperty(stepRatio_);
82     AttachProperty(sliderMode_);
83     AttachProperty(directionAxis_);
84     AttachProperty(isShowStep_);
85     AttachProperty(blockType_);
86 
87     InitializeShapeProperty();
88 }
89 
InitializeShapeProperty()90 void SliderContentModifier::InitializeShapeProperty()
91 {
92     shapeWidth_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
93     shapeHeight_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
94     circleRadius_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
95     ellipseRadiusX_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
96     ellipseRadiusY_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
97     rectTopLeftRadiusX_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
98     rectTopLeftRadiusY_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
99     rectTopRightRadiusX_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
100     rectTopRightRadiusY_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
101     rectBottomLeftRadiusX_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
102     rectBottomLeftRadiusY_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
103     rectBottomRightRadiusX_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
104     rectBottomRightRadiusY_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
105     AttachProperty(shapeWidth_);
106     AttachProperty(shapeHeight_);
107     AttachProperty(circleRadius_);
108     AttachProperty(ellipseRadiusX_);
109     AttachProperty(ellipseRadiusY_);
110     AttachProperty(rectTopLeftRadiusX_);
111     AttachProperty(rectTopLeftRadiusY_);
112     AttachProperty(rectTopRightRadiusX_);
113     AttachProperty(rectTopRightRadiusY_);
114     AttachProperty(rectBottomLeftRadiusX_);
115     AttachProperty(rectBottomLeftRadiusY_);
116     AttachProperty(rectBottomRightRadiusX_);
117     AttachProperty(rectBottomRightRadiusY_);
118 }
119 
onDraw(DrawingContext & context)120 void SliderContentModifier::onDraw(DrawingContext& context)
121 {
122     DrawBackground(context);
123     DrawStep(context);
124     DrawSelect(context);
125     DrawShadow(context);
126     DrawBlock(context);
127     DrawHoverOrPress(context);
128 }
129 
DrawBackground(DrawingContext & context)130 void SliderContentModifier::DrawBackground(DrawingContext& context)
131 {
132     auto& canvas = context.canvas;
133     auto trackBorderRadius = trackBorderRadius_->Get();
134 
135     RSBrush brush;
136     brush.SetAntiAlias(true);
137     brush.SetColor(ToRSColor(trackBackgroundColor_->Get()));
138 
139     canvas.AttachBrush(brush);
140     RSRoundRect roundRect(GetTrackRect(), trackBorderRadius, trackBorderRadius);
141     canvas.DrawRoundRect(roundRect);
142     canvas.DetachBrush();
143 }
144 
DrawStep(DrawingContext & context)145 void SliderContentModifier::DrawStep(DrawingContext& context)
146 {
147     if (!isShowStep_->Get()) {
148         return;
149     }
150     auto& canvas = context.canvas;
151     auto stepSize = stepSize_->Get();
152     auto stepColor = stepColor_->Get();
153     auto backStart = backStart_->Get();
154     auto backEnd = backEnd_->Get();
155     auto stepRatio = stepRatio_->Get();
156     if (NearEqual(stepRatio, .0f)) {
157         return;
158     }
159     float startX = backStart.GetX();
160     float endX = backEnd.GetX();
161     float startY = backStart.GetY();
162     float endY = backEnd.GetY();
163     if (NearEqual(startX, endX) && NearEqual(startY, endY)) {
164         return;
165     }
166     auto stepsLengthX = (endX - startX) * stepRatio;
167     auto stepsLengthY = (endY - startY) * stepRatio;
168 
169     RSBrush brush;
170     brush.SetAntiAlias(true);
171     brush.SetColor(ToRSColor(stepColor));
172     canvas.AttachBrush(brush);
173 
174     if (reverse_) {
175         while (GreatOrEqual(endX, startX) && GreatOrEqual(endY, startY)) {
176             canvas.DrawCircle(RSPoint(endX, endY), stepSize * HALF);
177             endX -= stepsLengthX;
178             endY -= stepsLengthY;
179         }
180     } else {
181         while (LessOrEqual(startX, endX) && LessOrEqual(startY, endY)) {
182             canvas.DrawCircle(RSPoint(startX, startY), stepSize * HALF);
183             startX += stepsLengthX;
184             startY += stepsLengthY;
185         }
186     }
187 
188     canvas.DetachBrush();
189 }
190 
DrawSelect(DrawingContext & context)191 void SliderContentModifier::DrawSelect(DrawingContext& context)
192 {
193     auto& canvas = context.canvas;
194     if (!NearEqual(selectStart_->Get().GetX(), selectEnd_->Get().GetX(), HALF) ||
195         !NearEqual(selectStart_->Get().GetY(), selectEnd_->Get().GetY(), HALF)) {
196         auto trackBorderRadius = trackBorderRadius_->Get();
197         auto direction = static_cast<Axis>(directionAxis_->Get());
198         auto blockCenter = GetBlockCenter();
199         auto trackThickness = trackThickness_->Get();
200         auto sliderMode = static_cast<SliderModelNG::SliderMode>(sliderMode_->Get());
201         auto rect = GetTrackRect();
202         auto insetOffset = .0f;
203         if (sliderMode == SliderModelNG::SliderMode::INSET) {
204             insetOffset = trackThickness * HALF;
205         }
206         if (!reverse_) {
207             if (direction == Axis::HORIZONTAL) {
208                 rect.SetRight(blockCenter.GetX() + std::max(trackBorderRadius, insetOffset));
209             } else {
210                 rect.SetBottom(blockCenter.GetY() + std::max(trackBorderRadius, insetOffset));
211             }
212         } else {
213             if (direction == Axis::HORIZONTAL) {
214                 rect.SetLeft(blockCenter.GetX() - std::max(trackBorderRadius, insetOffset));
215             } else {
216                 rect.SetTop(blockCenter.GetY() - std::max(trackBorderRadius, insetOffset));
217             }
218         }
219 
220         RSBrush brush;
221         brush.SetAntiAlias(true);
222         brush.SetColor(ToRSColor(selectColor_->Get()));
223 
224         canvas.AttachBrush(brush);
225         canvas.DrawRoundRect(RSRoundRect(rect, trackBorderRadius, trackBorderRadius));
226         canvas.DetachBrush();
227     }
228 }
229 
DrawDefaultBlock(DrawingContext & context)230 void SliderContentModifier::DrawDefaultBlock(DrawingContext& context)
231 {
232     auto& canvas = context.canvas;
233     auto borderWidth = blockBorderWidth_->Get();
234 
235     RSPen pen;
236     pen.SetAntiAlias(true);
237     pen.SetWidth(borderWidth);
238     pen.SetColor(ToRSColor(blockBorderColor_->Get()));
239     if (!NearEqual(borderWidth, .0f)) {
240         canvas.AttachPen(pen);
241     }
242     RSBrush brush;
243     brush.SetAntiAlias(true);
244     brush.SetColor(ToRSColor(blockColor_->Get()));
245     canvas.AttachBrush(brush);
246 
247     auto blockSize = blockSize_->Get();
248     auto blockCenter = GetBlockCenter();
249     float radius = std::min(blockSize.Width(), blockSize.Height()) * HALF - borderWidth * HALF;
250     canvas.DrawCircle(ToRSPoint(PointF(blockCenter.GetX(), blockCenter.GetY())), radius);
251     canvas.DetachBrush();
252     if (!NearEqual(borderWidth, .0f)) {
253         canvas.DetachPen();
254     }
255 }
256 
DrawHoverOrPress(DrawingContext & context)257 void SliderContentModifier::DrawHoverOrPress(DrawingContext& context)
258 {
259     if (static_cast<SliderModelNG::BlockStyleType>(blockType_->Get()) != SliderModelNG::BlockStyleType::DEFAULT) {
260         return;
261     }
262 
263     auto& canvas = context.canvas;
264     RSPen circleStatePen;
265     circleStatePen.SetAntiAlias(true);
266     // add animate color
267     circleStatePen.SetColor(ToRSColor(boardColor_->Get()));
268     circleStatePen.SetWidth(hotCircleShadowWidth_);
269     canvas.AttachPen(circleStatePen);
270     auto blockSize = blockSize_->Get();
271     float diameter = std::min(blockSize.Width(), blockSize.Height());
272     auto penRadius = (diameter + hotCircleShadowWidth_) * HALF;
273     auto blockCenter = GetBlockCenter();
274     canvas.DrawCircle(ToRSPoint(blockCenter), penRadius);
275     canvas.DetachPen();
276 }
277 
DrawShadow(DrawingContext & context)278 void SliderContentModifier::DrawShadow(DrawingContext& context)
279 {
280     if (static_cast<SliderModelNG::BlockStyleType>(blockType_->Get()) != SliderModelNG::BlockStyleType::DEFAULT) {
281         return;
282     }
283 
284     if (!mouseHoverFlag_ && !mousePressedFlag_) {
285         auto& canvas = context.canvas;
286         auto blockSize = blockSize_->Get();
287         auto blockCenter = GetBlockCenter();
288         float radius = std::min(blockSize.Width(), blockSize.Height()) * HALF;
289         canvas.Save();
290         RSBrush shadowBrush;
291         shadowBrush.SetAntiAlias(true);
292         shadowBrush.SetColor(ToRSColor(blockShadowColor_));
293         RSFilter filter;
294 #ifndef USE_ROSEN_DRAWING
295         filter.SetMaskFilter(RSMaskFilter::CreateBlurMaskFilter(
296 #else
297         filter.SetMaskFilter(RSRecordingMaskFilter::CreateBlurMaskFilter(
298 #endif
299             RSBlurType::NORMAL, RSDrawing::ConvertRadiusToSigma(hotCircleShadowWidth_)));
300         shadowBrush.SetFilter(filter);
301 
302         canvas.AttachBrush(shadowBrush);
303 #ifndef USE_ROSEN_DRAWING
304         RSPath path;
305 #else
306         RSRecordingPath path;
307 #endif
308         path.AddCircle(ToRSPoint(blockCenter).GetX(), ToRSPoint(blockCenter).GetY(), radius);
309         canvas.DrawPath(path);
310         canvas.DetachBrush();
311         canvas.Restore();
312     }
313 }
314 
SetBoardColor()315 void SliderContentModifier::SetBoardColor()
316 {
317     CHECK_NULL_VOID(boardColor_);
318     auto pipeline = PipelineBase::GetCurrentContext();
319     CHECK_NULL_VOID(pipeline);
320     auto theme = pipeline->GetTheme<SliderTheme>();
321     CHECK_NULL_VOID(theme);
322     Color shadowColor = Color::TRANSPARENT;
323     shadowColor = mouseHoverFlag_ ? theme->GetBlockHoverColor() : shadowColor;
324     shadowColor = mousePressedFlag_ ? theme->GetBlockPressedColor() : shadowColor;
325     auto duration = mousePressedFlag_ ? static_cast<int32_t>(theme->GetPressAnimationDuration())
326                                       : static_cast<int32_t>(theme->GetHoverAnimationDuration());
327     auto curve = mousePressedFlag_ ? Curves::SHARP : Curves::FRICTION;
328     AnimationOption option = AnimationOption();
329     option.SetDuration(duration);
330     option.SetCurve(curve);
331     AnimationUtils::Animate(option, [&]() { boardColor_->Set(LinearColor(shadowColor)); });
332 }
333 
UpdateData(const Parameters & parameters)334 void SliderContentModifier::UpdateData(const Parameters& parameters)
335 {
336     mouseHoverFlag_ = parameters.mouseHoverFlag_;
337     mousePressedFlag_ = parameters.mousePressedFlag_;
338     hotCircleShadowWidth_ = parameters.hotCircleShadowWidth;
339 }
340 
JudgeNeedAnimate(const RefPtr<SliderPaintProperty> & property)341 void SliderContentModifier::JudgeNeedAnimate(const RefPtr<SliderPaintProperty>& property)
342 {
343     auto reverse = property->GetReverseValue(false);
344     // when reverse is changed, slider block position changes do not animated.
345     if (reverse_ != reverse) {
346         SetNotAnimated();
347         reverse_ = reverse;
348     }
349 }
350 
StopSelectAnimation(const PointF & end)351 void SliderContentModifier::StopSelectAnimation(const PointF& end)
352 {
353     bool stop = false;
354     if (static_cast<Axis>(directionAxis_->Get()) == Axis::HORIZONTAL) {
355         auto current = selectEnd_->Get().GetX();
356         if ((LessNotEqual(targetSelectEnd_.GetX(), current) && GreatNotEqual(end.GetX(), current)) ||
357             (LessNotEqual(end.GetX(), current) && GreatNotEqual(targetSelectEnd_.GetX(), current))) {
358             stop = true;
359         }
360     } else {
361         auto current = selectEnd_->Get().GetY();
362         if ((LessNotEqual(targetSelectEnd_.GetY(), current) && GreatNotEqual(end.GetY(), current)) ||
363             (LessNotEqual(end.GetY(), current) && GreatNotEqual(targetSelectEnd_.GetY(), current))) {
364             stop = true;
365         }
366     }
367     if (stop) {
368         AnimationOption option = AnimationOption();
369         AnimationUtils::Animate(option, [this]() {
370             if (static_cast<Axis>(directionAxis_->Get()) == Axis::HORIZONTAL) {
371                 selectEnd_->Set(selectEnd_->Get());
372             } else {
373                 selectEnd_->Set(selectEnd_->Get());
374             }
375         });
376     }
377 }
378 
SetSelectSize(const PointF & start,const PointF & end)379 void SliderContentModifier::SetSelectSize(const PointF& start, const PointF& end)
380 {
381     if (selectStart_) {
382         selectStart_->Set(start - PointF());
383     }
384     CHECK_NULL_VOID(selectEnd_);
385     if (needAnimate_ && isVisible_) {
386         StopSelectAnimation(end);
387         AnimationOption option = AnimationOption();
388         auto motion =
389             AceType::MakeRefPtr<ResponsiveSpringMotion>(SPRING_MOTION_RESPONSE, SPRING_MOTION_DAMPING_FRACTION);
390         option.SetCurve(motion);
391         AnimationUtils::Animate(option, [&]() { selectEnd_->Set(end - PointF()); });
392     } else {
393         selectEnd_->Set(end - PointF());
394     }
395     targetSelectEnd_ = end - PointF();
396 }
397 
StopCircleCenterAnimation(const PointF & center)398 void SliderContentModifier::StopCircleCenterAnimation(const PointF& center)
399 {
400     bool stop = false;
401     if (static_cast<Axis>(directionAxis_->Get()) == Axis::HORIZONTAL) {
402         auto current = blockCenterX_->Get();
403         if ((LessNotEqual(targetCenter_.GetX(), current) && GreatNotEqual(center.GetX(), current)) ||
404             (LessNotEqual(center.GetX(), current) && GreatNotEqual(targetCenter_.GetX(), current))) {
405             stop = true;
406         }
407     } else {
408         auto current = blockCenterY_->Get();
409         if ((LessNotEqual(targetCenter_.GetY(), current) && GreatNotEqual(center.GetY(), current)) ||
410             (LessNotEqual(center.GetY(), current) && GreatNotEqual(targetCenter_.GetY(), current))) {
411             stop = true;
412         }
413     }
414     if (stop) {
415         AnimationOption option = AnimationOption();
416         AnimationUtils::Animate(option, [this]() {
417             if (static_cast<Axis>(directionAxis_->Get()) == Axis::HORIZONTAL) {
418                 blockCenterX_->Set(blockCenterX_->Get());
419             } else {
420                 blockCenterY_->Set(blockCenterY_->Get());
421             }
422         });
423     }
424 }
425 
SetCircleCenter(const PointF & center)426 void SliderContentModifier::SetCircleCenter(const PointF& center)
427 {
428     if (center == targetCenter_) {
429         return;
430     }
431 
432     CHECK_NULL_VOID(blockCenterX_);
433     CHECK_NULL_VOID(blockCenterY_);
434     if (needAnimate_ && isVisible_) {
435         StopCircleCenterAnimation(center);
436         AnimationOption option = AnimationOption();
437         auto motion =
438             AceType::MakeRefPtr<ResponsiveSpringMotion>(SPRING_MOTION_RESPONSE, SPRING_MOTION_DAMPING_FRACTION);
439         option.SetCurve(motion);
440         AnimationUtils::Animate(option, [this, center]() {
441             if (static_cast<Axis>(directionAxis_->Get()) == Axis::HORIZONTAL) {
442                 blockCenterX_->Set(center.GetX());
443             } else {
444                 blockCenterY_->Set(center.GetY());
445             }
446         });
447         if (static_cast<Axis>(directionAxis_->Get()) == Axis::HORIZONTAL) {
448             blockCenterY_->Set(center.GetY());
449         } else {
450             blockCenterX_->Set(center.GetX());
451         }
452     } else {
453         blockCenterX_->Set(center.GetX());
454         blockCenterY_->Set(center.GetY());
455     }
456     targetCenter_ = center;
457 }
458 
GetTrackRect()459 RSRect SliderContentModifier::GetTrackRect()
460 {
461     auto backStart = backStart_->Get();
462     auto backEnd = backEnd_->Get();
463     auto trackThickness = trackThickness_->Get();
464 
465     RSRect rect;
466     rect.SetLeft(backStart.GetX() - trackThickness * HALF);
467     rect.SetRight(backEnd.GetX() + trackThickness * HALF);
468     rect.SetTop(backStart.GetY() - trackThickness * HALF);
469     rect.SetBottom(backEnd.GetY() + trackThickness * HALF);
470 
471     return rect;
472 }
473 
DrawBlock(DrawingContext & context)474 void SliderContentModifier::DrawBlock(DrawingContext& context)
475 {
476     auto blockType = static_cast<SliderModelNG::BlockStyleType>(blockType_->Get());
477     if (blockType == SliderModelNG::BlockStyleType::DEFAULT) {
478         DrawDefaultBlock(context);
479     } else if (blockType == SliderModelNG::BlockStyleType::SHAPE) {
480         DrawBlockShape(context);
481     } else if (blockType == SliderModelNG::BlockStyleType::IMAGE) {
482         if (updateImageFunc_ != nullptr) {
483             updateImageFunc_();
484         }
485     }
486 }
487 
DrawBlockShape(DrawingContext & context)488 void SliderContentModifier::DrawBlockShape(DrawingContext& context)
489 {
490     if (shape_ == nullptr) {
491         return;
492     }
493 
494     switch (shape_->GetBasicShapeType()) {
495         case BasicShapeType::CIRCLE: {
496             auto circle = DynamicCast<Circle>(shape_);
497             CHECK_NULL_VOID(circle);
498             DrawBlockShapeCircle(context, circle);
499             break;
500         }
501         case BasicShapeType::ELLIPSE: {
502             auto ellipse = DynamicCast<Ellipse>(shape_);
503             CHECK_NULL_VOID(ellipse);
504             DrawBlockShapeEllipse(context, ellipse);
505             break;
506         }
507         case BasicShapeType::PATH: {
508             auto path = DynamicCast<Path>(shape_);
509             CHECK_NULL_VOID(path);
510             DrawBlockShapePath(context, path);
511             break;
512         }
513         case BasicShapeType::RECT: {
514             auto rect = DynamicCast<ShapeRect>(shape_);
515             CHECK_NULL_VOID(rect);
516             DrawBlockShapeRect(context, rect);
517             break;
518         }
519         default:
520             LOGW("Invalid shape type [%{public}d]", static_cast<int>(shape_->GetBasicShapeType()));
521             break;
522     }
523 }
524 
DrawBlockShapeCircle(DrawingContext & context,RefPtr<Circle> & circle)525 void SliderContentModifier::DrawBlockShapeCircle(DrawingContext& context, RefPtr<Circle>& circle)
526 {
527     auto blockSize = blockSize_->Get();
528     auto shapeWidth = shapeWidth_->Get();
529     auto shapeHeight = shapeHeight_->Get();
530     auto blockBorderWidth = blockBorderWidth_->Get();
531     if (NearZero(shapeWidth) || NearZero(shapeHeight)) {
532         return;
533     }
534 
535     auto blockCenter = GetBlockCenter();
536     float scale = std::max(blockSize.Width() / shapeWidth, blockSize.Height() / shapeHeight);
537     if (NearZero(scale)) {
538         return;
539     }
540     float blockBorderWidthUnscale = blockBorderWidth / scale;
541 
542     auto& canvas = context.canvas;
543     canvas.Save();
544     SetBlockClip(context);
545     canvas.Translate(blockCenter.GetX(), blockCenter.GetY());
546     canvas.Scale(scale, scale);
547     canvas.Translate(-blockCenter.GetX(), -blockCenter.GetY());
548 
549     RSPen pen;
550     pen.SetAntiAlias(true);
551     pen.SetWidth(blockBorderWidthUnscale);
552     pen.SetColor(ToRSColor(blockBorderColor_->Get()));
553     canvas.AttachPen(pen);
554     RSBrush brush;
555     brush.SetAntiAlias(true);
556     brush.SetColor(ToRSColor(blockColor_->Get()));
557     canvas.AttachBrush(brush);
558 
559     float radius = std::min(shapeWidth, shapeHeight) * HALF;
560     float drawRadius = radius - blockBorderWidthUnscale * HALF;
561     PointF drawCenter(
562         blockCenter.GetX() - shapeWidth * HALF + radius, blockCenter.GetY() - shapeHeight * HALF + radius);
563     canvas.DrawCircle(ToRSPoint(drawCenter), drawRadius);
564 
565     canvas.DetachBrush();
566     canvas.DetachPen();
567     canvas.Restore();
568 }
569 
DrawBlockShapeEllipse(DrawingContext & context,RefPtr<Ellipse> & ellipse)570 void SliderContentModifier::DrawBlockShapeEllipse(DrawingContext& context, RefPtr<Ellipse>& ellipse)
571 {
572     auto blockSize = blockSize_->Get();
573     auto shapeWidth = shapeWidth_->Get();
574     auto shapeHeight = shapeHeight_->Get();
575     auto blockBorderWidth = blockBorderWidth_->Get();
576     if (NearZero(shapeWidth) || NearZero(shapeHeight)) {
577         return;
578     }
579 
580     auto blockCenter = GetBlockCenter();
581     float scale = std::max(blockSize.Width() / shapeWidth, blockSize.Height() / shapeHeight);
582     if (NearZero(scale)) {
583         return;
584     }
585     float blockBorderWidthUnscale = blockBorderWidth / scale;
586 
587     auto& canvas = context.canvas;
588     canvas.Save();
589     SetBlockClip(context);
590     canvas.Translate(blockCenter.GetX(), blockCenter.GetY());
591     canvas.Scale(scale, scale);
592     canvas.Translate(-blockCenter.GetX(), -blockCenter.GetY());
593 
594     RSPen pen;
595     pen.SetAntiAlias(true);
596     pen.SetWidth(blockBorderWidth);
597     pen.SetColor(ToRSColor(blockBorderColor_->Get()));
598     canvas.AttachPen(pen);
599     RSBrush brush;
600     brush.SetAntiAlias(true);
601     brush.SetColor(ToRSColor(blockColor_->Get()));
602     canvas.AttachBrush(brush);
603 
604     RectF drawRect(blockCenter.GetX() - shapeWidth * HALF + blockBorderWidthUnscale * HALF,
605         blockCenter.GetY() - shapeHeight * HALF + blockBorderWidthUnscale * HALF, shapeWidth - blockBorderWidthUnscale,
606         shapeHeight - blockBorderWidthUnscale);
607     canvas.DrawOval(ToRSRect(drawRect));
608 
609     canvas.DetachBrush();
610     canvas.DetachPen();
611     canvas.Restore();
612 }
613 
DrawBlockShapePath(DrawingContext & context,RefPtr<Path> & path)614 void SliderContentModifier::DrawBlockShapePath(DrawingContext& context, RefPtr<Path>& path)
615 {
616     auto blockSize = blockSize_->Get();
617     auto blockBorderWidth = blockBorderWidth_->Get();
618 
619     auto blockCenter = GetBlockCenter();
620     SizeF shapeSize = PathPainter::GetPathSize(path->GetValue());
621     if (NearZero(shapeSize.Width()) || NearZero(shapeSize.Height())) {
622         return;
623     }
624     float scale = std::max(blockSize.Width() / (shapeSize.Width() + blockBorderWidth),
625         blockSize.Height() / (shapeSize.Height() + blockBorderWidth));
626     if (NearZero(scale)) {
627         return;
628     }
629 
630     auto& canvas = context.canvas;
631     canvas.Save();
632     SetBlockClip(context);
633     canvas.Translate(blockCenter.GetX(), blockCenter.GetY());
634     canvas.Scale(scale, scale);
635     canvas.Translate(-blockCenter.GetX(), -blockCenter.GetY());
636 
637     RSPen pen;
638     pen.SetAntiAlias(true);
639     pen.SetWidth(blockBorderWidth);
640     pen.SetColor(ToRSColor(blockBorderColor_->Get()));
641     canvas.AttachPen(pen);
642     RSBrush brush;
643     brush.SetAntiAlias(true);
644     brush.SetColor(ToRSColor(blockColor_->Get()));
645     canvas.AttachBrush(brush);
646 
647     OffsetF offset(blockCenter.GetX() - shapeSize.Width() * HALF, blockCenter.GetY() - shapeSize.Height() * HALF);
648     PathPainter::DrawPath(canvas, path->GetValue(), offset);
649     canvas.DetachBrush();
650     canvas.DetachPen();
651     canvas.Restore();
652 }
653 
SetShapeRectRadius(RSRoundRect & roundRect,float borderWidth)654 void SliderContentModifier::SetShapeRectRadius(RSRoundRect& roundRect, float borderWidth)
655 {
656     float radiusX = rectTopLeftRadiusX_->Get() - borderWidth * HALF;
657     float radiusY = rectTopLeftRadiusY_->Get() - borderWidth * HALF;
658     roundRect.SetCornerRadius(RSRoundRect::TOP_LEFT_POS, radiusX, radiusY);
659 
660     radiusX = rectTopRightRadiusX_->Get() - borderWidth * HALF;
661     radiusY = rectTopRightRadiusY_->Get() - borderWidth * HALF;
662     roundRect.SetCornerRadius(RSRoundRect::TOP_RIGHT_POS, radiusX, radiusY);
663 
664     radiusX = rectBottomLeftRadiusX_->Get() - borderWidth * HALF;
665     radiusY = rectBottomLeftRadiusY_->Get() - borderWidth * HALF;
666     roundRect.SetCornerRadius(RSRoundRect::BOTTOM_LEFT_POS, radiusX, radiusY);
667 
668     radiusX = rectBottomRightRadiusX_->Get() - borderWidth * HALF;
669     radiusY = rectBottomRightRadiusY_->Get() - borderWidth * HALF;
670     roundRect.SetCornerRadius(RSRoundRect::BOTTOM_RIGHT_POS, radiusX, radiusY);
671 }
672 
DrawBlockShapeRect(DrawingContext & context,RefPtr<ShapeRect> & rect)673 void SliderContentModifier::DrawBlockShapeRect(DrawingContext& context, RefPtr<ShapeRect>& rect)
674 {
675     auto shapeWidth = shapeWidth_->Get();
676     auto shapeHeight = shapeHeight_->Get();
677     if (NearZero(shapeWidth) || NearZero(shapeHeight)) {
678         return;
679     }
680     auto blockSize = blockSize_->Get();
681     float scale = std::max(blockSize.Width() / shapeWidth, blockSize.Height() / shapeHeight);
682     if (NearZero(scale)) {
683         return;
684     }
685     auto blockBorderWidth = blockBorderWidth_->Get();
686     float blockBorderWidthUnscale = blockBorderWidth / scale;
687     auto blockCenter = GetBlockCenter();
688 
689     auto& canvas = context.canvas;
690     canvas.Save();
691     SetBlockClip(context);
692     canvas.Translate(blockCenter.GetX(), blockCenter.GetY());
693     canvas.Scale(scale, scale);
694     canvas.Translate(-blockCenter.GetX(), -blockCenter.GetY());
695 
696     RSPen pen;
697     pen.SetAntiAlias(true);
698     pen.SetWidth(blockBorderWidth_->Get());
699     pen.SetColor(ToRSColor(blockBorderColor_->Get()));
700     canvas.AttachPen(pen);
701     RSBrush brush;
702     brush.SetAntiAlias(true);
703     brush.SetColor(ToRSColor(blockColor_->Get()));
704     canvas.AttachBrush(brush);
705 
706     RSRoundRect roundRect;
707     RSRect rsRect;
708     rsRect.SetLeft(blockCenter.GetX() - shapeWidth * HALF + blockBorderWidthUnscale * HALF);
709     rsRect.SetRight(blockCenter.GetX() + shapeWidth * HALF - blockBorderWidthUnscale);
710     rsRect.SetTop(blockCenter.GetY() - shapeHeight * HALF + blockBorderWidthUnscale * HALF);
711     rsRect.SetBottom(blockCenter.GetY() + shapeHeight * HALF - blockBorderWidthUnscale);
712     roundRect.SetRect(rsRect);
713     SetShapeRectRadius(roundRect, blockBorderWidthUnscale);
714 
715     canvas.DrawRoundRect(roundRect);
716     canvas.DetachBrush();
717     canvas.DetachPen();
718     canvas.Restore();
719 }
720 
SetBlockShape(const RefPtr<BasicShape> & shape)721 void SliderContentModifier::SetBlockShape(const RefPtr<BasicShape>& shape)
722 {
723     shape_ = shape;
724     CHECK_NULL_VOID(shape_);
725     shapeWidth_->Set(shape_->GetWidth().ConvertToPx());
726     shapeHeight_->Set(shape_->GetHeight().ConvertToPx());
727     if (shape->GetBasicShapeType() == BasicShapeType::CIRCLE) {
728         auto circle = DynamicCast<Circle>(shape_);
729         CHECK_NULL_VOID(circle);
730         if (circle->GetRadius().IsValid()) {
731             circleRadius_->Set(circle->GetRadius().ConvertToPx());
732         } else {
733             circleRadius_->Set(std::min(shape_->GetWidth().ConvertToPx(), shape_->GetHeight().ConvertToPx()) * HALF);
734         }
735     } else if (shape->GetBasicShapeType() == BasicShapeType::ELLIPSE) {
736         auto ellipse = DynamicCast<Ellipse>(shape_);
737         CHECK_NULL_VOID(ellipse);
738         if (ellipse->GetRadiusX().IsValid() && ellipse->GetRadiusY().IsValid()) {
739             ellipseRadiusX_->Set(ellipse->GetRadiusX().ConvertToPx());
740             ellipseRadiusY_->Set(ellipse->GetRadiusY().ConvertToPx());
741         } else {
742             ellipseRadiusX_->Set(shape_->GetWidth().ConvertToPx() * HALF);
743             ellipseRadiusY_->Set(shape_->GetHeight().ConvertToPx() * HALF);
744         }
745     } else if (shape->GetBasicShapeType() == BasicShapeType::RECT) {
746         auto rect = DynamicCast<ShapeRect>(shape_);
747         CHECK_NULL_VOID(rect);
748         rectTopLeftRadiusX_->Set(rect->GetTopLeftRadius().GetX().ConvertToPx());
749         rectTopLeftRadiusY_->Set(rect->GetTopLeftRadius().GetY().ConvertToPx());
750         rectTopRightRadiusX_->Set(rect->GetTopRightRadius().GetX().ConvertToPx());
751         rectTopRightRadiusY_->Set(rect->GetTopRightRadius().GetY().ConvertToPx());
752         rectBottomLeftRadiusX_->Set(rect->GetBottomLeftRadius().GetX().ConvertToPx());
753         rectBottomLeftRadiusY_->Set(rect->GetBottomLeftRadius().GetY().ConvertToPx());
754         rectBottomRightRadiusX_->Set(rect->GetBottomRightRadius().GetX().ConvertToPx());
755         rectBottomRightRadiusY_->Set(rect->GetBottomRightRadius().GetY().ConvertToPx());
756     }
757 }
758 
UpdateContentDirtyRect(const SizeF & frameSize)759 void SliderContentModifier::UpdateContentDirtyRect(const SizeF& frameSize)
760 {
761     auto pipeline = PipelineBase::GetCurrentContext();
762     CHECK_NULL_VOID(pipeline);
763     auto theme = pipeline->GetTheme<SliderTheme>();
764     CHECK_NULL_VOID(theme);
765     auto hotShadowWidth = sliderMode_->Get() == static_cast<int32_t>(SliderModel::SliderMode::OUTSET)
766                               ? theme->GetOutsetHotBlockShadowWidth().ConvertToPx()
767                               : theme->GetInsetHotBlockShadowWidth().ConvertToPx();
768     auto circleSize =
769         SizeF(blockSize_->Get().Width() + hotShadowWidth / HALF, blockSize_->Get().Height() + hotShadowWidth / HALF);
770     RectF rect;
771     if (directionAxis_->Get() == static_cast<int32_t>(Axis::HORIZONTAL)) {
772         auto maxWidth = std::max(circleSize.Height(), frameSize.Height()) * HALF;
773         rect.SetOffset(OffsetF(-circleSize.Width(), blockCenterY_->Get() - maxWidth));
774         rect.SetSize(SizeF(circleSize.Width() / HALF + frameSize.Width(), maxWidth / HALF));
775     } else {
776         auto maxWidth = std::max(circleSize.Width(), frameSize.Width()) * HALF;
777         rect.SetOffset(OffsetF(blockCenterX_->Get() - maxWidth, -circleSize.Height()));
778         rect.SetSize(SizeF(maxWidth / HALF, circleSize.Height() / HALF + frameSize.Height()));
779     }
780 
781     SetBoundsRect(rect);
782 }
783 
SetBlockClip(DrawingContext & context)784 void SliderContentModifier::SetBlockClip(DrawingContext& context)
785 {
786     auto& canvas = context.canvas;
787     auto blockCenter = GetBlockCenter();
788     auto blockSize = blockSize_->Get();
789     RectF rect(blockCenter.GetX() - blockSize.Width() * HALF, blockCenter.GetY() - blockSize.Height() * HALF,
790         blockSize.Width(), blockSize.Height());
791     canvas.ClipRect(ToRSRect(rect), RSClipOp::INTERSECT);
792 }
793 } // namespace OHOS::Ace::NG
794