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