• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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/bubble/rosen_render_bubble.h"
17 
18 #ifndef USE_ROSEN_DRAWING
19 #include "include/core/SkMaskFilter.h"
20 #include "include/effects/Sk1DPathEffect.h"
21 #include "include/effects/SkDashPathEffect.h"
22 #include "include/effects/SkGradientShader.h"
23 #endif
24 
25 #include "core/components/common/painter/rosen_decoration_painter.h"
26 #include "core/components/common/properties/shadow_config.h"
27 
28 #define SkPathkCCWDirection SkPathDirection::kCCW
29 
30 namespace OHOS::Ace {
31 
32 #ifndef USE_ROSEN_DRAWING
GetSkCanvas(RenderContext & context)33 SkCanvas* RosenRenderBubble::GetSkCanvas(RenderContext& context)
34 #else
35 RSCanvas* RosenRenderBubble::GetDrawingCanvas(RenderContext& context)
36 #endif
37 {
38     auto canvas = static_cast<RosenRenderContext*>(&context)->GetCanvas();
39     if (!canvas) {
40         LOGE("canvas fetch failed");
41         return nullptr;
42     }
43     return canvas;
44 }
45 
46 #ifndef USE_ROSEN_DRAWING
MakeRRect()47 SkRRect RosenRenderBubble::MakeRRect()
48 {
49     SkRect rect = SkRect::MakeXYWH(childOffset_.GetX(), childOffset_.GetY(), childSize_.Width(), childSize_.Height());
50     SkRRect rrect = SkRRect::MakeEmpty();
51     SkVector rectRadii[4] = { { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 } };
52     rectRadii[SkRRect::kUpperLeft_Corner] =
53         SkPoint::Make(NormalizeToPx(border_.TopLeftRadius().GetX()), NormalizeToPx(border_.TopLeftRadius().GetY()));
54     rectRadii[SkRRect::kUpperRight_Corner] =
55         SkPoint::Make(NormalizeToPx(border_.TopRightRadius().GetX()), NormalizeToPx(border_.TopRightRadius().GetY()));
56     rectRadii[SkRRect::kLowerRight_Corner] = SkPoint::Make(
57         NormalizeToPx(border_.BottomRightRadius().GetX()), NormalizeToPx(border_.BottomRightRadius().GetY()));
58     rectRadii[SkRRect::kLowerLeft_Corner] = SkPoint::Make(
59         NormalizeToPx(border_.BottomLeftRadius().GetX()), NormalizeToPx(border_.BottomLeftRadius().GetY()));
60     rrect.setRectRadii(rect, rectRadii);
61     return rrect;
62 }
63 #else
MakeRRect()64 RSRoundRect RosenRenderBubble::MakeRRect()
65 {
66     RSRect rect = RSRect(childOffset_.GetX(), childOffset_.GetY(), childSize_.Width() + childOffset_.GetX(),
67         childSize_.Height() + childOffset_.GetY());
68     std::vector<RSPoint> rectRadii;
69 
70     rectRadii.push_back(
71         RSPoint(NormalizeToPx(border_.TopLeftRadius().GetX()), NormalizeToPx(border_.TopLeftRadius().GetY())));
72     rectRadii.push_back(
73         RSPoint(NormalizeToPx(border_.TopRightRadius().GetX()), NormalizeToPx(border_.TopRightRadius().GetY())));
74     rectRadii.push_back(
75         RSPoint(NormalizeToPx(border_.BottomRightRadius().GetX()), NormalizeToPx(border_.BottomRightRadius().GetY())));
76     rectRadii.push_back(
77         RSPoint(NormalizeToPx(border_.BottomLeftRadius().GetX()), NormalizeToPx(border_.BottomLeftRadius().GetY())));
78     RSRoundRect rrect(rect, rectRadii);
79 
80     return rrect;
81 }
82 #endif
83 
Paint(RenderContext & context,const Offset & offset)84 void RosenRenderBubble::Paint(RenderContext& context, const Offset& offset)
85 {
86     if (!isShow_) {
87         return;
88     }
89     PaintMask(context);
90     PaintBubble(context);
91     RenderNode::Paint(context, offset);
92     PaintBorder(context);
93     if (onVisibilityChange_ && !hasEventFired_) {
94         std::string param = std::string("\"visibilitychange\",{\"visibility\":").append("true}");
95         onVisibilityChange_(param);
96         hasEventFired_ = true;
97     }
98 }
99 
100 #ifndef USE_ROSEN_DRAWING
PaintMask(RenderContext & context)101 void RosenRenderBubble::PaintMask(RenderContext& context)
102 {
103     SkCanvas* skCanvas = GetSkCanvas(context);
104     if (skCanvas == nullptr) {
105         return;
106     }
107     SkPaint paint;
108     paint.setColor(maskColor_.GetValue());
109     skCanvas->drawRect(SkRect::MakeXYWH(0.0, 0.0, GetLayoutSize().Width(), GetLayoutSize().Height()), paint);
110 }
111 #else
PaintMask(RenderContext & context)112 void RosenRenderBubble::PaintMask(RenderContext& context)
113 {
114     RSCanvas* canvas = GetDrawingCanvas(context);
115     if (canvas == nullptr) {
116         return;
117     }
118     RSBrush brush;
119     brush.SetColor(maskColor_.GetValue());
120 
121     canvas->AttachBrush(brush);
122     canvas->DrawRect(RSRect(0.0, 0.0, GetLayoutSize().Width(), GetLayoutSize().Height()));
123     canvas->DetachBrush();
124 }
125 #endif
126 
PaintBubble(RenderContext & context)127 void RosenRenderBubble::PaintBubble(RenderContext& context)
128 {
129 #ifndef USE_ROSEN_DRAWING
130     SkCanvas* skCanvas = GetSkCanvas(context);
131     SkPaint paint;
132     paint.setAntiAlias(true);
133     paint.setColor(backgroundColor_.GetValue());
134     if (!useCustom_) {
135         PaintNonCustomPopup(skCanvas, paint);
136         return;
137     }
138     if (enableArrow_ && showCustomArrow_) {
139         PaintBubbleWithArrow(skCanvas, paint);
140     } else {
141         PaintDefaultBubble(skCanvas, paint);
142     }
143 #else
144     RSCanvas* canvas = GetDrawingCanvas(context);
145     RSPen pen;
146     pen.SetAntiAlias(true);
147     pen.SetColor(backgroundColor_.GetValue());
148 
149     if (!useCustom_) {
150         PaintNonCustomPopup(canvas, pen);
151         return;
152     }
153 
154     if (enableArrow_ && showCustomArrow_) {
155         PaintBubbleWithArrow(canvas, pen);
156     } else {
157         PaintDefaultBubble(canvas, pen);
158     }
159 #endif
160 }
161 
162 #ifndef USE_ROSEN_DRAWING
PaintNonCustomPopup(SkCanvas * skCanvas,const SkPaint & paint)163 void RosenRenderBubble::PaintNonCustomPopup(SkCanvas* skCanvas, const SkPaint& paint)
164 #else
165 void RosenRenderBubble::PaintNonCustomPopup(RSCanvas* canvas, const RSPen& pen)
166 #endif
167 {
168     auto context = context_.Upgrade();
169     if (context && context->GetIsDeclarative()) {
170         switch (arrowPlacement_) {
171 #ifndef USE_ROSEN_DRAWING
172             case Placement::TOP:
173                 showTopArrow_ ? PaintTopBubble(skCanvas, paint) : PaintDefaultBubble(skCanvas, paint);
174                 break;
175             case Placement::BOTTOM:
176                 showBottomArrow_ ? PaintBottomBubble(skCanvas, paint) : PaintDefaultBubble(skCanvas, paint);
177                 break;
178 #else
179             case Placement::TOP:
180                 showTopArrow_ ? PaintTopBubble(canvas, pen) : PaintDefaultBubble(canvas, pen);
181                 break;
182             case Placement::BOTTOM:
183                 showBottomArrow_ ? PaintBottomBubble(canvas, pen) : PaintDefaultBubble(canvas, pen);
184                 break;
185 #endif
186             default:
187                 break;
188         }
189         return;
190     }
191     switch (arrowPlacement_) {
192 #ifndef USE_ROSEN_DRAWING
193         case Placement::TOP:
194             showTopArrow_ ? PaintTopBubbleInJs(skCanvas, paint) : PaintDefaultBubble(skCanvas, paint);
195             break;
196         case Placement::BOTTOM:
197             showBottomArrow_ ? PaintBottomBubbleInJs(skCanvas, paint) : PaintDefaultBubble(skCanvas, paint);
198             break;
199 #else
200         case Placement::TOP:
201             showTopArrow_ ? PaintTopBubbleInJs(canvas, pen) : PaintDefaultBubble(canvas, pen);
202             break;
203         case Placement::BOTTOM:
204             showBottomArrow_ ? PaintBottomBubbleInJs(canvas, pen) : PaintDefaultBubble(canvas, pen);
205             break;
206 #endif
207         default:
208             break;
209     }
210 }
211 
212 #ifndef USE_ROSEN_DRAWING
PaintBubbleWithArrow(SkCanvas * skCanvas,const SkPaint & paint)213 void RosenRenderBubble::PaintBubbleWithArrow(SkCanvas* skCanvas, const SkPaint& paint)
214 {
215     if (skCanvas == nullptr) {
216         return;
217     }
218 
219     BuildCompletePath(path_);
220     RosenDecorationPainter::PaintShadow(path_, ShadowConfig::DefaultShadowM, skCanvas);
221     skCanvas->drawPath(path_, paint);
222     skCanvas->clipPath(path_, SkClipOp::kIntersect, true);
223 }
224 #else
PaintBubbleWithArrow(RSCanvas * canvas,const RSPen & pen)225 void RosenRenderBubble::PaintBubbleWithArrow(RSCanvas* canvas, const RSPen& pen)
226 {
227     if (canvas == nullptr) {
228         return;
229     }
230 
231     BuildCompletePath(path_);
232     RosenDecorationPainter::PaintShadow(path_, ShadowConfig::DefaultShadowM, canvas);
233     canvas->AttachPen(pen);
234     canvas->DrawPath(path_);
235     canvas->ClipPath(path_, RSClipOp::INTERSECT);
236     canvas->DetachPen();
237 }
238 #endif
239 
240 #ifndef USE_ROSEN_DRAWING
PaintTopBubbleInJs(SkCanvas * skCanvas,const SkPaint & paint)241 void RosenRenderBubble::PaintTopBubbleInJs(SkCanvas* skCanvas, const SkPaint& paint)
242 {
243     if (skCanvas == nullptr) {
244         return;
245     }
246     double childHeight = childSize_.Height();
247     double childHalfWidth = childSize_.Width() / 2.0;
248     double bubbleSpacing = NormalizeToPx(BUBBLE_SPACING);
249     double arrowOffset = std::clamp(NormalizeToPx(arrowOffset_),
250         -(childHalfWidth - std::max(NormalizeToPx(padding_.Left()), NormalizeToPx(border_.TopLeftRadius().GetX())) -
251             NormalizeToPx(BEZIER_WIDTH_HALF)),
252         childHalfWidth - std::max(NormalizeToPx(padding_.Right()), NormalizeToPx(border_.TopRightRadius().GetY())) -
253             NormalizeToPx(BEZIER_WIDTH_HALF));
254 
255     path_.reset();
256     path_.moveTo(arrowPosition_.GetX() + arrowOffset, arrowPosition_.GetY());
257     path_.quadTo(arrowPosition_.GetX() + NormalizeToPx(BEZIER_HORIZON_OFFSET_FIRST) + arrowOffset,
258         arrowPosition_.GetY() + NormalizeToPx(BEZIER_VERTICAL_OFFSET_FIRST),
259         arrowPosition_.GetX() + NormalizeToPx(BEZIER_HORIZON_OFFSET_SECOND) + arrowOffset,
260         arrowPosition_.GetY() - NormalizeToPx(BEZIER_VERTICAL_OFFSET_SECOND));
261     path_.quadTo(arrowPosition_.GetX() + NormalizeToPx(BEZIER_HORIZON_OFFSET_THIRD) + arrowOffset,
262         arrowPosition_.GetY() - NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD),
263         arrowPosition_.GetX() + NormalizeToPx(BEZIER_HORIZON_OFFSET_FOURTH) + arrowOffset,
264         arrowPosition_.GetY() - NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD));
265     path_.lineTo(arrowPosition_.GetX() + (childHalfWidth - NormalizeToPx(border_.BottomRightRadius().GetX())),
266         arrowPosition_.GetY() - bubbleSpacing);
267     path_.arcTo(NormalizeToPx(border_.BottomRightRadius().GetX()), NormalizeToPx(border_.BottomRightRadius().GetY()),
268         0.0f, SkPath::ArcSize::kSmall_ArcSize, SkPathkCCWDirection, arrowPosition_.GetX() + childHalfWidth,
269         arrowPosition_.GetY() - bubbleSpacing - NormalizeToPx(border_.BottomRightRadius().GetY()));
270     path_.lineTo(arrowPosition_.GetX() + childHalfWidth,
271         arrowPosition_.GetY() - bubbleSpacing - (childHeight - NormalizeToPx(border_.TopRightRadius().GetY())));
272     path_.arcTo(NormalizeToPx(border_.TopRightRadius().GetX()), NormalizeToPx(border_.TopRightRadius().GetY()), 0.0f,
273         SkPath::ArcSize::kSmall_ArcSize, SkPathkCCWDirection,
274         arrowPosition_.GetX() + childHalfWidth - NormalizeToPx(border_.TopRightRadius().GetX()),
275         arrowPosition_.GetY() - bubbleSpacing - childHeight);
276     path_.lineTo(arrowPosition_.GetX() - (childHalfWidth - NormalizeToPx(border_.TopLeftRadius().GetX())),
277         arrowPosition_.GetY() - bubbleSpacing - childHeight);
278     path_.arcTo(NormalizeToPx(border_.TopLeftRadius().GetX()), NormalizeToPx(border_.TopLeftRadius().GetY()), 0.0f,
279         SkPath::ArcSize::kSmall_ArcSize, SkPathkCCWDirection, arrowPosition_.GetX() - childHalfWidth,
280         arrowPosition_.GetY() - bubbleSpacing - (childHeight - NormalizeToPx(border_.TopLeftRadius().GetY())));
281     path_.lineTo(arrowPosition_.GetX() - childHalfWidth,
282         arrowPosition_.GetY() - bubbleSpacing - NormalizeToPx(border_.BottomLeftRadius().GetY()));
283     path_.arcTo(NormalizeToPx(border_.BottomLeftRadius().GetX()), NormalizeToPx(border_.BottomLeftRadius().GetY()),
284         0.0f, SkPath::ArcSize::kSmall_ArcSize, SkPathkCCWDirection,
285         arrowPosition_.GetX() - (childHalfWidth - NormalizeToPx(border_.BottomLeftRadius().GetX())),
286         arrowPosition_.GetY() - bubbleSpacing);
287     path_.lineTo(arrowPosition_.GetX() - NormalizeToPx(BEZIER_HORIZON_OFFSET_FOURTH) + arrowOffset,
288         arrowPosition_.GetY() - NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD));
289     path_.quadTo(arrowPosition_.GetX() - NormalizeToPx(BEZIER_HORIZON_OFFSET_THIRD) + arrowOffset,
290         arrowPosition_.GetY() - NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD),
291         arrowPosition_.GetX() - NormalizeToPx(BEZIER_HORIZON_OFFSET_SECOND) + arrowOffset,
292         arrowPosition_.GetY() - NormalizeToPx(BEZIER_VERTICAL_OFFSET_SECOND));
293     path_.quadTo(arrowPosition_.GetX() - NormalizeToPx(BEZIER_HORIZON_OFFSET_FIRST) + arrowOffset,
294         arrowPosition_.GetY() + NormalizeToPx(BEZIER_VERTICAL_OFFSET_FIRST), arrowPosition_.GetX() + arrowOffset,
295         arrowPosition_.GetY());
296     path_.close();
297     RosenDecorationPainter::PaintShadow(path_, ShadowConfig::DefaultShadowM, skCanvas);
298     skCanvas->drawPath(path_, paint);
299     skCanvas->clipPath(path_, SkClipOp::kIntersect);
300 }
301 #else
PaintTopBubbleInJs(RSCanvas * canvas,const RSPen & pen)302 void RosenRenderBubble::PaintTopBubbleInJs(RSCanvas* canvas, const RSPen& pen)
303 {
304     if (canvas == nullptr) {
305         return;
306     }
307     double childHeight = childSize_.Height();
308     double childHalfWidth = childSize_.Width() / 2.0;
309     double bubbleSpacing = NormalizeToPx(BUBBLE_SPACING);
310     double arrowOffset = std::clamp(NormalizeToPx(arrowOffset_),
311         -(childHalfWidth - std::max(NormalizeToPx(padding_.Left()), NormalizeToPx(border_.TopLeftRadius().GetX())) -
312             NormalizeToPx(BEZIER_WIDTH_HALF)),
313         childHalfWidth - std::max(NormalizeToPx(padding_.Right()), NormalizeToPx(border_.TopRightRadius().GetY())) -
314             NormalizeToPx(BEZIER_WIDTH_HALF));
315 
316     path_.Reset();
317     path_.MoveTo(arrowPosition_.GetX() + arrowOffset, arrowPosition_.GetY());
318     path_.QuadTo(arrowPosition_.GetX() + NormalizeToPx(BEZIER_HORIZON_OFFSET_FIRST) + arrowOffset,
319         arrowPosition_.GetY() + NormalizeToPx(BEZIER_VERTICAL_OFFSET_FIRST),
320         arrowPosition_.GetX() + NormalizeToPx(BEZIER_HORIZON_OFFSET_SECOND) + arrowOffset,
321         arrowPosition_.GetY() - NormalizeToPx(BEZIER_VERTICAL_OFFSET_SECOND));
322     path_.QuadTo(arrowPosition_.GetX() + NormalizeToPx(BEZIER_HORIZON_OFFSET_THIRD) + arrowOffset,
323         arrowPosition_.GetY() - NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD),
324         arrowPosition_.GetX() + NormalizeToPx(BEZIER_HORIZON_OFFSET_FOURTH) + arrowOffset,
325         arrowPosition_.GetY() - NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD));
326     path_.LineTo(arrowPosition_.GetX() + (childHalfWidth - NormalizeToPx(border_.BottomRightRadius().GetX())),
327         arrowPosition_.GetY() - bubbleSpacing);
328     path_.ArcTo(NormalizeToPx(border_.BottomRightRadius().GetX()), NormalizeToPx(border_.BottomRightRadius().GetY()),
329         0.0f, RSPathDirection::CCW_DIRECTION, arrowPosition_.GetX() + childHalfWidth,
330         arrowPosition_.GetY() - bubbleSpacing - NormalizeToPx(border_.BottomRightRadius().GetY()));
331     path_.LineTo(arrowPosition_.GetX() + childHalfWidth,
332         arrowPosition_.GetY() - bubbleSpacing - (childHeight - NormalizeToPx(border_.TopRightRadius().GetY())));
333     path_.ArcTo(NormalizeToPx(border_.TopRightRadius().GetX()), NormalizeToPx(border_.TopRightRadius().GetY()), 0.0f,
334         RSPathDirection::CCW_DIRECTION,
335         arrowPosition_.GetX() + childHalfWidth - NormalizeToPx(border_.TopRightRadius().GetX()),
336         arrowPosition_.GetY() - bubbleSpacing - childHeight);
337     path_.LineTo(arrowPosition_.GetX() - (childHalfWidth - NormalizeToPx(border_.TopLeftRadius().GetX())),
338         arrowPosition_.GetY() - bubbleSpacing - childHeight);
339     path_.ArcTo(NormalizeToPx(border_.TopLeftRadius().GetX()), NormalizeToPx(border_.TopLeftRadius().GetY()), 0.0f,
340         RSPathDirection::CCW_DIRECTION, arrowPosition_.GetX() - childHalfWidth,
341         arrowPosition_.GetY() - bubbleSpacing - (childHeight - NormalizeToPx(border_.TopLeftRadius().GetY())));
342     path_.LineTo(arrowPosition_.GetX() - childHalfWidth,
343         arrowPosition_.GetY() - bubbleSpacing - NormalizeToPx(border_.BottomLeftRadius().GetY()));
344     path_.ArcTo(NormalizeToPx(border_.BottomLeftRadius().GetX()), NormalizeToPx(border_.BottomLeftRadius().GetY()),
345         0.0f, RSPathDirection::CCW_DIRECTION,
346         arrowPosition_.GetX() - (childHalfWidth - NormalizeToPx(border_.BottomLeftRadius().GetX())),
347         arrowPosition_.GetY() - bubbleSpacing);
348     path_.LineTo(arrowPosition_.GetX() - NormalizeToPx(BEZIER_HORIZON_OFFSET_FOURTH) + arrowOffset,
349         arrowPosition_.GetY() - NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD));
350     path_.QuadTo(arrowPosition_.GetX() - NormalizeToPx(BEZIER_HORIZON_OFFSET_THIRD) + arrowOffset,
351         arrowPosition_.GetY() - NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD),
352         arrowPosition_.GetX() - NormalizeToPx(BEZIER_HORIZON_OFFSET_SECOND) + arrowOffset,
353         arrowPosition_.GetY() - NormalizeToPx(BEZIER_VERTICAL_OFFSET_SECOND));
354     path_.QuadTo(arrowPosition_.GetX() - NormalizeToPx(BEZIER_HORIZON_OFFSET_FIRST) + arrowOffset,
355         arrowPosition_.GetY() + NormalizeToPx(BEZIER_VERTICAL_OFFSET_FIRST), arrowPosition_.GetX() + arrowOffset,
356         arrowPosition_.GetY());
357     path_.Close();
358     RosenDecorationPainter::PaintShadow(path_, ShadowConfig::DefaultShadowM, canvas);
359     canvas->AttachPen(pen);
360     canvas->DrawPath(path_);
361     canvas->ClipPath(path_, RSClipOp::INTERSECT);
362     canvas->DetachPen();
363 }
364 #endif
365 
366 #ifndef USE_ROSEN_DRAWING
PaintBottomBubbleInJs(SkCanvas * skCanvas,const SkPaint & paint)367 void RosenRenderBubble::PaintBottomBubbleInJs(SkCanvas* skCanvas, const SkPaint& paint)
368 {
369     if (skCanvas == nullptr) {
370         return;
371     }
372     double childHeight = childSize_.Height();
373     double childHalfWidth = childSize_.Width() / 2.0;
374     double bubbleSpacing = NormalizeToPx(BUBBLE_SPACING);
375     double arrowOffset = std::clamp(NormalizeToPx(arrowOffset_),
376         -(childHalfWidth - std::max(NormalizeToPx(padding_.Left()), NormalizeToPx(border_.BottomLeftRadius().GetX())) -
377             NormalizeToPx(BEZIER_WIDTH_HALF)),
378         childHalfWidth - std::max(NormalizeToPx(padding_.Right()), NormalizeToPx(border_.BottomRightRadius().GetY())) -
379             NormalizeToPx(BEZIER_WIDTH_HALF));
380 
381     path_.reset();
382     path_.moveTo(arrowPosition_.GetX() + arrowOffset, arrowPosition_.GetY());
383     path_.quadTo(arrowPosition_.GetX() + NormalizeToPx(BEZIER_HORIZON_OFFSET_FIRST) + arrowOffset,
384         arrowPosition_.GetY() - NormalizeToPx(BEZIER_VERTICAL_OFFSET_FIRST),
385         arrowPosition_.GetX() + NormalizeToPx(BEZIER_HORIZON_OFFSET_SECOND) + arrowOffset,
386         arrowPosition_.GetY() + NormalizeToPx(BEZIER_VERTICAL_OFFSET_SECOND));
387     path_.quadTo(arrowPosition_.GetX() + NormalizeToPx(BEZIER_HORIZON_OFFSET_THIRD) + arrowOffset,
388         arrowPosition_.GetY() + NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD),
389         arrowPosition_.GetX() + NormalizeToPx(BEZIER_HORIZON_OFFSET_FOURTH) + arrowOffset,
390         arrowPosition_.GetY() + NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD));
391     path_.lineTo(arrowPosition_.GetX() + (childHalfWidth - NormalizeToPx(border_.TopRightRadius().GetX())),
392         arrowPosition_.GetY() + bubbleSpacing);
393     path_.arcTo(NormalizeToPx(border_.TopRightRadius().GetX()), NormalizeToPx(border_.TopRightRadius().GetY()), 0.0f,
394         SkPath::ArcSize::kSmall_ArcSize, SkPathkCCWDirection, arrowPosition_.GetX() + childHalfWidth,
395         arrowPosition_.GetY() + bubbleSpacing + NormalizeToPx(border_.TopRightRadius().GetY()));
396     path_.lineTo(arrowPosition_.GetX() + childHalfWidth,
397         arrowPosition_.GetY() + bubbleSpacing + childHeight - NormalizeToPx(border_.BottomRightRadius().GetY()));
398     path_.arcTo(NormalizeToPx(border_.BottomRightRadius().GetX()), NormalizeToPx(border_.BottomRightRadius().GetY()),
399         0.0f, SkPath::ArcSize::kSmall_ArcSize, SkPathkCCWDirection,
400         arrowPosition_.GetX() + childHalfWidth - NormalizeToPx(border_.BottomRightRadius().GetX()),
401         arrowPosition_.GetY() + bubbleSpacing + childHeight);
402     path_.lineTo(arrowPosition_.GetX() - (childHalfWidth - NormalizeToPx(border_.BottomLeftRadius().GetX())),
403         arrowPosition_.GetY() + bubbleSpacing + childHeight);
404     path_.arcTo(NormalizeToPx(border_.BottomLeftRadius().GetX()), NormalizeToPx(border_.BottomLeftRadius().GetY()),
405         0.0f, SkPath::ArcSize::kSmall_ArcSize, SkPathkCCWDirection, arrowPosition_.GetX() - childHalfWidth,
406         arrowPosition_.GetY() + bubbleSpacing + childHeight - NormalizeToPx(border_.BottomLeftRadius().GetY()));
407     path_.lineTo(arrowPosition_.GetX() - childHalfWidth,
408         arrowPosition_.GetY() + bubbleSpacing + NormalizeToPx(border_.TopLeftRadius().GetY()));
409     path_.arcTo(NormalizeToPx(border_.TopLeftRadius().GetX()), NormalizeToPx(border_.TopLeftRadius().GetY()), 0.0f,
410         SkPath::ArcSize::kSmall_ArcSize, SkPathkCCWDirection,
411         arrowPosition_.GetX() - (childHalfWidth - NormalizeToPx(border_.TopLeftRadius().GetX())),
412         arrowPosition_.GetY() + bubbleSpacing);
413     path_.lineTo(arrowPosition_.GetX() - NormalizeToPx(BEZIER_HORIZON_OFFSET_FOURTH) + arrowOffset,
414         arrowPosition_.GetY() + NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD));
415     path_.quadTo(arrowPosition_.GetX() - NormalizeToPx(BEZIER_HORIZON_OFFSET_THIRD) + arrowOffset,
416         arrowPosition_.GetY() + NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD),
417         arrowPosition_.GetX() - NormalizeToPx(BEZIER_HORIZON_OFFSET_SECOND) + arrowOffset,
418         arrowPosition_.GetY() + NormalizeToPx(BEZIER_VERTICAL_OFFSET_SECOND));
419     path_.quadTo(arrowPosition_.GetX() - NormalizeToPx(BEZIER_HORIZON_OFFSET_FIRST) + arrowOffset,
420         arrowPosition_.GetY() - NormalizeToPx(BEZIER_VERTICAL_OFFSET_FIRST), arrowPosition_.GetX() + arrowOffset,
421         arrowPosition_.GetY());
422     path_.close();
423     RosenDecorationPainter::PaintShadow(path_, ShadowConfig::DefaultShadowM, skCanvas);
424     skCanvas->drawPath(path_, paint);
425     skCanvas->clipPath(path_, SkClipOp::kIntersect);
426 }
427 #else
PaintBottomBubbleInJs(RSCanvas * canvas,const RSPen & pen)428 void RosenRenderBubble::PaintBottomBubbleInJs(RSCanvas* canvas, const RSPen& pen)
429 {
430     if (canvas == nullptr) {
431         return;
432     }
433     double childHeight = childSize_.Height();
434     double childHalfWidth = childSize_.Width() / 2.0;
435     double bubbleSpacing = NormalizeToPx(BUBBLE_SPACING);
436     double arrowOffset = std::clamp(NormalizeToPx(arrowOffset_),
437         -(childHalfWidth - std::max(NormalizeToPx(padding_.Left()), NormalizeToPx(border_.BottomLeftRadius().GetX())) -
438             NormalizeToPx(BEZIER_WIDTH_HALF)),
439         childHalfWidth - std::max(NormalizeToPx(padding_.Right()), NormalizeToPx(border_.BottomRightRadius().GetY())) -
440             NormalizeToPx(BEZIER_WIDTH_HALF));
441 
442     path_.Reset();
443     path_.MoveTo(arrowPosition_.GetX() + arrowOffset, arrowPosition_.GetY());
444     path_.QuadTo(arrowPosition_.GetX() + NormalizeToPx(BEZIER_HORIZON_OFFSET_FIRST) + arrowOffset,
445         arrowPosition_.GetY() - NormalizeToPx(BEZIER_VERTICAL_OFFSET_FIRST),
446         arrowPosition_.GetX() + NormalizeToPx(BEZIER_HORIZON_OFFSET_SECOND) + arrowOffset,
447         arrowPosition_.GetY() + NormalizeToPx(BEZIER_VERTICAL_OFFSET_SECOND));
448     path_.QuadTo(arrowPosition_.GetX() + NormalizeToPx(BEZIER_HORIZON_OFFSET_THIRD) + arrowOffset,
449         arrowPosition_.GetY() + NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD),
450         arrowPosition_.GetX() + NormalizeToPx(BEZIER_HORIZON_OFFSET_FOURTH) + arrowOffset,
451         arrowPosition_.GetY() + NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD));
452     path_.LineTo(arrowPosition_.GetX() + (childHalfWidth - NormalizeToPx(border_.TopRightRadius().GetX())),
453         arrowPosition_.GetY() + bubbleSpacing);
454     path_.ArcTo(NormalizeToPx(border_.TopRightRadius().GetX()), NormalizeToPx(border_.TopRightRadius().GetY()), 0.0f,
455         RSPathDirection::CW_DIRECTION, arrowPosition_.GetX() + childHalfWidth,
456         arrowPosition_.GetY() + bubbleSpacing + NormalizeToPx(border_.TopRightRadius().GetY()));
457     path_.LineTo(arrowPosition_.GetX() + childHalfWidth,
458         arrowPosition_.GetY() + bubbleSpacing + childHeight - NormalizeToPx(border_.BottomRightRadius().GetY()));
459     path_.ArcTo(NormalizeToPx(border_.BottomRightRadius().GetX()), NormalizeToPx(border_.BottomRightRadius().GetY()),
460         0.0f, RSPathDirection::CW_DIRECTION,
461         arrowPosition_.GetX() + childHalfWidth - NormalizeToPx(border_.BottomRightRadius().GetX()),
462         arrowPosition_.GetY() + bubbleSpacing + childHeight);
463     path_.LineTo(arrowPosition_.GetX() - (childHalfWidth - NormalizeToPx(border_.BottomLeftRadius().GetX())),
464         arrowPosition_.GetY() + bubbleSpacing + childHeight);
465     path_.ArcTo(NormalizeToPx(border_.BottomLeftRadius().GetX()), NormalizeToPx(border_.BottomLeftRadius().GetY()),
466         0.0f, RSPathDirection::CW_DIRECTION, arrowPosition_.GetX() - childHalfWidth,
467         arrowPosition_.GetY() + bubbleSpacing + childHeight - NormalizeToPx(border_.BottomLeftRadius().GetY()));
468     path_.LineTo(arrowPosition_.GetX() - childHalfWidth,
469         arrowPosition_.GetY() + bubbleSpacing + NormalizeToPx(border_.TopLeftRadius().GetY()));
470     path_.ArcTo(NormalizeToPx(border_.TopLeftRadius().GetX()), NormalizeToPx(border_.TopLeftRadius().GetY()), 0.0f,
471         RSPathDirection::CW_DIRECTION,
472         arrowPosition_.GetX() - (childHalfWidth - NormalizeToPx(border_.TopLeftRadius().GetX())),
473         arrowPosition_.GetY() + bubbleSpacing);
474     path_.LineTo(arrowPosition_.GetX() - NormalizeToPx(BEZIER_HORIZON_OFFSET_FOURTH) + arrowOffset,
475         arrowPosition_.GetY() + NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD));
476     path_.QuadTo(arrowPosition_.GetX() - NormalizeToPx(BEZIER_HORIZON_OFFSET_THIRD) + arrowOffset,
477         arrowPosition_.GetY() + NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD),
478         arrowPosition_.GetX() - NormalizeToPx(BEZIER_HORIZON_OFFSET_SECOND) + arrowOffset,
479         arrowPosition_.GetY() + NormalizeToPx(BEZIER_VERTICAL_OFFSET_SECOND));
480     path_.QuadTo(arrowPosition_.GetX() - NormalizeToPx(BEZIER_HORIZON_OFFSET_FIRST) + arrowOffset,
481         arrowPosition_.GetY() - NormalizeToPx(BEZIER_VERTICAL_OFFSET_FIRST), arrowPosition_.GetX() + arrowOffset,
482         arrowPosition_.GetY());
483     path_.Close();
484     RosenDecorationPainter::PaintShadow(path_, ShadowConfig::DefaultShadowM, canvas);
485     canvas->AttachPen(pen);
486     canvas->DrawPath(path_);
487     canvas->ClipPath(path_, RSClipOp::INTERSECT);
488     canvas->DetachPen();
489 }
490 #endif
491 
492 #ifndef USE_ROSEN_DRAWING
PaintTopBubble(SkCanvas * skCanvas,const SkPaint & paint)493 void RosenRenderBubble::PaintTopBubble(SkCanvas* skCanvas, const SkPaint& paint)
494 {
495     if (skCanvas == nullptr) {
496         return;
497     }
498     double childHeight = childSize_.Height();
499     double childWidth = childSize_.Width();
500     double childOffsetX = childOffset_.GetX();
501     double childOffsetY = childOffset_.GetY();
502     double arrowPositionX = arrowPosition_.GetX();
503     double arrowPositionY = arrowPosition_.GetY();
504     double arrowOffset = GetArrowOffset(Placement::TOP);
505     path_.reset();
506     path_.moveTo(arrowPositionX + arrowOffset, arrowPositionY);
507     path_.quadTo(arrowPositionX + NormalizeToPx(BEZIER_HORIZON_OFFSET_FIRST) + arrowOffset,
508         arrowPositionY + NormalizeToPx(BEZIER_VERTICAL_OFFSET_FIRST),
509         arrowPositionX + NormalizeToPx(BEZIER_HORIZON_OFFSET_SECOND) + arrowOffset,
510         arrowPositionY - NormalizeToPx(BEZIER_VERTICAL_OFFSET_SECOND));
511     path_.quadTo(arrowPositionX + NormalizeToPx(BEZIER_HORIZON_OFFSET_THIRD) + arrowOffset,
512         arrowPositionY - NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD),
513         arrowPositionX + NormalizeToPx(BEZIER_HORIZON_OFFSET_FOURTH) + arrowOffset,
514         arrowPositionY - NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD));
515     path_.lineTo(
516         childOffsetX + childWidth - NormalizeToPx(border_.BottomRightRadius().GetX()), childOffsetY + childHeight);
517     path_.arcTo(NormalizeToPx(border_.BottomRightRadius().GetX()), NormalizeToPx(border_.BottomRightRadius().GetY()),
518         0.0f, SkPath::ArcSize::kSmall_ArcSize, SkPathkCCWDirection, childOffsetX + childWidth,
519         childOffsetY + childHeight - NormalizeToPx(border_.BottomRightRadius().GetY()));
520     path_.lineTo(childOffsetX + childWidth, childOffsetY + NormalizeToPx(border_.TopRightRadius().GetY()));
521     path_.arcTo(NormalizeToPx(border_.TopRightRadius().GetX()), NormalizeToPx(border_.TopRightRadius().GetY()), 0.0f,
522         SkPath::ArcSize::kSmall_ArcSize, SkPathkCCWDirection,
523         childOffsetX + childWidth - NormalizeToPx(border_.TopRightRadius().GetX()), childOffsetY);
524     path_.lineTo(childOffsetX + NormalizeToPx(border_.TopLeftRadius().GetX()), childOffsetY);
525     path_.arcTo(NormalizeToPx(border_.TopLeftRadius().GetX()), NormalizeToPx(border_.TopLeftRadius().GetY()), 0.0f,
526         SkPath::ArcSize::kSmall_ArcSize, SkPathkCCWDirection, childOffsetX,
527         childOffsetY + NormalizeToPx(border_.TopLeftRadius().GetY()));
528     path_.lineTo(childOffsetX, childOffsetY + childHeight - NormalizeToPx(border_.BottomLeftRadius().GetY()));
529     path_.arcTo(NormalizeToPx(border_.BottomLeftRadius().GetX()), NormalizeToPx(border_.BottomLeftRadius().GetY()),
530         0.0f, SkPath::ArcSize::kSmall_ArcSize, SkPathkCCWDirection,
531         childOffsetX + NormalizeToPx(border_.BottomLeftRadius().GetX()), childOffsetY + childHeight);
532     path_.lineTo(arrowPositionX - NormalizeToPx(BEZIER_HORIZON_OFFSET_FOURTH) + arrowOffset,
533         arrowPositionY - NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD));
534     path_.quadTo(arrowPositionX - NormalizeToPx(BEZIER_HORIZON_OFFSET_THIRD) + arrowOffset,
535         arrowPositionY - NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD),
536         arrowPositionX - NormalizeToPx(BEZIER_HORIZON_OFFSET_SECOND) + arrowOffset,
537         arrowPositionY - NormalizeToPx(BEZIER_VERTICAL_OFFSET_SECOND));
538     path_.quadTo(arrowPositionX - NormalizeToPx(BEZIER_HORIZON_OFFSET_FIRST) + arrowOffset,
539         arrowPositionY + NormalizeToPx(BEZIER_VERTICAL_OFFSET_FIRST), arrowPositionX + arrowOffset, arrowPositionY);
540     path_.close();
541     RosenDecorationPainter::PaintShadow(path_, ShadowConfig::DefaultShadowM, skCanvas);
542     skCanvas->drawPath(path_, paint);
543     skCanvas->clipPath(path_, SkClipOp::kIntersect);
544 }
545 #else
PaintTopBubble(RSCanvas * canvas,const RSPen & pen)546 void RosenRenderBubble::PaintTopBubble(RSCanvas* canvas, const RSPen& pen)
547 {
548     if (canvas == nullptr) {
549         return;
550     }
551     double childHeight = childSize_.Height();
552     double childWidth = childSize_.Width();
553     double childOffsetX = childOffset_.GetX();
554     double childOffsetY = childOffset_.GetY();
555     double arrowPositionX = arrowPosition_.GetX();
556     double arrowPositionY = arrowPosition_.GetY();
557     double arrowOffset = GetArrowOffset(Placement::TOP);
558     path_.Reset();
559     path_.MoveTo(arrowPositionX + arrowOffset, arrowPositionY);
560     path_.QuadTo(arrowPositionX + NormalizeToPx(BEZIER_HORIZON_OFFSET_FIRST) + arrowOffset,
561         arrowPositionY + NormalizeToPx(BEZIER_VERTICAL_OFFSET_FIRST),
562         arrowPositionX + NormalizeToPx(BEZIER_HORIZON_OFFSET_SECOND) + arrowOffset,
563         arrowPositionY - NormalizeToPx(BEZIER_VERTICAL_OFFSET_SECOND));
564     path_.QuadTo(arrowPositionX + NormalizeToPx(BEZIER_HORIZON_OFFSET_THIRD) + arrowOffset,
565         arrowPositionY - NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD),
566         arrowPositionX + NormalizeToPx(BEZIER_HORIZON_OFFSET_FOURTH) + arrowOffset,
567         arrowPositionY - NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD));
568     path_.LineTo(
569         childOffsetX + childWidth - NormalizeToPx(border_.BottomRightRadius().GetX()), childOffsetY + childHeight);
570     path_.ArcTo(NormalizeToPx(border_.BottomRightRadius().GetX()), NormalizeToPx(border_.BottomRightRadius().GetY()),
571         0.0f, RSPathDirection::CCW_DIRECTION, childOffsetX + childWidth,
572         childOffsetY + childHeight - NormalizeToPx(border_.BottomRightRadius().GetY()));
573     path_.LineTo(childOffsetX + childWidth, childOffsetY + NormalizeToPx(border_.TopRightRadius().GetY()));
574     path_.ArcTo(NormalizeToPx(border_.TopRightRadius().GetX()), NormalizeToPx(border_.TopRightRadius().GetY()), 0.0f,
575         RSPathDirection::CCW_DIRECTION, childOffsetX + childWidth - NormalizeToPx(border_.TopRightRadius().GetX()),
576         childOffsetY);
577     path_.LineTo(childOffsetX + NormalizeToPx(border_.TopLeftRadius().GetX()), childOffsetY);
578     path_.ArcTo(NormalizeToPx(border_.TopLeftRadius().GetX()), NormalizeToPx(border_.TopLeftRadius().GetY()), 0.0f,
579         RSPathDirection::CCW_DIRECTION, childOffsetX, childOffsetY + NormalizeToPx(border_.TopLeftRadius().GetY()));
580     path_.LineTo(childOffsetX, childOffsetY + childHeight - NormalizeToPx(border_.BottomLeftRadius().GetY()));
581     path_.ArcTo(NormalizeToPx(border_.BottomLeftRadius().GetX()), NormalizeToPx(border_.BottomLeftRadius().GetY()),
582         0.0f, RSPathDirection::CCW_DIRECTION, childOffsetX + NormalizeToPx(border_.BottomLeftRadius().GetX()),
583         childOffsetY + childHeight);
584     path_.LineTo(arrowPositionX - NormalizeToPx(BEZIER_HORIZON_OFFSET_FOURTH) + arrowOffset,
585         arrowPositionY - NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD));
586     path_.QuadTo(arrowPositionX - NormalizeToPx(BEZIER_HORIZON_OFFSET_THIRD) + arrowOffset,
587         arrowPositionY - NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD),
588         arrowPositionX - NormalizeToPx(BEZIER_HORIZON_OFFSET_SECOND) + arrowOffset,
589         arrowPositionY - NormalizeToPx(BEZIER_VERTICAL_OFFSET_SECOND));
590     path_.QuadTo(arrowPositionX - NormalizeToPx(BEZIER_HORIZON_OFFSET_FIRST) + arrowOffset,
591         arrowPositionY + NormalizeToPx(BEZIER_VERTICAL_OFFSET_FIRST), arrowPositionX + arrowOffset, arrowPositionY);
592     path_.Close();
593     RosenDecorationPainter::PaintShadow(path_, ShadowConfig::DefaultShadowM, canvas);
594     canvas->AttachPen(pen);
595     canvas->DrawPath(path_);
596     canvas->ClipPath(path_, RSClipOp::INTERSECT);
597     canvas->DetachPen();
598 }
599 #endif
600 
601 #ifndef USE_ROSEN_DRAWING
PaintBottomBubble(SkCanvas * skCanvas,const SkPaint & paint)602 void RosenRenderBubble::PaintBottomBubble(SkCanvas* skCanvas, const SkPaint& paint)
603 {
604     if (skCanvas == nullptr) {
605         return;
606     }
607     double childHeight = childSize_.Height();
608     double childWidth = childSize_.Width();
609     double childOffsetX = childOffset_.GetX();
610     double childOffsetY = childOffset_.GetY();
611     double arrowPositionX = arrowPosition_.GetX();
612     double arrowPositionY = arrowPosition_.GetY();
613     double arrowOffset = GetArrowOffset(Placement::BOTTOM);
614     path_.reset();
615     path_.moveTo(arrowPositionX + arrowOffset, arrowPositionY);
616     path_.quadTo(arrowPositionX + NormalizeToPx(BEZIER_HORIZON_OFFSET_FIRST) + arrowOffset,
617         arrowPositionY - NormalizeToPx(BEZIER_VERTICAL_OFFSET_FIRST),
618         arrowPositionX + NormalizeToPx(BEZIER_HORIZON_OFFSET_SECOND) + arrowOffset,
619         arrowPositionY + NormalizeToPx(BEZIER_VERTICAL_OFFSET_SECOND));
620     path_.quadTo(arrowPositionX + NormalizeToPx(BEZIER_HORIZON_OFFSET_THIRD) + arrowOffset,
621         arrowPositionY + NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD),
622         arrowPositionX + NormalizeToPx(BEZIER_HORIZON_OFFSET_FOURTH) + arrowOffset,
623         arrowPositionY + NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD));
624     path_.lineTo(childOffsetX + childWidth - NormalizeToPx(border_.TopRightRadius().GetX()), childOffsetY);
625     path_.arcTo(NormalizeToPx(border_.TopRightRadius().GetX()), NormalizeToPx(border_.TopRightRadius().GetY()), 0.0f,
626         SkPath::ArcSize::kSmall_ArcSize, SkPathkCCWDirection, childOffsetX + childWidth,
627         childOffsetY + NormalizeToPx(border_.TopRightRadius().GetY()));
628     path_.lineTo(
629         childOffsetX + childWidth, childOffsetY + childHeight - NormalizeToPx(border_.BottomRightRadius().GetY()));
630     path_.arcTo(NormalizeToPx(border_.BottomRightRadius().GetX()), NormalizeToPx(border_.BottomRightRadius().GetY()),
631         0.0f, SkPath::ArcSize::kSmall_ArcSize, SkPathkCCWDirection,
632         childOffsetX + childWidth - NormalizeToPx(border_.BottomRightRadius().GetX()), childOffsetY + childHeight);
633     path_.lineTo(childOffsetX + NormalizeToPx(border_.BottomLeftRadius().GetX()), childOffsetY + childHeight);
634     path_.arcTo(NormalizeToPx(border_.BottomLeftRadius().GetX()), NormalizeToPx(border_.BottomLeftRadius().GetY()),
635         0.0f, SkPath::ArcSize::kSmall_ArcSize, SkPathkCCWDirection, childOffsetX,
636         childOffsetY + childHeight - NormalizeToPx(border_.BottomLeftRadius().GetY()));
637     path_.lineTo(childOffsetX, childOffsetY + NormalizeToPx(border_.TopLeftRadius().GetY()));
638     path_.arcTo(NormalizeToPx(border_.TopLeftRadius().GetX()), NormalizeToPx(border_.TopLeftRadius().GetY()), 0.0f,
639         SkPath::ArcSize::kSmall_ArcSize, SkPathkCCWDirection,
640         childOffsetX + NormalizeToPx(border_.TopLeftRadius().GetX()), childOffsetY);
641     path_.lineTo(arrowPositionX - NormalizeToPx(BEZIER_HORIZON_OFFSET_FOURTH) + arrowOffset,
642         arrowPositionY + NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD));
643     path_.quadTo(arrowPositionX - NormalizeToPx(BEZIER_HORIZON_OFFSET_THIRD) + arrowOffset,
644         arrowPositionY + NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD),
645         arrowPositionX - NormalizeToPx(BEZIER_HORIZON_OFFSET_SECOND) + arrowOffset,
646         arrowPositionY + NormalizeToPx(BEZIER_VERTICAL_OFFSET_SECOND));
647     path_.quadTo(arrowPositionX - NormalizeToPx(BEZIER_HORIZON_OFFSET_FIRST) + arrowOffset,
648         arrowPositionY - NormalizeToPx(BEZIER_VERTICAL_OFFSET_FIRST), arrowPositionX + arrowOffset, arrowPositionY);
649     path_.close();
650     RosenDecorationPainter::PaintShadow(path_, ShadowConfig::DefaultShadowM, skCanvas);
651     skCanvas->drawPath(path_, paint);
652     skCanvas->clipPath(path_, SkClipOp::kIntersect);
653 }
654 #else
PaintBottomBubble(RSCanvas * canvas,const RSPen & pen)655 void RosenRenderBubble::PaintBottomBubble(RSCanvas* canvas, const RSPen& pen)
656 {
657     if (canvas == nullptr) {
658         return;
659     }
660     double childHeight = childSize_.Height();
661     double childWidth = childSize_.Width();
662     double childOffsetX = childOffset_.GetX();
663     double childOffsetY = childOffset_.GetY();
664     double arrowPositionX = arrowPosition_.GetX();
665     double arrowPositionY = arrowPosition_.GetY();
666     double arrowOffset = GetArrowOffset(Placement::BOTTOM);
667 
668     path_.Reset();
669     path_.MoveTo(arrowPositionX + arrowOffset, arrowPositionY);
670     path_.QuadTo(arrowPositionX + NormalizeToPx(BEZIER_HORIZON_OFFSET_FIRST) + arrowOffset,
671         arrowPositionY - NormalizeToPx(BEZIER_VERTICAL_OFFSET_FIRST),
672         arrowPositionX + NormalizeToPx(BEZIER_HORIZON_OFFSET_SECOND) + arrowOffset,
673         arrowPositionY + NormalizeToPx(BEZIER_VERTICAL_OFFSET_SECOND));
674     path_.QuadTo(arrowPositionX + NormalizeToPx(BEZIER_HORIZON_OFFSET_THIRD) + arrowOffset,
675         arrowPositionY + NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD),
676         arrowPositionX + NormalizeToPx(BEZIER_HORIZON_OFFSET_FOURTH) + arrowOffset,
677         arrowPositionY + NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD));
678     path_.LineTo(childOffsetX + childWidth - NormalizeToPx(border_.TopRightRadius().GetX()), childOffsetY);
679     path_.ArcTo(NormalizeToPx(border_.TopRightRadius().GetX()), NormalizeToPx(border_.TopRightRadius().GetY()), 0.0f,
680         RSPathDirection::CW_DIRECTION, childOffsetX + childWidth,
681         childOffsetY + NormalizeToPx(border_.TopRightRadius().GetY()));
682     path_.LineTo(
683         childOffsetX + childWidth, childOffsetY + childHeight - NormalizeToPx(border_.BottomRightRadius().GetY()));
684     path_.ArcTo(NormalizeToPx(border_.BottomRightRadius().GetX()), NormalizeToPx(border_.BottomRightRadius().GetY()),
685         0.0f, RSPathDirection::CW_DIRECTION,
686         childOffsetX + childWidth - NormalizeToPx(border_.BottomRightRadius().GetX()), childOffsetY + childHeight);
687     path_.LineTo(childOffsetX + NormalizeToPx(border_.BottomLeftRadius().GetX()), childOffsetY + childHeight);
688     path_.ArcTo(NormalizeToPx(border_.BottomLeftRadius().GetX()), NormalizeToPx(border_.BottomLeftRadius().GetY()),
689         0.0f, RSPathDirection::CW_DIRECTION, childOffsetX,
690         childOffsetY + childHeight - NormalizeToPx(border_.BottomLeftRadius().GetY()));
691     path_.LineTo(childOffsetX, childOffsetY + NormalizeToPx(border_.TopLeftRadius().GetY()));
692     path_.ArcTo(NormalizeToPx(border_.TopLeftRadius().GetX()), NormalizeToPx(border_.TopLeftRadius().GetY()), 0.0f,
693         RSPathDirection::CW_DIRECTION, childOffsetX + NormalizeToPx(border_.TopLeftRadius().GetX()), childOffsetY);
694     path_.LineTo(arrowPositionX - NormalizeToPx(BEZIER_HORIZON_OFFSET_FOURTH) + arrowOffset,
695         arrowPositionY + NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD));
696     path_.QuadTo(arrowPositionX - NormalizeToPx(BEZIER_HORIZON_OFFSET_THIRD) + arrowOffset,
697         arrowPositionY + NormalizeToPx(BEZIER_VERTICAL_OFFSET_THIRD),
698         arrowPositionX - NormalizeToPx(BEZIER_HORIZON_OFFSET_SECOND) + arrowOffset,
699         arrowPositionY + NormalizeToPx(BEZIER_VERTICAL_OFFSET_SECOND));
700     path_.QuadTo(arrowPositionX - NormalizeToPx(BEZIER_HORIZON_OFFSET_FIRST) + arrowOffset,
701         arrowPositionY - NormalizeToPx(BEZIER_VERTICAL_OFFSET_FIRST), arrowPositionX + arrowOffset, arrowPositionY);
702     path_.Close();
703     RosenDecorationPainter::PaintShadow(path_, ShadowConfig::DefaultShadowM, canvas);
704     canvas->AttachPen(pen);
705     canvas->DrawPath(path_);
706     canvas->ClipPath(path_, RSClipOp::INTERSECT);
707     canvas->DetachPen();
708 }
709 #endif
710 
711 #ifndef USE_ROSEN_DRAWING
PaintDefaultBubble(SkCanvas * skCanvas,const SkPaint & paint)712 void RosenRenderBubble::PaintDefaultBubble(SkCanvas* skCanvas, const SkPaint& paint)
713 {
714     if (skCanvas == nullptr) {
715         return;
716     }
717     rrect_ = MakeRRect();
718     RosenDecorationPainter::PaintShadow(SkPath().addRRect(rrect_), ShadowConfig::DefaultShadowM, skCanvas);
719     skCanvas->drawRRect(rrect_, paint);
720     skCanvas->clipRRect(rrect_, SkClipOp::kIntersect, true);
721 }
722 #else
PaintDefaultBubble(RSCanvas * canvas,const RSPen & pen)723 void RosenRenderBubble::PaintDefaultBubble(RSCanvas* canvas, const RSPen& pen)
724 {
725     if (canvas == nullptr) {
726         return;
727     }
728     rrect_ = MakeRRect();
729 
730     RSPath tmpPath;
731     tmpPath.AddRoundRect(rrect_);
732     RosenDecorationPainter::PaintShadow(tmpPath, ShadowConfig::DefaultShadowM, canvas);
733     canvas->AttachPen(pen);
734     canvas->DrawRoundRect(rrect_);
735     canvas->ClipRoundRect(rrect_, RSClipOp::INTERSECT);
736     canvas->DetachPen();
737 }
738 #endif
739 
740 #ifndef USE_ROSEN_DRAWING
PaintBorder(RenderContext & context)741 void RosenRenderBubble::PaintBorder(RenderContext& context)
742 {
743     SkCanvas* skCanvas = GetSkCanvas(context);
744     if (skCanvas == nullptr) {
745         return;
746     }
747     BorderEdge edge = border_.Left();
748     if (!border_.IsAllEqual()) {
749         edge = border_.GetValidEdge();
750         border_ = Border(edge);
751     }
752     if (!border_.HasValue()) {
753         return;
754     }
755     double borderWidth = NormalizeToPx(edge.GetWidth());
756     SkPaint paint;
757     paint.setStrokeWidth(borderWidth);
758     paint.setColor(edge.GetColor().GetValue());
759     paint.setStyle(SkPaint::Style::kStroke_Style);
760     paint.setAntiAlias(true);
761     if (edge.GetBorderStyle() == BorderStyle::DOTTED) {
762         SkPath dotPath;
763         dotPath.addCircle(0.0f, 0.0f, SkDoubleToScalar(borderWidth / 2.0));
764         paint.setPathEffect(
765             SkPath1DPathEffect::Make(dotPath, borderWidth * 2.0, 0.0, SkPath1DPathEffect::kRotate_Style));
766     } else if (edge.GetBorderStyle() == BorderStyle::DASHED) {
767         const float intervals[] = { SkDoubleToScalar(borderWidth), SkDoubleToScalar(borderWidth) };
768         paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 0.0));
769         skCanvas->drawPath(path_, paint);
770     } else {
771         paint.setPathEffect(nullptr);
772     }
773 
774     skCanvas->save();
775     skCanvas->translate(
776         childOffset_.GetX() + childSize_.Width() / 2.0, childOffset_.GetY() + childSize_.Height() / 2.0);
777     skCanvas->scale(1.0 - (borderWidth / childSize_.Width()), 1.0 - (borderWidth / childSize_.Height()));
778     skCanvas->translate(
779         -(childOffset_.GetX() + childSize_.Width() / 2.0), -(childOffset_.GetY() + childSize_.Height() / 2.0));
780     if ((arrowPlacement_ == Placement::TOP || arrowPlacement_ == Placement::BOTTOM) && !path_.isEmpty()) {
781         skCanvas->drawPath(path_, paint);
782     } else {
783         skCanvas->drawRRect(rrect_, paint);
784     }
785     skCanvas->restore();
786 }
787 #else
PaintBorder(RenderContext & context)788 void RosenRenderBubble::PaintBorder(RenderContext& context)
789 {
790     RSCanvas* canvas = GetDrawingCanvas(context);
791     if (canvas == nullptr) {
792         return;
793     }
794     BorderEdge edge = border_.Left();
795     if (!border_.IsAllEqual()) {
796         edge = border_.GetValidEdge();
797         border_ = Border(edge);
798     }
799     if (!border_.HasValue()) {
800         return;
801     }
802     double borderWidth = NormalizeToPx(edge.GetWidth());
803     RSPen pen;
804     pen.SetWidth(borderWidth);
805     pen.SetColor(edge.GetColor().GetValue());
806     pen.SetAntiAlias(true);
807     if (edge.GetBorderStyle() == BorderStyle::DOTTED) {
808         RSPath dotPath;
809         dotPath.AddCircle(0.0f, 0.0f, static_cast<RSScalar>(borderWidth / 2.0));
810         pen.SetPathEffect(RSPathEffect::CreatePathDashEffect(dotPath, borderWidth * 2.0, 0.0, RSPathDashStyle::ROTATE));
811     } else if (edge.GetBorderStyle() == BorderStyle::DASHED) {
812         const float intervals[] = { static_cast<RSScalar>(borderWidth), static_cast<RSScalar>(borderWidth) };
813         pen.SetPathEffect(RSPathEffect::CreateDashPathEffect(intervals, sizeof(intervals) / sizeof(RSScalar), 0.0));
814         canvas->AttachPen(pen);
815         canvas->DrawPath(path_);
816         canvas->DetachPen();
817     } else {
818         pen.SetPathEffect(nullptr);
819     }
820 
821     canvas->Save();
822     canvas->Translate(childOffset_.GetX() + childSize_.Width() / 2.0, childOffset_.GetY() + childSize_.Height() / 2.0);
823     canvas->Scale(1.0 - (borderWidth / childSize_.Width()), 1.0 - (borderWidth / childSize_.Height()));
824     canvas->Translate(
825         -(childOffset_.GetX() + childSize_.Width() / 2.0), -(childOffset_.GetY() + childSize_.Height() / 2.0));
826     canvas->AttachPen(pen);
827     if ((arrowPlacement_ == Placement::TOP || arrowPlacement_ == Placement::BOTTOM) && path_.IsValid()) {
828         canvas->DrawPath(path_);
829     } else {
830         canvas->DrawRoundRect(rrect_);
831     }
832     canvas->DetachPen();
833     canvas->Restore();
834 }
835 #endif
836 } // namespace OHOS::Ace