• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/pattern/slider/slider_tip_modifier.h"
17 
18 #include "base/geometry/ng/offset_t.h"
19 #include "core/components_ng/render/drawing_prop_convertor.h"
20 
21 namespace OHOS::Ace::NG {
22 namespace {
23 constexpr Dimension BEZIER_HORIZON_OFFSET_FIRST = 1.3_vp;
24 constexpr Dimension BEZIER_HORIZON_OFFSET_SECOND = 3.2_vp;
25 constexpr Dimension BEZIER_HORIZON_OFFSET_THIRD = 6.6_vp;
26 constexpr Dimension BEZIER_HORIZON_OFFSET_FOURTH = 16.0_vp;
27 constexpr Dimension BEZIER_VERTICAL_OFFSET_FIRST = 0.1_vp;
28 constexpr Dimension BEZIER_VERTICAL_OFFSET_SECOND = 3.0_vp;
29 constexpr Dimension BEZIER_VERTICAL_OFFSET_THIRD = 8.0_vp;
30 constexpr Dimension ARROW_HEIGHT = 8.0_vp;
31 constexpr float HALF = 0.5f;
32 } // namespace
33 
SliderTipModifier()34 SliderTipModifier::SliderTipModifier()
35     : tipFlag_(AceType::MakeRefPtr<PropertyBool>(false)),
36       contentOffset_(AceType::MakeRefPtr<PropertyOffsetF>(OffsetF())),
37       bubbleSize_(AceType::MakeRefPtr<PropertySizeF>(SizeF())),
38       bubbleOffset_(AceType::MakeRefPtr<PropertyOffsetF>(OffsetF())),
39       textOffset_(AceType::MakeRefPtr<PropertyOffsetF>(OffsetF()))
40 {
41     AttachProperty(tipFlag_);
42     AttachProperty(contentOffset_);
43     AttachProperty(bubbleSize_);
44     AttachProperty(bubbleOffset_);
45     AttachProperty(textOffset_);
46 }
47 
PaintTip(DrawingContext & context)48 void SliderTipModifier::PaintTip(DrawingContext& context)
49 {
50     auto textOffset = textOffset_->Get() + contentOffset_->Get();
51     PaintBubble(context);
52     CHECK_NULL_VOID(paragraph_);
53     paragraph_->Paint(context.canvas, textOffset.GetX(), textOffset.GetY());
54 }
55 
PaintBezier(bool isLeft,Axis axis,RSPath & path,const OffsetF & arrowCenter,const OffsetF & arrowEdge)56 void PaintBezier(bool isLeft, Axis axis, RSPath& path, const OffsetF& arrowCenter, const OffsetF& arrowEdge)
57 {
58     if (isLeft) {
59         path.MoveTo(arrowCenter.GetX(), arrowCenter.GetY());
60         if (axis == Axis::HORIZONTAL) {
61             path.QuadTo(arrowCenter.GetX() - static_cast<float>(BEZIER_HORIZON_OFFSET_FIRST.ConvertToPx()),
62                 arrowCenter.GetY() + static_cast<float>(BEZIER_VERTICAL_OFFSET_FIRST.ConvertToPx()),
63                 arrowCenter.GetX() - static_cast<float>(BEZIER_HORIZON_OFFSET_SECOND.ConvertToPx()),
64                 arrowCenter.GetY() - static_cast<float>(BEZIER_VERTICAL_OFFSET_SECOND.ConvertToPx()));
65             path.QuadTo(arrowCenter.GetX() - static_cast<float>(BEZIER_HORIZON_OFFSET_THIRD.ConvertToPx()),
66                 arrowCenter.GetY() - static_cast<float>(BEZIER_VERTICAL_OFFSET_THIRD.ConvertToPx()),
67                 arrowCenter.GetX() - static_cast<float>(BEZIER_HORIZON_OFFSET_FOURTH.ConvertToPx()),
68                 arrowCenter.GetY() - static_cast<float>(BEZIER_VERTICAL_OFFSET_THIRD.ConvertToPx()));
69         } else {
70             path.QuadTo(arrowCenter.GetX() + static_cast<float>(BEZIER_VERTICAL_OFFSET_FIRST.ConvertToPx()),
71                 arrowCenter.GetY() + static_cast<float>(BEZIER_HORIZON_OFFSET_FIRST.ConvertToPx()),
72                 arrowCenter.GetX() - static_cast<float>(BEZIER_VERTICAL_OFFSET_SECOND.ConvertToPx()),
73                 arrowCenter.GetY() + static_cast<float>(BEZIER_HORIZON_OFFSET_SECOND.ConvertToPx()));
74             path.QuadTo(arrowCenter.GetX() - static_cast<float>(BEZIER_VERTICAL_OFFSET_THIRD.ConvertToPx()),
75                 arrowCenter.GetY() + static_cast<float>(BEZIER_HORIZON_OFFSET_THIRD.ConvertToPx()),
76                 arrowCenter.GetX() - static_cast<float>(BEZIER_VERTICAL_OFFSET_THIRD.ConvertToPx()),
77                 arrowCenter.GetY() + static_cast<float>(BEZIER_HORIZON_OFFSET_FOURTH.ConvertToPx()));
78         }
79         path.LineTo(arrowEdge.GetX(), arrowEdge.GetY());
80     } else {
81         path.MoveTo(arrowEdge.GetX(), arrowEdge.GetY());
82         if (axis == Axis::HORIZONTAL) {
83             path.LineTo(arrowCenter.GetX() + static_cast<float>(BEZIER_HORIZON_OFFSET_FOURTH.ConvertToPx()),
84                 arrowCenter.GetY() - static_cast<float>(BEZIER_VERTICAL_OFFSET_THIRD.ConvertToPx()));
85             path.QuadTo(arrowCenter.GetX() + static_cast<float>(BEZIER_HORIZON_OFFSET_THIRD.ConvertToPx()),
86                 arrowCenter.GetY() - static_cast<float>(BEZIER_VERTICAL_OFFSET_THIRD.ConvertToPx()),
87                 arrowCenter.GetX() + static_cast<float>(BEZIER_HORIZON_OFFSET_SECOND.ConvertToPx()),
88                 arrowCenter.GetY() - static_cast<float>(BEZIER_VERTICAL_OFFSET_SECOND.ConvertToPx()));
89             path.QuadTo(arrowCenter.GetX() + static_cast<float>(BEZIER_HORIZON_OFFSET_FIRST.ConvertToPx()),
90                 arrowCenter.GetY() + static_cast<float>(BEZIER_VERTICAL_OFFSET_FIRST.ConvertToPx()), arrowCenter.GetX(),
91                 arrowCenter.GetY());
92         } else {
93             path.LineTo(arrowCenter.GetX() - static_cast<float>(BEZIER_VERTICAL_OFFSET_THIRD.ConvertToPx()),
94                 arrowCenter.GetY() - static_cast<float>(BEZIER_HORIZON_OFFSET_FOURTH.ConvertToPx()));
95             path.QuadTo(arrowCenter.GetX() - static_cast<float>(BEZIER_VERTICAL_OFFSET_THIRD.ConvertToPx()),
96                 arrowCenter.GetY() - static_cast<float>(BEZIER_HORIZON_OFFSET_THIRD.ConvertToPx()),
97                 arrowCenter.GetX() - static_cast<float>(BEZIER_VERTICAL_OFFSET_SECOND.ConvertToPx()),
98                 arrowCenter.GetY() - static_cast<float>(BEZIER_HORIZON_OFFSET_SECOND.ConvertToPx()));
99             path.QuadTo(arrowCenter.GetX() + static_cast<float>(BEZIER_VERTICAL_OFFSET_FIRST.ConvertToPx()),
100                 arrowCenter.GetY() - static_cast<float>(BEZIER_HORIZON_OFFSET_FIRST.ConvertToPx()), arrowCenter.GetX(),
101                 arrowCenter.GetY());
102         }
103     }
104 }
105 
PaintBubble(DrawingContext & context)106 void SliderTipModifier::PaintBubble(DrawingContext& context)
107 {
108     auto contentOffset = contentOffset_->Get();
109     auto offset = bubbleOffset_->Get() + contentOffset;
110     auto bubbleSize = bubbleSize_->Get();
111     auto arrowHeight = static_cast<float>(ARROW_HEIGHT.ConvertToPx());
112     RSPath path;
113     OffsetF arrowCenter;
114     OffsetF clockwiseFirstPoint;
115     OffsetF clockwiseSecondPoint;
116     float circularRadius = 0.0f;
117     OffsetF clockwiseThirdPoint;
118     OffsetF clockwiseFourthPoint;
119     if (axis_ == Axis::HORIZONTAL) {
120         arrowCenter = { offset.GetX() + bubbleSize.Width() * HALF, offset.GetY() + bubbleSize.Height() };
121         float bottomLineLength = bubbleSize.Width() - (bubbleSize.Height() - arrowHeight);
122         clockwiseFirstPoint = { arrowCenter.GetX() - bottomLineLength * HALF, arrowCenter.GetY() - arrowHeight };
123         clockwiseSecondPoint = { clockwiseFirstPoint.GetX(), offset.GetY() };
124         circularRadius = (clockwiseFirstPoint.GetY() - clockwiseSecondPoint.GetY()) * HALF;
125         clockwiseThirdPoint = { clockwiseSecondPoint.GetX() + bottomLineLength, clockwiseSecondPoint.GetY() };
126         clockwiseFourthPoint = { clockwiseThirdPoint.GetX(), offset.GetY() + circularRadius * 2 };
127     } else {
128         arrowCenter = { offset.GetX() + bubbleSize.Width(), offset.GetY() + bubbleSize.Height() * HALF };
129         float bottomLineLength = bubbleSize.Height() - (bubbleSize.Width() - arrowHeight);
130         clockwiseFirstPoint = { arrowCenter.GetX() - arrowHeight, arrowCenter.GetY() + bottomLineLength * HALF };
131         clockwiseSecondPoint = { offset.GetX(), clockwiseFirstPoint.GetY() };
132         circularRadius = (clockwiseFirstPoint.GetX() - clockwiseSecondPoint.GetX()) * HALF;
133         clockwiseThirdPoint = { clockwiseSecondPoint.GetX(), clockwiseSecondPoint.GetY() - bottomLineLength };
134         clockwiseFourthPoint = { offset.GetX() + circularRadius * 2, clockwiseThirdPoint.GetY() };
135     }
136     path.MoveTo(arrowCenter.GetX(), arrowCenter.GetY());
137     PaintBezier(
138         true, axis_, path, arrowCenter, clockwiseFirstPoint);
139     path.ArcTo(circularRadius, circularRadius, 0.0f, RSPathDirection::CW_DIRECTION, clockwiseSecondPoint.GetX(),
140         clockwiseSecondPoint.GetY());
141     path.LineTo(clockwiseThirdPoint.GetX(), clockwiseThirdPoint.GetY());
142     path.ArcTo(circularRadius, circularRadius, 0.0f, RSPathDirection::CW_DIRECTION, clockwiseFourthPoint.GetX(),
143         clockwiseFourthPoint.GetY());
144     PaintBezier(
145         false, axis_, path, arrowCenter, clockwiseFourthPoint);
146     RSPen pen;
147     pen.SetColor(ToRSColor(tipColor_));
148     pen.SetAntiAlias(true);
149     RSBrush brush;
150     brush.SetColor(ToRSColor(tipColor_));
151     auto& canvas = context.canvas;
152     canvas.AttachPen(pen);
153     canvas.AttachBrush(brush);
154     canvas.DrawPath(path);
155     canvas.ClipPath(path, RSClipOp::INTERSECT);
156 }
157 } // namespace OHOS::Ace::NG
158