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 #include "core/components_ng/pattern/menu/menu_paint_method.h"
16
17 #include "base/utils/utils.h"
18 #include "core/components/select/select_theme.h"
19 #include "core/components_ng/layout/layout_algorithm.h"
20 #include "core/components_ng/pattern/menu/menu_paint_property.h"
21 #include "core/components_ng/pattern/menu/menu_theme.h"
22 #include "core/components_ng/render/canvas_image.h"
23 #include "core/components_ng/render/divider_painter.h"
24 #include "core/components_ng/render/drawing_prop_convertor.h"
25 #include "core/pipeline/pipeline_base.h"
26 #include "core/pipeline_ng/pipeline_context.h"
27
28 namespace OHOS::Ace::NG {
29 namespace {
30 constexpr Dimension BEZIER_HORIZON_OFFSET_FIRST = 1.3_vp;
31 constexpr Dimension BEZIER_HORIZON_OFFSET_SECOND = 3.2_vp;
32 constexpr Dimension BEZIER_HORIZON_OFFSET_THIRD = 6.6_vp;
33 constexpr Dimension BEZIER_HORIZON_OFFSET_FOURTH = 16.0_vp;
34 constexpr Dimension BEZIER_VERTICAL_OFFSET_FIRST = 0.1_vp;
35 constexpr Dimension BEZIER_VERTICAL_OFFSET_SECOND = 3.0_vp;
36 constexpr Dimension BEZIER_VERTICAL_OFFSET_THIRD = 8.0_vp;
37 } // namespace
38
GetTopPath(float arrowX,float arrowY,RSPath & path)39 void MenuPaintMethod::GetTopPath(float arrowX, float arrowY, RSPath& path)
40 {
41 path.MoveTo(arrowX - horizonOffsetForth_, arrowY - verticalOffsetThird_);
42 path.QuadTo(arrowX - horizonOffsetThird_, arrowY - verticalOffsetThird_, arrowX - horizonOffsetSecond_,
43 arrowY - verticalOffsetSecond_);
44 path.QuadTo(arrowX - horizonOffsetFirst_, arrowY + verticalOffsetFirst_, arrowX, arrowY);
45 path.QuadTo(arrowX + horizonOffsetFirst_, arrowY + verticalOffsetFirst_, arrowX + horizonOffsetSecond_,
46 arrowY - verticalOffsetSecond_);
47 path.QuadTo(arrowX + horizonOffsetThird_, arrowY - verticalOffsetThird_, arrowX + horizonOffsetForth_,
48 arrowY - verticalOffsetThird_);
49 }
50
GetBottomPath(float arrowX,float arrowY,RSPath & path)51 void MenuPaintMethod::GetBottomPath(float arrowX, float arrowY, RSPath& path)
52 {
53 path.MoveTo(arrowX - horizonOffsetForth_, arrowY + verticalOffsetThird_);
54 path.QuadTo(arrowX - horizonOffsetThird_, arrowY + verticalOffsetThird_, arrowX - horizonOffsetSecond_,
55 arrowY + verticalOffsetSecond_);
56 path.QuadTo(arrowX - horizonOffsetFirst_, arrowY - verticalOffsetFirst_, arrowX, arrowY);
57 path.QuadTo(arrowX + horizonOffsetFirst_, arrowY - verticalOffsetFirst_, arrowX + horizonOffsetSecond_,
58 arrowY + verticalOffsetSecond_);
59 path.QuadTo(arrowX + horizonOffsetThird_, arrowY + verticalOffsetThird_, arrowX + horizonOffsetForth_,
60 arrowY + verticalOffsetThird_);
61 }
62
GetRightPath(float arrowX,float arrowY,RSPath & path)63 void MenuPaintMethod::GetRightPath(float arrowX, float arrowY, RSPath& path)
64 {
65 path.MoveTo(arrowX + verticalOffsetThird_, arrowY - horizonOffsetForth_);
66 path.QuadTo(arrowX + verticalOffsetThird_, arrowY - horizonOffsetThird_, arrowX + verticalOffsetSecond_,
67 arrowY - horizonOffsetSecond_);
68 path.QuadTo(arrowX - verticalOffsetFirst_, arrowY - horizonOffsetFirst_, arrowX, arrowY);
69 path.QuadTo(arrowX - verticalOffsetFirst_, arrowY + horizonOffsetFirst_, arrowX + verticalOffsetSecond_,
70 arrowY + horizonOffsetSecond_);
71 path.QuadTo(arrowX + verticalOffsetThird_, arrowY + horizonOffsetThird_, arrowX + verticalOffsetThird_,
72 arrowY + horizonOffsetForth_);
73 }
74
GetLeftPath(float arrowX,float arrowY,RSPath & path)75 void MenuPaintMethod::GetLeftPath(float arrowX, float arrowY, RSPath& path)
76 {
77 path.MoveTo(arrowX - verticalOffsetThird_, arrowY - horizonOffsetForth_);
78 path.QuadTo(arrowX - verticalOffsetThird_, arrowY - horizonOffsetThird_, arrowX - verticalOffsetSecond_,
79 arrowY - horizonOffsetSecond_);
80 path.QuadTo(arrowX + verticalOffsetFirst_, arrowY - horizonOffsetFirst_, arrowX, arrowY);
81 path.QuadTo(arrowX + verticalOffsetFirst_, arrowY + horizonOffsetFirst_, arrowX - verticalOffsetSecond_,
82 arrowY + horizonOffsetSecond_);
83 path.QuadTo(arrowX - verticalOffsetThird_, arrowY + horizonOffsetThird_, arrowX - verticalOffsetThird_,
84 arrowY + horizonOffsetForth_);
85 }
86
UpdateArrowPath(Placement placement,float arrowX,float arrowY,RSPath & path)87 void MenuPaintMethod::UpdateArrowPath(Placement placement, float arrowX, float arrowY, RSPath& path)
88 {
89 horizonOffsetFirst_ = BEZIER_HORIZON_OFFSET_FIRST.ConvertToPx();
90 horizonOffsetSecond_ = BEZIER_HORIZON_OFFSET_SECOND.ConvertToPx();
91 horizonOffsetThird_ = BEZIER_HORIZON_OFFSET_THIRD.ConvertToPx();
92 horizonOffsetForth_ = BEZIER_HORIZON_OFFSET_FOURTH.ConvertToPx();
93 verticalOffsetFirst_ = BEZIER_VERTICAL_OFFSET_FIRST.ConvertToPx();
94 verticalOffsetSecond_ = BEZIER_VERTICAL_OFFSET_SECOND.ConvertToPx();
95 verticalOffsetThird_ = BEZIER_VERTICAL_OFFSET_THIRD.ConvertToPx();
96 switch (placement) {
97 case Placement::TOP:
98 case Placement::TOP_LEFT:
99 case Placement::TOP_RIGHT:
100 GetTopPath(arrowX, arrowY, path);
101 break;
102 case Placement::BOTTOM:
103 case Placement::BOTTOM_LEFT:
104 case Placement::BOTTOM_RIGHT:
105 GetBottomPath(arrowX, arrowY, path);
106 break;
107 case Placement::RIGHT:
108 case Placement::RIGHT_BOTTOM:
109 case Placement::RIGHT_TOP:
110 GetRightPath(arrowX, arrowY, path);
111 break;
112 case Placement::LEFT:
113 case Placement::LEFT_BOTTOM:
114 case Placement::LEFT_TOP:
115 GetLeftPath(arrowX, arrowY, path);
116 break;
117 default:
118 break;
119 }
120 }
121
GetOverlayDrawFunction(PaintWrapper * paintWrapper)122 CanvasDrawFunction MenuPaintMethod::GetOverlayDrawFunction(PaintWrapper* paintWrapper)
123 {
124 return [weak = WeakClaim(this), paintWrapper](RSCanvas& canvas) {
125 auto menu = weak.Upgrade();
126 if (menu) {
127 auto props = DynamicCast<MenuPaintProperty>(paintWrapper->GetPaintProperty());
128 CHECK_NULL_VOID(props);
129 if (props->GetEnableArrow().has_value()) {
130 if (!props->GetEnableArrow().value() || !props->GetArrowPosition().has_value() ||
131 !props->GetArrowPlacement().has_value()) {
132 return;
133 }
134 auto arrowPosition = props->GetArrowPosition().value();
135 auto arrowPlaceMent = props->GetArrowPlacement().value();
136 auto arrowX = arrowPosition.GetX();
137 auto arrowY = arrowPosition.GetY();
138 RSPath path;
139 menu->UpdateArrowPath(arrowPlaceMent, arrowX, arrowY, path);
140 RSBrush brush;
141 auto pipeline = PipelineBase::GetCurrentContext();
142 CHECK_NULL_VOID(pipeline);
143 auto selectTheme = pipeline->GetTheme<SelectTheme>();
144 CHECK_NULL_VOID(selectTheme);
145 auto backgroundColor = selectTheme->GetBackgroundColor();
146 brush.SetColor(static_cast<int>(backgroundColor.GetValue()));
147 brush.SetAntiAlias(true);
148 canvas.AttachBrush(brush);
149 canvas.DrawPath(path);
150 canvas.DetachBrush();
151 }
152 }
153 };
154 }
155 } // namespace OHOS::Ace::NG
156