• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "render/rs_border.h"
17 
18 #ifndef USE_ROSEN_DRAWING
19 #include "include/core/SkCanvas.h"
20 #include "include/core/SkPaint.h"
21 #include "include/effects/Sk1DPathEffect.h"
22 #include "include/effects/SkDashPathEffect.h"
23 #else
24 #include "draw/path.h"
25 #endif
26 #include "platform/common/rs_log.h"
27 
28 namespace OHOS {
29 namespace Rosen {
30 namespace {
31 constexpr int PARAM_DOUBLE = 2;
32 constexpr int32_t DASHED_LINE_LENGTH = 3;
33 constexpr float TOP_START = 225.0f;
34 constexpr float TOP_END = 270.0f;
35 constexpr float RIGHT_START = 315.0f;
36 constexpr float RIGHT_END = 0.0f;
37 constexpr float BOTTOM_START = 45.0f;
38 constexpr float BOTTOM_END = 90.0f;
39 constexpr float LEFT_START = 135.0f;
40 constexpr float LEFT_END = 180.0f;
41 constexpr float SWEEP_ANGLE = 45.0f;
42 constexpr float EXTEND = 1024.0f;
43 } // namespace
44 
RSBorder(const bool & isOutline)45 RSBorder::RSBorder(const bool& isOutline)
46 {
47     if (isOutline) {
48         SetStyle(BorderStyle::SOLID);
49         SetColor(Color(0, 0, 0));
50     }
51 }
52 
SetColor(Color color)53 void RSBorder::SetColor(Color color)
54 {
55     colors_.clear();
56     colors_.push_back(color);
57 }
58 
SetWidth(float width)59 void RSBorder::SetWidth(float width)
60 {
61     widths_.clear();
62     widths_.push_back(width);
63 }
64 
SetStyle(BorderStyle style)65 void RSBorder::SetStyle(BorderStyle style)
66 {
67     styles_.clear();
68     styles_.push_back(style);
69 }
70 
GetColor(int idx) const71 Color RSBorder::GetColor(int idx) const
72 {
73     if (colors_.empty()) {
74         return RgbPalette::Transparent();
75     } else if (colors_.size() == 1) {
76         return colors_.front();
77     } else {
78         return colors_.at(idx);
79     }
80 }
81 
GetWidth(int idx) const82 float RSBorder::GetWidth(int idx) const
83 {
84     if (widths_.empty()) {
85         return 0.f;
86     } else if (widths_.size() == 1) {
87         return widths_.front();
88     } else {
89         return widths_.at(idx);
90     }
91 }
92 
GetStyle(int idx) const93 BorderStyle RSBorder::GetStyle(int idx) const
94 {
95     if (styles_.empty()) {
96         return BorderStyle::NONE;
97     } else if (styles_.size() == 1) {
98         return styles_.front();
99     } else {
100         return styles_.at(idx);
101     }
102 }
103 
SetColorFour(const Vector4<Color> & color)104 void RSBorder::SetColorFour(const Vector4<Color>& color)
105 {
106     if (color.x_ == color.y_ && color.x_ == color.z_ && color.x_ == color.w_) {
107         return SetColor(color.x_);
108     }
109     colors_ = { color.x_, color.y_, color.z_, color.w_ };
110 }
111 
SetWidthFour(const Vector4f & width)112 void RSBorder::SetWidthFour(const Vector4f& width)
113 {
114     if (width.x_ == width.y_ && width.x_ == width.z_ && width.x_ == width.w_) {
115         return SetWidth(width.x_);
116     }
117     widths_ = { width.x_, width.y_, width.z_, width.w_ };
118 }
119 
SetStyleFour(const Vector4<uint32_t> & style)120 void RSBorder::SetStyleFour(const Vector4<uint32_t>& style)
121 {
122     if (style.x_ == style.y_ && style.x_ == style.z_ && style.x_ == style.w_) {
123         return SetStyle(static_cast<BorderStyle>(style.x_));
124     }
125     styles_ = { static_cast<BorderStyle>(style.x_), static_cast<BorderStyle>(style.y_),
126                 static_cast<BorderStyle>(style.z_), static_cast<BorderStyle>(style.w_) };
127 }
128 
SetRadiusFour(const Vector4f & radius)129 void RSBorder::SetRadiusFour(const Vector4f& radius)
130 {
131     radius_ = { radius.x_, radius.y_, radius.z_, radius.w_ };
132 }
133 
GetColorFour() const134 Vector4<Color> RSBorder::GetColorFour() const
135 {
136     if (colors_.size() == 4) {
137         return Vector4<Color>(colors_[0], colors_[1], colors_[2], colors_[3]);
138     } else {
139         return Vector4<Color>(GetColor());
140     }
141 }
142 
GetWidthFour() const143 Vector4f RSBorder::GetWidthFour() const
144 {
145     if (widths_.size() == 4) {
146         return Vector4f(widths_[0], widths_[1], widths_[2], widths_[3]);
147     } else {
148         return Vector4f(GetWidth());
149     }
150 }
151 
GetStyleFour() const152 Vector4<uint32_t> RSBorder::GetStyleFour() const
153 {
154     if (styles_.size() == 4) {
155         return Vector4<uint32_t>(static_cast<uint32_t>(styles_[0]), static_cast<uint32_t>(styles_[1]),
156                                  static_cast<uint32_t>(styles_[2]), static_cast<uint32_t>(styles_[3]));
157     } else {
158         return Vector4<uint32_t>(static_cast<uint32_t>(GetStyle()));
159     }
160 }
161 
GetRadiusFour() const162 Vector4f RSBorder::GetRadiusFour() const
163 {
164     return radius_;
165 }
166 
167 #ifndef USE_ROSEN_DRAWING
SetBorderEffect(SkPaint & paint,BorderStyle style,float width,float spaceBetweenDot,float borderLength)168 void SetBorderEffect(SkPaint& paint, BorderStyle style, float width, float spaceBetweenDot, float borderLength)
169 #else
170 void SetBorderEffect(Drawing::Pen& pen, BorderStyle style, float width, float spaceBetweenDot, float borderLength)
171 #endif
172 {
173     if (ROSEN_EQ(width, 0.f)) {
174         return;
175     }
176     if (style == BorderStyle::DOTTED) {
177 #ifndef USE_ROSEN_DRAWING
178         SkPath dotPath;
179 #else
180         Drawing::Path dotPath;
181 #endif
182         if (ROSEN_EQ(spaceBetweenDot, 0.f)) {
183             spaceBetweenDot = width * PARAM_DOUBLE;
184         }
185 #ifndef USE_ROSEN_DRAWING
186         dotPath.addCircle(0.0f, 0.0f, width / PARAM_DOUBLE);
187         paint.setPathEffect(SkPath1DPathEffect::Make(dotPath, spaceBetweenDot, 0.0, SkPath1DPathEffect::kRotate_Style));
188 #else
189         dotPath.AddCircle(0.0f, 0.0f, width / PARAM_DOUBLE);
190         pen.SetPathEffect(Drawing::PathEffect::CreatePathDashEffect(dotPath, spaceBetweenDot, 0.0,
191             Drawing::PathDashStyle::ROTATE));
192 #endif
193     } else if (style == BorderStyle::DASHED) {
194         double addLen = 0.0; // When left < 2 * gap, splits left to gaps.
195         double delLen = 0.0; // When left > 2 * gap, add one dash and shortening them.
196         if (!ROSEN_EQ(borderLength, 0.f)) {
197             float count = borderLength / width;
198             float leftLen = fmod((count - DASHED_LINE_LENGTH), (DASHED_LINE_LENGTH + 1));
199             if (leftLen > DASHED_LINE_LENGTH - 1) {
200                 delLen = (DASHED_LINE_LENGTH + 1 - leftLen) * width /
201                          static_cast<int>((count - DASHED_LINE_LENGTH) / (DASHED_LINE_LENGTH + 1) + 2);
202             } else {
203                 addLen = leftLen * width / static_cast<int>((count - DASHED_LINE_LENGTH) / (DASHED_LINE_LENGTH + 1));
204             }
205         }
206         const float intervals[] = { width * DASHED_LINE_LENGTH - delLen, width + addLen };
207 #ifndef USE_ROSEN_DRAWING
208         paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 0.0));
209     } else {
210         paint.setPathEffect(nullptr);
211 #else
212         pen.SetPathEffect(Drawing::PathEffect::CreateDashPathEffect(intervals, sizeof(intervals)/sizeof(float), 0.0));
213     } else {
214         pen.SetPathEffect(nullptr);
215 #endif
216     }
217 }
218 
219 #ifndef USE_ROSEN_DRAWING
ApplyFillStyle(SkPaint & paint) const220 bool RSBorder::ApplyFillStyle(SkPaint& paint) const
221 #else
222 bool RSBorder::ApplyFillStyle(Drawing::Brush& brush) const
223 #endif
224 {
225     if (colors_.size() != 1) {
226         return false;
227     }
228     if (styles_.size() != 1 || GetStyle() != BorderStyle::SOLID) {
229         return false;
230     }
231     for (const float& width : widths_) {
232         if (ROSEN_LE(width, 0.f)) {
233             return false;
234         }
235     }
236 #ifndef USE_ROSEN_DRAWING
237     paint.setStyle(SkPaint::Style::kFill_Style);
238     paint.setColor(GetColor().AsArgbInt());
239 #else
240     brush.SetColor(GetColor().AsArgbInt());
241 #endif
242     return true;
243 }
244 
245 #ifndef USE_ROSEN_DRAWING
ApplyPathStyle(SkPaint & paint) const246 bool RSBorder::ApplyPathStyle(SkPaint& paint) const
247 #else
248 bool RSBorder::ApplyPathStyle(Drawing::Pen& pen) const
249 #endif
250 {
251     if (colors_.size() != 1 || widths_.size() != 1 || styles_.size() != 1) {
252         return false;
253     }
254 #ifndef USE_ROSEN_DRAWING
255     paint.setStrokeWidth(widths_.front());
256     paint.setStyle(SkPaint::Style::kStroke_Style);
257     paint.setColor(colors_.front().AsArgbInt());
258     SetBorderEffect(paint, GetStyle(), widths_.front(), 0.f, 0.f);
259 #else
260     pen.SetWidth(widths_.front());
261     pen.SetColor(colors_.front().AsArgbInt());
262     SetBorderEffect(pen, GetStyle(), widths_.front(), 0.f, 0.f);
263 #endif
264     return true;
265 }
266 
267 #ifndef USE_ROSEN_DRAWING
ApplyFourLine(SkPaint & paint) const268 bool RSBorder::ApplyFourLine(SkPaint& paint) const
269 #else
270 bool RSBorder::ApplyFourLine(Drawing::Pen& pen) const
271 #endif
272 {
273     if (colors_.size() != 1 || styles_.size() != 1) {
274         return false;
275     }
276 #ifndef USE_ROSEN_DRAWING
277     paint.setStyle(SkPaint::Style::kStroke_Style);
278 #endif
279     return true;
280 }
281 
282 #ifndef USE_ROSEN_DRAWING
ApplyLineStyle(SkPaint & paint,int borderIdx,float length) const283 bool RSBorder::ApplyLineStyle(SkPaint& paint, int borderIdx, float length) const
284 #else
285 bool RSBorder::ApplyLineStyle(Drawing::Pen& pen, int borderIdx, float length) const
286 #endif
287 {
288     if (GetWidth(borderIdx) <= 0.0f) {
289         return false;
290     }
291     float borderWidth = GetWidth(borderIdx);
292     BorderStyle borderStyle = GetStyle(borderIdx);
293     float addLen = (borderStyle != BorderStyle::DOTTED) ? 0.0f : 0.5f;
294     auto borderLength = length - borderWidth * addLen * PARAM_DOUBLE;
295     int32_t rawNumber = borderLength / (PARAM_DOUBLE * borderWidth);
296     if (borderStyle == BorderStyle::DOTTED && rawNumber == 0) {
297         return false;
298     }
299 
300 #ifndef USE_ROSEN_DRAWING
301     paint.setStrokeWidth(GetWidth(borderIdx));
302     Color color = GetColor(borderIdx);
303     paint.setColor(color.AsArgbInt());
304     SetBorderEffect(paint, GetStyle(borderIdx), borderWidth, borderLength / rawNumber, borderLength);
305 #else
306     pen.SetWidth(GetWidth(borderIdx));
307     Color color = GetColor(borderIdx);
308     pen.SetColor(color.AsArgbInt());
309     SetBorderEffect(pen, GetStyle(borderIdx), borderWidth, borderLength / rawNumber, borderLength);
310 #endif
311     return true;
312 }
313 
314 #ifndef USE_ROSEN_DRAWING
PaintFourLine(SkCanvas & canvas,SkPaint & paint,RectF rect) const315 void RSBorder::PaintFourLine(SkCanvas& canvas, SkPaint& paint, RectF rect) const
316 #else
317 void RSBorder::PaintFourLine(Drawing::Canvas& canvas, Drawing::Pen& pen, RectF rect) const
318 #endif
319 {
320     float borderLeftWidth = GetWidth(RSBorder::LEFT);
321     float borderRightWidth = GetWidth(RSBorder::RIGHT);
322     float borderTopWidth = GetWidth(RSBorder::TOP);
323     float borderBottomWidth = GetWidth(RSBorder::BOTTOM);
324 #ifndef USE_ROSEN_DRAWING
325     if (ApplyLineStyle(paint, RSBorder::LEFT, rect.height_)) {
326         float addLen = (GetStyle(RSBorder::LEFT) != BorderStyle::DOTTED) ? 0.0f : 0.5f;
327         canvas.drawLine(
328             rect.left_ + borderLeftWidth / PARAM_DOUBLE, rect.top_ + addLen * borderTopWidth,
329             rect.left_ + borderLeftWidth / PARAM_DOUBLE, rect.GetBottom() - borderBottomWidth, paint);
330     }
331     if (ApplyLineStyle(paint, RSBorder::RIGHT, rect.height_)) {
332         float addLen = (GetStyle(RSBorder::RIGHT) != BorderStyle::DOTTED) ? 0.0f : 0.5f;
333         canvas.drawLine(
334             rect.GetRight() - borderRightWidth / PARAM_DOUBLE, rect.GetBottom() - addLen * borderBottomWidth,
335             rect.GetRight() - borderRightWidth / PARAM_DOUBLE, rect.top_ + borderTopWidth, paint);
336     }
337     if (ApplyLineStyle(paint, RSBorder::TOP, rect.width_)) {
338         float addLen = (GetStyle(RSBorder::TOP) != BorderStyle::DOTTED) ? 0.0f : 0.5f;
339         canvas.drawLine(
340             rect.GetRight() - addLen * borderRightWidth, rect.top_ + borderTopWidth / PARAM_DOUBLE,
341             rect.left_ + borderLeftWidth, rect.top_ + borderTopWidth / PARAM_DOUBLE, paint);
342     }
343     if (ApplyLineStyle(paint, RSBorder::BOTTOM, rect.width_)) {
344         float addLen = (GetStyle(RSBorder::BOTTOM) != BorderStyle::DOTTED) ? 0.0f : 0.5f;
345         canvas.drawLine(
346             rect.left_ + addLen * borderLeftWidth, rect.GetBottom() - borderBottomWidth / PARAM_DOUBLE,
347             rect.GetRight() - borderRightWidth, rect.GetBottom() - borderBottomWidth / PARAM_DOUBLE, paint);
348     }
349 #else
350     if (ApplyLineStyle(pen, RSBorder::LEFT, rect.height_)) {
351         float addLen = (GetStyle(RSBorder::LEFT) != BorderStyle::DOTTED) ? 0.0f : 0.5f;
352         canvas.AttachPen(pen);
353         canvas.DrawLine(
354             Drawing::Point(rect.left_ + borderLeftWidth / PARAM_DOUBLE, rect.top_ + addLen * borderTopWidth),
355             Drawing::Point(rect.left_ + borderLeftWidth / PARAM_DOUBLE, rect.GetBottom() - borderBottomWidth));
356         canvas.DetachPen();
357     }
358     if (ApplyLineStyle(pen, RSBorder::RIGHT, rect.height_)) {
359         float addLen = (GetStyle(RSBorder::RIGHT) != BorderStyle::DOTTED) ? 0.0f : 0.5f;
360         canvas.AttachPen(pen);
361         canvas.DrawLine(
362             Drawing::Point(rect.GetRight() - borderRightWidth / PARAM_DOUBLE,
363                 rect.GetBottom() - addLen * borderBottomWidth),
364             Drawing::Point(rect.GetRight() - borderRightWidth / PARAM_DOUBLE, rect.top_ + borderTopWidth));
365         canvas.DetachPen();
366     }
367     if (ApplyLineStyle(pen, RSBorder::TOP, rect.width_)) {
368         float addLen = (GetStyle(RSBorder::TOP) != BorderStyle::DOTTED) ? 0.0f : 0.5f;
369         canvas.AttachPen(pen);
370         canvas.DrawLine(
371             Drawing::Point(rect.GetRight() - addLen * borderRightWidth, rect.top_ + borderTopWidth / PARAM_DOUBLE),
372             Drawing::Point(rect.left_ + borderLeftWidth, rect.top_ + borderTopWidth / PARAM_DOUBLE));
373         canvas.DetachPen();
374     }
375     if (ApplyLineStyle(pen, RSBorder::BOTTOM, rect.width_)) {
376         float addLen = (GetStyle(RSBorder::BOTTOM) != BorderStyle::DOTTED) ? 0.0f : 0.5f;
377         canvas.AttachPen(pen);
378         canvas.DrawLine(
379             Drawing::Point(rect.left_ + addLen * borderLeftWidth, rect.GetBottom() - borderBottomWidth / PARAM_DOUBLE),
380             Drawing::Point(rect.GetRight() - borderRightWidth, rect.GetBottom() - borderBottomWidth / PARAM_DOUBLE));
381         canvas.DetachPen();
382     }
383 #endif
384 }
385 
386 #ifndef USE_ROSEN_DRAWING
PaintTopPath(SkCanvas & canvas,SkPaint & paint,const SkRRect & rrect,const SkPoint & innerRectCenter) const387 void RSBorder::PaintTopPath(
388     SkCanvas& canvas, SkPaint& paint, const SkRRect& rrect, const SkPoint& innerRectCenter) const
389 #else
390 void RSBorder::PaintTopPath(Drawing::Canvas& canvas, Drawing::Pen& pen, const Drawing::RoundRect& rrect,
391     const Drawing::Point& innerRectCenter) const
392 #endif
393 {
394 #ifndef USE_ROSEN_DRAWING
395     float offsetX = rrect.rect().x();
396     float offsetY = rrect.rect().y();
397     float width = rrect.rect().width();
398 #else
399     float offsetX = rrect.GetRect().GetLeft();
400     float offsetY = rrect.GetRect().GetTop();
401     float width = rrect.GetRect().GetWidth();
402 #endif
403     auto style = GetStyle(RSBorder::TOP);
404     float leftW = GetWidth(RSBorder::LEFT);
405     float topW = GetWidth(RSBorder::TOP);
406     float rightW = GetWidth(RSBorder::RIGHT);
407     float bottomW = GetWidth(RSBorder::BOTTOM);
408     float x = offsetX + leftW / 2.0f;
409     float y = offsetY + topW / 2.0f;
410     float w = std::max(0.0f, width - (leftW + rightW) / 2.0f);
411 #ifndef USE_ROSEN_DRAWING
412     float tlX = std::max(0.0f, rrect.radii(SkRRect::kUpperLeft_Corner).x() - (topW + leftW) / 4.0f);
413     float tlY = std::max(0.0f, rrect.radii(SkRRect::kUpperLeft_Corner).y() - (topW + leftW) / 4.0f);
414     float trX = std::max(0.0f, rrect.radii(SkRRect::kUpperRight_Corner).x() - (topW + rightW) / 4.0f);
415     float trY = std::max(0.0f, rrect.radii(SkRRect::kUpperRight_Corner).y() - (topW + rightW) / 4.0f);
416 #else
417     float tlX = std::max(0.0f, rrect.GetCornerRadius(Drawing::RoundRect::TOP_LEFT_POS).GetX() - (topW + leftW) / 4.0f);
418     float tlY = std::max(0.0f, rrect.GetCornerRadius(Drawing::RoundRect::TOP_LEFT_POS).GetY() - (topW + leftW) / 4.0f);
419     float trX =
420         std::max(0.0f, rrect.GetCornerRadius(Drawing::RoundRect::TOP_RIGHT_POS).GetX() - (topW + rightW) / 4.0f);
421     float trY =
422         std::max(0.0f, rrect.GetCornerRadius(Drawing::RoundRect::TOP_RIGHT_POS).GetY() - (topW + rightW) / 4.0f);
423 #endif
424     if (topW > 0.f) {
425 #ifndef USE_ROSEN_DRAWING
426         ApplyLineStyle(paint, RSBorder::TOP, width);
427         auto rectStart = SkRect::MakeXYWH(x, y, tlX * 2.0f, tlY * 2.0f);
428         auto rectEnd = SkRect::MakeXYWH(x + w - trX * 2.0f, y, trX * 2.0f, trY * 2.0f);
429         SkPath topBorder;
430         paint.setStrokeWidth(std::max(std::max(leftW, topW), std::max(rightW, bottomW)));
431         SkAutoCanvasRestore acr(&canvas, true);
432         canvas.clipRect({ offsetX, offsetY, offsetX + width, innerRectCenter.y() });
433 #else
434         ApplyLineStyle(pen, RSBorder::TOP, width);
435         auto rectStart = Drawing::Rect(x, y, x + tlX * 2.0f, y + tlY * 2.0f);
436         auto rectEnd = Drawing::Rect(x + w - trX * 2.0f, y, x + w, y + trY * 2.0f);
437         Drawing::Path topBorder;
438         pen.SetWidth(std::max(std::max(leftW, topW), std::max(rightW, bottomW)));
439         Drawing::AutoCanvasRestore acr(canvas, true);
440         canvas.ClipRect({ offsetX, offsetY, offsetX + width, innerRectCenter.GetY() });
441 #endif
442         if ((style == BorderStyle::SOLID) || (ROSEN_EQ(tlX, 0.f) && !ROSEN_EQ(leftW, 0.f))) {
443 #ifndef USE_ROSEN_DRAWING
444             topBorder.moveTo(offsetX, y);
445             topBorder.lineTo(x, y);
446             SkPath topClipPath;
447             topClipPath.moveTo(offsetX - leftW, offsetY - topW);
448             topClipPath.lineTo(offsetX + leftW * EXTEND, offsetY + topW * EXTEND);
449             topClipPath.lineTo(offsetX, offsetY + topW * EXTEND);
450             topClipPath.close();
451             canvas.clipPath(topClipPath, SkClipOp::kDifference, true);
452 #else
453             topBorder.MoveTo(offsetX, y);
454             topBorder.LineTo(x, y);
455             Drawing::Path topClipPath;
456             topClipPath.MoveTo(offsetX - leftW, offsetY - topW);
457             topClipPath.LineTo(offsetX + leftW * EXTEND, offsetY + topW * EXTEND);
458             topClipPath.LineTo(offsetX, offsetY + topW * EXTEND);
459             topClipPath.Close();
460             topClipPath.Offset(-0.5, 0);
461             canvas.ClipPath(topClipPath, Drawing::ClipOp::DIFFERENCE, true);
462 #endif
463         }
464 #ifndef USE_ROSEN_DRAWING
465         topBorder.arcTo(rectStart, TOP_START, SWEEP_ANGLE, false);
466         topBorder.arcTo(rectEnd, TOP_END, SWEEP_ANGLE + 0.5f, false);
467 #else
468         topBorder.ArcTo(rectStart.GetLeft(), rectStart.GetTop(), rectStart.GetRight(), rectStart.GetBottom(),
469             TOP_START, SWEEP_ANGLE);
470         topBorder.ArcTo(rectEnd.GetLeft(), rectEnd.GetTop(), rectEnd.GetRight(), rectEnd.GetBottom(),
471             TOP_END, SWEEP_ANGLE + 0.5f);
472 #endif
473         if ((style == BorderStyle::SOLID) || (ROSEN_EQ(trX, 0.f) && !ROSEN_EQ(rightW, 0.f))) {
474 #ifndef USE_ROSEN_DRAWING
475             topBorder.lineTo(offsetX + width, y);
476             SkPath topClipPath;
477             topClipPath.moveTo(offsetX + width + rightW, offsetY - topW);
478             topClipPath.lineTo(offsetX + width - rightW * EXTEND, offsetY + topW * EXTEND);
479             topClipPath.lineTo(offsetX + width, offsetY + topW * EXTEND);
480             topClipPath.close();
481             canvas.clipPath(topClipPath, SkClipOp::kDifference, true);
482 #else
483             topBorder.LineTo(offsetX + width, y);
484             Drawing::Path topClipPath;
485             topClipPath.MoveTo(offsetX + width + rightW, offsetY - topW);
486             topClipPath.LineTo(offsetX + width - rightW * EXTEND, offsetY + topW * EXTEND);
487             topClipPath.LineTo(offsetX + width, offsetY + topW * EXTEND);
488             topClipPath.Close();
489             topClipPath.Offset(0.5, 0);
490             canvas.ClipPath(topClipPath, Drawing::ClipOp::DIFFERENCE, true);
491 #endif
492         }
493 #ifndef USE_ROSEN_DRAWING
494         if (style == BorderStyle::SOLID) {
495             paint.setStyle(SkPaint::Style::kStrokeAndFill_Style);
496             canvas.drawRect(topBorder.getBounds(), paint);
497         } else {
498             canvas.drawPath(topBorder, paint);
499         }
500 #else
501         canvas.AttachPen(pen);
502         if (style == BorderStyle::SOLID) {
503             Drawing::Brush brush;
504             brush.SetColor(pen.GetColor());
505             brush.SetAntiAlias(true);
506             canvas.AttachBrush(brush);
507             canvas.DrawRect(topBorder.GetBounds());
508             canvas.DetachBrush();
509         } else {
510             canvas.DrawPath(topBorder);
511         }
512         canvas.DetachPen();
513 #endif
514     }
515 }
516 
517 #ifndef USE_ROSEN_DRAWING
PaintRightPath(SkCanvas & canvas,SkPaint & paint,const SkRRect & rrect,const SkPoint & innerRectCenter) const518 void RSBorder::PaintRightPath(
519     SkCanvas& canvas, SkPaint& paint, const SkRRect& rrect, const SkPoint& innerRectCenter) const
520 {
521     float offsetX = rrect.rect().x();
522     float offsetY = rrect.rect().y();
523     float width = rrect.rect().width();
524     float height = rrect.rect().height();
525 #else
526 void RSBorder::PaintRightPath(Drawing::Canvas& canvas, Drawing::Pen& pen, const Drawing::RoundRect& rrect,
527     const Drawing::Point& innerRectCenter) const
528 {
529     float offsetX = rrect.GetRect().GetLeft();
530     float offsetY = rrect.GetRect().GetTop();
531     float width = rrect.GetRect().GetWidth();
532     float height = rrect.GetRect().GetHeight();
533 #endif
534     auto style = GetStyle(RSBorder::RIGHT);
535     float leftW = GetWidth(RSBorder::LEFT);
536     float topW = GetWidth(RSBorder::TOP);
537     float rightW = GetWidth(RSBorder::RIGHT);
538     float bottomW = GetWidth(RSBorder::BOTTOM);
539     float x = offsetX + leftW / 2.0f;
540     float y = offsetY + topW / 2.0f;
541     float w = std::max(0.0f, width - (leftW + rightW) / 2.0f);
542     float h = std::max(0.0f, height - (topW + bottomW) / 2.0f);
543 #ifndef USE_ROSEN_DRAWING
544     float trX = std::max(0.0f, rrect.radii(SkRRect::kUpperRight_Corner).x() - (topW + rightW) / 4.0f);
545     float trY = std::max(0.0f, rrect.radii(SkRRect::kUpperRight_Corner).y() - (topW + rightW) / 4.0f);
546     float brX = std::max(0.0f, rrect.radii(SkRRect::kLowerRight_Corner).x() - (bottomW + rightW) / 4.0f);
547     float brY = std::max(0.0f, rrect.radii(SkRRect::kLowerRight_Corner).y() - (bottomW + rightW) / 4.0f);
548 #else
549     float trX =
550         std::max(0.0f, rrect.GetCornerRadius(Drawing::RoundRect::TOP_RIGHT_POS).GetX() - (topW + rightW) / 4.0f);
551     float trY =
552         std::max(0.0f, rrect.GetCornerRadius(Drawing::RoundRect::TOP_RIGHT_POS).GetY() - (topW + rightW) / 4.0f);
553     float brX =
554         std::max(0.0f, rrect.GetCornerRadius(Drawing::RoundRect::BOTTOM_RIGHT_POS).GetX() - (bottomW + rightW) / 4.0f);
555     float brY =
556         std::max(0.0f, rrect.GetCornerRadius(Drawing::RoundRect::BOTTOM_RIGHT_POS).GetY() - (bottomW + rightW) / 4.0f);
557 #endif
558     if (rightW > 0.f) {
559 #ifndef USE_ROSEN_DRAWING
560         ApplyLineStyle(paint, RSBorder::RIGHT, height);
561         auto rectStart = SkRect::MakeXYWH(x + w - trX * 2.0f, y, trX * 2.0f, trY * 2.0f);
562         auto rectEnd = SkRect::MakeXYWH(x + w - brX * 2.0f, y + h - brY * 2.0f, brX * 2.0f, brY * 2.0f);
563         SkPath rightBorder;
564         paint.setStrokeWidth(std::max(std::max(leftW, topW), std::max(rightW, bottomW)));
565         SkAutoCanvasRestore acr(&canvas, true);
566         canvas.clipRect({ innerRectCenter.x(), offsetY, offsetX + width, offsetY + height });
567 #else
568         ApplyLineStyle(pen, RSBorder::RIGHT, height);
569         auto rectStart = Drawing::Rect(x + w - trX * 2.0f, y, x + w, y + trY * 2.0f);
570         auto rectEnd = Drawing::Rect(x + w - brX * 2.0f, y + h - brY * 2.0f, x + w, y + h);
571         Drawing::Path rightBorder;
572         pen.SetWidth(std::max(std::max(leftW, topW), std::max(rightW, bottomW)));
573         Drawing::AutoCanvasRestore acr(canvas, true);
574         canvas.ClipRect({ innerRectCenter.GetX(), offsetY, offsetX + width, offsetY + height });
575 #endif
576         if ((style == BorderStyle::SOLID) || (ROSEN_EQ(trX, 0.f) && !ROSEN_EQ(topW, 0.f))) {
577 #ifndef USE_ROSEN_DRAWING
578             rightBorder.moveTo(offsetX + width - rightW / 2.0f, offsetY);
579             rightBorder.lineTo(x + w - trX * 2.0f, y);
580             SkPath rightClipPath;
581             rightClipPath.moveTo(offsetX + width + rightW, offsetY - topW);
582             rightClipPath.lineTo(offsetX + width - rightW * EXTEND, offsetY + topW * EXTEND);
583             rightClipPath.lineTo(offsetX + width - rightW * EXTEND, offsetY);
584             rightClipPath.close();
585             canvas.clipPath(rightClipPath, SkClipOp::kDifference, true);
586 #else
587             rightBorder.MoveTo(offsetX + width - rightW / 2.0f, offsetY);
588             rightBorder.LineTo(x + w - trX * 2.0f, y);
589             Drawing::Path rightClipPath;
590             rightClipPath.MoveTo(offsetX + width + rightW, offsetY - topW);
591             rightClipPath.LineTo(offsetX + width - rightW * EXTEND, offsetY + topW * EXTEND);
592             rightClipPath.LineTo(offsetX + width - rightW * EXTEND, offsetY);
593             rightClipPath.Close();
594             rightClipPath.Offset(0, -0.5);
595             canvas.ClipPath(rightClipPath, Drawing::ClipOp::DIFFERENCE, true);
596 #endif
597         }
598 #ifndef USE_ROSEN_DRAWING
599         rightBorder.arcTo(rectStart, RIGHT_START, SWEEP_ANGLE, false);
600         rightBorder.arcTo(rectEnd, RIGHT_END, SWEEP_ANGLE + 0.5f, false);
601 #else
602         rightBorder.ArcTo(rectStart.GetLeft(), rectStart.GetTop(), rectStart.GetRight(), rectStart.GetBottom(),
603             RIGHT_START, SWEEP_ANGLE);
604         rightBorder.ArcTo(rectEnd.GetLeft(), rectEnd.GetTop(), rectEnd.GetRight(), rectEnd.GetBottom(),
605             RIGHT_END, SWEEP_ANGLE + 0.5f);
606 #endif
607         if ((style == BorderStyle::SOLID) || (ROSEN_EQ(brX, 0.f) && !ROSEN_EQ(bottomW, 0.f))) {
608 #ifndef USE_ROSEN_DRAWING
609             rightBorder.lineTo(offsetX + width - rightW / 2.0f, offsetY + height);
610             SkPath rightClipPath;
611             rightClipPath.moveTo(offsetX + width + rightW, offsetY + height + bottomW);
612             rightClipPath.lineTo(offsetX + width - rightW * EXTEND, offsetY + height - bottomW * EXTEND);
613             rightClipPath.lineTo(offsetX + width - rightW * EXTEND, offsetY + height);
614             rightClipPath.close();
615             canvas.clipPath(rightClipPath, SkClipOp::kDifference, true);
616 #else
617             rightBorder.LineTo(offsetX + width - rightW / 2.0f, offsetY + height);
618             Drawing::Path rightClipPath;
619             rightClipPath.MoveTo(offsetX + width + rightW, offsetY + height + bottomW);
620             rightClipPath.LineTo(offsetX + width - rightW * EXTEND, offsetY + height - bottomW * EXTEND);
621             rightClipPath.LineTo(offsetX + width - rightW * EXTEND, offsetY + height);
622             rightClipPath.Close();
623             rightClipPath.Offset(0, 0.5);
624             canvas.ClipPath(rightClipPath, Drawing::ClipOp::DIFFERENCE, true);
625 #endif
626         }
627 #ifndef USE_ROSEN_DRAWING
628         if (style == BorderStyle::SOLID) {
629             paint.setStyle(SkPaint::Style::kStrokeAndFill_Style);
630             canvas.drawRect(rightBorder.getBounds(), paint);
631         } else {
632             canvas.drawPath(rightBorder, paint);
633         }
634 #else
635         canvas.AttachPen(pen);
636         if (style == BorderStyle::SOLID) {
637             Drawing::Brush brush;
638             brush.SetColor(pen.GetColor());
639             brush.SetAntiAlias(true);
640             canvas.AttachBrush(brush);
641             canvas.DrawRect(rightBorder.GetBounds());
642             canvas.DetachBrush();
643         } else {
644             canvas.DrawPath(rightBorder);
645         }
646         canvas.DetachPen();
647 #endif
648     }
649 }
650 
651 #ifndef USE_ROSEN_DRAWING
652 void RSBorder::PaintBottomPath(
653     SkCanvas& canvas, SkPaint& paint, const SkRRect& rrect, const SkPoint& innerRectCenter) const
654 {
655     float offsetX = rrect.rect().x();
656     float offsetY = rrect.rect().y();
657     float width = rrect.rect().width();
658     float height = rrect.rect().height();
659 #else
660 void RSBorder::PaintBottomPath(Drawing::Canvas& canvas, Drawing::Pen& pen, const Drawing::RoundRect& rrect,
661     const Drawing::Point& innerRectCenter) const
662 {
663     float offsetX = rrect.GetRect().GetLeft();
664     float offsetY = rrect.GetRect().GetTop();
665     float width = rrect.GetRect().GetWidth();
666     float height = rrect.GetRect().GetHeight();
667 #endif
668     auto style = GetStyle(RSBorder::BOTTOM);
669     float leftW = GetWidth(RSBorder::LEFT);
670     float topW = GetWidth(RSBorder::TOP);
671     float rightW = GetWidth(RSBorder::RIGHT);
672     float bottomW = GetWidth(RSBorder::BOTTOM);
673     float x = offsetX + leftW / 2.0f;
674     float y = offsetY + topW / 2.0f;
675     float w = std::max(0.0f, width - (leftW + rightW) / 2.0f);
676     float h = std::max(0.0f, height - (topW + bottomW) / 2.0f);
677 #ifndef USE_ROSEN_DRAWING
678     float brX = std::max(0.0f, rrect.radii(SkRRect::kLowerRight_Corner).x() - (bottomW + rightW) / 4.0f);
679     float brY = std::max(0.0f, rrect.radii(SkRRect::kLowerRight_Corner).y() - (bottomW + rightW) / 4.0f);
680     float blX = std::max(0.0f, rrect.radii(SkRRect::kLowerLeft_Corner).x() - (bottomW + leftW) / 4.0f);
681     float blY = std::max(0.0f, rrect.radii(SkRRect::kLowerLeft_Corner).y() - (bottomW + leftW) / 4.0f);
682 #else
683     float brX =
684         std::max(0.0f, rrect.GetCornerRadius(Drawing::RoundRect::BOTTOM_RIGHT_POS).GetX() - (bottomW + rightW) / 4.0f);
685     float brY =
686         std::max(0.0f, rrect.GetCornerRadius(Drawing::RoundRect::BOTTOM_RIGHT_POS).GetY() - (bottomW + rightW) / 4.0f);
687     float blX =
688         std::max(0.0f, rrect.GetCornerRadius(Drawing::RoundRect::BOTTOM_LEFT_POS).GetX() - (bottomW + leftW) / 4.0f);
689     float blY =
690         std::max(0.0f, rrect.GetCornerRadius(Drawing::RoundRect::BOTTOM_LEFT_POS).GetY() - (bottomW + leftW) / 4.0f);
691 #endif
692     if (bottomW > 0.f) {
693 #ifndef USE_ROSEN_DRAWING
694         ApplyLineStyle(paint, RSBorder::BOTTOM, width);
695         auto rectStart = SkRect::MakeXYWH(x + w - brX * 2.0f, y + h - brY * 2.0f, brX * 2.0f, brY * 2.0f);
696         auto rectEnd = SkRect::MakeXYWH(x, y + h - blY * 2.0f, blX * 2.0f, blY * 2.0f);
697         SkPath bottomBorder;
698         if (GetStyle(RSBorder::BOTTOM) != BorderStyle::DOTTED) {
699             paint.setStrokeWidth(std::max(std::max(leftW, topW), std::max(rightW, bottomW)));
700         }
701         SkAutoCanvasRestore acr(&canvas, true);
702         canvas.clipRect({ offsetX, innerRectCenter.y(), offsetX + width, offsetY + height });
703 #else
704         ApplyLineStyle(pen, RSBorder::BOTTOM, width);
705         auto rectStart = Drawing::Rect(x + w - brX * 2.0f, y + h - brY * 2.0f, x + w, y + h);
706         auto rectEnd = Drawing::Rect(x, y + h - blY * 2.0f, x + blX * 2.0f, y + h);
707         Drawing::Path bottomBorder;
708         if (GetStyle(RSBorder::BOTTOM) != BorderStyle::DOTTED) {
709             pen.SetWidth(std::max(std::max(leftW, topW), std::max(rightW, bottomW)));
710         }
711         Drawing::AutoCanvasRestore acr(canvas, true);
712         canvas.ClipRect({ offsetX, innerRectCenter.GetY(), offsetX + width, offsetY + height });
713 #endif
714         if ((style == BorderStyle::SOLID) || (ROSEN_EQ(brX, 0.f) && !ROSEN_EQ(rightW, 0.f))) {
715 #ifndef USE_ROSEN_DRAWING
716             bottomBorder.moveTo(offsetX + width, offsetY + height - bottomW / 2.0f);
717             bottomBorder.lineTo(x + w - brX * 2.0f, y + h - brY * 2.0f);
718             SkPath bottomClipPath;
719             bottomClipPath.moveTo(offsetX + width + rightW, offsetY + height + bottomW);
720             bottomClipPath.lineTo(offsetX + width - rightW * EXTEND, offsetY + height - bottomW * EXTEND);
721             bottomClipPath.lineTo(offsetX + width, offsetY + height - bottomW * EXTEND);
722             bottomClipPath.close();
723             canvas.clipPath(bottomClipPath, SkClipOp::kDifference, true);
724 #else
725             bottomBorder.MoveTo(offsetX + width, offsetY + height - bottomW / 2.0f);
726             bottomBorder.LineTo(x + w - brX * 2.0f, y + h - brY * 2.0f);
727             Drawing::Path bottomClipPath;
728             bottomClipPath.MoveTo(offsetX + width + rightW, offsetY + height + bottomW);
729             bottomClipPath.LineTo(offsetX + width - rightW * EXTEND, offsetY + height - bottomW * EXTEND);
730             bottomClipPath.LineTo(offsetX + width, offsetY + height - bottomW * EXTEND);
731             bottomClipPath.Close();
732             bottomClipPath.Offset(0.5, 0);
733             canvas.ClipPath(bottomClipPath, Drawing::ClipOp::DIFFERENCE, true);
734 #endif
735         }
736 #ifndef USE_ROSEN_DRAWING
737         bottomBorder.arcTo(rectStart, BOTTOM_START, SWEEP_ANGLE, false);
738         bottomBorder.arcTo(rectEnd, BOTTOM_END, SWEEP_ANGLE + 0.5f, false);
739 #else
740         bottomBorder.ArcTo(rectStart.GetLeft(), rectStart.GetTop(), rectStart.GetRight(), rectStart.GetBottom(),
741             BOTTOM_START, SWEEP_ANGLE);
742         bottomBorder.ArcTo(rectEnd.GetLeft(), rectEnd.GetTop(), rectEnd.GetRight(), rectEnd.GetBottom(),
743             BOTTOM_END, SWEEP_ANGLE + 0.5f);
744 #endif
745         if ((style == BorderStyle::SOLID) || (ROSEN_EQ(blX, 0.f) && !ROSEN_EQ(leftW, 0.f))) {
746 #ifndef USE_ROSEN_DRAWING
747             bottomBorder.lineTo(offsetX, offsetY + height - bottomW / 2.0f);
748             SkPath bottomClipPath;
749             bottomClipPath.moveTo(offsetX - leftW, offsetY + height + bottomW);
750             bottomClipPath.lineTo(offsetX + leftW * EXTEND, offsetY + height - bottomW * EXTEND);
751             bottomClipPath.lineTo(offsetX, offsetY + height - bottomW * EXTEND);
752             bottomClipPath.close();
753             canvas.clipPath(bottomClipPath, SkClipOp::kDifference, true);
754 #else
755             bottomBorder.LineTo(offsetX, offsetY + height - bottomW / 2.0f);
756             Drawing::Path bottomClipPath;
757             bottomClipPath.MoveTo(offsetX - leftW, offsetY + height + bottomW);
758             bottomClipPath.LineTo(offsetX + leftW * EXTEND, offsetY + height - bottomW * EXTEND);
759             bottomClipPath.LineTo(offsetX, offsetY + height - bottomW * EXTEND);
760             bottomClipPath.Close();
761             bottomClipPath.Offset(-0.5, 0);
762             canvas.ClipPath(bottomClipPath, Drawing::ClipOp::DIFFERENCE, true);
763 #endif
764         }
765 #ifndef USE_ROSEN_DRAWING
766         if (style == BorderStyle::SOLID) {
767             paint.setStyle(SkPaint::Style::kStrokeAndFill_Style);
768             canvas.drawRect(bottomBorder.getBounds(), paint);
769         } else {
770             canvas.drawPath(bottomBorder, paint);
771         }
772 #else
773         canvas.AttachPen(pen);
774         if (style == BorderStyle::SOLID) {
775             Drawing::Brush brush;
776             brush.SetColor(pen.GetColor());
777             brush.SetAntiAlias(true);
778             canvas.AttachBrush(brush);
779             canvas.DrawRect(bottomBorder.GetBounds());
780             canvas.DetachBrush();
781         } else {
782             canvas.DrawPath(bottomBorder);
783         }
784         canvas.DetachPen();
785 #endif
786     }
787 }
788 
789 #ifndef USE_ROSEN_DRAWING
790 void RSBorder::PaintLeftPath(
791     SkCanvas& canvas, SkPaint& paint, const SkRRect& rrect, const SkPoint& innerRectCenter) const
792 {
793     float offsetX = rrect.rect().x();
794     float offsetY = rrect.rect().y();
795     float height = rrect.rect().height();
796 #else
797 void RSBorder::PaintLeftPath(Drawing::Canvas& canvas, Drawing::Pen& pen, const Drawing::RoundRect& rrect,
798     const Drawing::Point& innerRectCenter) const
799 {
800     float offsetX = rrect.GetRect().GetLeft();
801     float offsetY = rrect.GetRect().GetTop();
802     float height = rrect.GetRect().GetHeight();
803 #endif
804     auto style = GetStyle(RSBorder::LEFT);
805     float leftW = GetWidth(RSBorder::LEFT);
806     float topW = GetWidth(RSBorder::TOP);
807     float rightW = GetWidth(RSBorder::RIGHT);
808     float bottomW = GetWidth(RSBorder::BOTTOM);
809     float x = offsetX + leftW / 2.0f;
810     float y = offsetY + topW / 2.0f;
811     float h = std::max(0.0f, height - (topW + bottomW) / 2.0f);
812 #ifndef USE_ROSEN_DRAWING
813     float tlX = std::max(0.0f, rrect.radii(SkRRect::kUpperLeft_Corner).x() - (topW + leftW) / 4.0f);
814     float tlY = std::max(0.0f, rrect.radii(SkRRect::kUpperLeft_Corner).y() - (topW + leftW) / 4.0f);
815     float blX = std::max(0.0f, rrect.radii(SkRRect::kLowerLeft_Corner).x() - (bottomW + leftW) / 4.0f);
816     float blY = std::max(0.0f, rrect.radii(SkRRect::kLowerLeft_Corner).y() - (bottomW + leftW) / 4.0f);
817 #else
818     float tlX = std::max(0.0f, rrect.GetCornerRadius(Drawing::RoundRect::TOP_LEFT_POS).GetX() - (topW + leftW) / 4.0f);
819     float tlY = std::max(0.0f, rrect.GetCornerRadius(Drawing::RoundRect::TOP_LEFT_POS).GetY() - (topW + leftW) / 4.0f);
820     float blX =
821         std::max(0.0f, rrect.GetCornerRadius(Drawing::RoundRect::BOTTOM_LEFT_POS).GetX() - (bottomW + leftW) / 4.0f);
822     float blY =
823         std::max(0.0f, rrect.GetCornerRadius(Drawing::RoundRect::BOTTOM_LEFT_POS).GetY() - (bottomW + leftW) / 4.0f);
824 #endif
825     if (leftW > 0.f) {
826 #ifndef USE_ROSEN_DRAWING
827         ApplyLineStyle(paint, RSBorder::LEFT, height);
828         auto rectStart = SkRect::MakeXYWH(x, y + h - blY * 2.0f, blX * 2.0f, blY * 2.0f);
829         auto rectEnd = SkRect::MakeXYWH(x, y, tlX * 2.0f, tlY * 2.0f);
830         SkPath leftBorder;
831         if (GetStyle(RSBorder::LEFT) != BorderStyle::DOTTED) {
832             paint.setStrokeWidth(std::max(std::max(leftW, topW), std::max(rightW, bottomW)));
833         }
834         SkAutoCanvasRestore acr(&canvas, true);
835         canvas.clipRect({ offsetX, offsetY, innerRectCenter.x(), offsetY + height });
836 #else
837         ApplyLineStyle(pen, RSBorder::LEFT, height);
838         auto rectStart = Drawing::Rect(x, y + h - blY * 2.0f, x + blX * 2.0f, y + h);
839         auto rectEnd = Drawing::Rect(x, y, x + tlX * 2.0f, y + tlY * 2.0f);
840         Drawing::Path leftBorder;
841         if (GetStyle(RSBorder::LEFT) != BorderStyle::DOTTED) {
842             pen.SetWidth(std::max(std::max(leftW, topW), std::max(rightW, bottomW)));
843         }
844         Drawing::AutoCanvasRestore acr(canvas, true);
845         canvas.ClipRect({ offsetX, offsetY, innerRectCenter.GetX(), offsetY + height });
846 #endif
847         if ((style == BorderStyle::SOLID) || (ROSEN_EQ(blX, 0.f) && !ROSEN_EQ(bottomW, 0.f))) {
848 #ifndef USE_ROSEN_DRAWING
849             leftBorder.moveTo(offsetX + leftW / 2.0f, offsetY + height);
850             leftBorder.lineTo(x, y + h - blY * 2.0f);
851             SkPath leftClipPath;
852             leftClipPath.moveTo(offsetX - leftW, offsetY + height + bottomW);
853             leftClipPath.lineTo(offsetX + leftW * EXTEND, offsetY + height - bottomW * EXTEND);
854             leftClipPath.lineTo(offsetX + leftW * EXTEND, offsetY + height);
855             leftClipPath.close();
856             canvas.clipPath(leftClipPath, SkClipOp::kDifference, true);
857 #else
858             leftBorder.MoveTo(offsetX + leftW / 2.0f, offsetY + height);
859             leftBorder.LineTo(x, y + h - blY * 2.0f);
860             Drawing::Path leftClipPath;
861             leftClipPath.MoveTo(offsetX - leftW, offsetY + height + bottomW);
862             leftClipPath.LineTo(offsetX + leftW * EXTEND, offsetY + height - bottomW * EXTEND);
863             leftClipPath.LineTo(offsetX + leftW * EXTEND, offsetY + height);
864             leftClipPath.Close();
865             leftClipPath.Offset(0, 0.5);
866             canvas.ClipPath(leftClipPath, Drawing::ClipOp::DIFFERENCE, true);
867 #endif
868         }
869 #ifndef USE_ROSEN_DRAWING
870         leftBorder.arcTo(rectStart, LEFT_START, SWEEP_ANGLE, false);
871         leftBorder.arcTo(rectEnd, LEFT_END, SWEEP_ANGLE + 0.5f, false);
872 #else
873 
874         leftBorder.ArcTo(rectStart.GetLeft(), rectStart.GetTop(), rectStart.GetRight(), rectStart.GetBottom(),
875             LEFT_START, SWEEP_ANGLE);
876         leftBorder.ArcTo(rectEnd.GetLeft(), rectEnd.GetTop(), rectEnd.GetRight(), rectEnd.GetBottom(),
877             LEFT_END, SWEEP_ANGLE + 0.5f);
878 #endif
879         if ((style == BorderStyle::SOLID) || (ROSEN_EQ(tlX, 0.f) && !ROSEN_EQ(topW, 0.f))) {
880 #ifndef USE_ROSEN_DRAWING
881             leftBorder.lineTo(offsetX + leftW / 2.0f, offsetY);
882             SkPath leftClipPath;
883             leftClipPath.moveTo(offsetX - leftW, offsetY - topW);
884             leftClipPath.lineTo(offsetX + leftW * EXTEND, offsetY + topW * EXTEND);
885             leftClipPath.lineTo(offsetX + leftW * EXTEND, offsetY);
886             leftClipPath.close();
887             canvas.clipPath(leftClipPath, SkClipOp::kDifference, true);
888 #else
889             leftBorder.LineTo(offsetX + leftW / 2.0f, offsetY);
890             Drawing::Path leftClipPath;
891             leftClipPath.MoveTo(offsetX - leftW, offsetY - topW);
892             leftClipPath.LineTo(offsetX + leftW * EXTEND, offsetY + topW * EXTEND);
893             leftClipPath.LineTo(offsetX + leftW * EXTEND, offsetY);
894             leftClipPath.Close();
895             leftClipPath.Offset(0, -0.5);
896             canvas.ClipPath(leftClipPath, Drawing::ClipOp::DIFFERENCE, true);
897 #endif
898         }
899 #ifndef USE_ROSEN_DRAWING
900         if (style == BorderStyle::SOLID) {
901             paint.setStyle(SkPaint::Style::kStrokeAndFill_Style);
902             canvas.drawRect(leftBorder.getBounds(), paint);
903         } else {
904             canvas.drawPath(leftBorder, paint);
905         }
906 #else
907         canvas.AttachPen(pen);
908         if (style == BorderStyle::SOLID) {
909             Drawing::Brush brush;
910             brush.SetColor(pen.GetColor());
911             brush.SetAntiAlias(true);
912             canvas.AttachBrush(brush);
913             canvas.DrawRect(leftBorder.GetBounds());
914             canvas.DetachBrush();
915         } else {
916             canvas.DrawPath(leftBorder);
917         }
918         canvas.DetachPen();
919 #endif
920     }
921 }
922 
923 std::string RSBorder::ToString() const
924 {
925     std::stringstream ss;
926     if (colors_.size() > 0) {
927         ss << "colors: ";
928     }
929     for (auto color : colors_) {
930         ss << color.AsArgbInt() << ", ";
931     }
932     if (widths_.size() > 0) {
933         ss << "widths: ";
934     }
935     for (auto width : widths_) {
936         ss << width << ", ";
937     }
938     if (styles_.size() > 0) {
939         ss << "styles: ";
940     }
941     for (auto style : styles_) {
942         ss << static_cast<uint32_t>(style) << ", ";
943     }
944     std::string output = ss.str();
945     return output;
946 }
947 
948 bool RSBorder::HasBorder() const
949 {
950     return !colors_.empty() && !widths_.empty() && !styles_.empty() &&
951         !std::all_of(colors_.begin(), colors_.end(), [](const Color& color) { return color.GetAlpha() == 0; }) &&
952         !std::all_of(widths_.begin(), widths_.end(), [](const float& width) { return width <= 0.f; }) &&
953         !std::all_of(
954             styles_.begin(), styles_.end(), [](const BorderStyle& style) { return style == BorderStyle::NONE; });
955 }
956 } // namespace Rosen
957 } // namespace OHOS
958