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