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