1 /*
2 * Copyright (c) 2024 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/wrapper/menu_wrapper_paint_method.h"
16
17 #include "core/components/select/select_theme.h"
18 #include "core/components_ng/pattern/menu/menu_paint_property.h"
19 #include "core/components_ng/render/drawing_prop_convertor.h"
20 #include "core/components_ng/pattern/menu/menu_theme.h"
21 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.h"
22 #include "core/components_ng/render/drawing.h"
23 #include "core/components_ng/render/node_paint_method.h"
24 #include "core/components_ng/render/paint_wrapper.h"
25
26 namespace OHOS::Ace::NG {
27 namespace {
28 constexpr int32_t RADIUS_MIDPOINT = 2;
29 constexpr float BORDER_MULTIPLES = 2.0f;
30 constexpr Dimension ARROW_RADIUS = 2.0_vp;
31 constexpr Dimension ARROW_P1_OFFSET_X = 8.0_vp;
32 constexpr Dimension ARROW_P2_OFFSET_X = 1.5_vp;
33 constexpr Dimension ARROW_P1_OFFSET_Y = 8.0_vp;
34 constexpr Dimension ARROW_P2_OFFSET_Y = 0.68_vp;
35
GetMenuThemeFromPaintWrapper(PaintWrapper * paintWrapper)36 RefPtr<MenuTheme> GetMenuThemeFromPaintWrapper(PaintWrapper* paintWrapper)
37 {
38 CHECK_NULL_RETURN(paintWrapper, nullptr);
39 auto renderContext = paintWrapper->GetRenderContext();
40 CHECK_NULL_RETURN(renderContext, nullptr);
41 auto host = renderContext->GetHost();
42 CHECK_NULL_RETURN(host, nullptr);
43 auto pipelineContext = host->GetContextRefPtr();
44 CHECK_NULL_RETURN(pipelineContext, nullptr);
45 return pipelineContext->GetTheme<MenuTheme>();
46 }
47
GetMenuWrapperPatternFromPaintWrapper(PaintWrapper * paintWrapper)48 RefPtr<MenuWrapperPattern> GetMenuWrapperPatternFromPaintWrapper(PaintWrapper* paintWrapper)
49 {
50 CHECK_NULL_RETURN(paintWrapper, nullptr);
51 auto renderContext = paintWrapper->GetRenderContext();
52 CHECK_NULL_RETURN(renderContext, nullptr);
53 auto host = renderContext->GetHost();
54 CHECK_NULL_RETURN(host, nullptr);
55 return host->GetPattern<MenuWrapperPattern>();
56 }
57 }
58
GetOverlayDrawFunction(PaintWrapper * paintWrapper)59 CanvasDrawFunction MenuWrapperPaintMethod::GetOverlayDrawFunction(PaintWrapper* paintWrapper)
60 {
61 return [weak = WeakClaim(this), paintWrapper](RSCanvas& canvas) {
62 if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
63 return;
64 }
65 auto menuTheme = GetMenuThemeFromPaintWrapper(paintWrapper);
66 CHECK_NULL_VOID(menuTheme);
67 auto wrapperPattern = GetMenuWrapperPatternFromPaintWrapper(paintWrapper);
68 CHECK_NULL_VOID(wrapperPattern);
69 if (!menuTheme->GetDoubleBorderEnable() && !wrapperPattern->GetHasCustomOutlineWidth()) {
70 return;
71 }
72 auto paintMethod = weak.Upgrade();
73 if (paintMethod) {
74 paintMethod->PaintDoubleBorder(canvas, paintWrapper);
75 }
76 };
77 }
78
PaintDoubleBorder(RSCanvas & canvas,PaintWrapper * paintWrapper)79 void MenuWrapperPaintMethod::PaintDoubleBorder(RSCanvas& canvas, PaintWrapper* paintWrapper)
80 {
81 CHECK_NULL_VOID(paintWrapper);
82 auto renderContext = paintWrapper->GetRenderContext();
83 CHECK_NULL_VOID(renderContext);
84 auto host = renderContext->GetHost();
85 CHECK_NULL_VOID(host);
86 auto wrapperPattern = host->GetPattern<MenuWrapperPattern>();
87 CHECK_NULL_VOID(wrapperPattern);
88 if (wrapperPattern->GetMenuStatus() != MenuStatus::SHOW) {
89 return;
90 }
91 auto children = host->GetChildren();
92 if (children.empty()) {
93 return;
94 }
95 for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
96 auto& child = *iter;
97 if (!child || child->GetTag() != V2::MENU_ETS_TAG) {
98 continue;
99 }
100 auto frameNode = AceType::DynamicCast<FrameNode>(child);
101 CHECK_NULL_VOID(frameNode);
102 auto renderContext = frameNode->GetRenderContext();
103 CHECK_NULL_VOID(renderContext);
104 auto opacity = renderContext->GetOpacity().value_or(1.0);
105 if (!NearEqual(opacity, 1.0)) {
106 continue;
107 }
108 auto pattern = frameNode->GetPattern<MenuPattern>();
109 CHECK_NULL_VOID(pattern);
110 auto params = pattern->GetMenuPathParams();
111 if (params.has_value()) {
112 PaintInnerBorderAndClipSinglePath(canvas, paintWrapper, params.value());
113 PaintOuterBorderAndClipSinglePath(canvas, paintWrapper, params.value());
114 }
115 }
116 }
117
PaintInnerBorderAndClipSinglePath(RSCanvas & canvas,PaintWrapper * paintWrapper,const MenuPathParams & params)118 void MenuWrapperPaintMethod::PaintInnerBorderAndClipSinglePath(
119 RSCanvas& canvas, PaintWrapper* paintWrapper, const MenuPathParams& params)
120 {
121 RSPath rsPath;
122 BuildCompletePath(rsPath, params);
123 canvas.Save();
124 if (!params.didNeedArrow) {
125 canvas.ClipPath(rsPath, RSClipOp::DIFFERENCE, true);
126 return;
127 }
128 RSPen paint;
129 paint.SetAntiAlias(true);
130 auto menuTheme = GetMenuThemeFromPaintWrapper(paintWrapper);
131 CHECK_NULL_VOID(menuTheme);
132 // Because the canvas is cut by the ContentDrawFunction method, only half of the width can be drawn
133 paint.SetWidth(menuTheme->GetInnerBorderWidth() * BORDER_MULTIPLES);
134 paint.SetColor(menuTheme->GetInnerBorderColor().GetValue());
135 canvas.AttachPen(paint);
136 canvas.ClipPath(rsPath, RSClipOp::INTERSECT, true);
137 canvas.DrawPath(rsPath);
138 canvas.DetachPen();
139 canvas.Restore();
140 }
141
CanvasDrawOutline(RSCanvas & canvas,const RSPen & paint,const RSPath & rsPathEdge)142 void CanvasDrawOutline(RSCanvas& canvas, const RSPen& paint, const RSPath& rsPathEdge)
143 {
144 canvas.Save();
145 canvas.AttachPen(paint);
146 canvas.DrawPath(rsPathEdge);
147 canvas.DetachPen();
148 }
149
PaintEdgeOuterBorder(const MenuPathParams & params,RSCanvas & canvas,const MenuParam & menuParam)150 void MenuWrapperPaintMethod::PaintEdgeOuterBorder(
151 const MenuPathParams& params, RSCanvas& canvas, const MenuParam& menuParam)
152 {
153 RSPath rsPathTop;
154 RSPath rsPathRight;
155 RSPath rsPathBottom;
156 RSPath rsPathLeft;
157 RSPen paint;
158 paint.SetAntiAlias(true);
159 auto maxWidth =
160 std::max({ menuParam.outlineWidth->leftDimen->ConvertToPx(), menuParam.outlineWidth->topDimen->ConvertToPx(),
161 menuParam.outlineWidth->rightDimen->ConvertToPx(), menuParam.outlineWidth->bottomDimen->ConvertToPx() });
162 paint.SetWidth(maxWidth * BORDER_MULTIPLES);
163 rsPathTop.MoveTo(
164 params.childOffset.GetX() + params.radiusTopLeftPx - params.radiusTopLeftPx / sqrt(RADIUS_MIDPOINT),
165 params.childOffset.GetY() + params.radiusTopLeftPx - params.radiusTopLeftPx / sqrt(RADIUS_MIDPOINT));
166 BuildTopLinePath(rsPathTop, params);
167 paint.SetColor(menuParam.outlineColor->topColor->GetValue());
168 CanvasDrawOutline(canvas, paint, rsPathTop);
169
170 rsPathRight.MoveTo(params.childOffset.GetX() + params.frameSize.Width() - params.radiusTopRightPx +
171 params.radiusTopRightPx / sqrt(RADIUS_MIDPOINT),
172 params.childOffset.GetY() + params.radiusTopRightPx - params.radiusTopRightPx / sqrt(RADIUS_MIDPOINT));
173 BuildRightLinePath(rsPathRight, params);
174 paint.SetColor(menuParam.outlineColor->rightColor->GetValue());
175 CanvasDrawOutline(canvas, paint, rsPathRight);
176
177 rsPathBottom.MoveTo(params.childOffset.GetX() + params.frameSize.Width() - params.radiusBottomRightPx +
178 params.radiusBottomRightPx / sqrt(RADIUS_MIDPOINT),
179 params.childOffset.GetY() + params.frameSize.Height() - params.radiusBottomRightPx +
180 params.radiusBottomRightPx / sqrt(RADIUS_MIDPOINT));
181 BuildBottomLinePath(rsPathBottom, params);
182 paint.SetColor(menuParam.outlineColor->bottomColor->GetValue());
183 CanvasDrawOutline(canvas, paint, rsPathBottom);
184
185 rsPathLeft.MoveTo(
186 params.childOffset.GetX() + params.radiusBottomLeftPx - params.radiusBottomLeftPx / sqrt(RADIUS_MIDPOINT),
187 params.childOffset.GetY() + params.frameSize.Height() - params.radiusBottomLeftPx +
188 params.radiusBottomLeftPx / sqrt(RADIUS_MIDPOINT));
189 BuildLeftLinePath(rsPathLeft, params);
190 paint.SetColor(menuParam.outlineColor->leftColor->GetValue());
191 CanvasDrawOutline(canvas, paint, rsPathLeft);
192 }
193
PaintOuterBorderAndClipSinglePath(RSCanvas & canvas,PaintWrapper * paintWrapper,const MenuPathParams & params)194 void MenuWrapperPaintMethod::PaintOuterBorderAndClipSinglePath(
195 RSCanvas& canvas, PaintWrapper* paintWrapper, const MenuPathParams& params)
196 {
197 CHECK_NULL_VOID(paintWrapper);
198 auto wrapperPattern = GetMenuWrapperPatternFromPaintWrapper(paintWrapper);
199 CHECK_NULL_VOID(wrapperPattern);
200 RSPath rsPath;
201 MenuParam menuParam = wrapperPattern->GetMenuParam();
202 BuildCompletePath(rsPath, params);
203 canvas.Save();
204 if (!params.didNeedArrow) {
205 canvas.ClipPath(rsPath, RSClipOp::DIFFERENCE, true);
206 return;
207 }
208 RSPen paint;
209 paint.SetAntiAlias(true);
210 auto menuTheme = GetMenuThemeFromPaintWrapper(paintWrapper);
211 CHECK_NULL_VOID(menuTheme);
212 if (!wrapperPattern->GetHasCustomOutlineWidth()) {
213 paint.SetWidth(menuTheme->GetOuterBorderWidth() * BORDER_MULTIPLES);
214 paint.SetColor(menuTheme->GetOuterBorderColor().GetValue());
215 CanvasDrawOutline(canvas, paint, rsPath);
216 } else {
217 canvas.Save();
218 auto rsOutlinePath = BuildOutlinePath(params, menuParam);
219 canvas.ClipPath(rsOutlinePath, RSClipOp::INTERSECT, true);
220 canvas.ClipPath(rsPath, RSClipOp::DIFFERENCE, true);
221 PaintEdgeOuterBorder(params, canvas, menuParam);
222 }
223 }
224
BuildOutlinePath(const MenuPathParams & params,const MenuParam & menuParam)225 RSPath MenuWrapperPaintMethod::BuildOutlinePath(const MenuPathParams& params, const MenuParam& menuParam)
226 {
227 auto rsOutlineParam = params;
228 rsOutlineParam.childOffset.SetX(params.childOffset.GetX() - menuParam.outlineWidth->leftDimen->ConvertToPx());
229 rsOutlineParam.childOffset.SetY(params.childOffset.GetY() - menuParam.outlineWidth->topDimen->ConvertToPx());
230 rsOutlineParam.frameSize.SetWidth(params.frameSize.Width() + menuParam.outlineWidth->leftDimen->ConvertToPx() +
231 menuParam.outlineWidth->rightDimen->ConvertToPx());
232 rsOutlineParam.frameSize.SetHeight(params.frameSize.Height() + menuParam.outlineWidth->topDimen->ConvertToPx() +
233 menuParam.outlineWidth->bottomDimen->ConvertToPx());
234 arrowOutlineOffset_.top = menuParam.outlineWidth->topDimen->ConvertToPx();
235 arrowOutlineOffset_.left = menuParam.outlineWidth->leftDimen->ConvertToPx();
236 arrowOutlineOffset_.right = menuParam.outlineWidth->rightDimen->ConvertToPx();
237 arrowOutlineOffset_.bottom = menuParam.outlineWidth->bottomDimen->ConvertToPx();
238 RSPath rsOutlinePath;
239 BuildCompletePath(rsOutlinePath, rsOutlineParam);
240 arrowOutlineOffset_.Reset();
241 return rsOutlinePath;
242 }
243
BuildCompletePath(RSPath & rsPath,const MenuPathParams & params)244 void MenuWrapperPaintMethod::BuildCompletePath(RSPath& rsPath, const MenuPathParams& params)
245 {
246 rsPath.MoveTo(params.childOffset.GetX() + params.radiusTopLeftPx - params.radiusTopLeftPx / sqrt(RADIUS_MIDPOINT),
247 params.childOffset.GetY() + params.radiusTopLeftPx - params.radiusTopLeftPx / sqrt(RADIUS_MIDPOINT));
248 BuildTopLinePath(rsPath, params);
249 BuildRightLinePath(rsPath, params);
250 BuildBottomLinePath(rsPath, params);
251 BuildLeftLinePath(rsPath, params);
252 }
253
BuildTopLinePath(RSPath & rsPath,const MenuPathParams & params)254 void MenuWrapperPaintMethod::BuildTopLinePath(RSPath& rsPath, const MenuPathParams& params)
255 {
256 rsPath.ArcTo(params.radiusTopLeftPx, params.radiusTopLeftPx, 0.0f, RSPathDirection::CW_DIRECTION,
257 params.childOffset.GetX() + params.radiusTopLeftPx, params.childOffset.GetY());
258 if (params.didNeedArrow) {
259 switch (params.arrowPlacement) {
260 case Placement::BOTTOM:
261 case Placement::BOTTOM_LEFT:
262 case Placement::BOTTOM_RIGHT:
263 BuildBottomArrowPath(rsPath, params.arrowPosition.GetX(), params.arrowPosition.GetY());
264 break;
265 default:
266 break;
267 }
268 }
269 rsPath.LineTo(
270 params.childOffset.GetX() + params.frameSize.Width() - params.radiusTopRightPx, params.childOffset.GetY());
271 rsPath.ArcTo(params.radiusTopRightPx, params.radiusTopRightPx, 0.0f, RSPathDirection::CW_DIRECTION,
272 params.childOffset.GetX() + params.frameSize.Width() - params.radiusTopRightPx +
273 params.radiusTopRightPx / sqrt(RADIUS_MIDPOINT),
274 params.childOffset.GetY() + params.radiusTopRightPx - params.radiusTopRightPx / sqrt(RADIUS_MIDPOINT));
275 }
276
BuildRightLinePath(RSPath & rsPath,const MenuPathParams & params)277 void MenuWrapperPaintMethod::BuildRightLinePath(RSPath& rsPath, const MenuPathParams& params)
278 {
279 rsPath.ArcTo(params.radiusTopRightPx, params.radiusTopRightPx, 0.0f, RSPathDirection::CW_DIRECTION,
280 params.childOffset.GetX() + params.frameSize.Width(), params.childOffset.GetY() + params.radiusTopRightPx);
281 if (params.didNeedArrow) {
282 switch (params.arrowPlacement) {
283 case Placement::LEFT:
284 case Placement::LEFT_TOP:
285 case Placement::LEFT_BOTTOM:
286 BuildLeftArrowPath(rsPath, params.arrowPosition.GetX(), params.arrowPosition.GetY());
287 break;
288 default:
289 break;
290 }
291 }
292 rsPath.LineTo(params.childOffset.GetX() + params.frameSize.Width(),
293 params.childOffset.GetY() + params.frameSize.Height() - params.radiusBottomRightPx);
294 rsPath.ArcTo(params.radiusBottomRightPx, params.radiusBottomRightPx, 0.0f, RSPathDirection::CW_DIRECTION,
295 params.childOffset.GetX() + params.frameSize.Width() - params.radiusBottomRightPx +
296 params.radiusBottomRightPx / sqrt(RADIUS_MIDPOINT),
297 params.childOffset.GetY() + params.frameSize.Height() - params.radiusBottomRightPx +
298 params.radiusBottomRightPx / sqrt(RADIUS_MIDPOINT));
299 }
300
BuildBottomLinePath(RSPath & rsPath,const MenuPathParams & params)301 void MenuWrapperPaintMethod::BuildBottomLinePath(RSPath& rsPath, const MenuPathParams& params)
302 {
303 rsPath.ArcTo(params.radiusBottomRightPx, params.radiusBottomRightPx, 0.0f, RSPathDirection::CW_DIRECTION,
304 params.childOffset.GetX() + params.frameSize.Width() - params.radiusBottomRightPx,
305 params.childOffset.GetY() + params.frameSize.Height());
306 if (params.didNeedArrow) {
307 switch (params.arrowPlacement) {
308 case Placement::TOP:
309 case Placement::TOP_LEFT:
310 case Placement::TOP_RIGHT:
311 BuildTopArrowPath(rsPath, params.arrowPosition.GetX(), params.arrowPosition.GetY());
312 break;
313 default:
314 break;
315 }
316 }
317 rsPath.LineTo(
318 params.childOffset.GetX() + params.radiusBottomLeftPx, params.childOffset.GetY() + params.frameSize.Height());
319 rsPath.ArcTo(params.radiusBottomLeftPx, params.radiusBottomLeftPx, 0.0f, RSPathDirection::CW_DIRECTION,
320 params.childOffset.GetX() + params.radiusBottomLeftPx - params.radiusBottomLeftPx / sqrt(RADIUS_MIDPOINT),
321 params.childOffset.GetY() + params.frameSize.Height() - params.radiusBottomLeftPx +
322 params.radiusBottomLeftPx / sqrt(RADIUS_MIDPOINT));
323 }
324
BuildLeftLinePath(RSPath & rsPath,const MenuPathParams & params)325 void MenuWrapperPaintMethod::BuildLeftLinePath(RSPath& rsPath, const MenuPathParams& params)
326 {
327 rsPath.ArcTo(params.radiusBottomLeftPx, params.radiusBottomLeftPx, 0.0f, RSPathDirection::CW_DIRECTION,
328 params.childOffset.GetX(), params.childOffset.GetY() + params.frameSize.Height() - params.radiusBottomLeftPx);
329 if (params.didNeedArrow) {
330 switch (params.arrowPlacement) {
331 case Placement::RIGHT:
332 case Placement::RIGHT_TOP:
333 case Placement::RIGHT_BOTTOM:
334 BuildRightArrowPath(rsPath, params.arrowPosition.GetX(), params.arrowPosition.GetY());
335 break;
336 default:
337 break;
338 }
339 }
340 rsPath.LineTo(params.childOffset.GetX(), params.childOffset.GetY() + params.radiusTopLeftPx);
341 rsPath.ArcTo(params.radiusTopLeftPx, params.radiusTopLeftPx, 0.0f, RSPathDirection::CW_DIRECTION,
342 params.childOffset.GetX() + params.radiusTopLeftPx - params.radiusTopLeftPx / sqrt(RADIUS_MIDPOINT),
343 params.childOffset.GetY() + params.radiusTopLeftPx - params.radiusTopLeftPx / sqrt(RADIUS_MIDPOINT));
344 }
345
BuildBottomArrowPath(RSPath & rsPath,float arrowX,float arrowY)346 void MenuWrapperPaintMethod::BuildBottomArrowPath(RSPath& rsPath, float arrowX, float arrowY)
347 {
348 rsPath.LineTo(arrowX - ARROW_P1_OFFSET_X.ConvertToPx(),
349 arrowY + ARROW_P1_OFFSET_Y.ConvertToPx() - arrowOutlineOffset_.top); // P1
350 rsPath.LineTo(arrowX - ARROW_P2_OFFSET_X.ConvertToPx(),
351 arrowY + ARROW_P2_OFFSET_Y.ConvertToPx() - arrowOutlineOffset_.top); // P2
352 rsPath.ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, RSPathDirection::CW_DIRECTION,
353 arrowX + ARROW_P2_OFFSET_X.ConvertToPx(),
354 arrowY + ARROW_P2_OFFSET_Y.ConvertToPx() - arrowOutlineOffset_.top); // P4
355 rsPath.LineTo(arrowX + ARROW_P1_OFFSET_X.ConvertToPx(),
356 arrowY + ARROW_P1_OFFSET_Y.ConvertToPx() - arrowOutlineOffset_.top); // P5
357 }
358
BuildTopArrowPath(RSPath & rsPath,float arrowX,float arrowY)359 void MenuWrapperPaintMethod::BuildTopArrowPath(RSPath& rsPath, float arrowX, float arrowY)
360 {
361 rsPath.LineTo(arrowX + ARROW_P1_OFFSET_X.ConvertToPx(),
362 arrowY - ARROW_P1_OFFSET_Y.ConvertToPx() + arrowOutlineOffset_.bottom); // P1
363 rsPath.LineTo(arrowX + ARROW_P2_OFFSET_X.ConvertToPx(),
364 arrowY - ARROW_P2_OFFSET_Y.ConvertToPx() + arrowOutlineOffset_.bottom); // P2
365 rsPath.ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, RSPathDirection::CW_DIRECTION,
366 arrowX - ARROW_P2_OFFSET_X.ConvertToPx(),
367 arrowY - ARROW_P2_OFFSET_Y.ConvertToPx() + arrowOutlineOffset_.bottom); // P4
368 rsPath.LineTo(arrowX - ARROW_P1_OFFSET_X.ConvertToPx(),
369 arrowY - ARROW_P1_OFFSET_Y.ConvertToPx() + arrowOutlineOffset_.bottom); // P5
370 }
371
BuildRightArrowPath(RSPath & rsPath,float arrowX,float arrowY)372 void MenuWrapperPaintMethod::BuildRightArrowPath(RSPath& rsPath, float arrowX, float arrowY)
373 {
374 rsPath.LineTo(arrowX + ARROW_P1_OFFSET_Y.ConvertToPx() - arrowOutlineOffset_.left,
375 arrowY + ARROW_P1_OFFSET_X.ConvertToPx()); // P1
376 rsPath.LineTo(arrowX + ARROW_P2_OFFSET_Y.ConvertToPx() - arrowOutlineOffset_.left,
377 arrowY + ARROW_P2_OFFSET_X.ConvertToPx()); // P2
378 rsPath.ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, RSPathDirection::CW_DIRECTION,
379 arrowX + ARROW_P2_OFFSET_Y.ConvertToPx() - arrowOutlineOffset_.left,
380 arrowY - ARROW_P2_OFFSET_X.ConvertToPx()); // P4
381 rsPath.LineTo(arrowX + ARROW_P1_OFFSET_Y.ConvertToPx() - arrowOutlineOffset_.left,
382 arrowY - ARROW_P1_OFFSET_X.ConvertToPx()); // P5
383 }
384
BuildLeftArrowPath(RSPath & rsPath,float arrowX,float arrowY)385 void MenuWrapperPaintMethod::BuildLeftArrowPath(RSPath& rsPath, float arrowX, float arrowY)
386 {
387 rsPath.LineTo(arrowX - ARROW_P1_OFFSET_Y.ConvertToPx() + arrowOutlineOffset_.right,
388 arrowY - ARROW_P1_OFFSET_X.ConvertToPx()); // P1
389 rsPath.LineTo(arrowX - ARROW_P2_OFFSET_Y.ConvertToPx() + arrowOutlineOffset_.right,
390 arrowY - ARROW_P2_OFFSET_X.ConvertToPx()); // P2
391 rsPath.ArcTo(ARROW_RADIUS.ConvertToPx(), ARROW_RADIUS.ConvertToPx(), 0.0f, RSPathDirection::CW_DIRECTION,
392 arrowX - ARROW_P2_OFFSET_Y.ConvertToPx() + arrowOutlineOffset_.right,
393 arrowY + ARROW_P2_OFFSET_X.ConvertToPx()); // P4
394 rsPath.LineTo(arrowX - ARROW_P1_OFFSET_Y.ConvertToPx() + arrowOutlineOffset_.right,
395 arrowY + ARROW_P1_OFFSET_X.ConvertToPx()); // P5
396 }
397 } // namespace OHOS::Ace::NG
398