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