• 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/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