• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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/swiper_indicator/dot_indicator/dot_indicator_paint_method.h"
17 
18 #include <valarray>
19 
20 #include "core/components/common/layout/constants.h"
21 #include "core/components/common/properties/color.h"
22 #include "core/components/swiper/render_swiper.h"
23 #include "core/components_ng/pattern/swiper/swiper_layout_property.h"
24 #include "core/components_ng/pattern/swiper_indicator/indicator_common/swiper_indicator_utils.h"
25 #include "core/components_ng/render/paint_property.h"
26 #include "core/pipeline/pipeline_base.h"
27 namespace OHOS::Ace::NG {
28 namespace {
29 // for indicator
30 constexpr Dimension INDICATOR_ITEM_SPACE = 8.0_vp;
31 constexpr Dimension INDICATOR_PADDING_DEFAULT = 12.0_vp;
32 constexpr Dimension INDICATOR_PADDING_HOVER = 12.0_vp;
33 constexpr float INDICATOR_ZOOM_IN_SCALE = 1.33f;
34 
35 constexpr float BLACK_POINT_CENTER_BEZIER_CURVE_VELOCITY = 0.4f;
36 constexpr float LONG_POINT_LEFT_CENTER_BEZIER_CURVE_VELOCITY = 0.2f;
37 constexpr float LONG_POINT_RIGHT_CENTER_BEZIER_CURVE_VELOCITY = 1.0f;
38 constexpr float CENTER_BEZIER_CURVE_MASS = 0.0f;
39 constexpr float CENTER_BEZIER_CURVE_STIFFNESS = 1.0f;
40 constexpr float CENTER_BEZIER_CURVE_DAMPING = 1.0f;
41 constexpr uint32_t ITEM_HALF_WIDTH = 0;
42 constexpr uint32_t ITEM_HALF_HEIGHT = 1;
43 constexpr uint32_t SELECTED_ITEM_HALF_WIDTH = 2;
44 constexpr uint32_t SELECTED_ITEM_HALF_HEIGHT = 3;
45 constexpr float TOUCH_BOTTOM_BACKGROUND_WIDTH_MULTIPLE = 1.225f;
46 constexpr float TOUCH_BOTTOM_DOT_WIDTH_MULTIPLE = 0.0125f;
47 constexpr float LONG_POINT_TAIL_RATIO = 0.5f;
48 constexpr float HALF_SELECTED_WIDTH = 2.0f;
49 constexpr int TWOFOLD = 2;
50 } // namespace
51 
UpdateContentModifier(PaintWrapper * paintWrapper)52 void DotIndicatorPaintMethod::UpdateContentModifier(PaintWrapper* paintWrapper)
53 {
54     CHECK_NULL_VOID(dotIndicatorModifier_);
55     CHECK_NULL_VOID(paintWrapper);
56 
57     auto pipelineContext = PipelineBase::GetCurrentContext();
58     CHECK_NULL_VOID(pipelineContext);
59     auto swiperTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
60     CHECK_NULL_VOID(swiperTheme);
61 
62     const auto& geometryNode = paintWrapper->GetGeometryNode();
63     CHECK_NULL_VOID(geometryNode);
64 
65     auto paintProperty = DynamicCast<DotIndicatorPaintProperty>(paintWrapper->GetPaintProperty());
66     IsCustomSizeValue_ = paintProperty->GetIsCustomSizeValue(false);
67     dotIndicatorModifier_->SetAxis(axis_);
68     dotIndicatorModifier_->SetCurrentIndex(currentIndex_);
69     dotIndicatorModifier_->SetUnselectedColor(paintProperty->GetColorValue(swiperTheme->GetColor()));
70     dotIndicatorModifier_->SetSelectedColor(paintProperty->GetSelectedColorValue(swiperTheme->GetSelectedColor()));
71     dotIndicatorModifier_->SetIndicatorMask(paintProperty->GetIndicatorMaskValue(false));
72     dotIndicatorModifier_->SetIsIndicatorCustomSize(IsCustomSizeValue_);
73     dotIndicatorModifier_->SetOffset(geometryNode->GetContentOffset());
74     SizeF contentSize = geometryNode->GetFrameSize();
75     centerY_ = (axis_ == Axis::HORIZONTAL ? contentSize.Height() : contentSize.Width()) * 0.5;
76     dotIndicatorModifier_->SetCenterY(centerY_);
77     if (touchBottomType_ != TouchBottomType::NONE) {
78         if (!dotIndicatorModifier_->GetIsPressed()) {
79             PaintPressIndicator(paintWrapper);
80             dotIndicatorModifier_->SetIsPressed(true);
81         }
82         UpdateBackground(paintWrapper);
83     } else if (isPressed_) {
84         PaintPressIndicator(paintWrapper);
85         dotIndicatorModifier_->SetIsPressed(true);
86     } else if (isHover_) {
87         PaintHoverIndicator(paintWrapper);
88         dotIndicatorModifier_->SetIsHover(true);
89     } else {
90         PaintNormalIndicator(paintWrapper);
91         dotIndicatorModifier_->SetIsHover(false);
92         dotIndicatorModifier_->SetIsPressed(false);
93     }
94 }
95 
GetLongPointAnimationStateSecondCenter(const PaintWrapper * paintWrapper,std::vector<std::pair<float,float>> & pointCenterX)96 void DotIndicatorPaintMethod::GetLongPointAnimationStateSecondCenter(
97     const PaintWrapper* paintWrapper, std::vector<std::pair<float, float>>& pointCenterX)
98 {
99     bool leftBottom = (gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT &&
100                        touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT);
101     bool rightBottom = (gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT &&
102                         touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT);
103 
104     if (leftBottom || rightBottom) {
105         pointAnimationStage_ = PointAnimationStage::STATE_EXPAND_TO_LONG_POINT;
106         auto [longPointCenterX, _] = CalculateLongPointCenterX(paintWrapper);
107         pointAnimationStage_ = PointAnimationStage::STATE_SHRINKT_TO_BLACK_POINT;
108         pointCenterX.push_back(longPointCenterX);
109     }
110 }
111 
UpdateNormalIndicator(LinearVector<float> & itemHalfSizes,const PaintWrapper * paintWrapper)112 void DotIndicatorPaintMethod::UpdateNormalIndicator(
113     LinearVector<float>& itemHalfSizes, const PaintWrapper* paintWrapper)
114 {
115     if (gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT ||
116         gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT) {
117         std::vector<std::pair<float, float>> pointCenterX({ longPointCenterX_ });
118         GetLongPointAnimationStateSecondCenter(paintWrapper, pointCenterX);
119         dotIndicatorModifier_->PlayIndicatorAnimation(
120             vectorBlackPointCenterX_, pointCenterX, gestureState_, touchBottomTypeLoop_);
121     } else {
122         dotIndicatorModifier_->UpdateNormalPaintProperty(
123             normalMargin_, itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
124     }
125 }
126 
PaintNormalIndicator(const PaintWrapper * paintWrapper)127 void DotIndicatorPaintMethod::PaintNormalIndicator(const PaintWrapper* paintWrapper)
128 {
129     auto [longPointCenterX, itemHalfSizes] = CalculateLongPointCenterX(paintWrapper);
130     longPointCenterX_ = longPointCenterX;
131     if (dotIndicatorModifier_->GetIsHover()) {
132         dotIndicatorModifier_->UpdateHoverToNormalPaintProperty(
133             normalMargin_, itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
134     } else if (dotIndicatorModifier_->GetIsPressed()) {
135         dotIndicatorModifier_->UpdatePressToNormalPaintProperty(
136             normalMargin_, itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
137     } else {
138         UpdateNormalIndicator(itemHalfSizes, paintWrapper);
139     }
140 }
141 
PaintHoverIndicator(const PaintWrapper * paintWrapper)142 void DotIndicatorPaintMethod::PaintHoverIndicator(const PaintWrapper* paintWrapper)
143 {
144     CHECK_NULL_VOID(paintWrapper);
145     auto paintProperty = DynamicCast<DotIndicatorPaintProperty>(paintWrapper->GetPaintProperty());
146     CHECK_NULL_VOID(paintProperty);
147     auto swiperTheme = GetSwiperIndicatorTheme();
148     CHECK_NULL_VOID(swiperTheme);
149     // diameter calculation
150     auto itemWidth = static_cast<float>(paintProperty->GetItemWidthValue(swiperTheme->GetSize()).ConvertToPx());
151     auto itemHeight = static_cast<float>(paintProperty->GetItemHeightValue(swiperTheme->GetSize()).ConvertToPx());
152     auto selectedItemWidth =
153         static_cast<float>(paintProperty->GetSelectedItemWidthValue(swiperTheme->GetSize()).ConvertToPx());
154     auto selectedItemHeight =
155         static_cast<float>(paintProperty->GetSelectedItemHeightValue(swiperTheme->GetSize()).ConvertToPx());
156     // use radius calculation
157     LinearVector<float> itemHalfSizes;
158     itemHalfSizes.emplace_back(itemWidth * 0.5 * INDICATOR_ZOOM_IN_SCALE);
159     itemHalfSizes.emplace_back(itemHeight * 0.5 * INDICATOR_ZOOM_IN_SCALE);
160     itemHalfSizes.emplace_back(selectedItemWidth * 0.5 * INDICATOR_ZOOM_IN_SCALE);
161     itemHalfSizes.emplace_back(selectedItemHeight * 0.5 * INDICATOR_ZOOM_IN_SCALE);
162     longPointCenterX_ =
163         CalculatePointCenterX(itemHalfSizes, 0, static_cast<float>(INDICATOR_PADDING_HOVER.ConvertToPx()),
164             static_cast<float>(INDICATOR_ITEM_SPACE.ConvertToPx()), currentIndex_);
165 
166     if (dotIndicatorModifier_->GetIsPressed()) {
167         dotIndicatorModifier_->SetIsPressed(false);
168         dotIndicatorModifier_->UpdateHoverAndPressConversionPaintProperty();
169     } else if (dotIndicatorModifier_->GetIsHover()) {
170         if (!mouseClickIndex_.has_value()) {
171             dotIndicatorModifier_->UpdateHoverPaintProperty(itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
172         }
173     } else {
174         dotIndicatorModifier_->UpdateNormalToHoverPaintProperty(
175             itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
176     }
177 
178     CalculateHoverIndex(itemHalfSizes);
179     if (dotIndicatorModifier_->GetNormalToHoverIndex() != hoverIndex_) {
180         dotIndicatorModifier_->SetHoverToNormalIndex(dotIndicatorModifier_->GetNormalToHoverIndex());
181         dotIndicatorModifier_->UpdateHoverToNormalPointDilateRatio();
182         dotIndicatorModifier_->SetNormalToHoverIndex(hoverIndex_);
183         dotIndicatorModifier_->UpdateNormalToHoverPointDilateRatio();
184     }
185 
186     if (mouseClickIndex_) {
187         if (currentIndex_ == itemCount_ - displayCount_ && !isLoop_ && mouseClickIndex_ > currentIndex_ &&
188             mouseClickIndex_ < itemCount_) {
189             longPointCenterX_ =
190                 CalculatePointCenterX(itemHalfSizes, 0, static_cast<float>(INDICATOR_PADDING_HOVER.ConvertToPx()),
191                     static_cast<float>(INDICATOR_ITEM_SPACE.ConvertToPx()), currentIndex_);
192         } else {
193             longPointCenterX_ =
194                 CalculatePointCenterX(itemHalfSizes, 0, static_cast<float>(INDICATOR_PADDING_HOVER.ConvertToPx()),
195                     static_cast<float>(INDICATOR_ITEM_SPACE.ConvertToPx()), mouseClickIndex_.value());
196         }
197         dotIndicatorModifier_->UpdateAllPointCenterXAnimation(
198             gestureState_, vectorBlackPointCenterX_, longPointCenterX_);
199         longPointIsHover_ = true;
200         mouseClickIndex_ = std::nullopt;
201     }
202     if (dotIndicatorModifier_->GetLongPointIsHover() != longPointIsHover_) {
203         dotIndicatorModifier_->SetLongPointIsHover(longPointIsHover_);
204         dotIndicatorModifier_->UpdateLongPointDilateRatio();
205     }
206 }
207 
PaintPressIndicator(const PaintWrapper * paintWrapper)208 void DotIndicatorPaintMethod::PaintPressIndicator(const PaintWrapper* paintWrapper)
209 {
210     CHECK_NULL_VOID(paintWrapper);
211     auto paintProperty = DynamicCast<DotIndicatorPaintProperty>(paintWrapper->GetPaintProperty());
212     CHECK_NULL_VOID(paintProperty);
213     auto swiperTheme = GetSwiperIndicatorTheme();
214     CHECK_NULL_VOID(swiperTheme);
215     // diameter calculation
216     auto itemWidth = static_cast<float>(paintProperty->GetItemWidthValue(swiperTheme->GetSize()).ConvertToPx());
217     auto itemHeight = static_cast<float>(paintProperty->GetItemHeightValue(swiperTheme->GetSize()).ConvertToPx());
218     auto selectedItemWidth =
219         static_cast<float>(paintProperty->GetSelectedItemWidthValue(swiperTheme->GetSize()).ConvertToPx());
220     auto selectedItemHeight =
221         static_cast<float>(paintProperty->GetSelectedItemHeightValue(swiperTheme->GetSize()).ConvertToPx());
222     // use radius calculation
223     auto itemHalfWidth = itemWidth * 0.5 * INDICATOR_ZOOM_IN_SCALE;
224     auto itemHalfHeight = itemHeight * 0.5 * INDICATOR_ZOOM_IN_SCALE;
225     auto selectedItemHalfWidth = selectedItemWidth * 0.5 * INDICATOR_ZOOM_IN_SCALE;
226     auto selectedItemHalfHeight = selectedItemHeight * 0.5 * INDICATOR_ZOOM_IN_SCALE;
227     LinearVector<float> itemHalfSizes;
228     itemHalfSizes.emplace_back(itemHalfWidth);
229     itemHalfSizes.emplace_back(itemHalfHeight);
230     itemHalfSizes.emplace_back(selectedItemHalfWidth);
231     itemHalfSizes.emplace_back(selectedItemHalfHeight);
232     longPointCenterX_ =
233         CalculatePointCenterX(itemHalfSizes, 0, static_cast<float>(INDICATOR_PADDING_HOVER.ConvertToPx()),
234             static_cast<float>(INDICATOR_ITEM_SPACE.ConvertToPx()), currentIndex_);
235     if (dotIndicatorModifier_->GetIsPressed()) {
236         dotIndicatorModifier_->UpdatePressPaintProperty(itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
237     } else if (dotIndicatorModifier_->GetIsHover()) {
238         dotIndicatorModifier_->SetIsPressed(true);
239         dotIndicatorModifier_->UpdateHoverAndPressConversionPaintProperty();
240     } else {
241         dotIndicatorModifier_->UpdateNormalToPressPaintProperty(
242             itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
243     }
244 }
245 
CalculateNormalMargin(const LinearVector<float> & itemHalfSizes,const SizeF & frameSize)246 void DotIndicatorPaintMethod::CalculateNormalMargin(const LinearVector<float>& itemHalfSizes, const SizeF& frameSize)
247 {
248     // diameter calculation
249     auto itemWidth = itemHalfSizes[ITEM_HALF_WIDTH] * 2;
250     auto itemHeight = itemHalfSizes[ITEM_HALF_HEIGHT] * 2;
251     auto selectedItemWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH] * 2;
252     auto selectedItemHeight = itemHalfSizes[SELECTED_ITEM_HALF_HEIGHT] * 2;
253     auto allPointDiameterSum = itemWidth * static_cast<float>(itemCount_ + 1);
254     if (IsCustomSizeValue_) {
255         allPointDiameterSum = itemWidth * static_cast<float>(itemCount_ - 1) + selectedItemWidth;
256     }
257     auto allPointSpaceSum = static_cast<float>(INDICATOR_ITEM_SPACE.ConvertToPx()) * (itemCount_ - 1);
258     auto indicatorPadding = static_cast<float>(INDICATOR_PADDING_DEFAULT.ConvertToPx());
259     auto contentWidth = indicatorPadding + allPointDiameterSum + allPointSpaceSum + indicatorPadding;
260     auto contentHeight = indicatorPadding + itemHeight + indicatorPadding;
261     if (selectedItemHeight > itemHeight) {
262         contentHeight = indicatorPadding + selectedItemHeight + indicatorPadding;
263     }
264     float marginX = ((axis_ == Axis::HORIZONTAL ? frameSize.Width() : frameSize.Height()) - contentWidth) * 0.5;
265     float marginY = ((axis_ == Axis::HORIZONTAL ? frameSize.Height() : frameSize.Width()) - contentHeight) * 0.5;
266     normalMargin_.SetX(marginX);
267     normalMargin_.SetY(marginY);
268 }
269 
CalculatePointCenterX(const LinearVector<float> & itemHalfSizes,float margin,float padding,float space,int32_t index)270 std::pair<float, float> DotIndicatorPaintMethod::CalculatePointCenterX(
271     const LinearVector<float>& itemHalfSizes, float margin, float padding, float space, int32_t index)
272 {
273     if (itemCount_ == 0) {
274         return { 0, 0 };
275     }
276     float startCenterX = margin + padding;
277     float endCenterX = margin + padding;
278     if (Positive(turnPageRate_)) {
279         auto itemWidth = itemHalfSizes[ITEM_HALF_WIDTH] * TWOFOLD;
280         auto selectedItemWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH] * TWOFOLD;
281         float allPointDiameterSum = itemWidth * static_cast<float>(itemCount_ + 1);
282         if (IsCustomSizeValue_) {
283             allPointDiameterSum = itemWidth * static_cast<float>(itemCount_ - 1) + selectedItemWidth;
284         }
285         auto allPointSpaceSum = static_cast<float>(INDICATOR_ITEM_SPACE.ConvertToPx() * (itemCount_ - 1));
286         float rectWidth = padding + allPointDiameterSum + allPointSpaceSum + padding;
287         startCenterX = rectWidth - startCenterX;
288         endCenterX = rectWidth - endCenterX;
289         return BackwardCalculation(itemHalfSizes, startCenterX, endCenterX, space, index);
290     }
291     return ForwardCalculation(itemHalfSizes, startCenterX, endCenterX, space, index);
292 }
293 
CalculateLongPointCenterX(const PaintWrapper * paintWrapper)294 std::tuple<std::pair<float, float>, LinearVector<float>> DotIndicatorPaintMethod::CalculateLongPointCenterX(
295     const PaintWrapper* paintWrapper)
296 {
297     std::tuple<std::pair<float, float>, LinearVector<float>> tmp;
298     CHECK_NULL_RETURN(paintWrapper, tmp);
299     const auto& geometryNode = paintWrapper->GetGeometryNode();
300     CHECK_NULL_RETURN(geometryNode, tmp);
301     auto paintProperty = DynamicCast<DotIndicatorPaintProperty>(paintWrapper->GetPaintProperty());
302     CHECK_NULL_RETURN(paintProperty, tmp);
303     auto swiperTheme = GetSwiperIndicatorTheme();
304     CHECK_NULL_RETURN(swiperTheme, tmp);
305     SizeF frameSize = geometryNode->GetFrameSize();
306     // diameter calculation
307     auto itemWidth = static_cast<float>(paintProperty->GetItemWidthValue(swiperTheme->GetSize()).ConvertToPx());
308     auto itemHeight = static_cast<float>(paintProperty->GetItemHeightValue(swiperTheme->GetSize()).ConvertToPx());
309     auto selectedItemWidth =
310         static_cast<float>(paintProperty->GetSelectedItemWidthValue(swiperTheme->GetSize()).ConvertToPx());
311     auto selectedItemHeight =
312         static_cast<float>(paintProperty->GetSelectedItemHeightValue(swiperTheme->GetSize()).ConvertToPx());
313     // use radius calculation
314     LinearVector<float> itemHalfSizes;
315     itemHalfSizes.emplace_back(itemWidth * 0.5);
316     itemHalfSizes.emplace_back(itemHeight * 0.5);
317     itemHalfSizes.emplace_back(selectedItemWidth * 0.5);
318     itemHalfSizes.emplace_back(selectedItemHeight * 0.5);
319     CalculateNormalMargin(itemHalfSizes, frameSize);
320     auto longPointCenterX = CalculatePointCenterX(itemHalfSizes, normalMargin_.GetX(),
321         static_cast<float>(INDICATOR_PADDING_DEFAULT.ConvertToPx()),
322         static_cast<float>(INDICATOR_ITEM_SPACE.ConvertToPx()), currentIndex_);
323     return { longPointCenterX, itemHalfSizes };
324 }
325 
GetMoveRate()326 std::tuple<float, float, float> DotIndicatorPaintMethod::GetMoveRate()
327 {
328     float blackPointCenterMoveRate = CubicCurve(BLACK_POINT_CENTER_BEZIER_CURVE_VELOCITY, CENTER_BEZIER_CURVE_MASS,
329         CENTER_BEZIER_CURVE_STIFFNESS, CENTER_BEZIER_CURVE_DAMPING).MoveInternal(std::abs(turnPageRate_));
330     float longPointLeftCenterMoveRate = 0.0f;
331     float longPointRightCenterMoveRate = 0.0f;
332 
333     if (isPressed_ && touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE) {
334         longPointLeftCenterMoveRate = CubicCurve(turnPageRate_ > 0 ? LONG_POINT_LEFT_CENTER_BEZIER_CURVE_VELOCITY :
335             LONG_POINT_RIGHT_CENTER_BEZIER_CURVE_VELOCITY, CENTER_BEZIER_CURVE_MASS, CENTER_BEZIER_CURVE_STIFFNESS,
336             CENTER_BEZIER_CURVE_DAMPING).MoveInternal(std::abs(turnPageRate_));
337         longPointRightCenterMoveRate = CubicCurve(turnPageRate_ > 0 ? LONG_POINT_RIGHT_CENTER_BEZIER_CURVE_VELOCITY :
338             LONG_POINT_LEFT_CENTER_BEZIER_CURVE_VELOCITY, CENTER_BEZIER_CURVE_MASS, CENTER_BEZIER_CURVE_STIFFNESS,
339             CENTER_BEZIER_CURVE_DAMPING).MoveInternal(std::abs(turnPageRate_));
340     } else if (gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT ||
341                gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT) {
342         blackPointCenterMoveRate = 1;
343         longPointLeftCenterMoveRate = 1;
344         longPointRightCenterMoveRate = 1;
345     } else if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT) {
346         auto rateAbs = std::abs(turnPageRate_);
347         longPointLeftCenterMoveRate = longPointRightCenterMoveRate =
348             // x0:0.33, y0:0, x1:0.67, y1:1
349             CubicCurve(0.33, 0, 0.67, 1).MoveInternal(1.0 - rateAbs);
350     } else if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT) {
351         auto rateAbs = std::abs(turnPageRate_);
352         // x0:0.33, y0:0, x1:0.67, y1:1
353         longPointLeftCenterMoveRate = longPointRightCenterMoveRate = CubicCurve(0.33, 0, 0.67, 1).MoveInternal(rateAbs);
354     } else if (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT) {
355         longPointLeftCenterMoveRate =std::abs(turnPageRate_);
356         longPointRightCenterMoveRate = std::abs(turnPageRate_) +
357                                        ((1 - longPointLeftCenterMoveRate) * LONG_POINT_TAIL_RATIO);
358     } else if (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_RIGHT) {
359         longPointRightCenterMoveRate = std::abs(turnPageRate_);
360         longPointLeftCenterMoveRate = std::abs(turnPageRate_) * LONG_POINT_TAIL_RATIO;
361     }
362     return { blackPointCenterMoveRate, longPointLeftCenterMoveRate, longPointRightCenterMoveRate };
363 }
364 
CalculatePointCenterX(const StarAndEndPointCenter & starAndEndPointCenter,const LinearVector<float> & startVectorBlackPointCenterX,const LinearVector<float> & endVectorBlackPointCenterX)365 std::pair<float, float> DotIndicatorPaintMethod::CalculatePointCenterX(
366     const StarAndEndPointCenter& starAndEndPointCenter, const LinearVector<float>& startVectorBlackPointCenterX,
367     const LinearVector<float>& endVectorBlackPointCenterX)
368 {
369     const auto [blackPointCenterMoveRate, longPointLeftCenterMoveRate, longPointRightCenterMoveRate] = GetMoveRate();
370 
371     vectorBlackPointCenterX_.resize(itemCount_);
372     for (int32_t i = 0; i < itemCount_; ++i) {
373         vectorBlackPointCenterX_[i] = startVectorBlackPointCenterX[i] +
374         (endVectorBlackPointCenterX[i] - startVectorBlackPointCenterX[i]) * blackPointCenterMoveRate;
375     }
376 
377     std::pair<float, float> longPointCenterX;
378     longPointCenterX.first = starAndEndPointCenter.startLongPointLeftCenterX +
379         (starAndEndPointCenter.endLongPointLeftCenterX - starAndEndPointCenter.startLongPointLeftCenterX) *
380             longPointLeftCenterMoveRate;
381     longPointCenterX.second = starAndEndPointCenter.startLongPointRightCenterX +
382         (starAndEndPointCenter.endLongPointRightCenterX - starAndEndPointCenter.startLongPointRightCenterX) *
383             longPointRightCenterMoveRate;
384     return longPointCenterX;
385 }
386 
CalculateHoverIndex(const LinearVector<float> & itemHalfSizes)387 void DotIndicatorPaintMethod::CalculateHoverIndex(const LinearVector<float>& itemHalfSizes)
388 {
389     if (!isHover_) {
390         hoverIndex_ = std::nullopt;
391         longPointIsHover_ = false;
392         return;
393     }
394     for (size_t i = 0; i < vectorBlackPointCenterX_.size(); ++i) {
395         OffsetF center = { vectorBlackPointCenterX_[i], centerY_ };
396         if (isHoverPoint(hoverPoint_, center, center, itemHalfSizes)) {
397             hoverIndex_ = i;
398             break;
399         }
400     }
401 
402     OffsetF leftCenter = { longPointCenterX_.first, centerY_ };
403     OffsetF rightCenter = { longPointCenterX_.second, centerY_ };
404     longPointIsHover_ = isHoverPoint(hoverPoint_, leftCenter, rightCenter, itemHalfSizes);
405 }
406 
isHoverPoint(const PointF & hoverPoint,const OffsetF & leftCenter,const OffsetF & rightCenter,const LinearVector<float> & itemHalfSizes)407 bool DotIndicatorPaintMethod::isHoverPoint(
408     const PointF& hoverPoint, const OffsetF& leftCenter,
409     const OffsetF& rightCenter, const LinearVector<float>& itemHalfSizes)
410 {
411     float tempLeftCenterX = axis_ == Axis::HORIZONTAL ? leftCenter.GetX() : leftCenter.GetY();
412     float tempLeftCenterY = axis_ == Axis::HORIZONTAL ? leftCenter.GetY() : leftCenter.GetX();
413     float tempRightCenterX = axis_ == Axis::HORIZONTAL ? rightCenter.GetX() : rightCenter.GetY();
414     float tempRightCenterY = axis_ == Axis::HORIZONTAL ? rightCenter.GetY() : rightCenter.GetX();
415     float itemHalfWidth = itemHalfSizes[ITEM_HALF_WIDTH];
416     float itemHalfHeight = itemHalfSizes[ITEM_HALF_HEIGHT];
417     if (hoverIndex_ == currentIndex_) {
418         itemHalfWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
419         itemHalfHeight = itemHalfSizes[SELECTED_ITEM_HALF_HEIGHT];
420     }
421     return hoverPoint.GetX() >= (tempLeftCenterX - itemHalfWidth) && (hoverPoint.GetX() <=
422                 (tempRightCenterX + itemHalfWidth)) && (hoverPoint.GetY() >= (tempLeftCenterY - itemHalfHeight)) &&
423                 (hoverPoint.GetY() <= (tempRightCenterY + itemHalfHeight));
424 }
425 
UpdateBackground(const PaintWrapper * paintWrapper)426 void DotIndicatorPaintMethod::UpdateBackground(const PaintWrapper* paintWrapper)
427 {
428     CHECK_NULL_VOID(paintWrapper);
429     auto paintProperty = DynamicCast<DotIndicatorPaintProperty>(paintWrapper->GetPaintProperty());
430     CHECK_NULL_VOID(paintProperty);
431     auto swiperTheme = GetSwiperIndicatorTheme();
432     CHECK_NULL_VOID(swiperTheme);
433 
434     // diameter calculation
435     auto itemWidth = static_cast<float>(paintProperty->GetItemWidthValue(swiperTheme->GetSize()).ConvertToPx());
436     auto itemHeight = static_cast<float>(paintProperty->GetItemHeightValue(swiperTheme->GetSize()).ConvertToPx());
437     auto selectedItemWidth =
438         static_cast<float>(paintProperty->GetSelectedItemWidthValue(swiperTheme->GetSize()).ConvertToPx());
439     auto selectedItemHeight =
440         static_cast<float>(paintProperty->GetSelectedItemHeightValue(swiperTheme->GetSize()).ConvertToPx());
441     // use radius calculation
442     LinearVector<float> itemHalfSizes;
443     itemHalfSizes.emplace_back(itemWidth * 0.5f * INDICATOR_ZOOM_IN_SCALE);
444     itemHalfSizes.emplace_back(itemHeight * 0.5f * INDICATOR_ZOOM_IN_SCALE);
445     itemHalfSizes.emplace_back(selectedItemWidth * 0.5f * INDICATOR_ZOOM_IN_SCALE);
446     itemHalfSizes.emplace_back(selectedItemHeight * 0.5f * INDICATOR_ZOOM_IN_SCALE);
447     if (touchBottomType_ != TouchBottomType::NONE) {
448         float allPointDiameterSum = itemWidth * static_cast<float>(itemCount_ + 1);
449         if (IsCustomSizeValue_) {
450             allPointDiameterSum = itemWidth * static_cast<float>(itemCount_ - 1) + selectedItemWidth;
451         }
452         float allPointSpaceSum = static_cast<float>(INDICATOR_ITEM_SPACE.ConvertToPx()) * (itemCount_ - 1);
453         float padding = static_cast<float>(INDICATOR_PADDING_DEFAULT.ConvertToPx());
454         float rectWidth = padding + allPointDiameterSum + allPointSpaceSum + padding;
455         float newRectWidth =
456             rectWidth * (TOUCH_BOTTOM_BACKGROUND_WIDTH_MULTIPLE - TOUCH_BOTTOM_DOT_WIDTH_MULTIPLE * itemCount_);
457         auto changeValue = (newRectWidth - rectWidth) * touchBottomRate_;
458 
459         float space = static_cast<float>(INDICATOR_ITEM_SPACE.ConvertToPx());
460         if (itemCount_ > 1) {
461             space = (rectWidth + changeValue - padding * 2 - allPointDiameterSum) / (itemCount_ - 1);
462         }
463         longPointCenterX_ = CalculatePointCenterX(itemHalfSizes, 0, padding, space, currentIndex_);
464         if (touchBottomType_ == TouchBottomType::START) {
465             for (size_t index = 0; index < vectorBlackPointCenterX_.size(); index++) {
466                 vectorBlackPointCenterX_[index] = vectorBlackPointCenterX_[index] - changeValue;
467             }
468             longPointCenterX_.first = longPointCenterX_.first - changeValue;
469             longPointCenterX_.second = longPointCenterX_.second - changeValue;
470         }
471     }
472     dotIndicatorModifier_->UpdateTouchBottomAnimation(
473         touchBottomType_, vectorBlackPointCenterX_, longPointCenterX_, touchBottomRate_);
474 }
475 
GetIndex(int32_t index)476 std::pair<int32_t, int32_t> DotIndicatorPaintMethod::GetIndex(int32_t index)
477 {
478     if (mouseClickIndex_ || gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT ||
479         gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT) {
480         turnPageRate_ = 0;
481     }
482     // item may be invalid in auto linear scene
483     if (nextValidIndex_ >= 0) {
484         int32_t startCurrentIndex = index;
485         int32_t endCurrentIndex = NearEqual(turnPageRate_, 0.0f) || LessOrEqualCustomPrecision(turnPageRate_, -1.0f) ||
486                                           GreatOrEqualCustomPrecision(turnPageRate_, 1.0f)
487                                       ? index
488                                       : nextValidIndex_;
489         // reach edge scene
490         if (startCurrentIndex > endCurrentIndex) {
491             startCurrentIndex = currentIndexActual_;
492             endCurrentIndex = currentIndexActual_;
493         }
494         return { startCurrentIndex, endCurrentIndex };
495     }
496 
497     int32_t startCurrentIndex = index;
498     int32_t endCurrentIndex = NearEqual(turnPageRate_, 0.0f) || LessOrEqualCustomPrecision(turnPageRate_, -1.0f) ||
499                                       GreatOrEqualCustomPrecision(turnPageRate_, 1.0f)
500                                   ? endCurrentIndex = index
501                                   : (LessNotEqualCustomPrecision(turnPageRate_, 0.0f) ? index + 1 : index - 1);
502     if (endCurrentIndex == -1) {
503         endCurrentIndex = itemCount_ - 1;
504     } else if (endCurrentIndex == itemCount_) {
505         endCurrentIndex = 0;
506     }
507     return { startCurrentIndex, endCurrentIndex };
508 }
509 
GetStartAndEndIndex(int32_t index)510 std::pair<int32_t, int32_t> DotIndicatorPaintMethod::GetStartAndEndIndex(int32_t index)
511 {
512     auto [startCurrentIndex, endCurrentIndex] = GetIndex(index);
513 
514     if (pointAnimationStage_ == PointAnimationStage::STATE_EXPAND_TO_LONG_POINT &&
515         gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT &&
516         touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT) {
517         endCurrentIndex = startCurrentIndex;
518         return { startCurrentIndex, endCurrentIndex };
519     } else if (pointAnimationStage_ == PointAnimationStage::STATE_EXPAND_TO_LONG_POINT &&
520                gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT &&
521                touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT) {
522         endCurrentIndex = startCurrentIndex = 0;
523         return { startCurrentIndex, endCurrentIndex };
524     }
525 
526     if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT &&
527         !(endCurrentIndex == startCurrentIndex && startCurrentIndex != 0)) {
528         startCurrentIndex = endCurrentIndex = 0;
529     } else if (gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT &&
530                touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT) {
531         endCurrentIndex = startCurrentIndex = itemCount_ - 1;
532     } else if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT) {
533         endCurrentIndex = startCurrentIndex;
534     }
535 
536     return { startCurrentIndex, endCurrentIndex };
537 }
538 
AdjustPointCenterXForTouchBottom(StarAndEndPointCenter & pointCenter,LinearVector<float> & endVectorBlackPointCenterX,int32_t startCurrentIndex,int32_t endCurrentIndex,float selectedItemWidth,int32_t index)539 void DotIndicatorPaintMethod::AdjustPointCenterXForTouchBottom(StarAndEndPointCenter& pointCenter,
540     LinearVector<float>& endVectorBlackPointCenterX, int32_t startCurrentIndex, int32_t endCurrentIndex,
541     float selectedItemWidth, int32_t index)
542 {
543     auto [startIndex, endIndex] = GetIndex(index);
544     if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT &&
545         pointAnimationStage_ != PointAnimationStage::STATE_EXPAND_TO_LONG_POINT &&
546         (!(endIndex == startIndex && startIndex != 0) ||
547             (gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT ||
548                 gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT))) {
549         pointCenter.endLongPointRightCenterX = pointCenter.endLongPointLeftCenterX = endVectorBlackPointCenterX[0];
550     } else if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT &&
551                pointAnimationStage_ != PointAnimationStage::STATE_EXPAND_TO_LONG_POINT) {
552         pointCenter.endLongPointRightCenterX = pointCenter.endLongPointLeftCenterX =
553             endVectorBlackPointCenterX[startCurrentIndex];
554     }
555 
556     if (IsCustomSizeValue_) {
557         selectedItemWidth = 0;
558     }
559 
560     if (pointAnimationStage_ == PointAnimationStage::STATE_EXPAND_TO_LONG_POINT &&
561         gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT &&
562         touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT) {
563         pointCenter.startLongPointRightCenterX = endVectorBlackPointCenterX[endCurrentIndex];
564         pointCenter.endLongPointLeftCenterX =
565             endVectorBlackPointCenterX[endCurrentIndex] - (selectedItemWidth / HALF_SELECTED_WIDTH);
566     } else if (pointAnimationStage_ == PointAnimationStage::STATE_EXPAND_TO_LONG_POINT &&
567                gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT &&
568                touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT) {
569         pointCenter.startLongPointRightCenterX = endVectorBlackPointCenterX[0];
570         pointCenter.endLongPointLeftCenterX = endVectorBlackPointCenterX[0] - (selectedItemWidth / HALF_SELECTED_WIDTH);
571     }
572 }
573 
ForwardCalculation(const LinearVector<float> & itemHalfSizes,float startCenterX,float endCenterX,float space,int32_t index)574 std::pair<float, float> DotIndicatorPaintMethod::ForwardCalculation(
575     const LinearVector<float>& itemHalfSizes, float startCenterX, float endCenterX, float space, int32_t index)
576 {
577     auto itemWidth = itemHalfSizes[ITEM_HALF_WIDTH] * TWOFOLD;
578     auto selectedItemWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH] * TWOFOLD;
579     StarAndEndPointCenter pointCenter;
580     // Calculate the data required for the current pages
581     LinearVector<float> startVectorBlackPointCenterX(itemCount_);
582     // Calculate the data required for subsequent pages
583     LinearVector<float> endVectorBlackPointCenterX(itemCount_);
584 
585     auto [startCurrentIndex, endCurrentIndex] = GetStartAndEndIndex(index);
586     for (int32_t i = 0; i < itemCount_; ++i) {
587         if (i != startCurrentIndex) {
588             startVectorBlackPointCenterX[i] = startCenterX + itemHalfSizes[ITEM_HALF_WIDTH];
589             startCenterX += itemWidth;
590         } else {
591             if (IsCustomSizeValue_) {
592                 startVectorBlackPointCenterX[i] = startCenterX + itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
593                 pointCenter.startLongPointLeftCenterX = startCenterX + itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
594                 pointCenter.startLongPointRightCenterX = pointCenter.startLongPointLeftCenterX;
595                 startCenterX += selectedItemWidth;
596             } else {
597                 startVectorBlackPointCenterX[i] = startCenterX + selectedItemWidth;
598                 pointCenter.startLongPointLeftCenterX = startCenterX + itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
599                 pointCenter.startLongPointRightCenterX = pointCenter.startLongPointLeftCenterX + selectedItemWidth;
600                 startCenterX += selectedItemWidth * TWOFOLD;
601             }
602         }
603         if (i != endCurrentIndex) {
604             endVectorBlackPointCenterX[i] = endCenterX + itemHalfSizes[ITEM_HALF_WIDTH];
605             endCenterX += itemWidth;
606         } else {
607             if (IsCustomSizeValue_) {
608                 endVectorBlackPointCenterX[i] = endCenterX + itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
609                 pointCenter.endLongPointLeftCenterX = endCenterX + itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
610                 pointCenter.endLongPointRightCenterX = pointCenter.endLongPointLeftCenterX;
611                 endCenterX += selectedItemWidth;
612             } else {
613                 endVectorBlackPointCenterX[i] = endCenterX + selectedItemWidth;
614                 pointCenter.endLongPointLeftCenterX = endCenterX + itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
615                 pointCenter.endLongPointRightCenterX = pointCenter.endLongPointLeftCenterX + selectedItemWidth;
616                 endCenterX += selectedItemWidth * TWOFOLD;
617             }
618         }
619         startCenterX += space;
620         endCenterX += space;
621     }
622 
623     AdjustPointCenterXForTouchBottom(
624         pointCenter, endVectorBlackPointCenterX, startCurrentIndex, endCurrentIndex, selectedItemWidth, index);
625     return CalculatePointCenterX(pointCenter, startVectorBlackPointCenterX, endVectorBlackPointCenterX);
626 }
627 
BackwardCalculation(const LinearVector<float> & itemHalfSizes,float startCenterX,float endCenterX,float space,int32_t index)628 std::pair<float, float> DotIndicatorPaintMethod::BackwardCalculation(
629     const LinearVector<float>& itemHalfSizes, float startCenterX, float endCenterX, float space, int32_t index)
630 {
631     int32_t startCurrentIndex = index;
632     auto itemWidth = itemHalfSizes[ITEM_HALF_WIDTH] * TWOFOLD;
633     auto selectedItemWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH] * TWOFOLD;
634     StarAndEndPointCenter pointCenter;
635     // Calculate the data required for the current pages
636     LinearVector<float> startVectorBlackPointCenterX(itemCount_);
637     // Calculate the data required for subsequent pages
638     LinearVector<float> endVectorBlackPointCenterX(itemCount_);
639     int32_t endCurrentIndex = NearEqual(turnPageRate_, 0.0f) || turnPageRate_ <= -1.0f || turnPageRate_ >= 1.0f
640         ? endCurrentIndex = index : (turnPageRate_ < 0.0f ? index + 1 : index - 1);
641     if (endCurrentIndex == -1) {
642         endCurrentIndex = itemCount_ - 1;
643     } else if (endCurrentIndex == itemCount_) {
644         endCurrentIndex = 0;
645     }
646     for (int32_t i = itemCount_ - 1; i >= 0; --i) {
647         if (i != startCurrentIndex) {
648             startVectorBlackPointCenterX[i] = startCenterX - itemHalfSizes[ITEM_HALF_WIDTH];
649             startCenterX -= itemWidth;
650         } else {
651             if (IsCustomSizeValue_) {
652                 startVectorBlackPointCenterX[i] = startCenterX - itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
653                 pointCenter.startLongPointLeftCenterX = startCenterX - itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
654                 pointCenter.startLongPointRightCenterX = pointCenter.startLongPointLeftCenterX;
655                 startCenterX -= selectedItemWidth;
656             } else {
657                 startVectorBlackPointCenterX[i] = startCenterX - itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
658                 pointCenter.startLongPointRightCenterX = startCenterX - itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
659                 pointCenter.startLongPointLeftCenterX = pointCenter.startLongPointRightCenterX - selectedItemWidth;
660                 startCenterX -= selectedItemWidth * TWOFOLD;
661             }
662         }
663         if (i != endCurrentIndex) {
664             endVectorBlackPointCenterX[i] = endCenterX - itemHalfSizes[ITEM_HALF_WIDTH];
665             endCenterX -= itemWidth;
666         } else {
667             if (IsCustomSizeValue_) {
668                 endVectorBlackPointCenterX[i] = endCenterX - itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
669                 pointCenter.endLongPointLeftCenterX = endCenterX - itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
670                 pointCenter.endLongPointRightCenterX = pointCenter.endLongPointLeftCenterX;
671                 endCenterX -= selectedItemWidth;
672             } else {
673                 endVectorBlackPointCenterX[i] = endCenterX - itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
674                 pointCenter.endLongPointRightCenterX = endCenterX - itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
675                 pointCenter.endLongPointLeftCenterX = pointCenter.endLongPointRightCenterX - selectedItemWidth;
676                 endCenterX -= selectedItemWidth * TWOFOLD;
677             }
678         }
679         startCenterX -= space;
680         endCenterX -= space;
681     }
682     return CalculatePointCenterX(pointCenter, startVectorBlackPointCenterX, endVectorBlackPointCenterX);
683 }
684 } // namespace OHOS::Ace::NG
685