• 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 "core/components/common/layout/constants.h"
19 #include "core/components/common/properties/color.h"
20 namespace OHOS::Ace::NG {
21 namespace {
22 // for indicator
23 constexpr float BLACK_POINT_CENTER_BEZIER_CURVE_VELOCITY = 0.4f;
24 constexpr float LONG_POINT_LEFT_CENTER_BEZIER_CURVE_VELOCITY = 0.2f;
25 constexpr float LONG_POINT_RIGHT_CENTER_BEZIER_CURVE_VELOCITY = 1.0f;
26 constexpr float CENTER_BEZIER_CURVE_MASS = 0.0f;
27 constexpr float CENTER_BEZIER_CURVE_STIFFNESS = 1.0f;
28 constexpr float CENTER_BEZIER_CURVE_DAMPING = 1.0f;
29 constexpr uint32_t ITEM_HALF_WIDTH = 0;
30 constexpr uint32_t ITEM_HALF_HEIGHT = 1;
31 constexpr uint32_t SELECTED_ITEM_HALF_WIDTH = 2;
32 constexpr uint32_t SELECTED_ITEM_HALF_HEIGHT = 3;
33 constexpr float TOUCH_BOTTOM_BACKGROUND_WIDTH_MULTIPLE = 1.225f;
34 constexpr float TOUCH_BOTTOM_DOT_WIDTH_MULTIPLE = 0.0125f;
35 constexpr float LONG_POINT_TAIL_RATIO = 0.5f;
36 constexpr float FIFTY_PERCENT = 0.5f;
37 constexpr float HALF_SELECTED_WIDTH = 2.0f;
38 constexpr float HALF_FLOAT = 0.5f;
39 constexpr int TWOFOLD = 2;
40 constexpr float HALF = 0.5f;
41 } // namespace
42 
UpdateContentModifier(PaintWrapper * paintWrapper)43 void DotIndicatorPaintMethod::UpdateContentModifier(PaintWrapper* paintWrapper)
44 {
45     CHECK_NULL_VOID(dotIndicatorModifier_);
46     CHECK_NULL_VOID(paintWrapper);
47 
48     auto pipelineContext = PipelineBase::GetCurrentContext();
49     CHECK_NULL_VOID(pipelineContext);
50     auto swiperTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
51     CHECK_NULL_VOID(swiperTheme);
52 
53     const auto& geometryNode = paintWrapper->GetGeometryNode();
54     CHECK_NULL_VOID(geometryNode);
55 
56     auto paintProperty = DynamicCast<DotIndicatorPaintProperty>(paintWrapper->GetPaintProperty());
57     CHECK_NULL_VOID(paintProperty);
58     IsCustomSizeValue_ = paintProperty->GetIsCustomSizeValue(false);
59     dotIndicatorModifier_->SetAxis(axis_);
60     auto [currentIndex, currentIndexActual] = CalCurrentIndex();
61     dotIndicatorModifier_->SetCurrentIndex(currentIndex);
62     dotIndicatorModifier_->SetCurrentIndexActual(currentIndexActual);
63     dotIndicatorModifier_->SetUnselectedColor(paintProperty->GetColorValue(swiperTheme->GetColor()));
64     dotIndicatorModifier_->SetSelectedColor(paintProperty->GetSelectedColorValue(swiperTheme->GetSelectedColor()));
65     dotIndicatorModifier_->SetIndicatorMask(paintProperty->GetIndicatorMaskValue(false));
66     dotIndicatorModifier_->SetIsIndicatorCustomSize(IsCustomSizeValue_);
67     dotIndicatorModifier_->SetOffset(geometryNode->GetContentOffset());
68     dotIndicatorModifier_->SetIndicatorDotItemSpace(
69         paintProperty->GetSpaceValue(swiperTheme->GetIndicatorDotItemSpace()));
70 
71     SizeF contentSize = geometryNode->GetFrameSize();
72     centerY_ = (axis_ == Axis::HORIZONTAL ? contentSize.Height() : contentSize.Width()) * 0.5;
73     dotIndicatorModifier_->SetCenterY(centerY_);
74     if (touchBottomType_ != TouchBottomType::NONE) {
75         if (!dotIndicatorModifier_->GetIsPressed()) {
76             PaintPressIndicator(paintWrapper);
77             dotIndicatorModifier_->SetIsPressed(true);
78         }
79         UpdateBackground(paintWrapper);
80     } else if (isPressed_) {
81         PaintPressIndicator(paintWrapper);
82         dotIndicatorModifier_->SetIsPressed(true);
83     } else if (isHover_) {
84         PaintHoverIndicator(paintWrapper);
85         dotIndicatorModifier_->SetIsHover(true);
86     } else {
87         PaintNormalIndicator(paintWrapper);
88         dotIndicatorModifier_->SetIsHover(false);
89         dotIndicatorModifier_->SetIsPressed(false);
90     }
91 }
92 
CalCurrentIndex()93 std::pair<int32_t, int32_t> DotIndicatorPaintMethod::CalCurrentIndex()
94 {
95     totalItemCount_ = !isAutoLinear_ ? totalItemCount_ : itemCount_;
96     if (isHorizontalAndRightToLeft_) {
97         if (isSwipeByGroup_) {
98             currentIndex_ = totalItemCount_ - 1 - currentIndex_;
99         } else {
100             currentIndex_ = itemCount_ - 1 - currentIndex_;
101         }
102     }
103     auto currentIndex = currentIndex_;
104     auto currentIndexActual = currentIndexActual_;
105     if (!isAutoLinear_ && isSwipeByGroup_ && displayCount_ != 0) {
106         currentIndex = currentIndex_ / displayCount_;
107         currentIndexActual = currentIndexActual_ / displayCount_;
108     }
109     return { currentIndex, currentIndexActual };
110 }
111 
NeedBottomAnimation() const112 bool DotIndicatorPaintMethod::NeedBottomAnimation() const
113 {
114     auto currentIndexActual = currentIndexActual_;
115     auto firstIndex = firstIndex_;
116     if (!isAutoLinear_ && isSwipeByGroup_ && displayCount_ != 0) {
117         firstIndex /= displayCount_;
118         currentIndexActual /= displayCount_;
119     }
120     firstIndex = isHorizontalAndRightToLeft_ ? itemCount_ - 1 - firstIndex : firstIndex;
121     if (gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT) {
122         if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT) {
123             if (NearZero(touchBottomPageRate_)) {
124                 return true;
125             }
126 
127             if (currentIndexActual != firstIndex && std::abs(touchBottomPageRate_) < FIFTY_PERCENT) {
128                 return false;
129             }
130 
131             return true;
132         }
133 
134         if (currentIndexActual == firstIndex && firstIndex == itemCount_ - 1 &&
135             std::abs(touchBottomPageRate_) > FIFTY_PERCENT) {
136             return true;
137         }
138     }
139 
140     if (gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT) {
141         if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE) {
142             if (currentIndexActual == 0 && targetIndex_ && targetIndex_.value() == 0 &&
143                 std::abs(touchBottomPageRate_) < FIFTY_PERCENT && !NearZero(touchBottomPageRate_)) {
144                 return true;
145             }
146 
147             return false;
148         }
149 
150         if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT) {
151             if (currentIndexActual == firstIndex && std::abs(touchBottomPageRate_) > FIFTY_PERCENT) {
152                 return false;
153             }
154             // NearZero(touchBottomPageRate_) is Actual judgment, others are Preconditions.
155             if (currentIndexActual == itemCount_ - 1 && firstIndex == 0 && NearZero(touchBottomPageRate_)) {
156                 return false;
157             }
158 
159             return true;
160         }
161 
162         if (currentIndexActual == 0 && firstIndex == itemCount_ - 1 &&
163             std::abs(touchBottomPageRate_) < FIFTY_PERCENT) {
164             return true;
165         }
166     }
167 
168     return false;
169 }
170 
GetLongPointAnimationStateSecondCenter(const PaintWrapper * paintWrapper,std::vector<std::pair<float,float>> & pointCenterX)171 void DotIndicatorPaintMethod::GetLongPointAnimationStateSecondCenter(
172     const PaintWrapper* paintWrapper, std::vector<std::pair<float, float>>& pointCenterX)
173 {
174     if (NeedBottomAnimation()) {
175         pointAnimationStage_ = PointAnimationStage::STATE_EXPAND_TO_LONG_POINT;
176         auto [longPointCenterX, _] = CalculateLongPointCenterX(paintWrapper);
177         pointAnimationStage_ = PointAnimationStage::STATE_SHRINKT_TO_BLACK_POINT;
178         pointCenterX.push_back(longPointCenterX);
179     }
180 }
181 
UpdateNormalIndicator(LinearVector<float> & itemHalfSizes,const PaintWrapper * paintWrapper)182 void DotIndicatorPaintMethod::UpdateNormalIndicator(
183     LinearVector<float>& itemHalfSizes, const PaintWrapper* paintWrapper)
184 {
185     CHECK_NULL_VOID(dotIndicatorModifier_);
186     if (gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT ||
187         gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT) {
188         std::vector<std::pair<float, float>> pointCenterX({ longPointCenterX_ });
189         GetLongPointAnimationStateSecondCenter(paintWrapper, pointCenterX);
190         dotIndicatorModifier_->PlayIndicatorAnimation(
191             vectorBlackPointCenterX_, pointCenterX, gestureState_, touchBottomTypeLoop_);
192     } else {
193         dotIndicatorModifier_->UpdateNormalPaintProperty(
194             normalMargin_, itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
195     }
196 }
197 
PaintNormalIndicator(const PaintWrapper * paintWrapper)198 void DotIndicatorPaintMethod::PaintNormalIndicator(const PaintWrapper* paintWrapper)
199 {
200     CHECK_NULL_VOID(dotIndicatorModifier_);
201     auto [longPointCenterX, itemHalfSizes] = CalculateLongPointCenterX(paintWrapper);
202     longPointCenterX_ = longPointCenterX;
203 
204     if (dotIndicatorModifier_->GetIsHover()) {
205         dotIndicatorModifier_->UpdateHoverToNormalPaintProperty(
206             normalMargin_, itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
207     } else if (dotIndicatorModifier_->GetIsPressed()) {
208         dotIndicatorModifier_->UpdatePressToNormalPaintProperty(
209             normalMargin_, itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
210     } else {
211         UpdateNormalIndicator(itemHalfSizes, paintWrapper);
212     }
213 }
214 
PaintHoverIndicator(const PaintWrapper * paintWrapper)215 void DotIndicatorPaintMethod::PaintHoverIndicator(const PaintWrapper* paintWrapper)
216 {
217     CHECK_NULL_VOID(dotIndicatorModifier_);
218     CHECK_NULL_VOID(paintWrapper);
219     auto paintProperty = DynamicCast<DotIndicatorPaintProperty>(paintWrapper->GetPaintProperty());
220     CHECK_NULL_VOID(paintProperty);
221     auto indicatorTheme = GetSwiperIndicatorTheme();
222     CHECK_NULL_VOID(indicatorTheme);
223     // diameter calculation
224     auto itemWidth = static_cast<float>(paintProperty->GetItemWidthValue(indicatorTheme->GetSize()).ConvertToPx());
225     auto itemHeight = static_cast<float>(paintProperty->GetItemHeightValue(indicatorTheme->GetSize()).ConvertToPx());
226     auto selectedItemWidth =
227         static_cast<float>(paintProperty->GetSelectedItemWidthValue(indicatorTheme->GetSize()).ConvertToPx());
228     auto selectedItemHeight =
229         static_cast<float>(paintProperty->GetSelectedItemHeightValue(indicatorTheme->GetSize()).ConvertToPx());
230     // use radius calculation
231     LinearVector<float> itemHalfSizes;
232     float indicatorScale = indicatorTheme->GetIndicatorScale();
233     itemHalfSizes.emplace_back(itemWidth * HALF * indicatorScale);
234     itemHalfSizes.emplace_back(itemHeight * HALF * indicatorScale);
235     itemHalfSizes.emplace_back(selectedItemWidth * HALF * indicatorScale);
236     itemHalfSizes.emplace_back(selectedItemHeight * HALF * indicatorScale);
237     Dimension paddingSide = indicatorTheme->GetIndicatorPaddingDot();
238     Dimension indicatorDotItemSpace =
239         paintProperty->GetSpaceValue(indicatorTheme->GetIndicatorDotItemSpace());
240 
241     longPointCenterX_ =
242         CalculatePointCenterX(itemHalfSizes, 0, static_cast<float>(paddingSide.ConvertToPx()),
243             static_cast<float>(indicatorDotItemSpace.ConvertToPx()), currentIndex_);
244     if (dotIndicatorModifier_->GetIsPressed()) {
245         dotIndicatorModifier_->SetIsPressed(false);
246         dotIndicatorModifier_->UpdateHoverAndPressConversionPaintProperty();
247     } else if (dotIndicatorModifier_->GetIsHover()) {
248         if (!mouseClickIndex_.has_value()) {
249             dotIndicatorModifier_->UpdateHoverPaintProperty(itemHalfSizes,
250                 vectorBlackPointCenterX_, longPointCenterX_);
251         }
252     } else {
253         dotIndicatorModifier_->UpdateNormalToHoverPaintProperty(
254             itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
255     }
256 
257     CalculateHoverIndex(itemHalfSizes);
258     if (dotIndicatorModifier_->GetNormalToHoverIndex() != hoverIndex_) {
259         dotIndicatorModifier_->SetHoverToNormalIndex(dotIndicatorModifier_->GetNormalToHoverIndex());
260         dotIndicatorModifier_->UpdateHoverToNormalPointDilateRatio();
261         dotIndicatorModifier_->SetNormalToHoverIndex(hoverIndex_);
262         dotIndicatorModifier_->UpdateNormalToHoverPointDilateRatio();
263     }
264 
265     PaintHoverIndicator(itemHalfSizes, paddingSide, indicatorDotItemSpace);
266 }
267 
CalculateMouseClickIndexOnRTL()268 int32_t DotIndicatorPaintMethod::CalculateMouseClickIndexOnRTL()
269 {
270     int32_t mouseClickIndex = 0;
271     if (!mouseClickIndex_) {
272         return mouseClickIndex;
273     }
274 
275     if (isSwipeByGroup_) {
276         mouseClickIndex = totalItemCount_ - 1 - mouseClickIndex_.value();
277     } else {
278         mouseClickIndex = itemCount_ - 1 - mouseClickIndex_.value();
279     }
280 
281     return mouseClickIndex;
282 }
283 
PaintHoverIndicator(LinearVector<float> & itemHalfSizes,const Dimension paddingSide,const Dimension & indicatorDotItemSpace)284 void DotIndicatorPaintMethod::PaintHoverIndicator(LinearVector<float>& itemHalfSizes, const Dimension paddingSide,
285     const Dimension& indicatorDotItemSpace)
286 {
287     CHECK_NULL_VOID(dotIndicatorModifier_);
288     if (mouseClickIndex_) {
289         if (currentIndex_ == totalItemCount_ - displayCount_ && !isLoop_ && mouseClickIndex_ > currentIndex_ &&
290             mouseClickIndex_ < totalItemCount_) {
291             longPointCenterX_ = CalculatePointCenterX(itemHalfSizes, 0, static_cast<float>(paddingSide.ConvertToPx()),
292                 static_cast<float>(indicatorDotItemSpace.ConvertToPx()), currentIndex_);
293         } else {
294             auto mouseClickIndex = isHorizontalAndRightToLeft_ ?
295                 CalculateMouseClickIndexOnRTL() : mouseClickIndex_.value();
296             longPointCenterX_ = CalculatePointCenterX(itemHalfSizes, 0, static_cast<float>(paddingSide.ConvertToPx()),
297                 static_cast<float>(indicatorDotItemSpace.ConvertToPx()), mouseClickIndex);
298         }
299         dotIndicatorModifier_->UpdateAllPointCenterXAnimation(
300             gestureState_, vectorBlackPointCenterX_, longPointCenterX_);
301         mouseClickIndex_ = std::nullopt;
302     }
303     if (dotIndicatorModifier_->GetLongPointIsHover() != longPointIsHover_) {
304         dotIndicatorModifier_->SetLongPointIsHover(longPointIsHover_);
305         dotIndicatorModifier_->UpdateLongPointDilateRatio();
306     }
307 }
308 
PaintPressIndicator(const PaintWrapper * paintWrapper)309 void DotIndicatorPaintMethod::PaintPressIndicator(const PaintWrapper* paintWrapper)
310 {
311     CHECK_NULL_VOID(dotIndicatorModifier_);
312     CHECK_NULL_VOID(paintWrapper);
313     auto paintProperty = DynamicCast<DotIndicatorPaintProperty>(paintWrapper->GetPaintProperty());
314     CHECK_NULL_VOID(paintProperty);
315     auto indicatorTheme = GetSwiperIndicatorTheme();
316     CHECK_NULL_VOID(indicatorTheme);
317     // diameter calculation
318     auto itemWidth = static_cast<float>(paintProperty->GetItemWidthValue(indicatorTheme->GetSize()).ConvertToPx());
319     auto itemHeight = static_cast<float>(paintProperty->GetItemHeightValue(indicatorTheme->GetSize()).ConvertToPx());
320     auto selectedItemWidth =
321         static_cast<float>(paintProperty->GetSelectedItemWidthValue(indicatorTheme->GetSize()).ConvertToPx());
322     auto selectedItemHeight =
323         static_cast<float>(paintProperty->GetSelectedItemHeightValue(indicatorTheme->GetSize()).ConvertToPx());
324     // use radius calculation
325     float indicatorScale = indicatorTheme->GetIndicatorScale();
326     auto itemHalfWidth = itemWidth * HALF * indicatorScale;
327     auto itemHalfHeight = itemHeight * HALF * indicatorScale;
328     auto selectedItemHalfWidth = selectedItemWidth * HALF * indicatorScale;
329     auto selectedItemHalfHeight = selectedItemHeight * HALF * indicatorScale;
330     LinearVector<float> itemHalfSizes;
331     itemHalfSizes.emplace_back(itemHalfWidth);
332     itemHalfSizes.emplace_back(itemHalfHeight);
333     itemHalfSizes.emplace_back(selectedItemHalfWidth);
334     itemHalfSizes.emplace_back(selectedItemHalfHeight);
335     Dimension paddingSide = indicatorTheme->GetIndicatorPaddingDot();
336     Dimension indicatorDotItemSpace =
337         paintProperty->GetSpaceValue(indicatorTheme->GetIndicatorDotItemSpace());
338     longPointCenterX_ =
339         CalculatePointCenterX(itemHalfSizes, 0, static_cast<float>(paddingSide.ConvertToPx()),
340             static_cast<float>(indicatorDotItemSpace.ConvertToPx()), currentIndex_);
341     if (dotIndicatorModifier_->GetIsPressed()) {
342         dotIndicatorModifier_->UpdatePressPaintProperty(itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
343     } else if (dotIndicatorModifier_->GetIsHover()) {
344         dotIndicatorModifier_->SetIsPressed(true);
345         dotIndicatorModifier_->UpdateHoverAndPressConversionPaintProperty();
346     } else {
347         dotIndicatorModifier_->UpdateNormalToPressPaintProperty(
348             itemHalfSizes, vectorBlackPointCenterX_, longPointCenterX_);
349     }
350 }
351 
CalculateNormalMargin(const LinearVector<float> & itemHalfSizes,const SizeF & frameSize,const int32_t displayCount,const Dimension & indicatorDotItemSpace,bool ignoreSize)352 void DotIndicatorPaintMethod::CalculateNormalMargin(const LinearVector<float>& itemHalfSizes,
353     const SizeF& frameSize, const int32_t displayCount, const Dimension& indicatorDotItemSpace, bool ignoreSize)
354 {
355     // diameter calculation
356     auto itemWidth = itemHalfSizes[ITEM_HALF_WIDTH] * 2;
357     auto itemHeight = itemHalfSizes[ITEM_HALF_HEIGHT] * 2;
358     auto selectedItemWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH] * 2;
359     auto selectedItemHeight = itemHalfSizes[SELECTED_ITEM_HALF_HEIGHT] * 2;
360     auto allPointDiameterSum = itemWidth * static_cast<float>(displayCount + 1);
361     if (IsCustomSizeValue_) {
362         allPointDiameterSum = itemWidth * static_cast<float>(displayCount - 1) + selectedItemWidth;
363     }
364     auto allPointSpaceSum = static_cast<float>(indicatorDotItemSpace.ConvertToPx()) * (displayCount - 1);
365     auto indicatorTheme = GetSwiperIndicatorTheme();
366     CHECK_NULL_VOID(indicatorTheme);
367     Dimension paddingSide = indicatorTheme->GetIndicatorPaddingDot();
368     auto indicatorPaddingSide = static_cast<float>(paddingSide.ConvertToPx());
369     auto contentWidth = indicatorPaddingSide + allPointDiameterSum + allPointSpaceSum + indicatorPaddingSide;
370     auto indicatorHeightPadding = indicatorTheme->GetIndicatorBgHeight().ConvertToPx();
371 
372     auto contentHeight = indicatorHeightPadding + itemHeight + indicatorHeightPadding;
373     if (selectedItemHeight > itemHeight) {
374         contentHeight = indicatorHeightPadding + selectedItemHeight + indicatorHeightPadding;
375     }
376 
377     float marginX = ((axis_ == Axis::HORIZONTAL ? frameSize.Width() : frameSize.Height()) - contentWidth) * 0.5;
378     float marginY = ((axis_ == Axis::HORIZONTAL ? frameSize.Height() : frameSize.Width()) - contentHeight) * 0.5;
379     normalMargin_.SetX(marginX);
380     normalMargin_.SetY(marginY);
381 }
382 
CalculatePointCenterX(const LinearVector<float> & itemHalfSizes,float margin,float padding,float space,int32_t index)383 std::pair<float, float> DotIndicatorPaintMethod::CalculatePointCenterX(
384     const LinearVector<float>& itemHalfSizes, float margin, float padding, float space, int32_t index)
385 {
386     if (itemCount_ == 0) {
387         return { 0, 0 };
388     }
389     float startCenterX = margin + padding;
390     float endCenterX = margin + padding;
391 
392     if (!isAutoLinear_) {
393         if (isSwipeByGroup_ && displayCount_ != 0) {
394             index /= displayCount_;
395         }
396         if (isPressed_ && isSwipeByGroup_) {
397             touchBottomTypeLoop_ = TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE;
398         }
399     }
400 
401     if (Positive(turnPageRate_)) {
402         auto itemWidth = itemHalfSizes[ITEM_HALF_WIDTH] * TWOFOLD;
403         auto selectedItemWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH] * TWOFOLD;
404         float allPointDiameterSum = itemWidth * static_cast<float>(itemCount_ + 1);
405         if (IsCustomSizeValue_) {
406             allPointDiameterSum = itemWidth * static_cast<float>(itemCount_ - 1) + selectedItemWidth;
407         }
408         auto allPointSpaceSum = static_cast<float>(space * (itemCount_ - 1));
409 
410         float rectWidth = padding + allPointDiameterSum + allPointSpaceSum + padding;
411         startCenterX = rectWidth - startCenterX;
412         endCenterX = rectWidth - endCenterX;
413         return BackwardCalculation(itemHalfSizes, startCenterX, endCenterX, space, index);
414     }
415     return ForwardCalculation(itemHalfSizes, startCenterX, endCenterX, space, index);
416 }
417 
CalculateLongPointCenterX(const PaintWrapper * paintWrapper)418 std::tuple<std::pair<float, float>, LinearVector<float>> DotIndicatorPaintMethod::CalculateLongPointCenterX(
419     const PaintWrapper* paintWrapper)
420 {
421     std::tuple<std::pair<float, float>, LinearVector<float>> tmp;
422     CHECK_NULL_RETURN(paintWrapper, tmp);
423     const auto& geometryNode = paintWrapper->GetGeometryNode();
424     CHECK_NULL_RETURN(geometryNode, tmp);
425     auto paintProperty = DynamicCast<DotIndicatorPaintProperty>(paintWrapper->GetPaintProperty());
426     CHECK_NULL_RETURN(paintProperty, tmp);
427     auto indicatorTheme = GetSwiperIndicatorTheme();
428     CHECK_NULL_RETURN(indicatorTheme, tmp);
429     SizeF frameSize = geometryNode->GetFrameSize();
430     // diameter calculation
431     auto itemWidth = static_cast<float>(paintProperty->GetItemWidthValue(indicatorTheme->GetSize()).ConvertToPx());
432     auto itemHeight = static_cast<float>(paintProperty->GetItemHeightValue(indicatorTheme->GetSize()).ConvertToPx());
433     auto selectedItemWidth =
434         static_cast<float>(paintProperty->GetSelectedItemWidthValue(indicatorTheme->GetSize()).ConvertToPx());
435     auto selectedItemHeight =
436         static_cast<float>(paintProperty->GetSelectedItemHeightValue(indicatorTheme->GetSize()).ConvertToPx());
437     // use radius calculation
438     LinearVector<float> itemHalfSizes;
439     itemHalfSizes.emplace_back(itemWidth * 0.5);
440     itemHalfSizes.emplace_back(itemHeight * 0.5);
441     itemHalfSizes.emplace_back(selectedItemWidth * 0.5);
442     itemHalfSizes.emplace_back(selectedItemHeight * 0.5);
443 
444     Dimension indicatorDotItemSpace =
445         paintProperty->GetSpaceValue(indicatorTheme->GetIndicatorDotItemSpace());
446     bool ignoreSize = paintProperty->GetIgnoreSizeValue(false);
447     CalculateNormalMargin(itemHalfSizes, frameSize, itemCount_, indicatorDotItemSpace, ignoreSize);
448     Dimension paddingSide = indicatorTheme->GetIndicatorPaddingDot();
449     auto longPointCenterX = CalculatePointCenterX(itemHalfSizes, normalMargin_.GetX(),
450         static_cast<float>(paddingSide.ConvertToPx()),
451         static_cast<float>(indicatorDotItemSpace.ConvertToPx()), currentIndex_);
452     return { longPointCenterX, itemHalfSizes };
453 }
454 
GetMoveRate()455 std::tuple<float, float, float> DotIndicatorPaintMethod::GetMoveRate()
456 {
457     auto actualTurnPageRate = !isAutoLinear_ && isSwipeByGroup_ ? groupTurnPageRate_ : turnPageRate_;
458     float blackPointCenterMoveRate = CubicCurve(BLACK_POINT_CENTER_BEZIER_CURVE_VELOCITY, CENTER_BEZIER_CURVE_MASS,
459         CENTER_BEZIER_CURVE_STIFFNESS, CENTER_BEZIER_CURVE_DAMPING).MoveInternal(std::abs(actualTurnPageRate));
460     float longPointLeftCenterMoveRate = 0.0f;
461     float longPointRightCenterMoveRate = 0.0f;
462     if (isPressed_ && touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE) {
463         longPointLeftCenterMoveRate = CubicCurve(turnPageRate_ > 0 ? LONG_POINT_LEFT_CENTER_BEZIER_CURVE_VELOCITY :
464             LONG_POINT_RIGHT_CENTER_BEZIER_CURVE_VELOCITY, CENTER_BEZIER_CURVE_MASS, CENTER_BEZIER_CURVE_STIFFNESS,
465             CENTER_BEZIER_CURVE_DAMPING).MoveInternal(std::abs(turnPageRate_));
466         longPointRightCenterMoveRate = CubicCurve(turnPageRate_ > 0 ? LONG_POINT_RIGHT_CENTER_BEZIER_CURVE_VELOCITY :
467             LONG_POINT_LEFT_CENTER_BEZIER_CURVE_VELOCITY, CENTER_BEZIER_CURVE_MASS, CENTER_BEZIER_CURVE_STIFFNESS,
468             CENTER_BEZIER_CURVE_DAMPING).MoveInternal(std::abs(turnPageRate_));
469     } else if (gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT ||
470                gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT) {
471         blackPointCenterMoveRate = 1;
472         longPointLeftCenterMoveRate = 1;
473         longPointRightCenterMoveRate = 1;
474     } else if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT) {
475         auto rateAbs = 1.0f - std::abs(actualTurnPageRate);
476         // x0:0.33, y0:0, x1:0.67, y1:1
477         longPointLeftCenterMoveRate = longPointRightCenterMoveRate = CubicCurve(0.33, 0, 0.67, 1).MoveInternal(rateAbs);
478     } else if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT) {
479         auto rateAbs = std::abs(actualTurnPageRate);
480         // x0:0.33, y0:0, x1:0.67, y1:1
481         longPointLeftCenterMoveRate = longPointRightCenterMoveRate = CubicCurve(0.33, 0, 0.67, 1).MoveInternal(rateAbs);
482     } else if (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT) {
483         longPointLeftCenterMoveRate =std::abs(actualTurnPageRate);
484         longPointRightCenterMoveRate = std::abs(actualTurnPageRate) +
485                                        ((1 - longPointLeftCenterMoveRate) * LONG_POINT_TAIL_RATIO);
486     } else if (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_RIGHT) {
487         longPointRightCenterMoveRate = std::abs(actualTurnPageRate);
488         longPointLeftCenterMoveRate = std::abs(actualTurnPageRate) * LONG_POINT_TAIL_RATIO;
489     }
490     return { blackPointCenterMoveRate, longPointLeftCenterMoveRate, longPointRightCenterMoveRate };
491 }
492 
CalculatePointCenterX(const StarAndEndPointCenter & starAndEndPointCenter,const LinearVector<float> & startVectorBlackPointCenterX,const LinearVector<float> & endVectorBlackPointCenterX)493 std::pair<float, float> DotIndicatorPaintMethod::CalculatePointCenterX(
494     const StarAndEndPointCenter& starAndEndPointCenter, const LinearVector<float>& startVectorBlackPointCenterX,
495     const LinearVector<float>& endVectorBlackPointCenterX)
496 {
497     const auto [blackPointCenterMoveRate, longPointLeftCenterMoveRate, longPointRightCenterMoveRate] = GetMoveRate();
498 
499     vectorBlackPointCenterX_.resize(itemCount_);
500     for (int32_t i = 0; i < itemCount_; ++i) {
501         vectorBlackPointCenterX_[i] = startVectorBlackPointCenterX[i] +
502         (endVectorBlackPointCenterX[i] - startVectorBlackPointCenterX[i]) * blackPointCenterMoveRate;
503     }
504 
505     std::pair<float, float> longPointCenterX;
506     longPointCenterX.first = starAndEndPointCenter.startLongPointLeftCenterX +
507         (starAndEndPointCenter.endLongPointLeftCenterX - starAndEndPointCenter.startLongPointLeftCenterX) *
508             longPointLeftCenterMoveRate;
509     longPointCenterX.second = starAndEndPointCenter.startLongPointRightCenterX +
510         (starAndEndPointCenter.endLongPointRightCenterX - starAndEndPointCenter.startLongPointRightCenterX) *
511             longPointRightCenterMoveRate;
512     if (isHorizontalAndRightToLeft_) {
513         longPointCenterX.first = starAndEndPointCenter.startLongPointLeftCenterX +
514         (starAndEndPointCenter.endLongPointLeftCenterX - starAndEndPointCenter.startLongPointLeftCenterX) *
515             longPointLeftCenterMoveRate;
516         longPointCenterX.second = starAndEndPointCenter.startLongPointRightCenterX +
517             (starAndEndPointCenter.endLongPointRightCenterX - starAndEndPointCenter.startLongPointRightCenterX) *
518                 longPointRightCenterMoveRate;
519     }
520     return longPointCenterX;
521 }
522 
CalculateHoverIndex(const LinearVector<float> & itemHalfSizes)523 void DotIndicatorPaintMethod::CalculateHoverIndex(const LinearVector<float>& itemHalfSizes)
524 {
525     CHECK_NULL_VOID(dotIndicatorModifier_);
526     if (!isHover_) {
527         hoverIndex_ = std::nullopt;
528         longPointIsHover_ = false;
529         return;
530     }
531     for (size_t i = 0; i < vectorBlackPointCenterX_.size(); ++i) {
532         OffsetF center = { vectorBlackPointCenterX_[i], centerY_ };
533         if (isHoverPoint(hoverPoint_, center, center, itemHalfSizes)) {
534             hoverIndex_ = i;
535             break;
536         }
537     }
538     auto longPointCenterX = dotIndicatorModifier_->GetLongPointCenterX();
539 
540     OffsetF leftCenter = { longPointCenterX.first, centerY_ };
541     OffsetF rightCenter = { longPointCenterX.second, centerY_ };
542     longPointIsHover_ = isHoverPoint(hoverPoint_, leftCenter, rightCenter, itemHalfSizes);
543 }
544 
isHoverPoint(const PointF & hoverPoint,const OffsetF & leftCenter,const OffsetF & rightCenter,const LinearVector<float> & itemHalfSizes)545 bool DotIndicatorPaintMethod::isHoverPoint(
546     const PointF& hoverPoint, const OffsetF& leftCenter,
547     const OffsetF& rightCenter, const LinearVector<float>& itemHalfSizes)
548 {
549     float tempLeftCenterX = axis_ == Axis::HORIZONTAL ? leftCenter.GetX() : leftCenter.GetY();
550     float tempLeftCenterY = axis_ == Axis::HORIZONTAL ? leftCenter.GetY() : leftCenter.GetX();
551     float tempRightCenterX = axis_ == Axis::HORIZONTAL ? rightCenter.GetX() : rightCenter.GetY();
552     float tempRightCenterY = axis_ == Axis::HORIZONTAL ? rightCenter.GetY() : rightCenter.GetX();
553     float itemHalfWidth = itemHalfSizes[ITEM_HALF_WIDTH];
554     float itemHalfHeight = itemHalfSizes[ITEM_HALF_HEIGHT];
555     if (hoverIndex_ == currentIndex_) {
556         itemHalfWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
557         itemHalfHeight = itemHalfSizes[SELECTED_ITEM_HALF_HEIGHT];
558     }
559     return hoverPoint.GetX() >= (tempLeftCenterX - itemHalfWidth) && (hoverPoint.GetX() <=
560                 (tempRightCenterX + itemHalfWidth)) && (hoverPoint.GetY() >= (tempLeftCenterY - itemHalfHeight)) &&
561                 (hoverPoint.GetY() <= (tempRightCenterY + itemHalfHeight));
562 }
563 
UpdateBackground(const PaintWrapper * paintWrapper)564 void DotIndicatorPaintMethod::UpdateBackground(const PaintWrapper* paintWrapper)
565 {
566     CHECK_NULL_VOID(dotIndicatorModifier_);
567     CHECK_NULL_VOID(paintWrapper);
568     auto paintProperty = DynamicCast<DotIndicatorPaintProperty>(paintWrapper->GetPaintProperty());
569     CHECK_NULL_VOID(paintProperty);
570     auto indicatorTheme = GetSwiperIndicatorTheme();
571     CHECK_NULL_VOID(indicatorTheme);
572 
573     // diameter calculation
574     auto itemWidth = static_cast<float>(paintProperty->GetItemWidthValue(indicatorTheme->GetSize()).ConvertToPx());
575     auto itemHeight = static_cast<float>(paintProperty->GetItemHeightValue(indicatorTheme->GetSize()).ConvertToPx());
576     auto selectedItemWidth =
577         static_cast<float>(paintProperty->GetSelectedItemWidthValue(indicatorTheme->GetSize()).ConvertToPx());
578     auto selectedItemHeight =
579         static_cast<float>(paintProperty->GetSelectedItemHeightValue(indicatorTheme->GetSize()).ConvertToPx());
580     // use radius calculation
581     LinearVector<float> itemHalfSizes;
582     float indicatorScale = indicatorTheme->GetIndicatorScale();
583     itemHalfSizes.emplace_back(itemWidth * HALF * indicatorScale);
584     itemHalfSizes.emplace_back(itemHeight * HALF * indicatorScale);
585     itemHalfSizes.emplace_back(selectedItemWidth * HALF * indicatorScale);
586     itemHalfSizes.emplace_back(selectedItemHeight * HALF * indicatorScale);
587     if (touchBottomType_ != TouchBottomType::NONE) {
588         Dimension indicatorDotItemSpace = paintProperty->GetSpaceValue(indicatorTheme->GetIndicatorDotItemSpace());
589         float allPointDiameterSum = itemWidth * static_cast<float>(itemCount_ + 1);
590         if (IsCustomSizeValue_) {
591             allPointDiameterSum = itemWidth * static_cast<float>(itemCount_ - 1) + selectedItemWidth;
592         }
593         float allPointSpaceSum = static_cast<float>(indicatorDotItemSpace.ConvertToPx()) * (itemCount_ - 1);
594         Dimension paddingSide = indicatorTheme->GetIndicatorPaddingDot();
595         float padding = static_cast<float>(paddingSide.ConvertToPx());
596         float rectWidth = padding + allPointDiameterSum + allPointSpaceSum + padding;
597         float newRectWidth =
598             rectWidth * (TOUCH_BOTTOM_BACKGROUND_WIDTH_MULTIPLE - TOUCH_BOTTOM_DOT_WIDTH_MULTIPLE * itemCount_);
599         auto changeValue = (newRectWidth - rectWidth) * touchBottomRate_;
600 
601         float space = static_cast<float>(indicatorDotItemSpace.ConvertToPx());
602         if (itemCount_ > 1) {
603             space = (rectWidth + changeValue - padding * 2 - allPointDiameterSum) / (itemCount_ - 1);
604         }
605         longPointCenterX_ = CalculatePointCenterX(itemHalfSizes, 0, padding, space, currentIndex_);
606         if (touchBottomType_ == TouchBottomType::START) {
607             for (size_t index = 0; index < vectorBlackPointCenterX_.size(); index++) {
608                 vectorBlackPointCenterX_[index] = vectorBlackPointCenterX_[index] - changeValue;
609             }
610             longPointCenterX_.first = longPointCenterX_.first - changeValue;
611             longPointCenterX_.second = longPointCenterX_.second - changeValue;
612         }
613     }
614     dotIndicatorModifier_->UpdateTouchBottomAnimation(
615         touchBottomType_, vectorBlackPointCenterX_, longPointCenterX_, touchBottomRate_);
616 }
617 
GetIndexOnRTL(int32_t index)618 std::pair<int32_t, int32_t> DotIndicatorPaintMethod::GetIndexOnRTL(int32_t index)
619 {
620     auto actualTurnPageRate = turnPageRate_;
621     if (!isAutoLinear_ && isSwipeByGroup_ && !NearZero(groupTurnPageRate_)) {
622         actualTurnPageRate = groupTurnPageRate_;
623     }
624 
625     int32_t startCurrentIndex = index;
626     auto isInvalid = NearEqual(actualTurnPageRate, 0.0f) || LessOrEqualCustomPrecision(actualTurnPageRate, -1.0f) ||
627                      GreatOrEqualCustomPrecision(actualTurnPageRate, 1.0f);
628     if (!isInvalid) {
629         startCurrentIndex = LessNotEqualCustomPrecision(actualTurnPageRate, 0.0f) ? index - 1 : index + 1;
630     }
631 
632     if (startCurrentIndex <= -1) {
633         if (isLoop_) {
634             startCurrentIndex = itemCount_ - 1;
635         } else {
636             startCurrentIndex = 0;
637             if (index <= -1) {
638                 index = 0;
639             }
640         }
641     }
642 
643     return { startCurrentIndex, index };
644 }
645 
GetIndex(int32_t index)646 std::pair<int32_t, int32_t> DotIndicatorPaintMethod::GetIndex(int32_t index)
647 {
648     if (mouseClickIndex_ || gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT ||
649         gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT) {
650         turnPageRate_ = 0;
651         groupTurnPageRate_ = 0;
652     }
653 
654     if (isHorizontalAndRightToLeft_ && !isPressed_) {
655         return GetIndexOnRTL(index);
656     }
657 
658     auto actualTurnPageRate = turnPageRate_;
659     if (!isAutoLinear_ && isSwipeByGroup_ && groupTurnPageRate_ != 0) {
660         actualTurnPageRate = groupTurnPageRate_;
661     }
662 
663     // item may be invalid in auto linear scene
664     if (nextValidIndex_ >= 0) {
665         int32_t startCurrentIndex = index;
666         int32_t endCurrentIndex = NearEqual(turnPageRate_, 0.0f) || LessOrEqualCustomPrecision(turnPageRate_, -1.0f) ||
667                                           GreatOrEqualCustomPrecision(turnPageRate_, 1.0f)
668                                       ? index
669                                       : nextValidIndex_;
670         // reach edge scene
671         if (startCurrentIndex > endCurrentIndex) {
672             startCurrentIndex = currentIndexActual_;
673             endCurrentIndex = currentIndexActual_;
674         }
675         return { startCurrentIndex, endCurrentIndex };
676     }
677 
678     int32_t startCurrentIndex = index;
679     int32_t endCurrentIndex = NearEqual(actualTurnPageRate, 0.0f) ||
680         LessOrEqualCustomPrecision(actualTurnPageRate, -1.0f) || GreatOrEqualCustomPrecision(actualTurnPageRate, 1.0f)
681                                   ? endCurrentIndex = index
682                                   : (LessNotEqualCustomPrecision(actualTurnPageRate, 0.0f) ? index + 1 : index - 1);
683     if (endCurrentIndex == -1) {
684         endCurrentIndex = itemCount_ - 1;
685     } else if (endCurrentIndex >= itemCount_) {
686         if (isLoop_) {
687             endCurrentIndex = 0;
688         } else {
689             if (startCurrentIndex >= itemCount_) {
690                 startCurrentIndex = itemCount_ - 1;
691             }
692             endCurrentIndex = itemCount_ - 1;
693         }
694     }
695 
696     return { startCurrentIndex, endCurrentIndex };
697 }
698 
GetStartAndEndIndex(int32_t index)699 std::pair<int32_t, int32_t> DotIndicatorPaintMethod::GetStartAndEndIndex(int32_t index)
700 {
701     auto [startCurrentIndex, endCurrentIndex] = GetIndex(index);
702 
703     if (pointAnimationStage_ == PointAnimationStage::STATE_EXPAND_TO_LONG_POINT &&
704         gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT &&
705         touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT) {
706         endCurrentIndex = startCurrentIndex;
707         return { startCurrentIndex, endCurrentIndex };
708     } else if (pointAnimationStage_ == PointAnimationStage::STATE_EXPAND_TO_LONG_POINT &&
709                gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT &&
710                touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT) {
711         endCurrentIndex = startCurrentIndex = 0;
712         return { startCurrentIndex, endCurrentIndex };
713     }
714 
715     auto actualTurnPageRate = !isAutoLinear_ && isSwipeByGroup_ ? groupTurnPageRate_ : turnPageRate_;
716     if (touchBottomTypeLoop_ != TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_NONE && Negative(actualTurnPageRate)) {
717         if (std::abs(actualTurnPageRate) >= FIFTY_PERCENT) {
718             return { endCurrentIndex, endCurrentIndex };
719         }
720 
721         return { startCurrentIndex, startCurrentIndex };
722     }
723 
724     return { startCurrentIndex, endCurrentIndex };
725 }
726 
AdjustPointCenterXForTouchBottomNew(StarAndEndPointCenter & pointCenter,LinearVector<float> & endVectorBlackPointCenterX,int32_t endCurrentIndex,float selectedItemWidth)727 bool DotIndicatorPaintMethod::AdjustPointCenterXForTouchBottomNew(StarAndEndPointCenter& pointCenter,
728     LinearVector<float>& endVectorBlackPointCenterX, int32_t endCurrentIndex, float selectedItemWidth)
729 {
730     auto pageRate = std::abs(touchBottomPageRate_);
731     bool releaseLeftBottom = (gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT &&
732                               touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT);
733     bool releaseRightBottom = (gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT &&
734                                touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT);
735     if ((releaseLeftBottom && (!NearZero(touchBottomPageRate_) && pageRate <= FIFTY_PERCENT)) ||
736         (releaseRightBottom && (pageRate >= FIFTY_PERCENT || NearZero(pageRate)))) {
737         return true;
738     }
739 
740     bool dragLeftBottom = (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_LEFT &&
741                            touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT);
742     bool dragRightBottom = (gestureState_ == GestureState::GESTURE_STATE_FOLLOW_RIGHT &&
743                             touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT);
744     if (dragLeftBottom && (!NearZero(touchBottomPageRate_) && pageRate <= FIFTY_PERCENT)) {
745         pointCenter.startLongPointLeftCenterX = pointCenter.startLongPointRightCenterX =
746             endVectorBlackPointCenterX[endCurrentIndex];
747         pointCenter.endLongPointLeftCenterX =
748             endVectorBlackPointCenterX[endCurrentIndex] - selectedItemWidth / HALF_SELECTED_WIDTH;
749         pointCenter.endLongPointRightCenterX =
750             endVectorBlackPointCenterX[endCurrentIndex] + selectedItemWidth / HALF_SELECTED_WIDTH;
751         return true;
752     }
753 
754     if (dragRightBottom && pageRate >= FIFTY_PERCENT) {
755         pointCenter.startLongPointLeftCenterX = pointCenter.startLongPointRightCenterX = endVectorBlackPointCenterX[0];
756         pointCenter.endLongPointLeftCenterX = endVectorBlackPointCenterX[0] - selectedItemWidth / HALF_SELECTED_WIDTH;
757         pointCenter.endLongPointRightCenterX = endVectorBlackPointCenterX[0] + selectedItemWidth / HALF_SELECTED_WIDTH;
758         return true;
759     }
760 
761     return false;
762 }
763 
AdjustPointCenterXForTouchBottom(StarAndEndPointCenter & pointCenter,LinearVector<float> & endVectorBlackPointCenterX,int32_t startCurrentIndex,int32_t endCurrentIndex,float selectedItemWidth,int32_t index)764 void DotIndicatorPaintMethod::AdjustPointCenterXForTouchBottom(StarAndEndPointCenter& pointCenter,
765     LinearVector<float>& endVectorBlackPointCenterX, int32_t startCurrentIndex, int32_t endCurrentIndex,
766     float selectedItemWidth, int32_t index)
767 {
768     if (!isAutoLinear_ && isSwipeByGroup_ && !isLoop_) {
769         return;
770     }
771 
772     if (AdjustPointCenterXForTouchBottomNew(
773         pointCenter, endVectorBlackPointCenterX, endCurrentIndex, selectedItemWidth)) {
774         return;
775     }
776 
777     auto [startIndex, endIndex] = GetIndex(index);
778     if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT &&
779         pointAnimationStage_ != PointAnimationStage::STATE_EXPAND_TO_LONG_POINT &&
780         (!(endIndex == startIndex && startIndex != 0) ||
781             (gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT ||
782                 gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT))) {
783         pointCenter.endLongPointRightCenterX = pointCenter.endLongPointLeftCenterX = endVectorBlackPointCenterX[0];
784     } else if (touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT &&
785                pointAnimationStage_ != PointAnimationStage::STATE_EXPAND_TO_LONG_POINT) {
786         pointCenter.endLongPointRightCenterX = pointCenter.endLongPointLeftCenterX =
787             endVectorBlackPointCenterX[startCurrentIndex];
788     }
789 
790     if (pointAnimationStage_ == PointAnimationStage::STATE_EXPAND_TO_LONG_POINT &&
791         gestureState_ == GestureState::GESTURE_STATE_RELEASE_LEFT &&
792         touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_LEFT) {
793         pointCenter.startLongPointRightCenterX = endVectorBlackPointCenterX[endCurrentIndex];
794         pointCenter.endLongPointLeftCenterX =
795             endVectorBlackPointCenterX[endCurrentIndex] - (selectedItemWidth / HALF_SELECTED_WIDTH);
796     } else if (pointAnimationStage_ == PointAnimationStage::STATE_EXPAND_TO_LONG_POINT &&
797                gestureState_ == GestureState::GESTURE_STATE_RELEASE_RIGHT &&
798                touchBottomTypeLoop_ == TouchBottomTypeLoop::TOUCH_BOTTOM_TYPE_LOOP_RIGHT) {
799         pointCenter.startLongPointRightCenterX = endVectorBlackPointCenterX[0];
800         pointCenter.endLongPointLeftCenterX = endVectorBlackPointCenterX[0] - (selectedItemWidth / HALF_SELECTED_WIDTH);
801     }
802 }
803 
ForwardCalculation(const LinearVector<float> & itemHalfSizes,float startCenterX,float endCenterX,float space,int32_t index)804 std::pair<float, float> DotIndicatorPaintMethod::ForwardCalculation(
805     const LinearVector<float>& itemHalfSizes, float startCenterX, float endCenterX, float space, int32_t index)
806 {
807     auto itemWidth = itemHalfSizes[ITEM_HALF_WIDTH] * TWOFOLD;
808     auto selectedItemWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH] * TWOFOLD;
809     auto itemHalfWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
810     if (IsCustomSizeValue_) {
811         selectedItemWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
812         itemHalfWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH] * HALF_FLOAT;
813     }
814     StarAndEndPointCenter pointCenter;
815     // Calculate the data required for the current pages
816     LinearVector<float> startVectorBlackPointCenterX(itemCount_);
817     // Calculate the data required for subsequent pages
818     LinearVector<float> endVectorBlackPointCenterX(itemCount_);
819 
820     auto [startCurrentIndex, endCurrentIndex] = GetStartAndEndIndex(index);
821     startCurrentIndex = std::clamp(startCurrentIndex, 0, itemCount_ - 1);
822     endCurrentIndex = std::clamp(endCurrentIndex, 0, itemCount_ - 1);
823     for (int32_t i = 0; i < itemCount_; ++i) {
824         if (i != startCurrentIndex) {
825             startVectorBlackPointCenterX[i] = startCenterX + itemHalfSizes[ITEM_HALF_WIDTH];
826             startCenterX += itemWidth;
827         } else {
828             startVectorBlackPointCenterX[i] = startCenterX + selectedItemWidth;
829             pointCenter.startLongPointLeftCenterX = startCenterX + itemHalfWidth;
830             pointCenter.startLongPointRightCenterX = pointCenter.startLongPointLeftCenterX + selectedItemWidth;
831             startCenterX += selectedItemWidth * TWOFOLD;
832         }
833         if (i != endCurrentIndex) {
834             endVectorBlackPointCenterX[i] = endCenterX + itemHalfSizes[ITEM_HALF_WIDTH];
835             endCenterX += itemWidth;
836         } else {
837             endVectorBlackPointCenterX[i] = endCenterX + selectedItemWidth;
838             pointCenter.endLongPointLeftCenterX = endCenterX + itemHalfWidth;
839             pointCenter.endLongPointRightCenterX = pointCenter.endLongPointLeftCenterX + selectedItemWidth;
840             endCenterX += selectedItemWidth * TWOFOLD;
841         }
842         startCenterX += space;
843         endCenterX += space;
844     }
845     AdjustPointCenterXForTouchBottom(
846         pointCenter, endVectorBlackPointCenterX, startCurrentIndex, endCurrentIndex, selectedItemWidth, index);
847     return CalculatePointCenterX(pointCenter, startVectorBlackPointCenterX, endVectorBlackPointCenterX);
848 }
849 
BackwardCalculation(const LinearVector<float> & itemHalfSizes,float startCenterX,float endCenterX,float space,int32_t index)850 std::pair<float, float> DotIndicatorPaintMethod::BackwardCalculation(
851     const LinearVector<float>& itemHalfSizes, float startCenterX, float endCenterX, float space, int32_t index)
852 {
853     int32_t startCurrentIndex = index;
854     auto itemWidth = itemHalfSizes[ITEM_HALF_WIDTH] * TWOFOLD;
855     auto selectedItemWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH] * TWOFOLD;
856     auto itemHalfWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
857     if (IsCustomSizeValue_) {
858         selectedItemWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH];
859         itemHalfWidth = itemHalfSizes[SELECTED_ITEM_HALF_WIDTH] * HALF_FLOAT;
860     }
861     StarAndEndPointCenter pointCenter;
862     // Calculate the data required for the current pages
863     LinearVector<float> startVectorBlackPointCenterX(itemCount_);
864     // Calculate the data required for subsequent pages
865     LinearVector<float> endVectorBlackPointCenterX(itemCount_);
866     int32_t endCurrentIndex = NearEqual(turnPageRate_, 0.0f) || turnPageRate_ <= -1.0f || turnPageRate_ >= 1.0f
867         ? endCurrentIndex = index : (turnPageRate_ < 0.0f ? index + 1 : index - 1);
868     if (endCurrentIndex == -1) {
869         endCurrentIndex = itemCount_ - 1;
870     } else if (endCurrentIndex == itemCount_) {
871         endCurrentIndex = 0;
872     }
873     for (int32_t i = itemCount_ - 1; i >= 0; --i) {
874         if (i != startCurrentIndex) {
875             startVectorBlackPointCenterX[i] = startCenterX - itemHalfSizes[ITEM_HALF_WIDTH];
876             startCenterX -= itemWidth;
877         } else {
878             startVectorBlackPointCenterX[i] = startCenterX - itemHalfWidth;
879             pointCenter.startLongPointRightCenterX = startCenterX - itemHalfWidth;
880             pointCenter.startLongPointLeftCenterX = pointCenter.startLongPointRightCenterX - selectedItemWidth;
881             startCenterX -= selectedItemWidth * TWOFOLD;
882         }
883         if (i != endCurrentIndex) {
884             endVectorBlackPointCenterX[i] = endCenterX - itemHalfSizes[ITEM_HALF_WIDTH];
885             endCenterX -= itemWidth;
886         } else {
887             endVectorBlackPointCenterX[i] = endCenterX - itemHalfWidth;
888             pointCenter.endLongPointRightCenterX = endCenterX - itemHalfWidth;
889             pointCenter.endLongPointLeftCenterX = pointCenter.endLongPointRightCenterX - selectedItemWidth;
890             endCenterX -= selectedItemWidth * TWOFOLD;
891         }
892         startCenterX -= space;
893         endCenterX -= space;
894     }
895     return CalculatePointCenterX(pointCenter, startVectorBlackPointCenterX, endVectorBlackPointCenterX);
896 }
897 } // namespace OHOS::Ace::NG
898