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