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/select_overlay/select_overlay_content_modifier.h"
17
18 #include "core/components/common/properties/color.h"
19 #include "core/components/text_overlay/text_overlay_theme.h"
20 #include "core/components_ng/pattern/select_overlay/select_overlay_pattern.h"
21 #include "core/components_ng/render/drawing.h"
22
23 namespace OHOS::Ace::NG {
24 namespace {
25 constexpr float VIEW_PORT_MODIFICATION_VALUE = 1.0f;
26 }
SelectOverlayContentModifier(const WeakPtr<Pattern> & pattern)27 SelectOverlayContentModifier::SelectOverlayContentModifier(const WeakPtr<Pattern>& pattern)
28 : inShowArea_(AceType::MakeRefPtr<PropertyBool>(false)),
29 handleReverse_(AceType::MakeRefPtr<PropertyBool>(false)),
30 isSingleHandle_(AceType::MakeRefPtr<PropertyBool>(false)),
31 firstHandleIsShow_(AceType::MakeRefPtr<PropertyBool>(false)),
32 firstCircleIsShow_(AceType::MakeRefPtr<PropertyBool>(true)),
33 secondHandleIsShow_(AceType::MakeRefPtr<PropertyBool>(false)),
34 secondCircleIsShow_(AceType::MakeRefPtr<PropertyBool>(true)),
35 isHiddenHandle_(AceType::MakeRefPtr<PropertyBool>(false)),
36 isHandleLineShow_(AceType::MakeRefPtr<PropertyBool>(false)),
37 viewPort_(AceType::MakeRefPtr<PropertyRectF>(RectF(0, 0, 0, 0))),
38 firstHandle_(AceType::MakeRefPtr<PropertyRectF>(RectF(0, 0, 0, 0))),
39 secondHandle_(AceType::MakeRefPtr<PropertyRectF>(RectF(0, 0, 0, 0))),
40 handleColor_(AceType::MakeRefPtr<PropertyColor>(Color::BLACK)),
41 innerHandleColor_(AceType::MakeRefPtr<PropertyColor>(Color::BLACK)),
42 handleRadius_(AceType::MakeRefPtr<PropertyFloat>(0.0)),
43 handleStrokeWidth_(AceType::MakeRefPtr<PropertyFloat>(0.0)),
44 innerHandleRadius_(AceType::MakeRefPtr<PropertyFloat>(0.0)),
45 handleOpacity_(AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0)),
46 pattern_(pattern)
47 {
48 AttachProperty(inShowArea_);
49 AttachProperty(handleReverse_);
50 AttachProperty(isSingleHandle_);
51 AttachProperty(firstHandleIsShow_);
52 AttachProperty(firstCircleIsShow_);
53 AttachProperty(secondHandleIsShow_);
54 AttachProperty(secondCircleIsShow_);
55 AttachProperty(isHiddenHandle_);
56 AttachProperty(isHandleLineShow_);
57 AttachProperty(viewPort_);
58 AttachProperty(firstHandle_);
59 AttachProperty(secondHandle_);
60 AttachProperty(handleColor_);
61 AttachProperty(innerHandleColor_);
62 AttachProperty(handleRadius_);
63 AttachProperty(handleStrokeWidth_);
64 AttachProperty(innerHandleRadius_);
65 AttachProperty(handleOpacity_);
66 }
67
onDraw(DrawingContext & drawingContext)68 void SelectOverlayContentModifier::onDraw(DrawingContext& drawingContext)
69 {
70 CHECK_NULL_VOID(!isUsingMouse_);
71 CHECK_NULL_VOID(isHiddenHandle_);
72 if (isHiddenHandle_->Get()) {
73 return;
74 }
75
76 CHECK_NULL_VOID(inShowArea_);
77 if (!inShowArea_->Get()) {
78 return;
79 }
80
81 auto& canvas = drawingContext.canvas;
82 canvas.Save();
83 ClipViewPort(canvas);
84
85 CHECK_NULL_VOID(isSingleHandle_);
86 if (isSingleHandle_->Get()) {
87 PaintSingleHandle(canvas);
88 } else {
89 PaintDoubleHandle(canvas);
90 }
91
92 canvas.Restore();
93 }
94
PaintSingleHandle(RSCanvas & canvas)95 void SelectOverlayContentModifier::PaintSingleHandle(RSCanvas& canvas)
96 {
97 if (PaintSingleHandleWithPoints(canvas)) {
98 return;
99 }
100 PaintSingleHandleWithRect(canvas);
101 }
102
CalculateCenterPoint(const OffsetF & start,const OffsetF & end,float radius,bool handleOnTop)103 OffsetF SelectOverlayContentModifier::CalculateCenterPoint(
104 const OffsetF& start, const OffsetF& end, float radius, bool handleOnTop)
105 {
106 float vectorX = end.GetX() - start.GetX();
107 float vectorY = end.GetY() - start.GetY();
108 if (handleOnTop) {
109 vectorX = -vectorX;
110 vectorY = -vectorY;
111 }
112 float vectorLen = std::sqrt(vectorX * vectorX + vectorY * vectorY);
113 float unitVectorX = NearZero(vectorLen) ? 0.0f : vectorX / vectorLen;
114 float unitVectorY = NearZero(vectorLen) ? 0.0f : vectorY / vectorLen;
115 float extendedVectorX = unitVectorX * radius;
116 float extendedVectorY = unitVectorY * radius;
117 float centerX = handleOnTop ? start.GetX() + extendedVectorX : end.GetX() + extendedVectorX;
118 float centerY = handleOnTop ? start.GetY() + extendedVectorY : end.GetY() + extendedVectorY;
119 return OffsetF(centerX, centerY);
120 }
121
PaintSingleHandleWithPoints(RSCanvas & canvas)122 bool SelectOverlayContentModifier::PaintSingleHandleWithPoints(RSCanvas& canvas)
123 {
124 CHECK_NULL_RETURN(isPaintHandleUsePoints_, false);
125
126 CHECK_NULL_RETURN(firstHandleIsShow_, false);
127 CHECK_NULL_RETURN(secondHandleIsShow_, false);
128 CHECK_NULL_RETURN(isHandleLineShow_, false);
129
130 if (firstHandleIsShow_->Get()) {
131 CHECK_NULL_RETURN(firstCircleIsShow_, false);
132 auto startPoint = firstHandlePaintInfo_.startPoint;
133 startPoint.SetY(startPoint.GetY() + 1.0f);
134 auto centerOffset = CalculateCenterPoint(
135 firstHandlePaintInfo_.startPoint, firstHandlePaintInfo_.endPoint, GetDrawHandleRadius(), false);
136 HandleDrawInfo drawInfo = {
137 .startPoint = startPoint - centerOffset,
138 .endPoint = firstHandlePaintInfo_.endPoint - centerOffset,
139 .centerOffset = centerOffset,
140 .handleWidth = firstHandlePaintInfo_.width,
141 .isHandleLineShow = isHandleLineShow_->Get(),
142 .isCircleShow = firstCircleIsShow_->Get()
143 };
144 PaintHandle(canvas, drawInfo);
145 }
146 if (secondHandleIsShow_->Get()) {
147 CHECK_NULL_RETURN(secondCircleIsShow_, false);
148 auto startPoint = secondHandlePaintInfo_.startPoint;
149 startPoint.SetY(startPoint.GetY() + 1.0f);
150 auto centerOffset = CalculateCenterPoint(
151 secondHandlePaintInfo_.startPoint, secondHandlePaintInfo_.endPoint, GetDrawHandleRadius(), false);
152 HandleDrawInfo drawInfo = {
153 .startPoint = startPoint - centerOffset,
154 .endPoint = secondHandlePaintInfo_.endPoint - centerOffset,
155 .centerOffset = centerOffset,
156 .handleWidth = secondHandlePaintInfo_.width,
157 .isHandleLineShow = isHandleLineShow_->Get(),
158 .isCircleShow = secondCircleIsShow_->Get()
159 };
160 PaintHandle(canvas, drawInfo);
161 }
162 return true;
163 }
164
PaintSingleHandleWithRect(RSCanvas & canvas)165 void SelectOverlayContentModifier::PaintSingleHandleWithRect(RSCanvas& canvas)
166 {
167 CHECK_NULL_VOID(firstHandleIsShow_);
168 CHECK_NULL_VOID(secondHandleIsShow_);
169 CHECK_NULL_VOID(isHandleLineShow_);
170 if (firstHandleIsShow_->Get()) {
171 CHECK_NULL_VOID(firstHandle_);
172 CHECK_NULL_VOID(firstCircleIsShow_);
173 PaintHandle(canvas, firstHandle_->Get(), false,
174 { isHandleLineShow_->Get(), firstCircleIsShow_->Get(), IsDraggingHandle(true) });
175 return;
176 }
177 if (secondHandleIsShow_->Get() || isClipHandleDrawRect_) {
178 CHECK_NULL_VOID(secondHandle_);
179 CHECK_NULL_VOID(secondCircleIsShow_);
180 PaintHandle(canvas, secondHandle_->Get(), false,
181 { isHandleLineShow_->Get(), secondCircleIsShow_->Get(), IsDraggingHandle(false) });
182 }
183 }
184
PaintDoubleHandle(RSCanvas & canvas)185 void SelectOverlayContentModifier::PaintDoubleHandle(RSCanvas& canvas)
186 {
187 if (PaintDoubleHandleWithPoint(canvas)) {
188 return;
189 }
190 PaintDoubleHandleWithRect(canvas);
191 }
192
PaintDoubleHandleWithPoint(RSCanvas & canvas)193 bool SelectOverlayContentModifier::PaintDoubleHandleWithPoint(RSCanvas& canvas)
194 {
195 CHECK_NULL_RETURN(isPaintHandleUsePoints_, false);
196
197 CHECK_NULL_RETURN(firstHandleIsShow_, false);
198 CHECK_NULL_RETURN(secondHandleIsShow_, false);
199 CHECK_NULL_RETURN(handleReverse_, false);
200 if (firstHandleIsShow_->Get()) {
201 CHECK_NULL_RETURN(firstCircleIsShow_, false);
202 auto handleOnTop = !handleReverse_->Get();
203 auto centerOffset = CalculateCenterPoint(
204 firstHandlePaintInfo_.startPoint, firstHandlePaintInfo_.endPoint, GetDrawHandleRadius(), handleOnTop);
205 auto offsetY = handleOnTop ? -1.0f : 1.0f;
206 auto startPoint = firstHandlePaintInfo_.startPoint;
207 startPoint.SetY(startPoint.GetY() + offsetY);
208 HandleDrawInfo drawInfo = {
209 .startPoint = startPoint - centerOffset,
210 .endPoint = firstHandlePaintInfo_.endPoint - centerOffset,
211 .centerOffset = centerOffset,
212 .handleWidth = firstHandlePaintInfo_.width,
213 .isCircleShow = firstCircleIsShow_->Get()
214 };
215 PaintHandle(canvas, drawInfo);
216 }
217 if (secondHandleIsShow_->Get()) {
218 CHECK_NULL_RETURN(secondCircleIsShow_, false);
219 auto handleOnTop = handleReverse_->Get();
220 auto centerOffset = CalculateCenterPoint(
221 secondHandlePaintInfo_.startPoint, secondHandlePaintInfo_.endPoint, GetDrawHandleRadius(), handleOnTop);
222 auto offsetY = handleOnTop ? -1.0f : 1.0f;
223 auto startPoint = secondHandlePaintInfo_.startPoint;
224 startPoint.SetY(startPoint.GetY() + offsetY);
225 HandleDrawInfo drawInfo = {
226 .startPoint = startPoint - centerOffset,
227 .endPoint = secondHandlePaintInfo_.endPoint - centerOffset,
228 .centerOffset = centerOffset,
229 .handleWidth = secondHandlePaintInfo_.width,
230 .isCircleShow = secondCircleIsShow_->Get()
231 };
232 PaintHandle(canvas, drawInfo);
233 }
234 return true;
235 }
236
PaintDoubleHandleWithRect(RSCanvas & canvas)237 void SelectOverlayContentModifier::PaintDoubleHandleWithRect(RSCanvas& canvas)
238 {
239 CHECK_NULL_VOID(firstHandleIsShow_);
240 CHECK_NULL_VOID(secondHandleIsShow_);
241 CHECK_NULL_VOID(handleReverse_);
242 if (firstHandleIsShow_->Get() || isClipHandleDrawRect_) {
243 CHECK_NULL_VOID(firstHandle_);
244 CHECK_NULL_VOID(firstCircleIsShow_);
245 PaintHandle(canvas, firstHandle_->Get(), !handleReverse_->Get(),
246 { true, firstCircleIsShow_->Get(), IsDraggingHandle(true) });
247 }
248 if (secondHandleIsShow_->Get() || isClipHandleDrawRect_) {
249 CHECK_NULL_VOID(secondHandle_);
250 CHECK_NULL_VOID(secondCircleIsShow_);
251 PaintHandle(canvas, secondHandle_->Get(), handleReverse_->Get(),
252 { true, secondCircleIsShow_->Get(), IsDraggingHandle(false) });
253 }
254 }
255
ClipViewPort(RSCanvas & canvas)256 void SelectOverlayContentModifier::ClipViewPort(RSCanvas& canvas)
257 {
258 if (!isOverlayMode_ || isClipHandleDrawRect_) {
259 return;
260 }
261 CHECK_NULL_VOID(viewPort_);
262 auto left = viewPort_->Get().Left();
263 auto top = viewPort_->Get().Top();
264 auto right = viewPort_->Get().Right();
265 auto bottom = viewPort_->Get().Bottom();
266 auto upHandle = GetFirstPaintRect();
267 CHECK_NULL_VOID(firstHandleIsShow_);
268 auto upHandleIsShow = firstHandleIsShow_->Get();
269 auto downHandle = GetSecondPaintRect();
270 CHECK_NULL_VOID(secondHandleIsShow_);
271 auto downHandleIsShow = secondHandleIsShow_->Get();
272 CHECK_NULL_VOID(isSingleHandle_);
273 CHECK_NULL_VOID(handleReverse_);
274 if (isSingleHandle_->Get()) {
275 upHandleIsShow = false;
276 downHandleIsShow = firstHandleIsShow_->Get() || secondHandleIsShow_->Get();
277 downHandle = firstHandleIsShow_->Get() ? GetFirstPaintRect()
278 : (secondHandleIsShow_->Get() ? GetSecondPaintRect() : downHandle);
279 } else if (handleReverse_->Get()) {
280 upHandle = GetSecondPaintRect();
281 upHandleIsShow = secondHandleIsShow_->Get();
282 downHandle = GetFirstPaintRect();
283 downHandleIsShow = firstHandleIsShow_->Get();
284 }
285 CHECK_NULL_VOID(handleRadius_);
286 auto handleDiameter = handleRadius_->Get() * 2;
287 auto handleRadius = isPaintHandleUsePoints_ ? 0.0f : handleRadius_->Get();
288 if (upHandleIsShow) {
289 auto halfWidth = isPaintHandleUsePoints_ ? 0.0f : upHandle.Width() / 2.0f;
290 left = std::min(upHandle.Left() + halfWidth - handleRadius, left);
291 right = std::max(upHandle.Right() - halfWidth + handleRadius, right);
292 top = std::min(upHandle.Top() - handleDiameter, top);
293 bottom = std::max(upHandle.Bottom(), bottom);
294 }
295 if (downHandleIsShow) {
296 auto halfWidth = isPaintHandleUsePoints_ ? 0 : downHandle.Width() / 2.0f;
297 left = std::min(downHandle.Left() + halfWidth - handleRadius, left);
298 right = std::max(downHandle.Right() - halfWidth + handleRadius, right);
299 top = std::min(downHandle.Top(), top);
300 bottom = std::max(downHandle.Bottom() + handleDiameter, bottom);
301 }
302 CHECK_NULL_VOID(handleStrokeWidth_);
303 auto strokeWidth = handleStrokeWidth_->Get();
304 RSRect clipInnerRect = RSRect(left - strokeWidth, top - strokeWidth, right + strokeWidth, bottom + strokeWidth);
305 canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT);
306 }
307
ConvertPointsToRect(const SelectHandlePaintInfo & paintInfo) const308 RectF SelectOverlayContentModifier::ConvertPointsToRect(const SelectHandlePaintInfo& paintInfo) const
309 {
310 CHECK_NULL_RETURN(handleRadius_, RectF());
311 auto handleDiameter = handleRadius_->Get() * 2;
312 auto left = std::min(paintInfo.startPoint.GetX(), paintInfo.endPoint.GetX()) - handleDiameter;
313 auto right = std::max(paintInfo.startPoint.GetX(), paintInfo.endPoint.GetX()) + handleDiameter;
314 auto top = std::min(paintInfo.startPoint.GetY(), paintInfo.endPoint.GetY()) - handleDiameter;
315 auto bottom = std::max(paintInfo.startPoint.GetY(), paintInfo.endPoint.GetY()) + handleDiameter;
316 auto width = std::max(right - left, paintInfo.width);
317 auto height = std::max(bottom - top, paintInfo.width);
318 return RectF(OffsetF(left, top), SizeF(width, height));
319 }
320
GetFirstPaintRect() const321 RectF SelectOverlayContentModifier::GetFirstPaintRect() const
322 {
323 if (isPaintHandleUsePoints_) {
324 return ConvertPointsToRect(firstHandlePaintInfo_);
325 }
326 CHECK_NULL_RETURN(firstHandle_, RectF());
327 return firstHandle_->Get();
328 }
329
GetSecondPaintRect() const330 RectF SelectOverlayContentModifier::GetSecondPaintRect() const
331 {
332 if (isPaintHandleUsePoints_) {
333 return ConvertPointsToRect(secondHandlePaintInfo_);
334 }
335 CHECK_NULL_RETURN(secondHandle_, RectF());
336 return secondHandle_->Get();
337 }
338
PaintHandle(RSCanvas & canvas,const RectF & handleRect,bool handleOnTop,const PaintHandleParams & params)339 void SelectOverlayContentModifier::PaintHandle(
340 RSCanvas& canvas, const RectF& handleRect, bool handleOnTop, const PaintHandleParams& params)
341 {
342 auto rectTopX = (handleRect.Left() + handleRect.Right()) / 2.0f;
343 auto centerOffset = OffsetF(rectTopX, 0.0f);
344 OffsetF startPoint(0.0, 0.0);
345 OffsetF endPoint(0.0, 0.0);
346 auto scaleY = isOverlayMode_ ? 1.0f : scale_.y;
347 CHECK_NULL_VOID(handleRadius_);
348 auto handleRadius = handleRadius_->Get() * scaleY;
349 CHECK_NULL_VOID(handleStrokeWidth_);
350 auto gap = NearEqual(scaleY, 1.0f) ? 0.0f : handleStrokeWidth_->Get() * scaleY;
351 if (handleOnTop) {
352 centerOffset.SetY(handleRect.Top() - handleRadius);
353 startPoint.SetY(handleRadius + gap);
354 endPoint.SetY(handleRadius + handleRect.Height() + gap);
355 } else {
356 centerOffset.SetY(handleRect.Bottom() + handleRadius);
357 startPoint.SetY(-handleRadius - gap);
358 endPoint.SetY(-handleRadius - handleRect.Height() - gap);
359 }
360 auto checkCircleIsShow = !isClipHandleDrawRect_ || CheckHandleCircleIsShow(handleRect);
361 HandleDrawInfo drawInfo = { .startPoint = startPoint,
362 .endPoint = endPoint,
363 .centerOffset = centerOffset,
364 .handleWidth = handleRect.Width(),
365 .isHandleLineShow = params.isHandleLineShow,
366 .isCircleShow = params.isCircleShow && checkCircleIsShow };
367 canvas.Save();
368 ClipHandleDrawRect(canvas, handleRect, handleOnTop, params.isDragging);
369 PaintHandle(canvas, drawInfo);
370 canvas.Restore();
371 }
372
PaintHandle(RSCanvas & canvas,const HandleDrawInfo & handleInfo)373 void SelectOverlayContentModifier::PaintHandle(RSCanvas& canvas, const HandleDrawInfo& handleInfo)
374 {
375 auto scaleX = isOverlayMode_ ? 1.0f : scale_.x;
376 auto scaleY = isOverlayMode_ ? 1.0f : scale_.y;
377 canvas.Save();
378 canvas.Translate(handleInfo.centerOffset.GetX(), handleInfo.centerOffset.GetY());
379 CHECK_NULL_VOID(handleColor_);
380 Color handleColor = handleColor_->Get();
381 CHECK_NULL_VOID(handleOpacity_);
382 handleColor = handleColor.BlendOpacity(handleOpacity_->Get());
383 if (handleInfo.isCircleShow) {
384 CHECK_NULL_VOID(innerHandleColor_);
385 CHECK_NULL_VOID(innerHandleRadius_);
386 CHECK_NULL_VOID(handleStrokeWidth_);
387 CHECK_NULL_VOID(handleRadius_);
388 canvas.Save();
389 canvas.Scale(scaleX, scaleY);
390 // Paint inner circle.
391 Color innerHandleColor = innerHandleColor_->Get();
392 innerHandleColor = innerHandleColor.BlendOpacity(handleOpacity_->Get());
393 RSBrush brush;
394 brush.SetAntiAlias(true);
395 brush.SetColor(innerHandleColor.GetValue());
396 canvas.AttachBrush(brush);
397 canvas.DrawCircle(RSPoint(0.0, 0.0), innerHandleRadius_->Get());
398 canvas.DetachBrush();
399 // Paint outer hollow circle.
400 float strokeWidth = handleStrokeWidth_->Get();
401 RSPen strokePen;
402 strokePen.SetAntiAlias(true);
403 strokePen.SetColor(handleColor.GetValue());
404 strokePen.SetWidth(strokeWidth);
405 canvas.AttachPen(strokePen);
406 canvas.DrawCircle(RSPoint(0.0, 0.0), handleRadius_->Get());
407 canvas.DetachPen();
408 canvas.Restore();
409 }
410 PaintHandleLine(canvas, handleInfo, handleColor);
411 canvas.Restore();
412 }
413
PaintHandleLine(RSCanvas & canvas,const HandleDrawInfo & handleInfo,Color handleColor)414 void SelectOverlayContentModifier::PaintHandleLine(
415 RSCanvas& canvas, const HandleDrawInfo& handleInfo, Color handleColor)
416 {
417 auto scaleX = isOverlayMode_ ? 1.0f : scale_.x;
418 float handleLineWidth = handleInfo.handleWidth;
419 if (handleInfo.isHandleLineShow && !NearZero(handleLineWidth)) {
420 canvas.Save();
421 canvas.Scale(scaleX, 1.0f);
422 RSPen pen;
423 pen.SetAntiAlias(true);
424 // Paint line of handle.
425 pen.SetColor(handleColor.GetValue());
426 pen.SetWidth(handleLineWidth);
427 pen.SetCapStyle(RSPen::CapStyle::ROUND_CAP);
428 canvas.AttachPen(pen);
429 canvas.DrawLine(RSPoint(handleInfo.startPoint.GetX(), handleInfo.startPoint.GetY()),
430 RSPoint(handleInfo.endPoint.GetX(), handleInfo.endPoint.GetY()));
431 canvas.DetachPen();
432 canvas.Restore();
433 }
434 }
435
CheckHandleCircleIsShow(const RectF & handleRect)436 bool SelectOverlayContentModifier::CheckHandleCircleIsShow(const RectF& handleRect)
437 {
438 auto viewPort = viewPort_->Get();
439 return GreatOrEqual(handleRect.Right(), viewPort.Left() - VIEW_PORT_MODIFICATION_VALUE) &&
440 LessOrEqual(handleRect.Left(), viewPort.Right() + VIEW_PORT_MODIFICATION_VALUE);
441 }
442
ClipHandleDrawRect(RSCanvas & canvas,const RectF & handleRect,bool handleOnTop,bool isDragging)443 void SelectOverlayContentModifier::ClipHandleDrawRect(
444 RSCanvas& canvas, const RectF& handleRect, bool handleOnTop, bool isDragging)
445 {
446 if (!isClipHandleDrawRect_) {
447 return;
448 }
449 CHECK_NULL_VOID(handleRadius_);
450 CHECK_NULL_VOID(handleStrokeWidth_);
451 auto extendDimension = handleRadius_->Get() + handleStrokeWidth_->Get() / 2.0f;
452 CHECK_NULL_VOID(viewPort_);
453 auto viewPort = viewPort_->Get();
454 auto left = GreatOrEqual(handleRect.Right(), viewPort.Left() - VIEW_PORT_MODIFICATION_VALUE)
455 ? handleRect.Left() - extendDimension
456 : viewPort.Left();
457 auto topInViewPort = GreatOrEqual(handleRect.Top(), viewPort.Top() - VIEW_PORT_MODIFICATION_VALUE);
458 // 扩大裁剪区域绘制手柄末端的圆弧
459 auto top = viewPort.Top() - (topInViewPort ? handleRect.Width() / 2.0f : 0.0f);
460 // 扩大裁剪区域绘制手柄圆圈
461 if (handleOnTop && topInViewPort) {
462 top = viewPort.Top() - extendDimension * 2.0f;
463 }
464 auto right = LessOrEqual(handleRect.Left(), viewPort.Right() + VIEW_PORT_MODIFICATION_VALUE)
465 ? handleRect.Right() + extendDimension
466 : viewPort.Right();
467 auto bottomInViewPort = LessOrEqual(handleRect.Bottom(), viewPort.Bottom() + VIEW_PORT_MODIFICATION_VALUE);
468 auto bottom = viewPort.Bottom() + (bottomInViewPort ? handleRect.Width() / 2.0f : 0.0f);
469 if (!handleOnTop && bottomInViewPort) {
470 bottom = viewPort.Bottom() + extendDimension * 2.0f;
471 }
472 RSRect clipInnerRect = RSRect(left, top, right, bottom);
473 if (isDragging) {
474 RSRect draggingRect = RSRect(handleRect.Left(), handleRect.Top(), handleRect.Right(), handleRect.Bottom());
475 clipInnerRect.Join(draggingRect);
476 }
477 canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT);
478 }
479
IsDraggingHandle(bool isFirst)480 bool SelectOverlayContentModifier::IsDraggingHandle(bool isFirst)
481 {
482 auto overlayPattern = AceType::DynamicCast<SelectOverlayPattern>(pattern_.Upgrade());
483 CHECK_NULL_RETURN(overlayPattern, false);
484 return overlayPattern->IsDraggingHandle(isFirst);
485 }
486 } // namespace OHOS::Ace::NG
487