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