• 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 "core/components_ng/pattern/slider/slider_pattern.h"
19 #include "core/components_ng/render/drawing_prop_convertor.h"
20 #include "core/components_ng/render/path_painter.h"
21 
22 namespace OHOS::Ace::NG {
23 namespace {
24 constexpr float HALF = 0.5f;
25 constexpr float SPRING_MOTION_RESPONSE = 0.314f;
26 constexpr float SPRING_MOTION_DAMPING_FRACTION = 0.95f;
27 constexpr double DEFAULT_SCALE_VALUE = 1.0;
28 constexpr int32_t STEPS_MIN_NUMBER = 2;
29 } // namespace
SliderContentModifier(const Parameters & parameters,std::function<void (float)> updateImageCenterX,std::function<void (float)> updateImageCenterY)30 SliderContentModifier::SliderContentModifier(const Parameters& parameters,
31     std::function<void(float)> updateImageCenterX, std::function<void(float)> updateImageCenterY)
32     : updateImageCenterX_(std::move(updateImageCenterX)), updateImageCenterY_(std::move(updateImageCenterY)),
33       boardColor_(AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(Color::TRANSPARENT)))
34 {
35     // animatable property
36     selectStart_ = AceType::MakeRefPtr<AnimatablePropertyOffsetF>(parameters.selectStart - PointF());
37     selectEnd_ = AceType::MakeRefPtr<AnimatablePropertyOffsetF>(parameters.selectEnd - PointF());
38     backStart_ = AceType::MakeRefPtr<AnimatablePropertyOffsetF>(parameters.backStart - PointF());
39     backEnd_ = AceType::MakeRefPtr<AnimatablePropertyOffsetF>(parameters.backEnd - PointF());
40     blockCenterX_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(parameters.circleCenter.GetX());
41     blockCenterY_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(parameters.circleCenter.GetY());
42     trackThickness_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(parameters.trackThickness);
43     trackBackgroundColor_ =
44         AceType::MakeRefPtr<AnimatablePropertyVectorColor>(GradientArithmetic(parameters.trackBackgroundColor));
45     selectGradientColor_ =
46         AceType::MakeRefPtr<AnimatablePropertyVectorColor>(GradientArithmetic(parameters.selectGradientColor));
47     blockColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(parameters.blockColor));
48     trackBorderRadius_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(parameters.trackThickness * HALF);
49     selectedBorderRadius_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(trackBorderRadius_->Get());
50     stepSize_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(1);
51     blockBorderWidth_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(0);
52     stepColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor::TRANSPARENT);
53     blockBorderColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(parameters.blockColor));
54     blockSize_ = AceType::MakeRefPtr<AnimatablePropertySizeF>(parameters.blockSize);
55     // non-animatable property
56     stepRatio_ = AceType::MakeRefPtr<PropertyFloat>(parameters.stepRatio);
57     sliderMode_ = AceType::MakeRefPtr<PropertyInt>(static_cast<int>(SliderModelNG::SliderMode::OUTSET));
58     directionAxis_ = AceType::MakeRefPtr<PropertyInt>(static_cast<int>(Axis::HORIZONTAL));
59     isShowStep_ = AceType::MakeRefPtr<PropertyBool>(false);
60     sliderInteractionMode_ =
61         AceType::MakeRefPtr<PropertyInt>(static_cast<int>(SliderModelNG::SliderInteraction::SLIDE_AND_CLICK));
62     minResponse_ = AceType::MakeRefPtr<PropertyFloat>(0.0f);
63     blockType_ = AceType::MakeRefPtr<PropertyInt>(static_cast<int>(SliderModelNG::BlockStyleType::DEFAULT));
64     useContentModifier_ = AceType::MakeRefPtr<PropertyBool>(false);
65     isHovered_ = AceType::MakeRefPtr<PropertyBool>(false);
66     isPressed_ = AceType::MakeRefPtr<PropertyBool>(false);
67     isFocused_ = AceType::MakeRefPtr<PropertyBool>(false);
68     // others
69     UpdateData(parameters);
70     UpdateThemeColor();
71 
72     AttachProperty(selectStart_);
73     AttachProperty(selectEnd_);
74     AttachProperty(backStart_);
75     AttachProperty(backEnd_);
76     AttachProperty(blockCenterX_);
77     AttachProperty(blockCenterY_);
78     AttachProperty(trackThickness_);
79     AttachProperty(trackBackgroundColor_);
80     AttachProperty(selectGradientColor_);
81     AttachProperty(blockColor_);
82     AttachProperty(boardColor_);
83     AttachProperty(trackBorderRadius_);
84     AttachProperty(selectedBorderRadius_);
85     AttachProperty(stepSize_);
86     AttachProperty(blockBorderWidth_);
87     AttachProperty(stepColor_);
88     AttachProperty(blockBorderColor_);
89     AttachProperty(blockSize_);
90     AttachProperty(stepRatio_);
91     AttachProperty(sliderMode_);
92     AttachProperty(directionAxis_);
93     AttachProperty(isShowStep_);
94     AttachProperty(sliderInteractionMode_);
95     AttachProperty(minResponse_);
96     AttachProperty(blockType_);
97     AttachProperty(isHovered_);
98     AttachProperty(isPressed_);
99     AttachProperty(isFocused_);
100 
101     InitializeShapeProperty();
102 }
103 
InitializeShapeProperty()104 void SliderContentModifier::InitializeShapeProperty()
105 {
106     shapeWidth_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
107     shapeHeight_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
108     circleRadius_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
109     ellipseRadiusX_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
110     ellipseRadiusY_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
111     rectTopLeftRadiusX_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
112     rectTopLeftRadiusY_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
113     rectTopRightRadiusX_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
114     rectTopRightRadiusY_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
115     rectBottomLeftRadiusX_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
116     rectBottomLeftRadiusY_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
117     rectBottomRightRadiusX_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
118     rectBottomRightRadiusY_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(.0f);
119     AttachProperty(shapeWidth_);
120     AttachProperty(shapeHeight_);
121     AttachProperty(circleRadius_);
122     AttachProperty(ellipseRadiusX_);
123     AttachProperty(ellipseRadiusY_);
124     AttachProperty(rectTopLeftRadiusX_);
125     AttachProperty(rectTopLeftRadiusY_);
126     AttachProperty(rectTopRightRadiusX_);
127     AttachProperty(rectTopRightRadiusY_);
128     AttachProperty(rectBottomLeftRadiusX_);
129     AttachProperty(rectBottomLeftRadiusY_);
130     AttachProperty(rectBottomRightRadiusX_);
131     AttachProperty(rectBottomRightRadiusY_);
132 }
133 
onDraw(DrawingContext & context)134 void SliderContentModifier::onDraw(DrawingContext& context)
135 {
136     if (useContentModifier_->Get()) {
137         return;
138     }
139     DrawBackground(context);
140     DrawStep(context);
141     DrawSelect(context);
142     DrawShadow(context);
143     DrawBlock(context);
144     DrawHoverOrPress(context);
145     UpdateSliderEndsPosition();
146 }
147 
UpdateSliderEndsPosition()148 void SliderContentModifier::UpdateSliderEndsPosition()
149 {
150     if (StepPointCallback_) {
151         StepPointCallback_();
152     }
153 }
154 
SetStartEndPointLocation(Axis & direction,RSRect & trackRect,RSPoint & startPoint,RSPoint & endPoint)155 void SetStartEndPointLocation(Axis& direction, RSRect& trackRect, RSPoint& startPoint, RSPoint& endPoint)
156 {
157     if (direction == Axis::HORIZONTAL) {
158         startPoint.SetX(trackRect.GetLeft());
159         startPoint.SetY(trackRect.GetTop());
160         endPoint.SetX(trackRect.GetRight());
161         endPoint.SetY(trackRect.GetTop());
162     } else {
163         startPoint.SetX(trackRect.GetLeft());
164         startPoint.SetY(trackRect.GetTop());
165         endPoint.SetX(trackRect.GetLeft());
166         endPoint.SetY(trackRect.GetBottom());
167     }
168 }
169 
DrawBackground(DrawingContext & context)170 void SliderContentModifier::DrawBackground(DrawingContext& context)
171 {
172     auto& canvas = context.canvas;
173     auto trackBorderRadius = trackBorderRadius_->Get();
174     auto pipeline = PipelineBase::GetCurrentContextSafelyWithCheck();
175     CHECK_NULL_VOID(pipeline);
176     auto theme = pipeline->GetTheme<SliderTheme>();
177     CHECK_NULL_VOID(theme);
178     scaleValue_ = theme->GetFocusedScaleValue();
179     std::vector<GradientColor> gradientColors = GetTrackBackgroundColor();
180     std::vector<RSColorQuad> colors;
181     std::vector<float> pos;
182     for (size_t i = 0; i < gradientColors.size(); i++) {
183         colors.emplace_back(gradientColors[i].GetLinearColor().GetValue());
184         pos.emplace_back(gradientColors[i].GetDimension().Value());
185     }
186     if (sliderMode_->Get() != static_cast<int32_t>(SliderModel::SliderMode::INSET)) {
187         isEnlarge_ = isPressed_->Get() || isHovered_->Get() || isFocused_->Get();
188     }
189     RSRect trackRect = GetTrackRect();
190     auto direction = static_cast<Axis>(directionAxis_->Get());
191     RSPoint startPoint;
192     RSPoint endPoint;
193     SetStartEndPointLocation(direction, trackRect, startPoint, endPoint);
194     RSBrush brush;
195     brush.SetAntiAlias(true);
196     if (reverse_) {
197 #ifndef USE_ROSEN_DRAWING
198         brush.SetShaderEffect(
199             RSShaderEffect::CreateLinearGradient(endPoint, startPoint, colors, pos, RSTileMode::CLAMP));
200 #else
201         brush.SetShaderEffect(
202             RSRecordingShaderEffect::CreateLinearGradient(endPoint, startPoint, colors, pos, RSTileMode::CLAMP));
203 #endif
204     } else {
205 #ifndef USE_ROSEN_DRAWING
206         brush.SetShaderEffect(
207             RSShaderEffect::CreateLinearGradient(startPoint, endPoint, colors, pos, RSTileMode::CLAMP));
208 #else
209         brush.SetShaderEffect(
210             RSRecordingShaderEffect::CreateLinearGradient(startPoint, endPoint, colors, pos, RSTileMode::CLAMP));
211 #endif
212     }
213     canvas.AttachBrush(brush);
214     auto trackRadius = isEnlarge_ ? trackBorderRadius * scaleValue_ : trackBorderRadius;
215     RSRoundRect roundRect(trackRect, trackRadius, trackRadius);
216     canvas.DrawRoundRect(roundRect);
217     canvas.DetachBrush();
218     canvas.Save();
219     canvas.ClipRoundRect(roundRect, RSClipOp::INTERSECT, true);
220 }
221 
AddStepPoint(float startX,float startY,float endX,float endY,RSCanvas & canvas)222 void SliderContentModifier::AddStepPoint(float startX, float startY, float endX, float endY, RSCanvas& canvas)
223 {
224     auto stepRatio = stepRatio_->Get();
225     if (NearEqual(stepRatio, .0f)) {
226         return;
227     }
228 
229     auto stepsLengthX = (endX - startX) * stepRatio;
230     auto stepsLengthY = (endY - startY) * stepRatio;
231     int numberOfSteps = std::max(static_cast<int>(std::round((endX - startX) / stepsLengthX) + 1),
232         static_cast<int>(std::round((endY - startY) / stepsLengthY) + 1));
233     if (numberOfSteps <= STEPS_MIN_NUMBER && hasPrefix_ && hasSuffix_) {
234         // If there are less than or equal to 2 steps, skip drawing
235         canvas.DetachBrush();
236         return;
237      }
238 
239     if (reverse_) {
240         int32_t stepIndex = 0;
241         while (GreatOrEqual(endX, startX) && GreatOrEqual(endY, startY)) {
242         DrawStepPoint(endX, endY, stepIndex, canvas, numberOfSteps);
243             if (NearEqual(endX, startX) && NearEqual(endY, startY)) {
244                     return;
245             }
246             endX -= stepsLengthX;
247             endY -= stepsLengthY;
248             stepIndex++;
249         }
250         endX += stepsLengthX;
251         endY += stepsLengthY;
252         if (!NearEqual(endX, startX) || !NearEqual(endY, startY)) {
253             stepPointVec_.emplace_back(PointF(startX, startY));
254         }
255     } else {
256         int32_t stepIndex = 0;
257         while (LessOrEqual(startX, endX) && LessOrEqual(startY, endY)) {
258         DrawStepPoint(startX, startY, stepIndex, canvas, numberOfSteps);
259             if (NearEqual(startX, endX) && NearEqual(startY, endY)) {
260                 return;
261             }
262             startX += stepsLengthX;
263             startY += stepsLengthY;
264             stepIndex++;
265         }
266         startX -= stepsLengthX;
267         startY -= stepsLengthY;
268         if (!NearEqual(startX, endX) || !NearEqual(startY, endY)) {
269             stepPointVec_.emplace_back(PointF(endX, endY));
270         }
271     }
272 }
273 
DrawStepPoint(float x,float y,int32_t index,RSCanvas & canvas,int32_t numberOfSteps)274 void SliderContentModifier::DrawStepPoint(float x, float y, int32_t index, RSCanvas& canvas, int32_t numberOfSteps)
275 {
276     int32_t noneModeNum = 2;
277     int32_t insetModeNum = 1;
278     auto stepSize = stepSize_->Get();
279     auto trackThickness = trackThickness_->Get();
280     if (GreatNotEqual(stepSize, trackThickness)) {
281         stepSize = trackThickness;
282     }
283     int noneModeSteps = numberOfSteps - noneModeNum;
284     int insetModeSteps = numberOfSteps - insetModeNum;
285     auto model = static_cast<SliderModel::SliderMode>(sliderMode_->Get());
286     if (model == SliderModel::SliderMode::NONE) {
287         if (index == 1 && hasPrefix_) {
288             stepPointVec_.emplace_back(PointF(x, y));
289             return;
290         }
291         if (index == noneModeSteps && hasSuffix_) {
292             stepPointVec_.emplace_back(PointF(x, y));
293             return;
294         }
295     }
296     if (model == SliderModel::SliderMode::INSET) {
297         if (index == 0 && hasPrefix_) {
298             stepPointVec_.emplace_back(PointF(x, y));
299             return;
300         }
301         if (index == insetModeSteps && hasSuffix_) {
302             stepPointVec_.emplace_back(PointF(x, y));
303             return;
304         }
305     }
306     canvas.DrawCircle(RSPoint(x, y), isEnlarge_ ? stepSize * HALF * scaleValue_ : stepSize * HALF);
307     stepPointVec_.emplace_back(PointF(x, y));
308 }
309 
DrawStep(DrawingContext & context)310 void SliderContentModifier::DrawStep(DrawingContext& context)
311 {
312     if (!isShowStep_->Get()) {
313         return;
314     }
315     auto& canvas = context.canvas;
316     auto stepColor = stepColor_->Get();
317     auto backStart = backStart_->Get();
318     auto backEnd = backEnd_->Get();
319     auto stepRatio = stepRatio_->Get();
320     if (NearEqual(stepRatio, .0f)) {
321         return;
322     }
323     float startX = backStart.GetX();
324     float endX = backEnd.GetX();
325     float startY = backStart.GetY();
326     float endY = backEnd.GetY();
327     if (NearEqual(startX, endX) && NearEqual(startY, endY)) {
328         return;
329     }
330 
331     RSBrush brush;
332     brush.SetAntiAlias(true);
333     brush.SetColor(ToRSColor(stepColor));
334     canvas.AttachBrush(brush);
335     stepPointVec_.clear();
336     AddStepPoint(startX, startY, endX, endY, canvas);
337     canvas.DetachBrush();
338     if (updateAccessibilityVirtualNode_) {
339         updateAccessibilityVirtualNode_();
340     }
341 }
342 
DrawSelect(DrawingContext & context)343 void SliderContentModifier::DrawSelect(DrawingContext& context)
344 {
345     auto& canvas = context.canvas;
346     if (!NearEqual(selectStart_->Get().GetX(), selectEnd_->Get().GetX(), HALF) ||
347         !NearEqual(selectStart_->Get().GetY(), selectEnd_->Get().GetY(), HALF)) {
348         auto selectedBorderRadius = selectedBorderRadius_->Get();
349         auto direction = static_cast<Axis>(directionAxis_->Get());
350         auto blockCenter = GetBlockCenter();
351         auto trackThickness = trackThickness_->Get();
352         auto sliderMode = static_cast<SliderModelNG::SliderMode>(sliderMode_->Get());
353         auto rect = GetTrackRect();
354         auto insetOffset = .0f;
355         if (sliderMode == SliderModelNG::SliderMode::INSET) {
356             insetOffset = std::max(selectedBorderRadius, trackThickness * HALF);
357         }
358         if (!reverse_) {
359             if (direction == Axis::HORIZONTAL) {
360                 rect.SetRight(blockCenter.GetX() + insetOffset);
361             } else {
362                 rect.SetBottom(blockCenter.GetY() + insetOffset);
363             }
364         } else {
365             if (direction == Axis::HORIZONTAL) {
366                 rect.SetLeft(blockCenter.GetX() - insetOffset);
367             } else {
368                 rect.SetTop(blockCenter.GetY() - insetOffset);
369             }
370         }
371 
372         RSBrush brush;
373         DrawSelectColor(brush, rect);
374         canvas.AttachBrush(brush);
375         canvas.DrawRoundRect(RSRoundRect(rect, selectedBorderRadius, selectedBorderRadius));
376         canvas.DetachBrush();
377     }
378     canvas.Restore();
379 }
380 
DrawDefaultBlock(DrawingContext & context)381 void SliderContentModifier::DrawDefaultBlock(DrawingContext& context)
382 {
383     auto& canvas = context.canvas;
384     auto borderWidth = blockBorderWidth_->Get();
385     auto blockSize = blockSize_->Get();
386     auto blockCenter = GetBlockCenter();
387     float blockRadius = std::min(blockSize.Width(), blockSize.Height()) * HALF;
388     float radius = blockRadius;
389     RSBrush brush;
390     brush.SetAntiAlias(true);
391     if (GreatOrEqual(borderWidth * HALF, radius)) {
392         brush.SetColor(ToRSColor(blockBorderColor_->Get()));
393     } else {
394         radius = std::min(blockSize.Width(), blockSize.Height()) * HALF - borderWidth * HALF;
395         brush.SetColor(ToRSColor(blockColor_->Get()));
396     }
397     canvas.AttachBrush(brush);
398     RSPen pen;
399     if (!NearEqual(borderWidth, .0f) && LessNotEqual(borderWidth * HALF, blockRadius)) {
400         pen.SetAntiAlias(true);
401         pen.SetWidth(borderWidth);
402         pen.SetColor(ToRSColor(blockBorderColor_->Get()));
403         canvas.AttachPen(pen);
404     }
405     canvas.DrawCircle(
406         ToRSPoint(PointF(blockCenter.GetX(), blockCenter.GetY())), isEnlarge_ ? radius * scaleValue_ : radius);
407     canvas.DetachBrush();
408     if (!NearEqual(borderWidth, .0f) && LessNotEqual(borderWidth * HALF, blockRadius)) {
409         canvas.DetachPen();
410     }
411 }
412 
DrawHoverOrPress(DrawingContext & context)413 void SliderContentModifier::DrawHoverOrPress(DrawingContext& context)
414 {
415     auto sliderMode = static_cast<SliderModelNG::SliderMode>(sliderMode_->Get());
416     if (static_cast<SliderModelNG::BlockStyleType>(blockType_->Get()) != SliderModelNG::BlockStyleType::DEFAULT ||
417         sliderMode == SliderModelNG::SliderMode::NONE) {
418         return;
419     }
420 
421     auto& canvas = context.canvas;
422     RSPen circleStatePen;
423     circleStatePen.SetAntiAlias(true);
424     // add animate color
425     circleStatePen.SetColor(ToRSColor(boardColor_->Get()));
426     circleStatePen.SetWidth(isEnlarge_ ? hotCircleShadowWidth_ * scaleValue_ : hotCircleShadowWidth_);
427     canvas.AttachPen(circleStatePen);
428     auto blockSize = blockSize_->Get();
429     float diameter = std::min(blockSize.Width(), blockSize.Height());
430     auto penRadius = (diameter + hotCircleShadowWidth_) * HALF;
431     auto blockCenter = GetBlockCenter();
432     canvas.DrawCircle(ToRSPoint(blockCenter), isEnlarge_ ? penRadius * scaleValue_ : penRadius);
433     canvas.DetachPen();
434 }
435 
DrawShadow(DrawingContext & context)436 void SliderContentModifier::DrawShadow(DrawingContext& context)
437 {
438     auto sliderMode = static_cast<SliderModelNG::SliderMode>(sliderMode_->Get());
439     if (static_cast<SliderModelNG::BlockStyleType>(blockType_->Get()) != SliderModelNG::BlockStyleType::DEFAULT ||
440         sliderMode == SliderModelNG::SliderMode::NONE) {
441         return;
442     }
443 
444     if (!mouseHoverFlag_ && !mousePressedFlag_) {
445         auto& canvas = context.canvas;
446         auto blockSize = blockSize_->Get();
447         auto blockCenter = GetBlockCenter();
448         float radius = std::min(blockSize.Width(), blockSize.Height()) * HALF;
449         canvas.Save();
450         RSBrush shadowBrush;
451         shadowBrush.SetAntiAlias(true);
452         shadowBrush.SetColor(ToRSColor(blockShadowColor_));
453         RSFilter filter;
454         filter.SetMaskFilter(RSMaskFilter::CreateBlurMaskFilter(
455             RSBlurType::NORMAL, RSDrawing::ConvertRadiusToSigma(hotCircleShadowWidth_)));
456         shadowBrush.SetFilter(filter);
457 
458         canvas.AttachBrush(shadowBrush);
459         RSPath path;
460         path.AddCircle(ToRSPoint(blockCenter).GetX(), ToRSPoint(blockCenter).GetY(), radius);
461         canvas.DrawPath(path);
462         canvas.DetachBrush();
463         canvas.Restore();
464     }
465 }
466 
SetBoardColor(const RefPtr<FrameNode> & host)467 void SliderContentModifier::SetBoardColor(const RefPtr<FrameNode>& host)
468 {
469     CHECK_NULL_VOID(host);
470     CHECK_NULL_VOID(boardColor_);
471     auto pipeline = PipelineBase::GetCurrentContext();
472     CHECK_NULL_VOID(pipeline);
473     auto theme = pipeline->GetTheme<SliderTheme>();
474     CHECK_NULL_VOID(theme);
475     Color shadowColor = Color::TRANSPARENT;
476     shadowColor = mouseHoverFlag_ ? theme->GetBlockHoverColor() : shadowColor;
477     shadowColor = mousePressedFlag_ ? theme->GetBlockPressedColor() : shadowColor;
478     auto duration = mousePressedFlag_ ? static_cast<int32_t>(theme->GetPressAnimationDuration())
479                                       : static_cast<int32_t>(theme->GetHoverAnimationDuration());
480     auto curve = mousePressedFlag_ ? Curves::SHARP : Curves::FRICTION;
481     AnimationOption option = AnimationOption();
482     option.SetDuration(duration);
483     option.SetCurve(curve);
484     AnimationUtils::Animate(
485         option, [&]() { boardColor_->Set(LinearColor(shadowColor)); }, nullptr, nullptr, host->GetContextRefPtr());
486 }
487 
UpdateData(const Parameters & parameters)488 void SliderContentModifier::UpdateData(const Parameters& parameters)
489 {
490     mouseHoverFlag_ = parameters.mouseHoverFlag_;
491     mousePressedFlag_ = parameters.mousePressedFlag_;
492     hotCircleShadowWidth_ = parameters.hotCircleShadowWidth;
493     SetIsHovered(mouseHoverFlag_);
494 }
495 
JudgeNeedAnimate(bool reverse)496 void SliderContentModifier::JudgeNeedAnimate(bool reverse)
497 {
498     // when reverse is changed, slider block position changes do not animated.
499     if (reverse_ != reverse) {
500         SetAnimatorStatus(SliderStatus::DEFAULT);
501         reverse_ = reverse;
502     }
503 }
504 
StopSelectAnimation(const RefPtr<FrameNode> & host)505 void SliderContentModifier::StopSelectAnimation(const RefPtr<FrameNode>& host)
506 {
507     CHECK_NULL_VOID(host);
508     AnimationOption option = AnimationOption();
509     option.SetCurve(Curves::LINEAR);
510     AnimationUtils::Animate(option, [this]() {
511         selectEnd_->Set(selectEnd_->Get());
512         if (animatorStatus_ == SliderStatus::MOVE) {
513             selectEnd_->Set(targetSelectEnd_);
514         }
515     }, nullptr, nullptr, host->GetContextRefPtr());
516 }
517 
SetSelectSize(const PointF & start,const PointF & end,const RefPtr<FrameNode> & host)518 void SliderContentModifier::SetSelectSize(const PointF& start, const PointF& end, const RefPtr<FrameNode>& host)
519 {
520     CHECK_NULL_VOID(host);
521     if (selectStart_) {
522         selectStart_->Set(start - PointF());
523     }
524     CHECK_NULL_VOID(selectEnd_);
525     auto currentEnd = end - PointF();
526     if (targetSelectEnd_ == currentEnd) {
527         return;
528     }
529     if (animatorStatus_ != SliderStatus::DEFAULT && isVisible_) {
530         StopSelectAnimation(host);
531         AnimationOption option = AnimationOption();
532         auto motion =
533             AceType::MakeRefPtr<ResponsiveSpringMotion>(SPRING_MOTION_RESPONSE, SPRING_MOTION_DAMPING_FRACTION);
534         option.SetCurve(motion);
535         AnimationUtils::Animate(
536             option, [&]() { selectEnd_->Set(end - PointF()); }, nullptr, nullptr, host->GetContextRefPtr());
537     } else {
538         selectEnd_->Set(end - PointF());
539     }
540     targetSelectEnd_ = end - PointF();
541 }
542 
StopCircleCenterAnimation(const RefPtr<FrameNode> & host)543 void SliderContentModifier::StopCircleCenterAnimation(const RefPtr<FrameNode>& host)
544 {
545     CHECK_NULL_VOID(host);
546     AnimationOption option = AnimationOption();
547     option.SetCurve(Curves::LINEAR);
548     AnimationUtils::Animate(option, [this]() {
549         if (static_cast<Axis>(directionAxis_->Get()) == Axis::HORIZONTAL) {
550             blockCenterX_->Set(blockCenterX_->Get());
551         } else {
552             blockCenterY_->Set(blockCenterY_->Get());
553         }
554         if (animatorStatus_ == SliderStatus::MOVE) {
555             if (static_cast<Axis>(directionAxis_->Get()) == Axis::HORIZONTAL) {
556                 blockCenterX_->Set(targetCenter_.GetX());
557             } else {
558                 blockCenterY_->Set(targetCenter_.GetY());
559             }
560         }
561     }, nullptr, nullptr, host->GetContextRefPtr());
562 }
563 
SetCircleCenter(const PointF & center,const RefPtr<FrameNode> & host)564 void SliderContentModifier::SetCircleCenter(const PointF& center, const RefPtr<FrameNode>& host)
565 {
566     CHECK_NULL_VOID(host);
567     if (center == targetCenter_) {
568         return;
569     }
570 
571     CHECK_NULL_VOID(blockCenterX_);
572     CHECK_NULL_VOID(blockCenterY_);
573     if (animatorStatus_ != SliderStatus::DEFAULT && isVisible_) {
574         StopCircleCenterAnimation(host);
575         AnimationOption option = AnimationOption();
576         auto motion =
577             AceType::MakeRefPtr<ResponsiveSpringMotion>(SPRING_MOTION_RESPONSE, SPRING_MOTION_DAMPING_FRACTION);
578         option.SetCurve(motion);
579         AnimationUtils::Animate(option, [this, center]() {
580             if (static_cast<Axis>(directionAxis_->Get()) == Axis::HORIZONTAL) {
581                 blockCenterX_->Set(center.GetX());
582             } else {
583                 blockCenterY_->Set(center.GetY());
584             }
585         }, nullptr, nullptr, host->GetContextRefPtr());
586         if (static_cast<Axis>(directionAxis_->Get()) == Axis::HORIZONTAL) {
587             blockCenterY_->Set(center.GetY());
588         } else {
589             blockCenterX_->Set(center.GetX());
590         }
591     } else {
592         blockCenterX_->Set(center.GetX());
593         blockCenterY_->Set(center.GetY());
594     }
595     targetCenter_ = center;
596 }
597 
GetTrackRect()598 RSRect SliderContentModifier::GetTrackRect()
599 {
600     auto backStart = backStart_->Get();
601     auto backEnd = backEnd_->Get();
602     auto trackThickness = trackThickness_->Get();
603     auto direction = static_cast<Axis>(directionAxis_->Get());
604     auto stepSize = stepSize_->Get();
605     if (GreatNotEqual(stepSize, trackThickness)) {
606         stepSize = trackThickness;
607     }
608     RSRect rect;
609     auto calculatedThickness = isEnlarge_ ? trackThickness * HALF * scaleValue_ : trackThickness * HALF;
610     if (direction == Axis::HORIZONTAL) {
611         if (sliderMode_->Get() == static_cast<int32_t>(SliderModel::SliderMode::OUTSET)) {
612             rect.SetLeft(backStart.GetX() - stepSize * HALF);
613             rect.SetRight(backEnd.GetX() + stepSize * HALF);
614         } else if (sliderMode_->Get() == static_cast<int32_t>(SliderModel::SliderMode::INSET)) {
615             rect.SetLeft(backStart.GetX() - trackThickness * HALF);
616             rect.SetRight(backEnd.GetX() + trackThickness * HALF);
617         } else {
618             rect.SetLeft(backStart.GetX());
619             rect.SetRight(backEnd.GetX());
620         }
621         rect.SetTop(backStart.GetY() - calculatedThickness);
622         rect.SetBottom(backEnd.GetY() + calculatedThickness);
623     } else {
624         rect.SetLeft(backStart.GetX() - calculatedThickness);
625         rect.SetRight(backEnd.GetX() + calculatedThickness);
626         if (sliderMode_->Get() == static_cast<int32_t>(SliderModel::SliderMode::OUTSET)) {
627             rect.SetTop(backStart.GetY() - stepSize * HALF);
628             rect.SetBottom(backEnd.GetY() + stepSize * HALF);
629         } else if (sliderMode_->Get() == static_cast<int32_t>(SliderModel::SliderMode::INSET)) {
630             rect.SetTop(backStart.GetY() - trackThickness * HALF);
631             rect.SetBottom(backEnd.GetY() + trackThickness * HALF);
632         } else {
633             rect.SetTop(backStart.GetY());
634             rect.SetBottom(backEnd.GetY());
635         }
636     }
637     return rect;
638 }
639 
DrawBlock(DrawingContext & context)640 void SliderContentModifier::DrawBlock(DrawingContext& context)
641 {
642     auto sliderMode = static_cast<SliderModelNG::SliderMode>(sliderMode_->Get());
643     if (sliderMode != SliderModelNG::SliderMode::NONE) {
644         auto blockType = static_cast<SliderModelNG::BlockStyleType>(blockType_->Get());
645         if (blockType == SliderModelNG::BlockStyleType::DEFAULT) {
646             DrawDefaultBlock(context);
647         } else if (blockType == SliderModelNG::BlockStyleType::SHAPE) {
648             DrawBlockShape(context);
649         } else if (blockType == SliderModelNG::BlockStyleType::IMAGE) {
650             auto blockCenter = GetBlockCenter();
651             if (updateImageCenterX_) {
652                 updateImageCenterX_(blockCenter.GetX());
653             }
654             if (updateImageCenterY_) {
655                 updateImageCenterY_(blockCenter.GetY());
656             }
657         }
658     }
659 }
660 
DrawBlockShape(DrawingContext & context)661 void SliderContentModifier::DrawBlockShape(DrawingContext& context)
662 {
663     if (shape_ == nullptr) {
664         return;
665     }
666 
667     switch (shape_->GetBasicShapeType()) {
668         case BasicShapeType::CIRCLE: {
669             auto circle = DynamicCast<Circle>(shape_);
670             CHECK_NULL_VOID(circle);
671             DrawBlockShapeCircle(context, circle);
672             break;
673         }
674         case BasicShapeType::ELLIPSE: {
675             auto ellipse = DynamicCast<Ellipse>(shape_);
676             CHECK_NULL_VOID(ellipse);
677             DrawBlockShapeEllipse(context, ellipse);
678             break;
679         }
680         case BasicShapeType::PATH: {
681             auto path = DynamicCast<Path>(shape_);
682             CHECK_NULL_VOID(path);
683             DrawBlockShapePath(context, path);
684             break;
685         }
686         case BasicShapeType::RECT: {
687             auto rect = DynamicCast<ShapeRect>(shape_);
688             CHECK_NULL_VOID(rect);
689             DrawBlockShapeRect(context, rect);
690             break;
691         }
692         default:
693             break;
694     }
695 }
696 
DrawBlockShapeCircle(DrawingContext & context,RefPtr<Circle> & circle)697 void SliderContentModifier::DrawBlockShapeCircle(DrawingContext& context, RefPtr<Circle>& circle)
698 {
699     auto blockSize = blockSize_->Get();
700     auto shapeWidth = shapeWidth_->Get();
701     auto shapeHeight = shapeHeight_->Get();
702     auto blockBorderWidth = blockBorderWidth_->Get();
703     if (NearZero(shapeWidth) || NearZero(shapeHeight)) {
704         return;
705     }
706 
707     auto blockCenter = GetBlockCenter();
708     float scale = std::max(blockSize.Width() / shapeWidth, blockSize.Height() / shapeHeight);
709     if (NearZero(scale)) {
710         return;
711     }
712     float blockBorderWidthUnscale = blockBorderWidth / scale;
713 
714     auto& canvas = context.canvas;
715     canvas.Save();
716     SetBlockClip(context);
717     canvas.Translate(blockCenter.GetX(), blockCenter.GetY());
718     canvas.Scale(scale, scale);
719     canvas.Translate(-blockCenter.GetX(), -blockCenter.GetY());
720 
721     RSPen pen;
722     pen.SetAntiAlias(true);
723     pen.SetWidth(blockBorderWidthUnscale);
724     pen.SetColor(ToRSColor(blockBorderColor_->Get()));
725     canvas.AttachPen(pen);
726     RSBrush brush;
727     brush.SetAntiAlias(true);
728     brush.SetColor(ToRSColor(blockColor_->Get()));
729     canvas.AttachBrush(brush);
730 
731     float radius = std::min(shapeWidth, shapeHeight) * HALF;
732     float drawRadius = radius - blockBorderWidthUnscale * HALF;
733     PointF drawCenter(
734         blockCenter.GetX() - shapeWidth * HALF + radius, blockCenter.GetY() - shapeHeight * HALF + radius);
735     canvas.DrawCircle(ToRSPoint(drawCenter), drawRadius);
736 
737     canvas.DetachBrush();
738     canvas.DetachPen();
739     canvas.Restore();
740 }
741 
DrawBlockShapeEllipse(DrawingContext & context,RefPtr<Ellipse> & ellipse)742 void SliderContentModifier::DrawBlockShapeEllipse(DrawingContext& context, RefPtr<Ellipse>& ellipse)
743 {
744     auto blockSize = blockSize_->Get();
745     auto shapeWidth = shapeWidth_->Get();
746     auto shapeHeight = shapeHeight_->Get();
747     auto blockBorderWidth = blockBorderWidth_->Get();
748     if (NearZero(shapeWidth) || NearZero(shapeHeight)) {
749         return;
750     }
751 
752     auto blockCenter = GetBlockCenter();
753     float scale = std::max(blockSize.Width() / shapeWidth, blockSize.Height() / shapeHeight);
754     if (NearZero(scale)) {
755         return;
756     }
757     float blockBorderWidthUnscale = blockBorderWidth / scale;
758 
759     auto& canvas = context.canvas;
760     canvas.Save();
761     SetBlockClip(context);
762     canvas.Translate(blockCenter.GetX(), blockCenter.GetY());
763     canvas.Scale(scale, scale);
764     canvas.Translate(-blockCenter.GetX(), -blockCenter.GetY());
765 
766     RSPen pen;
767     pen.SetAntiAlias(true);
768     pen.SetWidth(blockBorderWidth);
769     pen.SetColor(ToRSColor(blockBorderColor_->Get()));
770     canvas.AttachPen(pen);
771     RSBrush brush;
772     brush.SetAntiAlias(true);
773     brush.SetColor(ToRSColor(blockColor_->Get()));
774     canvas.AttachBrush(brush);
775 
776     RectF drawRect(blockCenter.GetX() - shapeWidth * HALF + blockBorderWidthUnscale * HALF,
777         blockCenter.GetY() - shapeHeight * HALF + blockBorderWidthUnscale * HALF, shapeWidth - blockBorderWidthUnscale,
778         shapeHeight - blockBorderWidthUnscale);
779     canvas.DrawOval(ToRSRect(drawRect));
780 
781     canvas.DetachBrush();
782     canvas.DetachPen();
783     canvas.Restore();
784 }
785 
DrawBlockShapePath(DrawingContext & context,RefPtr<Path> & path)786 void SliderContentModifier::DrawBlockShapePath(DrawingContext& context, RefPtr<Path>& path)
787 {
788     auto blockSize = blockSize_->Get();
789     auto blockBorderWidth = blockBorderWidth_->Get();
790 
791     auto blockCenter = GetBlockCenter();
792     SizeF shapeSize = PathPainter::GetPathSize(path->GetValue());
793     if (NearZero(shapeSize.Width()) || NearZero(shapeSize.Height())) {
794         return;
795     }
796     float scale = std::max(blockSize.Width() / (shapeSize.Width() + blockBorderWidth),
797         blockSize.Height() / (shapeSize.Height() + blockBorderWidth));
798     if (NearZero(scale)) {
799         return;
800     }
801 
802     auto& canvas = context.canvas;
803     canvas.Save();
804     SetBlockClip(context);
805     canvas.Translate(blockCenter.GetX(), blockCenter.GetY());
806     canvas.Scale(scale, scale);
807     canvas.Translate(-blockCenter.GetX(), -blockCenter.GetY());
808 
809     RSPen pen;
810     pen.SetAntiAlias(true);
811     pen.SetWidth(blockBorderWidth);
812     pen.SetColor(ToRSColor(blockBorderColor_->Get()));
813     canvas.AttachPen(pen);
814     RSBrush brush;
815     brush.SetAntiAlias(true);
816     brush.SetColor(ToRSColor(blockColor_->Get()));
817     canvas.AttachBrush(brush);
818 
819     OffsetF offset(blockCenter.GetX() - shapeSize.Width() * HALF, blockCenter.GetY() - shapeSize.Height() * HALF);
820     PathPainter::DrawPath(canvas, path->GetValue(), offset);
821     canvas.DetachBrush();
822     canvas.DetachPen();
823     canvas.Restore();
824 }
825 
SetShapeRectRadius(RSRoundRect & roundRect,float borderWidth)826 void SliderContentModifier::SetShapeRectRadius(RSRoundRect& roundRect, float borderWidth)
827 {
828     float radiusX = rectTopLeftRadiusX_->Get() - borderWidth * HALF;
829     float radiusY = rectTopLeftRadiusY_->Get() - borderWidth * HALF;
830     roundRect.SetCornerRadius(RSRoundRect::TOP_LEFT_POS, radiusX, radiusY);
831 
832     radiusX = rectTopRightRadiusX_->Get() - borderWidth * HALF;
833     radiusY = rectTopRightRadiusY_->Get() - borderWidth * HALF;
834     roundRect.SetCornerRadius(RSRoundRect::TOP_RIGHT_POS, radiusX, radiusY);
835 
836     radiusX = rectBottomLeftRadiusX_->Get() - borderWidth * HALF;
837     radiusY = rectBottomLeftRadiusY_->Get() - borderWidth * HALF;
838     roundRect.SetCornerRadius(RSRoundRect::BOTTOM_LEFT_POS, radiusX, radiusY);
839 
840     radiusX = rectBottomRightRadiusX_->Get() - borderWidth * HALF;
841     radiusY = rectBottomRightRadiusY_->Get() - borderWidth * HALF;
842     roundRect.SetCornerRadius(RSRoundRect::BOTTOM_RIGHT_POS, radiusX, radiusY);
843 }
844 
DrawBlockShapeRect(DrawingContext & context,RefPtr<ShapeRect> & rect)845 void SliderContentModifier::DrawBlockShapeRect(DrawingContext& context, RefPtr<ShapeRect>& rect)
846 {
847     auto shapeWidth = shapeWidth_->Get();
848     auto shapeHeight = shapeHeight_->Get();
849     if (NearZero(shapeWidth) || NearZero(shapeHeight)) {
850         return;
851     }
852     auto blockSize = blockSize_->Get();
853     float scale = std::max(blockSize.Width() / shapeWidth, blockSize.Height() / shapeHeight);
854     if (NearZero(scale)) {
855         return;
856     }
857     auto blockBorderWidth = blockBorderWidth_->Get();
858     float blockBorderWidthUnscale = blockBorderWidth / scale;
859     auto blockCenter = GetBlockCenter();
860 
861     auto& canvas = context.canvas;
862     canvas.Save();
863     SetBlockClip(context);
864     canvas.Translate(blockCenter.GetX(), blockCenter.GetY());
865     canvas.Scale(scale, scale);
866     canvas.Translate(-blockCenter.GetX(), -blockCenter.GetY());
867 
868     RSPen pen;
869     pen.SetAntiAlias(true);
870     pen.SetWidth(blockBorderWidth_->Get());
871     pen.SetColor(ToRSColor(blockBorderColor_->Get()));
872     canvas.AttachPen(pen);
873     RSBrush brush;
874     brush.SetAntiAlias(true);
875     brush.SetColor(ToRSColor(blockColor_->Get()));
876     canvas.AttachBrush(brush);
877 
878     RSRoundRect roundRect;
879     RSRect rsRect;
880     rsRect.SetLeft(blockCenter.GetX() - shapeWidth * HALF + blockBorderWidthUnscale * HALF);
881     rsRect.SetRight(blockCenter.GetX() + shapeWidth * HALF - blockBorderWidthUnscale);
882     rsRect.SetTop(blockCenter.GetY() - shapeHeight * HALF + blockBorderWidthUnscale * HALF);
883     rsRect.SetBottom(blockCenter.GetY() + shapeHeight * HALF - blockBorderWidthUnscale);
884     roundRect.SetRect(rsRect);
885     SetShapeRectRadius(roundRect, blockBorderWidthUnscale);
886 
887     canvas.DrawRoundRect(roundRect);
888     canvas.DetachBrush();
889     canvas.DetachPen();
890     canvas.Restore();
891 }
892 
SetBlockShape(const RefPtr<BasicShape> & shape)893 void SliderContentModifier::SetBlockShape(const RefPtr<BasicShape>& shape)
894 {
895     shape_ = shape;
896     CHECK_NULL_VOID(shape_);
897     shapeWidth_->Set(shape_->GetWidth().ConvertToPx());
898     shapeHeight_->Set(shape_->GetHeight().ConvertToPx());
899     if (shape->GetBasicShapeType() == BasicShapeType::CIRCLE) {
900         auto circle = DynamicCast<Circle>(shape_);
901         CHECK_NULL_VOID(circle);
902         if (circle->GetRadius().IsValid()) {
903             circleRadius_->Set(circle->GetRadius().ConvertToPx());
904         } else {
905             circleRadius_->Set(std::min(shape_->GetWidth().ConvertToPx(), shape_->GetHeight().ConvertToPx()) * HALF);
906         }
907     } else if (shape->GetBasicShapeType() == BasicShapeType::ELLIPSE) {
908         auto ellipse = DynamicCast<Ellipse>(shape_);
909         CHECK_NULL_VOID(ellipse);
910         if (ellipse->GetRadiusX().IsValid() && ellipse->GetRadiusY().IsValid()) {
911             ellipseRadiusX_->Set(ellipse->GetRadiusX().ConvertToPx());
912             ellipseRadiusY_->Set(ellipse->GetRadiusY().ConvertToPx());
913         } else {
914             ellipseRadiusX_->Set(shape_->GetWidth().ConvertToPx() * HALF);
915             ellipseRadiusY_->Set(shape_->GetHeight().ConvertToPx() * HALF);
916         }
917     } else if (shape->GetBasicShapeType() == BasicShapeType::RECT) {
918         auto rect = DynamicCast<ShapeRect>(shape_);
919         CHECK_NULL_VOID(rect);
920         rectTopLeftRadiusX_->Set(rect->GetTopLeftRadius().GetX().ConvertToPx());
921         rectTopLeftRadiusY_->Set(rect->GetTopLeftRadius().GetY().ConvertToPx());
922         rectTopRightRadiusX_->Set(rect->GetTopRightRadius().GetX().ConvertToPx());
923         rectTopRightRadiusY_->Set(rect->GetTopRightRadius().GetY().ConvertToPx());
924         rectBottomLeftRadiusX_->Set(rect->GetBottomLeftRadius().GetX().ConvertToPx());
925         rectBottomLeftRadiusY_->Set(rect->GetBottomLeftRadius().GetY().ConvertToPx());
926         rectBottomRightRadiusX_->Set(rect->GetBottomRightRadius().GetX().ConvertToPx());
927         rectBottomRightRadiusY_->Set(rect->GetBottomRightRadius().GetY().ConvertToPx());
928     }
929 }
930 
UpdateContentDirtyRect(const SizeF & frameSize)931 void SliderContentModifier::UpdateContentDirtyRect(const SizeF& frameSize)
932 {
933     if (useContentModifier_->Get()) {
934         return;
935     }
936     auto pipeline = PipelineBase::GetCurrentContext();
937     CHECK_NULL_VOID(pipeline);
938     auto theme = pipeline->GetTheme<SliderTheme>();
939     CHECK_NULL_VOID(theme);
940     auto hotShadowWidth = sliderMode_->Get() == static_cast<int32_t>(SliderModel::SliderMode::OUTSET)
941                               ? theme->GetOutsetHotBlockShadowWidth().ConvertToPx()
942                               : theme->GetInsetHotBlockShadowWidth().ConvertToPx();
943     auto circleSize =
944         SizeF(blockSize_->Get().Width() + hotShadowWidth / HALF, blockSize_->Get().Height() + hotShadowWidth / HALF);
945     if (GreatNotEqual(scaleValue_, DEFAULT_SCALE_VALUE)) {
946         circleSize = circleSize * scaleValue_;
947     }
948     RectF rect;
949     if (directionAxis_->Get() == static_cast<int32_t>(Axis::HORIZONTAL)) {
950         auto maxWidth = std::max(circleSize.Height(), frameSize.Height()) * HALF;
951         rect.SetOffset(OffsetF(-circleSize.Width(), blockCenterY_->Get() - maxWidth));
952         rect.SetSize(SizeF(circleSize.Width() / HALF + frameSize.Width(), maxWidth / HALF));
953     } else {
954         auto maxWidth = std::max(circleSize.Width(), frameSize.Width()) * HALF;
955         rect.SetOffset(OffsetF(blockCenterX_->Get() - maxWidth, -circleSize.Height()));
956         rect.SetSize(SizeF(maxWidth / HALF, circleSize.Height() / HALF + frameSize.Height()));
957     }
958 
959     SetBoundsRect(rect);
960 }
961 
SetBlockClip(DrawingContext & context)962 void SliderContentModifier::SetBlockClip(DrawingContext& context)
963 {
964     auto& canvas = context.canvas;
965     auto blockCenter = GetBlockCenter();
966     auto blockSize = blockSize_->Get();
967     RectF rect(blockCenter.GetX() - blockSize.Width() * HALF, blockCenter.GetY() - blockSize.Height() * HALF,
968         blockSize.Width(), blockSize.Height());
969     canvas.ClipRect(ToRSRect(rect), RSClipOp::INTERSECT);
970 }
971 
GetTrackBackgroundColor() const972 std::vector<GradientColor> SliderContentModifier::GetTrackBackgroundColor() const
973 {
974     Gradient gradient = SortGradientColorsByOffset(trackBackgroundColor_->Get().GetGradient());
975     std::vector<GradientColor> gradientColors = gradient.GetColors();
976     // Fault protection processing, if gradientColors is empty, set to default colors.
977 
978     if (gradientColors.empty()) {
979         auto host = host_.Upgrade();
980         CHECK_NULL_RETURN(host, gradientColors);
981         auto pipeline = host->GetContext();
982         CHECK_NULL_RETURN(pipeline, gradientColors);
983         auto theme = pipeline->GetTheme<SliderTheme>(host->GetThemeScopeId());
984         CHECK_NULL_RETURN(theme, gradientColors);
985         gradientColors = SliderModelNG::CreateSolidGradient(theme->GetTrackBgColor()).GetColors();
986     }
987     return gradientColors;
988 }
989 
SortGradientColorsByOffset(const Gradient & gradient) const990 Gradient SliderContentModifier::SortGradientColorsByOffset(const Gradient& gradient) const
991 {
992     auto srcGradientColors = gradient.GetColors();
993     std::sort(
994         srcGradientColors.begin(), srcGradientColors.end(), [](const GradientColor& left, const GradientColor& right) {
995             return left.GetDimension().Value() < right.GetDimension().Value();
996         });
997 
998     Gradient sortedGradient;
999     for (const auto& item : srcGradientColors) {
1000         sortedGradient.AddColor(item);
1001     }
1002 
1003     return sortedGradient;
1004 }
1005 
DrawSelectColor(RSBrush & brush,RSRect & rect)1006 void SliderContentModifier::DrawSelectColor(RSBrush& brush, RSRect& rect)
1007 {
1008     Gradient gradient = SortGradientColorsByOffset(selectGradientColor_->Get().GetGradient());
1009     std::vector<GradientColor> gradientColors = gradient.GetColors();
1010 
1011     if (gradientColors.empty()) {
1012         auto pipeline = PipelineBase::GetCurrentContextSafely();
1013         CHECK_NULL_VOID(pipeline);
1014         auto theme = pipeline->GetTheme<SliderTheme>();
1015         CHECK_NULL_VOID(theme);
1016         gradientColors = SliderModelNG::CreateSolidGradient(theme->GetTrackSelectedColor()).GetColors();
1017     }
1018 
1019     std::vector<RSColorQuad> colors;
1020     std::vector<float> pos;
1021     for (size_t i = 0; i < gradientColors.size(); i++) {
1022         colors.emplace_back(gradientColors[i].GetLinearColor().GetValue());
1023         pos.emplace_back(gradientColors[i].GetDimension().Value());
1024     }
1025     RSPoint startPoint;
1026     RSPoint endPoint;
1027     auto direction = static_cast<Axis>(directionAxis_->Get());
1028     SetStartEndPointLocation(direction, rect, startPoint, endPoint);
1029 
1030     brush.SetAntiAlias(true);
1031     if (reverse_) {
1032 #ifndef USE_ROSEN_DRAWING
1033         brush.SetShaderEffect(
1034             RSShaderEffect::CreateLinearGradient(endPoint, startPoint, colors, pos, RSTileMode::CLAMP));
1035 #else
1036         brush.SetShaderEffect(
1037             RSRecordingShaderEffect::CreateLinearGradient(endPoint, startPoint, colors, pos, RSTileMode::CLAMP));
1038 #endif
1039     } else {
1040 #ifndef USE_ROSEN_DRAWING
1041         brush.SetShaderEffect(
1042             RSShaderEffect::CreateLinearGradient(startPoint, endPoint, colors, pos, RSTileMode::CLAMP));
1043 #else
1044         brush.SetShaderEffect(
1045             RSRecordingShaderEffect::CreateLinearGradient(startPoint, endPoint, colors, pos, RSTileMode::CLAMP));
1046 #endif
1047     }
1048 }
1049 } // namespace OHOS::Ace::NG
1050