1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components/common/painter/rosen_decoration_painter.h"
17 
18 #ifndef USE_ROSEN_DRAWING
19 #include "include/core/SkBitmap.h"
20 #include "include/core/SkCanvas.h"
21 #include "include/core/SkColor.h"
22 #include "include/core/SkColorFilter.h"
23 #include "include/core/SkImage.h"
24 #include "include/core/SkMaskFilter.h"
25 #include "include/effects/Sk1DPathEffect.h"
26 #include "include/effects/SkDashPathEffect.h"
27 #include "include/effects/SkGradientShader.h"
28 #include "include/effects/SkImageFilters.h"
29 #include "include/utils/SkShadowUtils.h"
30 #endif
31 
32 #include "core/components/common/painter/border_image_painter.h"
33 #include "core/pipeline/base/rosen_render_context.h"
34 
35 namespace OHOS::Ace {
36 namespace {
37 
38 constexpr int32_t DOUBLE_WIDTH = 2;
39 constexpr int32_t DASHED_LINE_LENGTH = 3;
40 constexpr int32_t DEL_NUM = 2;
41 
42 constexpr float TOP_START = 225.0f;
43 constexpr float TOP_END = 270.0f;
44 constexpr float RIGHT_START = 315.0f;
45 constexpr float RIGHT_END = 0.0f;
46 constexpr float BOTTOM_START = 45.0f;
47 constexpr float BOTTOM_END = 90.0f;
48 constexpr float LEFT_START = 135.0f;
49 constexpr float LEFT_END = 180.0f;
50 constexpr float SWEEP_ANGLE = 45.0f;
51 
52 constexpr float EXTEND = 1024.0f;
53 constexpr uint32_t COLOR_MASK = 0xff000000;
54 #ifdef USE_ROSEN_DRAWING
55 constexpr float FLOAT_HALF = 0.5f;
56 #endif
57 
58 class GradientShader {
59 public:
60     struct ColorStop {
61 #ifndef USE_ROSEN_DRAWING
62         SkColor color { SK_ColorTRANSPARENT };
63 #else
64         RSColorQuad color { RSColor::COLOR_TRANSPARENT };
65 #endif
66         float offset { 0.0f };
67         bool hasValue { false };
68         bool isLength { false };
69     };
70 
GradientShader(const Gradient & gradient)71     explicit GradientShader(const Gradient& gradient)
72     {
73         for (auto& stop : gradient.GetColors()) {
74             ColorStop colorStop;
75             colorStop.color = stop.GetColor().GetValue();
76             colorStop.hasValue = stop.GetHasValue();
77             if (colorStop.hasValue) {
78                 colorStop.isLength = stop.GetDimension().Unit() != DimensionUnit::PERCENT;
79                 if (colorStop.isLength) {
80                     colorStop.offset = static_cast<float>(stop.GetDimension().Value());
81                 } else {
82                     colorStop.offset = static_cast<float>(stop.GetDimension().Value() / 100.0);
83                 }
84             }
85             colorStops_.emplace_back(colorStop);
86         }
87         isRepeat_ = gradient.GetRepeat();
88     }
89     virtual ~GradientShader() = default;
90 #ifndef USE_ROSEN_DRAWING
CreateGradientShader()91     virtual sk_sp<SkShader> CreateGradientShader()
92 #else
93     virtual std::shared_ptr<RSShaderEffect> CreateGradientShader()
94 #endif
95     {
96         return nullptr;
97     }
98 
99 protected:
AddColorStops(float gradientLength)100     void AddColorStops(float gradientLength)
101     {
102         uint32_t colorSize = colorStops_.size();
103         for (uint32_t i = 0; i < colorSize; i++) {
104             auto& colorStop = colorStops_[i];
105             if (colorStop.hasValue) {
106                 if (colorStop.isLength) {
107                     // only support px and percent
108                     colorStop.offset = GreatNotEqual(gradientLength, 0.0) ? colorStop.offset / gradientLength : 0.0f;
109                     colorStop.hasValue = true;
110                 }
111             } else if (i == 0) {
112                 // default: start with 0.0%
113                 colorStop.offset = 0.0f;
114                 colorStop.hasValue = true;
115             } else if (colorSize > 1 && i == colorSize - 1) {
116                 // default: end with 100.0%
117                 colorStop.offset = 1.0f;
118                 colorStop.hasValue = true;
119             }
120             // make sure colors in increasing order
121             if (colorStop.hasValue && i > 0) {
122                 auto prev = static_cast<int32_t>(i - 1);
123                 while (prev >= 0 && !colorStops_[prev].hasValue) {
124                     prev--;
125                 }
126                 if (prev >= 0 && colorStop.offset < colorStops_[prev].offset) {
127                     colorStop.offset = colorStops_[prev].offset;
128                 }
129             }
130         }
131         AdjustNoValueColorStop();
132     }
133 
AdjustNoValueColorStop()134     void AdjustNoValueColorStop()
135     {
136         // deal with not specified color stop
137         uint32_t colorSize = colorStops_.size();
138         if (colorSize <= 2) {
139             return;
140         }
141         int32_t noValueStartIndex = 0;
142         bool inUnspecifiedRun = false;
143         for (uint32_t i = 0; i < colorSize; ++i) {
144             if (!colorStops_[i].hasValue && !inUnspecifiedRun) {
145                 noValueStartIndex = static_cast<int32_t>(i);
146                 inUnspecifiedRun = true;
147             } else if (colorStops_[i].hasValue && inUnspecifiedRun) {
148                 auto noValueEndIndex = static_cast<int32_t>(i);
149                 if (noValueStartIndex < noValueEndIndex) {
150                     auto beginValue = colorStops_[noValueStartIndex - 1].offset;
151                     auto endValue = colorStops_[noValueEndIndex].offset;
152                     auto delta = (endValue - beginValue) / static_cast<float>(noValueEndIndex - noValueStartIndex + 1);
153 
154                     for (int32_t j = noValueStartIndex; j < noValueEndIndex; ++j) {
155                         colorStops_[j].offset = (beginValue + static_cast<float>(j - noValueStartIndex + 1) * delta);
156                         colorStops_[j].hasValue = true;
157                     }
158                 }
159                 inUnspecifiedRun = false;
160             }
161         }
162     }
163 
NeedAdjustColorStops() const164     bool NeedAdjustColorStops() const
165     {
166         if (colorStops_.size() < 2) {
167             return false;
168         }
169 
170         if (isRepeat_) {
171             return true;
172         }
173         // not in the range of [0, 1]
174         if (colorStops_.front().offset < 0.0f || colorStops_.back().offset > 1.0f) {
175             return true;
176         }
177         return false;
178     }
179 
AdjustColorStops()180     void AdjustColorStops()
181     {
182         const auto firstOffset = colorStops_.front().offset;
183         const auto lastOffset = colorStops_.back().offset;
184         const float span = std::min(std::max(lastOffset - firstOffset, 0.0f), std::numeric_limits<float>::max());
185         if (NearZero(span)) {
186             return;
187         }
188         for (auto& stop : colorStops_) {
189             const auto relativeOffset = std::min(stop.offset - firstOffset, std::numeric_limits<float>::max());
190             const auto adjustOffset = relativeOffset / span;
191             stop.offset = adjustOffset;
192         }
193     }
194 
195 #ifndef USE_ROSEN_DRAWING
ToSkColors(std::vector<SkScalar> & pos,std::vector<SkColor> & colors) const196     void ToSkColors(std::vector<SkScalar>& pos, std::vector<SkColor>& colors) const
197 #else
198     void ToDrawingColors(std::vector<RSScalar>& pos, std::vector<RSColorQuad>& colors) const
199 #endif
200     {
201 #ifndef USE_ROSEN_DRAWING
202         if (colorStops_.empty()) {
203             pos.push_back(0.0f);
204             colors.push_back(SK_ColorTRANSPARENT);
205         } else if (colorStops_.front().offset > 0.0f) {
206             pos.push_back(0.0f);
207             colors.push_back(SkColor(colorStops_.front().color));
208         }
209 #else
210         if (colorStops_.empty()) {
211             pos.push_back(0.0f);
212             colors.push_back(RSColor::COLOR_TRANSPARENT);
213         } else if (colorStops_.front().offset > 0.0f) {
214             pos.push_back(0.0f);
215             colors.push_back(colorStops_.front().color);
216         }
217 #endif
218 
219         for (const auto& stop : colorStops_) {
220             pos.push_back(stop.offset);
221             colors.push_back(stop.color);
222         }
223 
224         if (pos.back() < 1.0f) {
225             pos.push_back(1.0f);
226             colors.push_back(colors.back());
227         }
228     }
229 
230 protected:
231     std::vector<ColorStop> colorStops_;
232     bool isRepeat_ { false };
233 };
234 
235 class LinearGradientShader final : public GradientShader {
236 public:
237 #ifndef USE_ROSEN_DRAWING
LinearGradientShader(const Gradient & gradient,const SkPoint & firstPoint,const SkPoint & secondPoint)238     LinearGradientShader(const Gradient& gradient, const SkPoint& firstPoint, const SkPoint& secondPoint)
239         : GradientShader(gradient), firstPoint_(firstPoint), secondPoint_(secondPoint)
240     {}
241 #else
242     LinearGradientShader(const Gradient& gradient, const RSPoint& firstPoint, const RSPoint& secondPoint)
243         : GradientShader(gradient), firstPoint_(firstPoint), secondPoint_(secondPoint)
244     {}
245 #endif
246     ~LinearGradientShader() = default;
247 
248 #ifndef USE_ROSEN_DRAWING
CreateGradientShader()249     sk_sp<SkShader> CreateGradientShader() override
250     {
251         AddColorStops((secondPoint_ - firstPoint_).length());
252         if (NeedAdjustColorStops()) {
253             auto startOffset = colorStops_.front().offset;
254             auto endOffset = colorStops_.back().offset;
255             AdjustColorStops();
256             AdjustPoint(startOffset, endOffset);
257         }
258 
259         std::vector<SkScalar> pos;
260         std::vector<SkColor> colors;
261         ToSkColors(pos, colors);
262         SkPoint pts[2] = { firstPoint_, secondPoint_ };
263 
264         SkTileMode tileMode = SkTileMode::kClamp;
265         if (isRepeat_) {
266             tileMode = SkTileMode::kRepeat;
267         }
268         return SkGradientShader::MakeLinear(pts, &colors[0], &pos[0], colors.size(), tileMode);
269     }
270 #else
CreateGradientShader()271     std::shared_ptr<RSShaderEffect> CreateGradientShader() override
272     {
273         auto point = secondPoint_ - firstPoint_;
274         AddColorStops(std::sqrt(std::pow(point.GetX(), 2) + std::pow(point.GetY(), 2)));
275         if (NeedAdjustColorStops()) {
276             auto startOffset = colorStops_.front().offset;
277             auto endOffset = colorStops_.back().offset;
278             AdjustColorStops();
279             AdjustPoint(startOffset, endOffset);
280         }
281 
282         std::vector<RSScalar> pos;
283         std::vector<RSColorQuad> colors;
284         ToDrawingColors(pos, colors);
285         RSTileMode tileMode = RSTileMode::CLAMP;
286         if (isRepeat_) {
287             tileMode = RSTileMode::REPEAT;
288         }
289         return RSRecordingShaderEffect::CreateLinearGradient(firstPoint_, secondPoint_, colors, pos, tileMode);
290     }
291 #endif
292 
293 #ifndef USE_ROSEN_DRAWING
CreateLinearGradient(const Gradient & gradient,const SkSize & size)294     static std::unique_ptr<GradientShader> CreateLinearGradient(const Gradient& gradient, const SkSize& size)
295     {
296         auto linearGradient = gradient.GetLinearGradient();
297         SkPoint firstPoint { 0.0f, 0.0f };
298         SkPoint secondPoint { 0.0f, 0.0f };
299         if (linearGradient.angle) {
300             EndPointsFromAngle(linearGradient.angle.value().Value(), size, firstPoint, secondPoint);
301         } else {
302             if (linearGradient.linearX && linearGradient.linearY) {
303                 float width = size.width();
304                 float height = size.height();
305                 if (linearGradient.linearX == GradientDirection::LEFT) {
306                     height *= -1;
307                 }
308                 if (linearGradient.linearY == GradientDirection::BOTTOM) {
309                     width *= -1;
310                 }
311                 float angle = 90.0f - Rad2deg(atan2(width, height));
312                 EndPointsFromAngle(angle, size, firstPoint, secondPoint);
313             } else if (linearGradient.linearX || linearGradient.linearY) {
314                 secondPoint = DirectionToPoint(linearGradient.linearX, linearGradient.linearY, size);
315                 if (linearGradient.linearX) {
316                     firstPoint.fX = size.width() - secondPoint.x();
317                 }
318                 if (linearGradient.linearY) {
319                     firstPoint.fY = size.height() - secondPoint.y();
320                 }
321             } else {
322                 secondPoint.set(0.0f, size.height());
323             }
324         }
325         return std::make_unique<LinearGradientShader>(gradient, firstPoint, secondPoint);
326     }
327 #else
CreateLinearGradient(const Gradient & gradient,const RSSize & size)328     static std::unique_ptr<GradientShader> CreateLinearGradient(const Gradient& gradient, const RSSize& size)
329     {
330         auto linearGradient = gradient.GetLinearGradient();
331         RSPoint firstPoint { 0.0f, 0.0f };
332         RSPoint secondPoint { 0.0f, 0.0f };
333         if (linearGradient.angle) {
334             EndPointsFromAngle(linearGradient.angle.value().Value(), size, firstPoint, secondPoint);
335         } else {
336             if (linearGradient.linearX && linearGradient.linearY) {
337                 float width = size.Width();
338                 float height = size.Height();
339                 if (linearGradient.linearX == GradientDirection::LEFT) {
340                     height *= -1;
341                 }
342                 if (linearGradient.linearY == GradientDirection::BOTTOM) {
343                     width *= -1;
344                 }
345                 float angle = 90.0f - Rad2deg(atan2(width, height));
346                 EndPointsFromAngle(angle, size, firstPoint, secondPoint);
347             } else if (linearGradient.linearX || linearGradient.linearY) {
348                 secondPoint = DirectionToPoint(linearGradient.linearX, linearGradient.linearY, size);
349                 if (linearGradient.linearX) {
350                     firstPoint.SetX(size.Width() - secondPoint.GetX());
351                 }
352                 if (linearGradient.linearY) {
353                     firstPoint.SetY(size.Height() - secondPoint.GetY());
354                 }
355             } else {
356                 secondPoint = { 0.0f, size.Height() };
357             }
358         }
359         return std::make_unique<LinearGradientShader>(gradient, firstPoint, secondPoint);
360     }
361 #endif
362 
363 private:
AdjustPoint(float firstOffset,float lastOffset)364     void AdjustPoint(float firstOffset, float lastOffset)
365     {
366         const auto delta = secondPoint_ - firstPoint_;
367         secondPoint_ = firstPoint_ + delta * lastOffset;
368         firstPoint_ = firstPoint_ + delta * firstOffset;
369     }
370 
Deg2rad(float deg)371     static float Deg2rad(float deg)
372     {
373         return static_cast<float>(deg * M_PI / 180.0);
374     }
375 
Rad2deg(float rad)376     static float Rad2deg(float rad)
377     {
378         return static_cast<float>(rad * 180.0 / M_PI);
379     }
380 
381 #ifndef USE_ROSEN_DRAWING
EndPointsFromAngle(float angle,const SkSize & size,SkPoint & firstPoint,SkPoint & secondPoint)382     static void EndPointsFromAngle(float angle, const SkSize& size, SkPoint& firstPoint, SkPoint& secondPoint)
383     {
384         angle = fmod(angle, 360.0f);
385         if (LessNotEqual(angle, 0.0)) {
386             angle += 360.0f;
387         }
388 
389         if (NearEqual(angle, 0.0)) {
390             firstPoint.set(0.0f, size.height());
391             secondPoint.set(0.0f, 0.0f);
392             return;
393         } else if (NearEqual(angle, 90.0)) {
394             firstPoint.set(0.0f, 0.0f);
395             secondPoint.set(size.width(), 0.0f);
396             return;
397         } else if (NearEqual(angle, 180.0)) {
398             firstPoint.set(0.0f, 0.0f);
399             secondPoint.set(0, size.height());
400             return;
401         } else if (NearEqual(angle, 270.0)) {
402             firstPoint.set(size.width(), 0.0f);
403             secondPoint.set(0.0f, 0.0f);
404             return;
405         }
406         float slope = tan(Deg2rad(90.0f - angle));
407         float perpendicularSlope = -1 / slope;
408 
409         float halfHeight = size.height() / 2;
410         float halfWidth = size.width() / 2;
411         SkPoint cornerPoint { 0.0f, 0.0f };
412         if (angle < 90.0) {
413             cornerPoint.set(halfWidth, halfHeight);
414         } else if (angle < 180) {
415             cornerPoint.set(halfWidth, -halfHeight);
416         } else if (angle < 270) {
417             cornerPoint.set(-halfWidth, -halfHeight);
418         } else {
419             cornerPoint.set(-halfWidth, halfHeight);
420         }
421 
422         // Compute b (of y = kx + b) using the corner point.
423         float b = cornerPoint.y() - perpendicularSlope * cornerPoint.x();
424         float endX = b / (slope - perpendicularSlope);
425         float endY = perpendicularSlope * endX + b;
426 
427         secondPoint.set(halfWidth + endX, halfHeight - endY);
428         firstPoint.set(halfWidth - endX, halfHeight + endY);
429     }
430 #else
EndPointsFromAngle(float angle,const RSSize & size,RSPoint & firstPoint,RSPoint & secondPoint)431     static void EndPointsFromAngle(float angle, const RSSize& size, RSPoint& firstPoint, RSPoint& secondPoint)
432     {
433         angle = fmod(angle, 360.0f);
434         if (LessNotEqual(angle, 0.0)) {
435             angle += 360.0f;
436         }
437 
438         if (NearEqual(angle, 0.0)) {
439             firstPoint = { 0.0f, size.Height() };
440             secondPoint = { 0.0f, 0.0f };
441             return;
442         } else if (NearEqual(angle, 90.0)) {
443             firstPoint = { 0.0f, 0.0f };
444             secondPoint = { size.Width(), 0.0f };
445             return;
446         } else if (NearEqual(angle, 180.0)) {
447             firstPoint = { 0.0f, 0.0f };
448             secondPoint = { 0, size.Height() };
449             return;
450         } else if (NearEqual(angle, 270.0)) {
451             firstPoint = { size.Width(), 0.0f };
452             secondPoint = { 0.0f, 0.0f };
453             return;
454         }
455         float slope = tan(Deg2rad(90.0f - angle));
456         float perpendicularSlope = -1 / slope;
457 
458         float halfHeight = size.Height() / 2;
459         float halfWidth = size.Width() / 2;
460         RSPoint cornerPoint { 0.0f, 0.0f };
461         if (angle < 90.0) {
462             cornerPoint = { halfWidth, halfHeight };
463         } else if (angle < 180) {
464             cornerPoint = { halfWidth, -halfHeight };
465         } else if (angle < 270) {
466             cornerPoint = { -halfWidth, -halfHeight };
467         } else {
468             cornerPoint = { -halfWidth, halfHeight };
469         }
470 
471         // Compute b (of y = kx + b) using the corner point.
472         float b = cornerPoint.GetY() - perpendicularSlope * cornerPoint.GetX();
473         float endX = b / (slope - perpendicularSlope);
474         float endY = perpendicularSlope * endX + b;
475 
476         secondPoint = { halfWidth + endX, halfHeight - endY };
477         firstPoint = { halfWidth - endX, halfHeight + endY };
478     }
479 #endif
480 
481 #ifndef USE_ROSEN_DRAWING
DirectionToPoint(const std::optional<GradientDirection> & x,const std::optional<GradientDirection> & y,const SkSize & size)482     static SkPoint DirectionToPoint(
483         const std::optional<GradientDirection>& x, const std::optional<GradientDirection>& y, const SkSize& size)
484     {
485         SkPoint point { 0.0f, 0.0f };
486         if (x) {
487             if (x == GradientDirection::LEFT) {
488                 point.fX = 0.0f;
489             } else {
490                 point.fX = size.width();
491             }
492         }
493 
494         if (y) {
495             if (y == GradientDirection::TOP) {
496                 point.fY = 0.0f;
497             } else {
498                 point.fY = size.height();
499             }
500         }
501 
502         return point;
503     }
504 #else
DirectionToPoint(const std::optional<GradientDirection> & x,const std::optional<GradientDirection> & y,const RSSize & size)505     static RSPoint DirectionToPoint(
506         const std::optional<GradientDirection>& x, const std::optional<GradientDirection>& y, const RSSize& size)
507     {
508         RSPoint point { 0.0f, 0.0f };
509         if (x) {
510             if (x == GradientDirection::LEFT) {
511                 point.SetX(0.0f);
512             } else {
513                 point.SetX(size.Width());
514             }
515         }
516 
517         if (y) {
518             if (y == GradientDirection::TOP) {
519                 point.SetY(0.0f);
520             } else {
521                 point.SetY(size.Height());
522             }
523         }
524 
525         return point;
526     }
527 #endif
528 
529 private:
530 #ifndef USE_ROSEN_DRAWING
531     SkPoint firstPoint_ { 0.0f, 0.0f };
532     SkPoint secondPoint_ { 0.0f, 0.0f };
533 #else
534     RSPoint firstPoint_ { 0.0f, 0.0f };
535     RSPoint secondPoint_ { 0.0f, 0.0f };
536 #endif
537 };
538 
539 class RadialGradientShader final : public GradientShader {
540 public:
541 #ifndef USE_ROSEN_DRAWING
RadialGradientShader(const Gradient & gradient,const SkPoint & center,float radius0,float radius1,float ratio)542     RadialGradientShader(const Gradient& gradient, const SkPoint& center, float radius0, float radius1, float ratio)
543         : GradientShader(gradient), center_(center), radius0_(radius0), radius1_(radius1), ratio_(ratio)
544     {}
545 #else
546     RadialGradientShader(const Gradient& gradient, const RSPoint& center, float radius0, float radius1, float ratio)
547         : GradientShader(gradient), center_(center), radius0_(radius0), radius1_(radius1), ratio_(ratio)
548     {}
549 #endif
550 
551     ~RadialGradientShader() = default;
552 
553 #ifndef USE_ROSEN_DRAWING
CreateGradientShader()554     sk_sp<SkShader> CreateGradientShader() override
555     {
556         SkMatrix matrix = SkMatrix::I();
557         ratio_ = NearZero(ratio_) ? 1.0f : ratio_;
558         if (ratio_ != 1.0f) {
559             matrix.preScale(1.0f, 1 / ratio_, center_.x(), center_.y());
560         }
561         AddColorStops(radius1_);
562         if (NeedAdjustColorStops()) {
563             auto startOffset = colorStops_.front().offset;
564             auto endOffset = colorStops_.back().offset;
565             AdjustColorStops();
566             AdjustRadius(startOffset, endOffset);
567         }
568 
569         SkTileMode tileMode = SkTileMode::kClamp;
570         if (isRepeat_) {
571             ClampNegativeOffsets();
572 
573             tileMode = SkTileMode::kRepeat;
574         }
575         std::vector<SkScalar> pos;
576         std::vector<SkColor> colors;
577         ToSkColors(pos, colors);
578         radius0_ = std::max(radius0_, 0.0f);
579         radius1_ = std::max(radius1_, 0.0f);
580         return SkGradientShader::MakeTwoPointConical(
581             center_, radius0_, center_, radius1_, &colors[0], &pos[0], colors.size(), tileMode, 0, &matrix);
582     }
583 #else
CreateGradientShader()584     std::shared_ptr<RSShaderEffect> CreateGradientShader() override
585     {
586         RSMatrix matrix;
587         ratio_ = NearZero(ratio_) ? 1.0f : ratio_;
588         if (ratio_ != 1.0f) {
589             matrix.Scale(1.0f, 1 / ratio_, center_.GetX(), center_.GetY());
590         }
591         AddColorStops(radius1_);
592         if (NeedAdjustColorStops()) {
593             auto startOffset = colorStops_.front().offset;
594             auto endOffset = colorStops_.back().offset;
595             AdjustColorStops();
596             AdjustRadius(startOffset, endOffset);
597         }
598 
599         RSTileMode tileMode = RSTileMode::CLAMP;
600         if (isRepeat_) {
601             ClampNegativeOffsets();
602             tileMode = RSTileMode::REPEAT;
603         }
604         std::vector<RSScalar> pos;
605         std::vector<RSColorQuad> colors;
606         ToDrawingColors(pos, colors);
607         radius0_ = std::max(radius0_, 0.0f);
608         radius1_ = std::max(radius1_, 0.0f);
609         return RSRecordingShaderEffect::CreateTwoPointConical(
610             center_, radius0_, center_, radius1_, colors, pos, tileMode, &matrix);
611     }
612 #endif
613 
614 #ifndef USE_ROSEN_DRAWING
CreateRadialGradient(const Gradient & gradient,const SkSize & size,float dipScale)615     static std::unique_ptr<GradientShader> CreateRadialGradient(
616         const Gradient& gradient, const SkSize& size, float dipScale)
617     {
618         auto radialGradient = gradient.GetRadialGradient();
619         SkPoint center = GetCenter(radialGradient, size, dipScale);
620         SkSize circleSize = GetCircleSize(radialGradient, size, center, dipScale);
621         bool isDegenerate = NearZero(circleSize.width()) || NearZero(circleSize.height());
622         float ratio = NearZero(circleSize.height()) ? 1.0f : circleSize.width() / circleSize.height();
623         float radius0 = 0.0f;
624         float radius1 = circleSize.width();
625         if (isDegenerate) {
626             ratio = 1.0f;
627             radius1 = 0.0f;
628         }
629         return std::make_unique<RadialGradientShader>(gradient, center, radius0, radius1, ratio);
630     }
631 #else
CreateRadialGradient(const Gradient & gradient,const RSSize & size,float dipScale)632     static std::unique_ptr<GradientShader> CreateRadialGradient(
633         const Gradient& gradient, const RSSize& size, float dipScale)
634     {
635         auto radialGradient = gradient.GetRadialGradient();
636         RSPoint center = GetCenter(radialGradient, size, dipScale);
637         RSSize circleSize = GetCircleSize(radialGradient, size, center, dipScale);
638         bool isDegenerate = NearZero(circleSize.Width()) || NearZero(circleSize.Height());
639         float ratio = NearZero(circleSize.Height()) ? 1.0f : circleSize.Width() / circleSize.Height();
640         float radius0 = 0.0f;
641         float radius1 = circleSize.Width();
642         if (isDegenerate) {
643             ratio = 1.0f;
644             radius1 = 0.0f;
645         }
646         return std::make_unique<RadialGradientShader>(gradient, center, radius0, radius1, ratio);
647     }
648 #endif
649 
650 private:
AdjustRadius(float firstOffset,float lastOffset)651     void AdjustRadius(float firstOffset, float lastOffset)
652     {
653         float adjustedR0 = radius1_ * firstOffset;
654         float adjustedR1 = radius1_ * lastOffset;
655         if (adjustedR0 < 0.0) {
656             const float radiusSpan = adjustedR1 - adjustedR0;
657             const float shiftToPositive = radiusSpan * ceilf(-adjustedR0 / radiusSpan);
658             adjustedR0 += shiftToPositive;
659             adjustedR1 += shiftToPositive;
660         }
661         radius0_ = adjustedR0;
662         radius1_ = adjustedR1;
663     }
664 
ClampNegativeOffsets()665     void ClampNegativeOffsets()
666     {
667         float lastNegativeOffset = 0.0f;
668         for (uint32_t i = 0; i < colorStops_.size(); ++i) {
669             auto current = colorStops_[i].offset;
670             if (GreatOrEqual(current, 0.0f)) {
671                 if (i > 0) {
672                     float fraction = -lastNegativeOffset / (current - lastNegativeOffset);
673                     LinearEvaluator<Color> evaluator;
674                     Color adjustColor =
675                         evaluator.Evaluate(Color(colorStops_[i - 1].color), Color(colorStops_[i].color), fraction);
676                     colorStops_[i - 1].color = adjustColor.GetValue();
677                 }
678                 break;
679             }
680             colorStops_[i].offset = 0.0f;
681             lastNegativeOffset = current;
682         }
683     }
684 
685 #ifndef USE_ROSEN_DRAWING
GetCenter(const RadialGradient & radialGradient,const SkSize & size,float dipScale)686     static SkPoint GetCenter(const RadialGradient& radialGradient, const SkSize& size, float dipScale)
687     {
688         SkPoint center = SkPoint::Make(size.width() / 2.0f, size.height() / 2.0f);
689         if (radialGradient.radialCenterX) {
690             const auto& value = radialGradient.radialCenterX.value();
691             center.fX = static_cast<float>(value.Unit() == DimensionUnit::PERCENT ? value.Value() / 100.0 * size.width()
692                                                                                   : value.ConvertToPx(dipScale));
693         }
694         if (radialGradient.radialCenterY) {
695             const auto& value = radialGradient.radialCenterY.value();
696             center.fY =
697                 static_cast<float>(value.Unit() == DimensionUnit::PERCENT ? value.Value() / 100.0 * size.height()
698                                                                           : value.ConvertToPx(dipScale));
699         }
700         return center;
701     }
702 #else
GetCenter(const RadialGradient & radialGradient,const RSSize & size,float dipScale)703     static RSPoint GetCenter(const RadialGradient& radialGradient, const RSSize& size, float dipScale)
704     {
705         RSPoint center = RSPoint(size.Width() / 2.0f, size.Height() / 2.0f);
706         if (radialGradient.radialCenterX) {
707             const auto& value = radialGradient.radialCenterX.value();
708             center.SetX(static_cast<float>(value.Unit() == DimensionUnit::PERCENT ? value.Value() / 100.0 * size.Width()
709                                                                                   : value.ConvertToPx(dipScale)));
710         }
711         if (radialGradient.radialCenterY) {
712             const auto& value = radialGradient.radialCenterY.value();
713             center.SetY(
714                 static_cast<float>(value.Unit() == DimensionUnit::PERCENT ? value.Value() / 100.0 * size.Height()
715                                                                           : value.ConvertToPx(dipScale)));
716         }
717         return center;
718     }
719 #endif
720 
721 #ifndef USE_ROSEN_DRAWING
GetCircleSize(const RadialGradient & radialGradient,const SkSize & size,const SkPoint & center,float dipScale)722     static SkSize GetCircleSize(
723         const RadialGradient& radialGradient, const SkSize& size, const SkPoint& center, float dipScale)
724     {
725         SkSize circleSize { 0.0f, 0.0f };
726         if (radialGradient.radialHorizontalSize) {
727             const auto& hValue = radialGradient.radialHorizontalSize.value();
728             circleSize.fWidth = static_cast<float>(
729                 hValue.Unit() == DimensionUnit::PERCENT ? hValue.Value() * size.width() : hValue.ConvertToPx(dipScale));
730             circleSize.fHeight = circleSize.fWidth;
731             if (radialGradient.radialVerticalSize) {
732                 const auto& wValue = radialGradient.radialVerticalSize.value();
733                 circleSize.fHeight =
734                     static_cast<float>(wValue.Unit() == DimensionUnit::PERCENT ? wValue.Value() * size.height()
735                                                                                : wValue.ConvertToPx(dipScale));
736             }
737         } else {
738             RadialShapeType shape = RadialShapeType::ELLIPSE;
739             if ((radialGradient.radialShape && radialGradient.radialShape.value() == RadialShapeType::CIRCLE) ||
740                 (!radialGradient.radialShape && !radialGradient.radialSizeType && radialGradient.radialHorizontalSize &&
741                     !radialGradient.radialVerticalSize)) {
742                 shape = RadialShapeType::CIRCLE;
743             }
744             auto sizeType =
745                 radialGradient.radialSizeType ? radialGradient.radialSizeType.value() : RadialSizeType::NONE;
746             switch (sizeType) {
747                 case RadialSizeType::CLOSEST_SIDE:
748                     circleSize = RadiusToSide(center, size, shape, std::less<>());
749                     break;
750                 case RadialSizeType::FARTHEST_SIDE:
751                     circleSize = RadiusToSide(center, size, shape, std::greater<>());
752                     break;
753                 case RadialSizeType::CLOSEST_CORNER:
754                     circleSize = RadiusToCorner(center, size, shape, std::less<>());
755                     break;
756                 case RadialSizeType::FARTHEST_CORNER:
757                 case RadialSizeType::NONE:
758                 default:
759                     circleSize = RadiusToCorner(center, size, shape, std::greater<>());
760                     break;
761             }
762         }
763         return circleSize;
764     }
765 #else
GetCircleSize(const RadialGradient & radialGradient,const RSSize & size,const RSPoint & center,float dipScale)766     static RSSize GetCircleSize(
767         const RadialGradient& radialGradient, const RSSize& size, const RSPoint& center, float dipScale)
768     {
769         RSSize circleSize { 0.0f, 0.0f };
770         if (radialGradient.radialHorizontalSize) {
771             const auto& hValue = radialGradient.radialHorizontalSize.value();
772             RSScalar value = static_cast<float>(
773                 hValue.Unit() == DimensionUnit::PERCENT ? hValue.Value() * size.Width() : hValue.ConvertToPx(dipScale));
774             circleSize.SetWidth(value);
775             circleSize.SetHeight(value);
776             if (radialGradient.radialVerticalSize) {
777                 const auto& wValue = radialGradient.radialVerticalSize.value();
778                 value = static_cast<float>(wValue.Unit() == DimensionUnit::PERCENT ? wValue.Value() * size.Height()
779                                                                                    : wValue.ConvertToPx(dipScale));
780                 circleSize.SetHeight(value);
781             }
782         } else {
783             RadialShapeType shape = RadialShapeType::ELLIPSE;
784             if ((radialGradient.radialShape && radialGradient.radialShape.value() == RadialShapeType::CIRCLE) ||
785                 (!radialGradient.radialShape && !radialGradient.radialSizeType && radialGradient.radialHorizontalSize &&
786                     !radialGradient.radialVerticalSize)) {
787                 shape = RadialShapeType::CIRCLE;
788             }
789             auto sizeType =
790                 radialGradient.radialSizeType ? radialGradient.radialSizeType.value() : RadialSizeType::NONE;
791             switch (sizeType) {
792                 case RadialSizeType::CLOSEST_SIDE:
793                     circleSize = RadiusToSide(center, size, shape, std::less<>());
794                     break;
795                 case RadialSizeType::FARTHEST_SIDE:
796                     circleSize = RadiusToSide(center, size, shape, std::greater<>());
797                     break;
798                 case RadialSizeType::CLOSEST_CORNER:
799                     circleSize = RadiusToCorner(center, size, shape, std::less<>());
800                     break;
801                 case RadialSizeType::FARTHEST_CORNER:
802                 case RadialSizeType::NONE:
803                 default:
804                     circleSize = RadiusToCorner(center, size, shape, std::greater<>());
805                     break;
806             }
807         }
808         return circleSize;
809     }
810 #endif
811 
812     using CompareType = std::function<bool(float, float)>;
813 
814 #ifndef USE_ROSEN_DRAWING
RadiusToSide(const SkPoint & center,const SkSize & size,RadialShapeType type,const CompareType & compare)815     static SkSize RadiusToSide(
816         const SkPoint& center, const SkSize& size, RadialShapeType type, const CompareType& compare)
817     {
818         auto dx1 = static_cast<float>(std::fabs(center.fX));
819         auto dy1 = static_cast<float>(std::fabs(center.fY));
820         auto dx2 = static_cast<float>(std::fabs(center.fX - size.width()));
821         auto dy2 = static_cast<float>(std::fabs(center.fY - size.height()));
822 
823         auto dx = compare(dx1, dx2) ? dx1 : dx2;
824         auto dy = compare(dy1, dy2) ? dy1 : dy2;
825 
826         if (type == RadialShapeType::CIRCLE) {
827             return compare(dx, dy) ? SkSize::Make(dx, dx) : SkSize::Make(dy, dy);
828         }
829         return SkSize::Make(dx, dy);
830     }
831 #else
RadiusToSide(const RSPoint & center,const RSSize & size,RadialShapeType type,const CompareType & compare)832     static RSSize RadiusToSide(
833         const RSPoint& center, const RSSize& size, RadialShapeType type, const CompareType& compare)
834     {
835         auto dx1 = static_cast<float>(std::fabs(center.GetX()));
836         auto dy1 = static_cast<float>(std::fabs(center.GetY()));
837         auto dx2 = static_cast<float>(std::fabs(center.GetX() - size.Width()));
838         auto dy2 = static_cast<float>(std::fabs(center.GetY() - size.Height()));
839 
840         auto dx = compare(dx1, dx2) ? dx1 : dx2;
841         auto dy = compare(dy1, dy2) ? dy1 : dy2;
842 
843         if (type == RadialShapeType::CIRCLE) {
844             return compare(dx, dy) ? RSSize(dx, dx) : RSSize(dy, dy);
845         }
846         return RSSize(dx, dy);
847     }
848 #endif
849 
850 #ifndef USE_ROSEN_DRAWING
EllipseRadius(const SkPoint & p,float ratio)851     static inline SkSize EllipseRadius(const SkPoint& p, float ratio)
852     {
853         if (NearZero(ratio) || std::isinf(ratio)) {
854             return SkSize { 0.0f, 0.0f };
855         }
856         // x^2/a^2 + y^2/b^2 = 1
857         // a/b = ratio, b = a/ratio
858         // a = sqrt(x^2 + y^2/(1/r^2))
859         float a = sqrtf(p.fX * p.fX + p.fY * p.fY * ratio * ratio);
860         return SkSize::Make(a, a / ratio);
861     }
862 #else
EllipseRadius(const RSPoint & p,float ratio)863     static inline RSSize EllipseRadius(const RSPoint& p, float ratio)
864     {
865         if (NearZero(ratio) || std::isinf(ratio)) {
866             return RSSize { 0.0f, 0.0f };
867         }
868         // x^2/a^2 + y^2/b^2 = 1
869         // a/b = ratio, b = a/ratio
870         // a = sqrt(x^2 + y^2/(1/r^2))
871         float a = sqrtf(p.GetX() * p.GetX() + p.GetY() * p.GetY() * ratio * ratio);
872         return RSSize(a, a / ratio);
873     }
874 #endif
875 
876 #ifndef USE_ROSEN_DRAWING
RadiusToCorner(const SkPoint & center,const SkSize & size,RadialShapeType type,const CompareType & compare)877     static SkSize RadiusToCorner(
878         const SkPoint& center, const SkSize& size, RadialShapeType type, const CompareType& compare)
879     {
880         const SkPoint corners[4] = {
881             SkPoint::Make(0.0f, 0.0f),
882             SkPoint::Make(size.width(), 0.0f),
883             SkPoint::Make(size.width(), size.height()),
884             SkPoint::Make(0.0f, size.height()),
885         };
886 
887         int32_t cornerIndex = 0;
888         float distance = (center - corners[cornerIndex]).length();
889         for (int32_t i = 1; i < 4; i++) {
890             float newDistance = (center - corners[i]).length();
891             if (compare(newDistance, distance)) {
892                 cornerIndex = i;
893                 distance = newDistance;
894             }
895         }
896 
897         if (type == RadialShapeType::CIRCLE) {
898             return SkSize::Make(distance, distance);
899         }
900 
901         SkSize sideRadius = RadiusToSide(center, size, RadialShapeType::ELLIPSE, compare);
902         return EllipseRadius(corners[cornerIndex] - center,
903             NearZero(sideRadius.height()) ? 1.0f : sideRadius.width() / sideRadius.height());
904     }
905 #else
RadiusToCorner(const RSPoint & center,const RSSize & size,RadialShapeType type,const CompareType & compare)906     static RSSize RadiusToCorner(
907         const RSPoint& center, const RSSize& size, RadialShapeType type, const CompareType& compare)
908     {
909         const RSPoint corners[4] = {
910             RSPoint(0.0f, 0.0f),
911             RSPoint(size.Width(), 0.0f),
912             RSPoint(size.Width(), size.Height()),
913             RSPoint(0.0f, size.Height()),
914         };
915 
916         int32_t cornerIndex = 0;
917         auto point = center - corners[cornerIndex];
918         float distance = std::sqrt(std::pow(point.GetX(), 2) + std::pow(point.GetY(), 2));
919         for (int32_t i = 1; i < 4; i++) {
920             auto point = center - corners[i];
921             float newDistance = std::sqrt(std::pow(point.GetX(), 2) + std::pow(point.GetY(), 2));
922             if (compare(newDistance, distance)) {
923                 cornerIndex = i;
924                 distance = newDistance;
925             }
926         }
927 
928         if (type == RadialShapeType::CIRCLE) {
929             return RSSize(distance, distance);
930         }
931 
932         RSSize sideRadius = RadiusToSide(center, size, RadialShapeType::ELLIPSE, compare);
933         return EllipseRadius(corners[cornerIndex] - center,
934             NearZero(sideRadius.Height()) ? 1.0f : sideRadius.Width() / sideRadius.Height());
935     }
936 #endif
937 
938 private:
939 #ifndef USE_ROSEN_DRAWING
940     SkPoint center_ { 0.0f, 0.0f };
941 #else
942     RSPoint center_ { 0.0f, 0.0f };
943 #endif
944     float radius0_ { 0.0f };
945     float radius1_ { 0.0f };
946     float ratio_ { 1.0f };
947 };
948 
949 class SweepGradientShader final : public GradientShader {
950 public:
951 #ifndef USE_ROSEN_DRAWING
SweepGradientShader(const Gradient & gradient,const SkPoint & center,float startAngle,float endAngle,float rotation)952     SweepGradientShader(
953         const Gradient& gradient, const SkPoint& center, float startAngle, float endAngle, float rotation)
954         : GradientShader(gradient), center_(center), startAngle_(startAngle), endAngle_(endAngle), rotation_(rotation)
955     {}
956 #else
957     SweepGradientShader(
958         const Gradient& gradient, const RSPoint& center, float startAngle, float endAngle, float rotation)
959         : GradientShader(gradient), center_(center), startAngle_(startAngle), endAngle_(endAngle), rotation_(rotation)
960     {}
961 #endif
962     ~SweepGradientShader() = default;
963 
964 #ifndef USE_ROSEN_DRAWING
CreateGradientShader()965     sk_sp<SkShader> CreateGradientShader() override
966     {
967         AddColorStops(1.0f);
968         if (NeedAdjustColorStops()) {
969             auto startOffset = colorStops_.front().offset;
970             auto endOffset = colorStops_.back().offset;
971             AdjustColorStops();
972             AdjustAngle(startOffset, endOffset);
973         }
974 
975         SkMatrix matrix = SkMatrix::I();
976         if (!NearZero(rotation_)) {
977             matrix.preRotate(rotation_, center_.fX, center_.fY);
978         }
979 
980         std::vector<SkScalar> pos;
981         std::vector<SkColor> colors;
982         ToSkColors(pos, colors);
983 
984         SkTileMode tileMode = SkTileMode::kClamp;
985         if (isRepeat_) {
986             tileMode = SkTileMode::kRepeat;
987         }
988         return SkGradientShader::MakeSweep(
989             center_.fX, center_.fY, &colors[0], &pos[0], colors.size(), tileMode, startAngle_, endAngle_, 0, &matrix);
990     }
991 #else
CreateGradientShader()992     std::shared_ptr<RSShaderEffect> CreateGradientShader() override
993     {
994         AddColorStops(1.0f);
995         if (NeedAdjustColorStops()) {
996             auto startOffset = colorStops_.front().offset;
997             auto endOffset = colorStops_.back().offset;
998             AdjustColorStops();
999             AdjustAngle(startOffset, endOffset);
1000         }
1001 
1002         RSMatrix matrix;
1003         if (!NearZero(rotation_)) {
1004             matrix.PreRotate(rotation_, center_.GetX(), center_.GetY());
1005         }
1006 
1007         std::vector<RSScalar> pos;
1008         std::vector<RSColorQuad> colors;
1009         ToDrawingColors(pos, colors);
1010         RSTileMode tileMode = RSTileMode::CLAMP;
1011         if (isRepeat_) {
1012             tileMode = RSTileMode::REPEAT;
1013         }
1014         return RSRecordingShaderEffect::CreateSweepGradient(
1015             center_, colors, pos, tileMode, startAngle_, endAngle_, &matrix);
1016     }
1017 #endif
1018 
1019 #ifndef USE_ROSEN_DRAWING
CreateSweepGradient(const Gradient & gradient,const SkSize & size,float dipScale)1020     static std::unique_ptr<GradientShader> CreateSweepGradient(
1021         const Gradient& gradient, const SkSize& size, float dipScale)
1022 #else
1023     static std::unique_ptr<GradientShader> CreateSweepGradient(
1024         const Gradient& gradient, const RSSize& size, float dipScale)
1025 #endif
1026     {
1027         auto sweepGradient = gradient.GetSweepGradient();
1028 #ifndef USE_ROSEN_DRAWING
1029         SkPoint center = GetCenter(sweepGradient, size, dipScale);
1030 #else
1031         RSPoint center = GetCenter(sweepGradient, size, dipScale);
1032 #endif
1033         float rotationAngle = 0.0f;
1034         if (sweepGradient.rotation) {
1035             rotationAngle = fmod(sweepGradient.rotation.value().Value(), 360.0f);
1036             if (LessNotEqual(rotationAngle, 0.0f)) {
1037                 rotationAngle += 360.0f;
1038             }
1039         }
1040         float startAngle = 0.0f;
1041         float endAngle = 0.0f;
1042         if (sweepGradient.startAngle.has_value()) {
1043             startAngle = sweepGradient.startAngle.value().Value();
1044         }
1045         if (sweepGradient.endAngle.has_value()) {
1046             endAngle = sweepGradient.endAngle.value().Value();
1047         }
1048         return std::make_unique<SweepGradientShader>(gradient, center, startAngle, endAngle, rotationAngle);
1049     }
1050 
1051 private:
1052 #ifndef USE_ROSEN_DRAWING
GetCenter(const SweepGradient & sweepGradient,const SkSize & size,float dipScale)1053     static SkPoint GetCenter(const SweepGradient& sweepGradient, const SkSize& size, float dipScale)
1054     {
1055         SkPoint center = SkPoint::Make(size.width() / 2.0f, size.height() / 2.0f);
1056 
1057         if (sweepGradient.centerX) {
1058             const auto& value = sweepGradient.centerX.value();
1059             center.fX =
1060                 static_cast<float>(value.Unit() == DimensionUnit::PERCENT ? value.Value() / 100.0f * size.width()
1061                                                                           : value.ConvertToPx(dipScale));
1062         }
1063         if (sweepGradient.centerY) {
1064             const auto& value = sweepGradient.centerY.value();
1065             center.fY =
1066                 static_cast<float>(value.Unit() == DimensionUnit::PERCENT ? value.Value() / 100.0f * size.height()
1067                                                                           : value.ConvertToPx(dipScale));
1068         }
1069         return center;
1070     }
1071 #else
1072     static RSPoint GetCenter(const SweepGradient& sweepGradient, const RSSize& size, float dipScale)
1073     {
1074         RSPoint center = RSPoint(size.Width() / 2.0f, size.Height() / 2.0f);
1075 
1076         if (sweepGradient.centerX) {
1077             const auto& value = sweepGradient.centerX.value();
1078             center.SetX(
1079                 static_cast<float>(value.Unit() == DimensionUnit::PERCENT ? value.Value() / 100.0f * size.Width()
1080                                                                           : value.ConvertToPx(dipScale)));
1081         }
1082         if (sweepGradient.centerY) {
1083             const auto& value = sweepGradient.centerY.value();
1084             center.SetY(
1085                 static_cast<float>(value.Unit() == DimensionUnit::PERCENT ? value.Value() / 100.0f * size.Height()
1086                                                                           : value.ConvertToPx(dipScale)));
1087         }
1088         return center;
1089     }
1090 #endif
1091 
AdjustAngle(float firstOffset,float lastOffset)1092     void AdjustAngle(float firstOffset, float lastOffset)
1093     {
1094         const auto delta = endAngle_ - startAngle_;
1095         endAngle_ = startAngle_ + delta * lastOffset;
1096         startAngle_ = startAngle_ + delta * firstOffset;
1097     }
1098 
1099 private:
1100 #ifndef USE_ROSEN_DRAWING
1101     SkPoint center_ { 0.0f, 0.0f };
1102 #else
1103     RSPoint center_ { 0.0f, 0.0f };
1104 #endif
1105     float startAngle_ { 0.0f };
1106     float endAngle_ { 0.0f };
1107     float rotation_ { 0.0f };
1108 };
1109 
1110 } // namespace
1111 
RosenDecorationPainter(const RefPtr<Decoration> & decoration,const Rect & paintRect,const Size & paintSize,double dipScale)1112 RosenDecorationPainter::RosenDecorationPainter(
1113     const RefPtr<Decoration>& decoration, const Rect& paintRect, const Size& paintSize, double dipScale)
1114     : dipScale_(dipScale), paintRect_(paintRect), decoration_(decoration), paintSize_(paintSize)
1115 {}
1116 
1117 #ifndef USE_ROSEN_DRAWING
PaintDecoration(const Offset & offset,SkCanvas * canvas,RenderContext & context)1118 void RosenDecorationPainter::PaintDecoration(const Offset& offset, SkCanvas* canvas, RenderContext& context)
1119 #else
1120 void RosenDecorationPainter::PaintDecoration(const Offset& offset, RSCanvas* canvas, RenderContext& context)
1121 #endif
1122 {
1123     auto rsNode = static_cast<RosenRenderContext*>(&context)->GetRSNode();
1124     if (!canvas || !paintSize_.IsValid() || !rsNode) {
1125         LOGE("PaintDecoration failed.");
1126         return;
1127     }
1128 
1129     Border borderFour;
1130     Rosen::Vector4f cornerRadius;
1131     if (decoration_) {
1132 #ifndef USE_ROSEN_DRAWING
1133         SkPaint paint;
1134 
1135         if (opacity_ != UINT8_MAX) {
1136             paint.setAlpha(opacity_);
1137         }
1138 
1139         Border border = decoration_->GetBorder();
1140         PaintColorAndImage(offset, canvas, paint, context);
1141 #else
1142         RSBrush brush;
1143 
1144         if (opacity_ != UINT8_MAX) {
1145             brush.SetAlpha(opacity_);
1146         }
1147 
1148         Border border = decoration_->GetBorder();
1149         PaintColorAndImage(offset, canvas, brush, context);
1150 #endif
1151         if (border.HasRadius()) {
1152             cornerRadius.SetValues(NormalizeToPx(border.TopLeftRadius().GetX()),
1153                 NormalizeToPx(border.TopRightRadius().GetX()), NormalizeToPx(border.BottomRightRadius().GetX()),
1154                 NormalizeToPx(border.BottomLeftRadius().GetX()));
1155         }
1156         if (border.HasValue()) {
1157             borderFour = border;
1158         }
1159     }
1160     PaintBorder(rsNode, borderFour, dipScale_);
1161     rsNode->SetCornerRadius(cornerRadius);
1162 }
1163 
1164 #ifndef USE_ROSEN_DRAWING
PaintBorderImage(RefPtr<OHOS::Ace::Decoration> & decoration,Size & paintSize,const Offset & position,SkCanvas * canvas,const sk_sp<SkImage> & image,double dipScale)1165 void RosenDecorationPainter::PaintBorderImage(RefPtr<OHOS::Ace::Decoration>& decoration, Size& paintSize,
1166     const Offset& position, SkCanvas* canvas, const sk_sp<SkImage>& image, double dipScale)
1167 {
1168     if (!decoration->GetHasBorderImageSource() && !decoration->GetHasBorderImageGradient()) {
1169         return;
1170     }
1171     // set AntiAlias
1172     SkPaint paint;
1173     paint.setAntiAlias(true);
1174     if (decoration->GetHasBorderImageSource()) {
1175         if (!image) {
1176             return;
1177         }
1178         canvas->save();
1179 
1180         BorderImagePainter borderImagePainter(paintSize, decoration, image, dipScale);
1181         borderImagePainter.InitPainter();
1182         borderImagePainter.PaintBorderImage(position, canvas, paint);
1183         canvas->restore();
1184     }
1185     if (decoration->GetHasBorderImageGradient()) {
1186         Gradient gradient = decoration->GetBorderImageGradient();
1187         if (!gradient.IsValid()) {
1188             LOGE("Gradient not valid");
1189             return;
1190         }
1191         if (NearZero(paintSize.Width()) || NearZero(paintSize.Height())) {
1192             return;
1193         }
1194         canvas->save();
1195 
1196         SkSize skPaintSize = SkSize::Make(paintSize.Width(), paintSize.Height());
1197         auto shader = CreateGradientShader(gradient, skPaintSize, dipScale);
1198         paint.setShader(std::move(shader));
1199 
1200         auto imageInfo = SkImageInfo::Make(paintSize.Width(), paintSize.Height(), SkColorType::kRGBA_8888_SkColorType,
1201             SkAlphaType::kOpaque_SkAlphaType);
1202         SkBitmap skBitmap;
1203         skBitmap.allocPixels(imageInfo);
1204         std::unique_ptr<SkCanvas> skCanvas = std::make_unique<SkCanvas>(skBitmap);
1205         skCanvas->drawPaint(paint);
1206         sk_sp<SkImage> skImage = SkImage::MakeFromBitmap(skBitmap);
1207 
1208         BorderImagePainter borderImagePainter(paintSize, decoration, skImage, dipScale);
1209         borderImagePainter.InitPainter();
1210         borderImagePainter.PaintBorderImage(position, canvas, paint);
1211         paint.setShader(nullptr);
1212         canvas->restore();
1213     }
1214 }
1215 #else
PaintBorderImage(RefPtr<OHOS::Ace::Decoration> & decoration,Size & paintSize,const Offset & position,RSCanvas * canvas,const std::shared_ptr<RSImage> & image,double dipScale)1216 void RosenDecorationPainter::PaintBorderImage(RefPtr<OHOS::Ace::Decoration>& decoration, Size& paintSize,
1217     const Offset& position, RSCanvas* canvas, const std::shared_ptr<RSImage>& image, double dipScale)
1218 {
1219     if (!decoration->GetHasBorderImageSource() && !decoration->GetHasBorderImageGradient()) {
1220         return;
1221     }
1222     // set AntiAlias
1223     RSBrush brush;
1224     brush.SetAntiAlias(true);
1225     if (decoration->GetHasBorderImageSource()) {
1226         if (!image) {
1227             return;
1228         }
1229         canvas->Save();
1230 
1231         BorderImagePainter borderImagePainter(paintSize, decoration, image, dipScale);
1232         borderImagePainter.InitPainter();
1233         borderImagePainter.PaintBorderImage(position, canvas, brush);
1234         canvas->Restore();
1235     }
1236     if (decoration->GetHasBorderImageGradient()) {
1237         Gradient gradient = decoration->GetBorderImageGradient();
1238         if (!gradient.IsValid()) {
1239             LOGE("Gradient not valid");
1240             return;
1241         }
1242         if (NearZero(paintSize.Width()) || NearZero(paintSize.Height())) {
1243             return;
1244         }
1245         canvas->Save();
1246         RSSize drPaintSize(static_cast<float>(paintSize.Width()), static_cast<float>(paintSize.Height()));
1247         auto shader = CreateGradientShader(gradient, drPaintSize, dipScale);
1248         brush.SetShaderEffect(shader);
1249 
1250         RSBitmapFormat bitmapFormat;
1251         bitmapFormat.colorType = RSColorType::COLORTYPE_RGBA_8888;
1252         bitmapFormat.alphaType = RSAlphaType::ALPHATYPE_OPAQUE;
1253 
1254         RSBitmap bitmap;
1255         bitmap.Build(paintSize.Width(), paintSize.Height(), bitmapFormat);
1256 
1257         std::unique_ptr<RSCanvas> drCanvas = std::make_unique<RSCanvas>();
1258         drCanvas->Bind(bitmap);
1259         drCanvas->DrawBackground(brush);
1260 
1261         auto image = std::make_shared<RSImage>();
1262         image->BuildFromBitmap(bitmap);
1263 
1264         BorderImagePainter borderImagePainter(paintSize, decoration, image, dipScale);
1265         borderImagePainter.InitPainter();
1266         borderImagePainter.PaintBorderImage(position, canvas, brush);
1267         brush.SetShaderEffect(nullptr);
1268         canvas->Restore();
1269     }
1270 }
1271 #endif
1272 
1273 #ifndef USE_ROSEN_DRAWING
PaintDecoration(const Offset & offset,SkCanvas * canvas,RenderContext & context,const sk_sp<SkImage> & image)1274 void RosenDecorationPainter::PaintDecoration(
1275     const Offset& offset, SkCanvas* canvas, RenderContext& context, const sk_sp<SkImage>& image)
1276 {
1277     auto rsNode = static_cast<RosenRenderContext*>(&context)->GetRSNode();
1278     if (!canvas || !rsNode) {
1279         LOGE("PaintDecoration failed, canvas is null.");
1280         return;
1281     }
1282     if (decoration_ && rsNode) {
1283         canvas->save();
1284         SkPaint paint;
1285 
1286         if (opacity_ != UINT8_MAX) {
1287             paint.setAlpha(opacity_);
1288         }
1289         Border border = decoration_->GetBorder();
1290         PaintColorAndImage(offset, canvas, paint, context);
1291         if (border.HasValue()) {
1292             PaintBorder(rsNode, border, dipScale_);
1293             Gradient gradient = decoration_->GetBorderImageGradient();
1294             if (gradient.IsValid()) {
1295                 if (NearZero(paintSize_.Width()) || NearZero(paintSize_.Height())) {
1296                     return;
1297                 }
1298                 auto size = SkSize::Make(GetLayoutSize().Width(), GetLayoutSize().Width());
1299                 auto shader = CreateGradientShader(gradient, size);
1300 #ifdef OHOS_PLATFORM
1301                 rsNode->SetBackgroundShader(Rosen::RSShader::CreateRSShader(shader));
1302 #endif
1303             }
1304         }
1305         canvas->restore();
1306     }
1307 }
1308 #else
PaintDecoration(const Offset & offset,RSCanvas * canvas,RenderContext & context,const std::shared_ptr<RSImage> & image)1309 void RosenDecorationPainter::PaintDecoration(
1310     const Offset& offset, RSCanvas* canvas, RenderContext& context, const std::shared_ptr<RSImage>& image)
1311 {
1312     auto rsNode = static_cast<RosenRenderContext*>(&context)->GetRSNode();
1313     if (!canvas || !rsNode) {
1314         LOGE("PaintDecoration failed, canvas is null.");
1315         return;
1316     }
1317     if (decoration_ && rsNode) {
1318         canvas->Save();
1319         RSBrush brush;
1320 
1321         if (opacity_ != UINT8_MAX) {
1322             brush.SetAlpha(opacity_);
1323         }
1324         Border border = decoration_->GetBorder();
1325         PaintColorAndImage(offset, canvas, brush, context);
1326         if (border.HasValue()) {
1327             PaintBorder(rsNode, border, dipScale_);
1328             Gradient gradient = decoration_->GetBorderImageGradient();
1329             if (gradient.IsValid()) {
1330                 if (NearZero(paintSize_.Width()) || NearZero(paintSize_.Height())) {
1331                     return;
1332                 }
1333                 auto size = RSSize(GetLayoutSize().Width(), GetLayoutSize().Width());
1334                 auto shader = CreateGradientShader(gradient, size);
1335 #ifdef OHOS_PLATFORM
1336                 rsNode->SetBackgroundShader(Rosen::RSShader::CreateRSShader(shader));
1337 #endif
1338             }
1339         }
1340         canvas->Restore();
1341     }
1342 }
1343 #endif
1344 
CheckWidth(const Border & border)1345 void RosenDecorationPainter::CheckWidth(const Border& border)
1346 {
1347     if (NearZero(leftWidth_)) {
1348         leftWidth_ = NormalizeToPx(border.Left().GetWidth());
1349     }
1350     if (NearZero(topWidth_)) {
1351         topWidth_ = NormalizeToPx(border.Top().GetWidth());
1352     }
1353     if (NearZero(rightWidth_)) {
1354         rightWidth_ = NormalizeToPx(border.Right().GetWidth());
1355     }
1356     if (NearZero(bottomWidth_)) {
1357         bottomWidth_ = NormalizeToPx(border.Bottom().GetWidth());
1358     }
1359 }
1360 
1361 #ifndef USE_ROSEN_DRAWING
PaintGrayScale(const SkRRect & outerRRect,SkCanvas * canvas,const Dimension & grayscale,const Color & color)1362 void RosenDecorationPainter::PaintGrayScale(
1363     const SkRRect& outerRRect, SkCanvas* canvas, const Dimension& grayscale, const Color& color)
1364 {
1365     double scale = grayscale.Value();
1366     if (GreatNotEqual(scale, 0.0)) {
1367         if (canvas) {
1368             SkAutoCanvasRestore acr(canvas, true);
1369             canvas->clipRRect(outerRRect, true);
1370             SkPaint paint;
1371             paint.setAntiAlias(true);
1372             float matrix[20] = { 0 };
1373             matrix[0] = matrix[5] = matrix[10] = 0.2126f * scale;
1374             matrix[1] = matrix[6] = matrix[11] = 0.7152f * scale;
1375             matrix[2] = matrix[7] = matrix[12] = 0.0722f * scale;
1376             matrix[18] = 1.0f * scale;
1377 
1378             paint.setColorFilter(SkColorFilters::Matrix(matrix));
1379             SkCanvas::SaveLayerRec slr(nullptr, &paint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
1380             canvas->saveLayer(slr);
1381         }
1382     }
1383 }
1384 #else
PaintGrayScale(const RSRoundRect & outerRRect,RSCanvas * canvas,const Dimension & grayscale,const Color & color)1385 void RosenDecorationPainter::PaintGrayScale(
1386     const RSRoundRect& outerRRect, RSCanvas* canvas, const Dimension& grayscale, const Color& color)
1387 {
1388     double scale = grayscale.Value();
1389     if (GreatNotEqual(scale, 0.0)) {
1390         if (canvas) {
1391             RSAutoCanvasRestore acr(*canvas, true);
1392             canvas->ClipRoundRect(outerRRect, RSClipOp::INTERSECT, true);
1393             RSScalar matrix[20] = { 0 };
1394             matrix[0] = matrix[5] = matrix[10] = 0.2126f * scale;
1395             matrix[1] = matrix[6] = matrix[11] = 0.7152f * scale;
1396             matrix[2] = matrix[7] = matrix[12] = 0.0722f * scale;
1397             matrix[18] = 1.0f * scale;
1398             RSColorMatrix colorMatrix;
1399             colorMatrix.SetArray(matrix);
1400             std::shared_ptr<RSColorFilter> colorFilter = RSColorFilter::CreateMatrixColorFilter(colorMatrix);
1401             RSFilter filter;
1402             filter.SetColorFilter(colorFilter);
1403 
1404             RSBrush brush;
1405             brush.SetAntiAlias(true);
1406             brush.SetFilter(filter);
1407             RSSaveLayerOps slr(nullptr, &brush, RSSaveLayerOps::INIT_WITH_PREVIOUS);
1408             canvas->SaveLayer(slr);
1409         }
1410     }
1411 }
1412 #endif
1413 
1414 #ifndef USE_ROSEN_DRAWING
PaintBrightness(const SkRRect & outerRRect,SkCanvas * canvas,const Dimension & brightness,const Color & color)1415 void RosenDecorationPainter::PaintBrightness(
1416     const SkRRect& outerRRect, SkCanvas* canvas, const Dimension& brightness, const Color& color)
1417 {
1418     double bright = brightness.Value();
1419     // brightness range = (0, 2)
1420     // skip painting when brightness is normal
1421     if (NearEqual(bright, 1.0)) {
1422         return;
1423     }
1424     if (canvas) {
1425         SkAutoCanvasRestore acr(canvas, true);
1426         canvas->clipRRect(outerRRect, true);
1427         SkPaint paint;
1428         paint.setAntiAlias(true);
1429         float matrix[20] = { 0 };
1430         // shift brightness to (-1, 1)
1431         bright = bright - 1;
1432         matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1.0f;
1433         matrix[4] = matrix[9] = matrix[14] = bright;
1434 
1435         paint.setColorFilter(SkColorFilters::Matrix(matrix));
1436         SkCanvas::SaveLayerRec slr(nullptr, &paint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
1437         canvas->saveLayer(slr);
1438     }
1439 }
1440 #else
PaintBrightness(const RSRoundRect & outerRRect,RSCanvas * canvas,const Dimension & brightness,const Color & color)1441 void RosenDecorationPainter::PaintBrightness(
1442     const RSRoundRect& outerRRect, RSCanvas* canvas, const Dimension& brightness, const Color& color)
1443 {
1444     double bright = brightness.Value();
1445     // brightness range = (0, 2)
1446     // skip painting when brightness is normal
1447     if (NearEqual(bright, 1.0)) {
1448         return;
1449     }
1450     if (canvas) {
1451         RSAutoCanvasRestore acr(*canvas, true);
1452         canvas->ClipRoundRect(outerRRect, RSClipOp::INTERSECT, true);
1453         RSBrush brush;
1454         brush.SetAntiAlias(true);
1455         RSScalar matrix[20] = { 0 };
1456         // shift brightness to (-1, 1)
1457         bright = bright - 1;
1458         matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1.0f;
1459         matrix[4] = matrix[9] = matrix[14] = bright;
1460         RSColorMatrix colorMatrix;
1461         colorMatrix.SetArray(matrix);
1462         std::shared_ptr<RSColorFilter> colorFilter = RSColorFilter::CreateMatrixColorFilter(colorMatrix);
1463         RSFilter filter;
1464         filter.SetColorFilter(colorFilter);
1465         RSSaveLayerOps slr(nullptr, &brush, RSSaveLayerOps::INIT_WITH_PREVIOUS);
1466         canvas->SaveLayer(slr);
1467     }
1468 }
1469 #endif
1470 
1471 #ifndef USE_ROSEN_DRAWING
PaintContrast(const SkRRect & outerRRect,SkCanvas * canvas,const Dimension & contrast,const Color & color)1472 void RosenDecorationPainter::PaintContrast(
1473     const SkRRect& outerRRect, SkCanvas* canvas, const Dimension& contrast, const Color& color)
1474 {
1475     double contrasts = contrast.Value();
1476     // skip painting if contrast is normal
1477     if (NearEqual(contrasts, 1.0)) {
1478         return;
1479     }
1480     if (canvas) {
1481         SkAutoCanvasRestore acr(canvas, true);
1482         canvas->clipRRect(outerRRect, true);
1483         SkPaint paint;
1484         paint.setAntiAlias(true);
1485         float matrix[20] = { 0 };
1486         matrix[0] = matrix[6] = matrix[12] = contrasts;
1487         matrix[4] = matrix[9] = matrix[14] = 128 * (1 - contrasts) / 255;
1488         matrix[18] = 1.0f;
1489 
1490         paint.setColorFilter(SkColorFilters::Matrix(matrix));
1491         SkCanvas::SaveLayerRec slr(nullptr, &paint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
1492         canvas->saveLayer(slr);
1493     }
1494 }
1495 #else
PaintContrast(const RSRoundRect & outerRRect,RSCanvas * canvas,const Dimension & contrast,const Color & color)1496 void RosenDecorationPainter::PaintContrast(
1497     const RSRoundRect& outerRRect, RSCanvas* canvas, const Dimension& contrast, const Color& color)
1498 {
1499     double contrasts = contrast.Value();
1500     // skip painting if contrast is normal
1501     if (NearEqual(contrasts, 1.0)) {
1502         return;
1503     }
1504     if (canvas) {
1505         RSAutoCanvasRestore acr(*canvas, true);
1506         canvas->ClipRoundRect(outerRRect, RSClipOp::INTERSECT, true);
1507         RSBrush brush;
1508         brush.SetAntiAlias(true);
1509         RSScalar matrix[20] = { 0 };
1510         matrix[0] = matrix[6] = matrix[12] = contrasts;
1511         matrix[4] = matrix[9] = matrix[14] = 128 * (1 - contrasts) / 255;
1512         matrix[18] = 1.0f;
1513         RSColorMatrix colorMatrix;
1514         colorMatrix.SetArray(matrix);
1515         std::shared_ptr<RSColorFilter> colorFilter = RSColorFilter::CreateMatrixColorFilter(colorMatrix);
1516         RSFilter filter;
1517         filter.SetColorFilter(colorFilter);
1518         brush.SetFilter(filter);
1519         RSSaveLayerOps slr(nullptr, &brush, RSSaveLayerOps::INIT_WITH_PREVIOUS);
1520         canvas->SaveLayer(slr);
1521     }
1522 }
1523 #endif
1524 
1525 #ifndef USE_ROSEN_DRAWING
PaintColorBlend(const SkRRect & outerRRect,SkCanvas * canvas,const Color & colorBlend,const Color & color)1526 void RosenDecorationPainter::PaintColorBlend(
1527     const SkRRect& outerRRect, SkCanvas* canvas, const Color& colorBlend, const Color& color)
1528 {
1529     if (colorBlend.GetValue() != COLOR_MASK) {
1530         if (canvas) {
1531             SkAutoCanvasRestore acr(canvas, true);
1532             canvas->clipRRect(outerRRect, true);
1533             SkPaint paint;
1534             paint.setAntiAlias(true);
1535 
1536             paint.setColorFilter(SkColorFilters::Blend(
1537                 SkColorSetARGB(colorBlend.GetAlpha(), colorBlend.GetRed(), colorBlend.GetGreen(), colorBlend.GetBlue()),
1538                 SkBlendMode::kPlus));
1539             SkCanvas::SaveLayerRec slr(nullptr, &paint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
1540             canvas->saveLayer(slr);
1541         }
1542     }
1543 }
1544 #else
PaintColorBlend(const RSRoundRect & outerRRect,RSCanvas * canvas,const Color & colorBlend,const Color & color)1545 void RosenDecorationPainter::PaintColorBlend(
1546     const RSRoundRect& outerRRect, RSCanvas* canvas, const Color& colorBlend, const Color& color)
1547 {
1548     if (colorBlend.GetValue() != COLOR_MASK) {
1549         if (canvas) {
1550             RSAutoCanvasRestore acr(*canvas, true);
1551             canvas->ClipRoundRect(outerRRect, RSClipOp::INTERSECT, true);
1552             std::shared_ptr<RSColorFilter> colorFilter =
1553                 RSColorFilter::CreateBlendModeColorFilter(colorBlend.GetValue(), RSBlendMode::PLUS);
1554             RSFilter filter;
1555             filter.SetColorFilter(colorFilter);
1556 
1557             RSBrush brush;
1558             brush.SetAntiAlias(true);
1559             brush.SetFilter(filter);
1560             RSSaveLayerOps slr(nullptr, &brush, RSSaveLayerOps::INIT_WITH_PREVIOUS);
1561             canvas->SaveLayer(slr);
1562         }
1563     }
1564 }
1565 #endif
1566 
1567 #ifndef USE_ROSEN_DRAWING
PaintSaturate(const SkRRect & outerRRect,SkCanvas * canvas,const Dimension & saturate,const Color & color)1568 void RosenDecorationPainter::PaintSaturate(
1569     const SkRRect& outerRRect, SkCanvas* canvas, const Dimension& saturate, const Color& color)
1570 {
1571     double saturates = saturate.Value();
1572     if (!NearEqual(saturates, 1.0) && GreatOrEqual(saturates, 0.0)) {
1573         if (canvas) {
1574             SkAutoCanvasRestore acr(canvas, true);
1575             canvas->clipRRect(outerRRect, true);
1576             SkPaint paint;
1577             paint.setAntiAlias(true);
1578             float matrix[20] = { 0 };
1579             matrix[0] = 0.3086f * (1 - saturates) + saturates;
1580             matrix[1] = matrix[11] = 0.6094f * (1 - saturates);
1581             matrix[2] = matrix[7] = 0.0820f * (1 - saturates);
1582             matrix[5] = matrix[10] = 0.3086f * (1 - saturates);
1583             matrix[6] = 0.6094f * (1 - saturates) + saturates;
1584             matrix[12] = 0.0820f * (1 - saturates) + saturates;
1585             matrix[18] = 1.0f;
1586 
1587             paint.setColorFilter(SkColorFilters::Matrix(matrix));
1588             SkCanvas::SaveLayerRec slr(nullptr, &paint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
1589             canvas->saveLayer(slr);
1590         }
1591     }
1592 }
1593 #else
PaintSaturate(const RSRoundRect & outerRRect,RSCanvas * canvas,const Dimension & saturate,const Color & color)1594 void RosenDecorationPainter::PaintSaturate(
1595     const RSRoundRect& outerRRect, RSCanvas* canvas, const Dimension& saturate, const Color& color)
1596 {
1597     double saturates = saturate.Value();
1598     if (!NearEqual(saturates, 1.0) && GreatOrEqual(saturates, 0.0)) {
1599         if (canvas) {
1600             RSAutoCanvasRestore acr(*canvas, true);
1601             canvas->ClipRoundRect(outerRRect, RSClipOp::INTERSECT, true);
1602             RSBrush brush;
1603             brush.SetAntiAlias(true);
1604             RSScalar matrix[20] = { 0 };
1605             matrix[0] = 0.3086f * (1 - saturates) + saturates;
1606             matrix[1] = matrix[11] = 0.6094f * (1 - saturates);
1607             matrix[2] = matrix[7] = 0.0820f * (1 - saturates);
1608             matrix[5] = matrix[10] = 0.3086f * (1 - saturates);
1609             matrix[6] = 0.6094f * (1 - saturates) + saturates;
1610             matrix[12] = 0.0820f * (1 - saturates) + saturates;
1611             matrix[18] = 1.0f;
1612             RSColorMatrix colorMatrix;
1613             colorMatrix.SetArray(matrix);
1614             std::shared_ptr<RSColorFilter> colorFilter = RSColorFilter::CreateMatrixColorFilter(colorMatrix);
1615             RSFilter filter;
1616             filter.SetColorFilter(colorFilter);
1617             brush.SetFilter(filter);
1618             RSSaveLayerOps slr(nullptr, &brush, RSSaveLayerOps::INIT_WITH_PREVIOUS);
1619             canvas->SaveLayer(slr);
1620         }
1621     }
1622 }
1623 #endif
1624 
1625 #ifndef USE_ROSEN_DRAWING
PaintSepia(const SkRRect & outerRRect,SkCanvas * canvas,const Dimension & sepia,const Color & color)1626 void RosenDecorationPainter::PaintSepia(
1627     const SkRRect& outerRRect, SkCanvas* canvas, const Dimension& sepia, const Color& color)
1628 {
1629     double sepias = sepia.Value();
1630     if (sepias > 1.0) {
1631         sepias = 1.0;
1632     }
1633     if (GreatNotEqual(sepias, 0.0)) {
1634         if (canvas) {
1635             SkAutoCanvasRestore acr(canvas, true);
1636             canvas->clipRRect(outerRRect, true);
1637             SkPaint paint;
1638             paint.setAntiAlias(true);
1639             float matrix[20] = { 0 };
1640             matrix[0] = 0.393f * sepias;
1641             matrix[1] = 0.769f * sepias;
1642             matrix[2] = 0.189f * sepias;
1643 
1644             matrix[5] = 0.349f * sepias;
1645             matrix[6] = 0.686f * sepias;
1646             matrix[7] = 0.168f * sepias;
1647 
1648             matrix[10] = 0.272f * sepias;
1649             matrix[11] = 0.534f * sepias;
1650             matrix[12] = 0.131f * sepias;
1651             matrix[18] = 1.0f * sepias;
1652 
1653             paint.setColorFilter(SkColorFilters::Matrix(matrix));
1654             SkCanvas::SaveLayerRec slr(nullptr, &paint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
1655             canvas->saveLayer(slr);
1656         }
1657     }
1658 }
1659 #else
PaintSepia(const RSRoundRect & outerRRect,RSCanvas * canvas,const Dimension & sepia,const Color & color)1660 void RosenDecorationPainter::PaintSepia(
1661     const RSRoundRect& outerRRect, RSCanvas* canvas, const Dimension& sepia, const Color& color)
1662 {
1663     double sepias = sepia.Value();
1664     if (sepias > 1.0) {
1665         sepias = 1.0;
1666     }
1667     if (GreatNotEqual(sepias, 0.0)) {
1668         if (canvas) {
1669             RSAutoCanvasRestore acr(*canvas, true);
1670             canvas->ClipRoundRect(outerRRect, RSClipOp::INTERSECT, true);
1671             RSBrush brush;
1672             brush.SetAntiAlias(true);
1673             RSScalar matrix[20] = { 0 };
1674             matrix[0] = 0.393f * sepias;
1675             matrix[1] = 0.769f * sepias;
1676             matrix[2] = 0.189f * sepias;
1677 
1678             matrix[5] = 0.349f * sepias;
1679             matrix[6] = 0.686f * sepias;
1680             matrix[7] = 0.168f * sepias;
1681 
1682             matrix[10] = 0.272f * sepias;
1683             matrix[11] = 0.534f * sepias;
1684             matrix[12] = 0.131f * sepias;
1685             matrix[18] = 1.0f * sepias;
1686             RSColorMatrix colorMatrix;
1687             colorMatrix.SetArray(matrix);
1688             std::shared_ptr<RSColorFilter> colorFilter = RSColorFilter::CreateMatrixColorFilter(colorMatrix);
1689             RSFilter filter;
1690             filter.SetColorFilter(colorFilter);
1691 
1692             brush.SetFilter(filter);
1693             RSSaveLayerOps slr(nullptr, &brush, RSSaveLayerOps::INIT_WITH_PREVIOUS);
1694             canvas->SaveLayer(slr);
1695         }
1696     }
1697 }
1698 #endif
1699 
1700 #ifndef USE_ROSEN_DRAWING
PaintInvert(const SkRRect & outerRRect,SkCanvas * canvas,const Dimension & invert,const Color & color)1701 void RosenDecorationPainter::PaintInvert(
1702     const SkRRect& outerRRect, SkCanvas* canvas, const Dimension& invert, const Color& color)
1703 {
1704     double inverts = invert.Value();
1705     if (GreatNotEqual(inverts, 0.0)) {
1706         if (canvas) {
1707             SkAutoCanvasRestore acr(canvas, true);
1708             canvas->clipRRect(outerRRect, true);
1709             SkPaint paint;
1710             paint.setAntiAlias(true);
1711             float matrix[20] = { 0 };
1712             if (inverts > 1.0) {
1713                 inverts = 1.0;
1714             }
1715             // complete color invert when dstRGB = 1 - srcRGB
1716             // map (0, 1) to (1, -1)
1717             matrix[0] = matrix[6] = matrix[12] = 1.0 - 2.0 * inverts;
1718             matrix[18] = 1.0f;
1719             // inverts = 0.5 -> RGB = (0.5, 0.5, 0.5) -> image completely gray
1720             matrix[4] = matrix[9] = matrix[14] = inverts;
1721 
1722             paint.setColorFilter(SkColorFilters::Matrix(matrix));
1723             SkCanvas::SaveLayerRec slr(nullptr, &paint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
1724             canvas->saveLayer(slr);
1725         }
1726     }
1727 }
1728 #else
PaintInvert(const RSRoundRect & outerRRect,RSCanvas * canvas,const Dimension & invert,const Color & color)1729 void RosenDecorationPainter::PaintInvert(
1730     const RSRoundRect& outerRRect, RSCanvas* canvas, const Dimension& invert, const Color& color)
1731 {
1732     double inverts = invert.Value();
1733     if (GreatNotEqual(inverts, 0.0)) {
1734         if (canvas) {
1735             RSAutoCanvasRestore acr(*canvas, true);
1736             canvas->ClipRoundRect(outerRRect, RSClipOp::INTERSECT, true);
1737             RSBrush brush;
1738             brush.SetAntiAlias(true);
1739             RSScalar matrix[20] = { 0 };
1740             if (inverts > 1.0) {
1741                 inverts = 1.0;
1742             }
1743             // complete color invert when dstRGB = 1 - srcRGB
1744             // map (0, 1) to (1, -1)
1745             matrix[0] = matrix[6] = matrix[12] = -1.0f * inverts;
1746             matrix[18] = 1.0f;
1747             // inverts = 0.5 -> RGB = (0.5, 0.5, 0.5) -> image completely gray
1748             matrix[4] = matrix[9] = matrix[14] = 1.0f;
1749             RSColorMatrix colorMatrix;
1750             colorMatrix.SetArray(matrix);
1751             std::shared_ptr<RSColorFilter> colorFilter = RSColorFilter::CreateMatrixColorFilter(colorMatrix);
1752             RSFilter filter;
1753             filter.SetColorFilter(colorFilter);
1754 
1755             brush.SetFilter(filter);
1756             RSSaveLayerOps slr(nullptr, &brush, RSSaveLayerOps::INIT_WITH_PREVIOUS);
1757             canvas->SaveLayer(slr);
1758         }
1759     }
1760 }
1761 #endif
1762 
1763 #ifndef USE_ROSEN_DRAWING
PaintHueRotate(const SkRRect & outerRRect,SkCanvas * canvas,const float & hueRotate,const Color & color)1764 void RosenDecorationPainter::PaintHueRotate(
1765     const SkRRect& outerRRect, SkCanvas* canvas, const float& hueRotate, const Color& color)
1766 {
1767     float hueRotates = hueRotate;
1768     if (GreatNotEqual(hueRotates, 0.0)) {
1769         if (canvas) {
1770             SkAutoCanvasRestore acr(canvas, true);
1771             canvas->clipRRect(outerRRect, true);
1772             SkPaint paint;
1773             paint.setAntiAlias(true);
1774             while (GreatOrEqual(hueRotates, 360)) {
1775                 hueRotates -= 360;
1776             }
1777             float matrix[20] = { 0 };
1778             int32_t type = hueRotates / 120;
1779             float N = (hueRotates - 120 * type) / 120;
1780             switch (type) {
1781                 case 0:
1782                     // color change = R->G, G->B, B->R
1783                     matrix[2] = matrix[5] = matrix[11] = N;
1784                     matrix[0] = matrix[6] = matrix[12] = 1 - N;
1785                     matrix[18] = 1.0f;
1786                     break;
1787                 case 1:
1788                     // compare to original: R->B, G->R, B->G
1789                     matrix[1] = matrix[7] = matrix[10] = N;
1790                     matrix[2] = matrix[5] = matrix[11] = 1 - N;
1791                     matrix[18] = 1.0f;
1792                     break;
1793                 case 2:
1794                     // back to normal color
1795                     matrix[0] = matrix[6] = matrix[12] = N;
1796                     matrix[1] = matrix[7] = matrix[10] = 1 - N;
1797                     matrix[18] = 1.0f;
1798                     break;
1799                 default:
1800                     break;
1801             }
1802 
1803             paint.setColorFilter(SkColorFilters::Matrix(matrix));
1804             SkCanvas::SaveLayerRec slr(nullptr, &paint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
1805             canvas->saveLayer(slr);
1806         }
1807     }
1808 }
1809 #else
PaintHueRotate(const RSRoundRect & outerRRect,RSCanvas * canvas,const float & hueRotate,const Color & color)1810 void RosenDecorationPainter::PaintHueRotate(
1811     const RSRoundRect& outerRRect, RSCanvas* canvas, const float& hueRotate, const Color& color)
1812 {
1813     float hueRotates = hueRotate;
1814     if (GreatNotEqual(hueRotates, 0.0)) {
1815         if (canvas) {
1816             RSAutoCanvasRestore acr(*canvas, true);
1817             canvas->ClipRoundRect(outerRRect, RSClipOp::INTERSECT, true);
1818             RSBrush brush;
1819             brush.SetAntiAlias(true);
1820             while (GreatOrEqual(hueRotates, 360)) {
1821                 hueRotates -= 360;
1822             }
1823             float matrix[20] = { 0 };
1824             int32_t type = hueRotates / 120;
1825             float N = (hueRotates - 120 * type) / 120;
1826             switch (type) {
1827                 case 0:
1828                     // color change = R->G, G->B, B->R
1829                     matrix[2] = matrix[5] = matrix[11] = N;
1830                     matrix[0] = matrix[6] = matrix[12] = 1 - N;
1831                     matrix[18] = 1.0f;
1832                     break;
1833                 case 1:
1834                     // compare to original: R->B, G->R, B->G
1835                     matrix[1] = matrix[7] = matrix[10] = N;
1836                     matrix[2] = matrix[5] = matrix[11] = 1 - N;
1837                     matrix[18] = 1.0f;
1838                     break;
1839                 case 2:
1840                     // back to normal color
1841                     matrix[0] = matrix[6] = matrix[12] = N;
1842                     matrix[1] = matrix[7] = matrix[10] = 1 - N;
1843                     matrix[18] = 1.0f;
1844                     break;
1845                 default:
1846                     break;
1847             }
1848             RSColorMatrix colorMatrix;
1849             colorMatrix.SetArray(matrix);
1850             std::shared_ptr<RSColorFilter> colorFilter = RSColorFilter::CreateMatrixColorFilter(colorMatrix);
1851             RSFilter filter;
1852             filter.SetColorFilter(colorFilter);
1853 
1854             brush.SetFilter(filter);
1855             RSSaveLayerOps slr(nullptr, &brush, RSSaveLayerOps::INIT_WITH_PREVIOUS);
1856             canvas->SaveLayer(slr);
1857         }
1858     }
1859 }
1860 #endif
1861 
PaintBlur(RenderContext & context,const Dimension & blurRadius)1862 void RosenDecorationPainter::PaintBlur(RenderContext& context, const Dimension& blurRadius)
1863 {
1864     auto rsNode = static_cast<RosenRenderContext*>(&context)->GetRSNode();
1865     auto radius = ConvertRadiusToSigma(NormalizeToPx(blurRadius));
1866     if (GreatNotEqual(radius, 0.0)) {
1867         if (rsNode) {
1868             float backblurRadius = ConvertRadiusToSigma(radius);
1869             auto backFilter = Rosen::RSFilter::CreateBlurFilter(backblurRadius, backblurRadius);
1870             rsNode->SetBackgroundFilter(backFilter);
1871         }
1872     }
1873 }
1874 
PaintBorder(std::shared_ptr<RSNode> & rsNode,Border & border,double dipScale)1875 void RosenDecorationPainter::PaintBorder(std::shared_ptr<RSNode>& rsNode, Border& border, double dipScale)
1876 {
1877     if (!rsNode) {
1878         return;
1879     }
1880     AdjustBorderStyle(border);
1881     rsNode->SetBorderColor(border.Left().GetColor().GetValue(), border.Top().GetColor().GetValue(),
1882         border.Right().GetColor().GetValue(), border.Bottom().GetColor().GetValue());
1883     rsNode->SetBorderWidth(border.Left().GetWidth().ConvertToPx(dipScale),
1884         border.Top().GetWidth().ConvertToPx(dipScale), border.Right().GetWidth().ConvertToPx(dipScale),
1885         border.Bottom().GetWidth().ConvertToPx(dipScale));
1886     rsNode->SetBorderStyle(static_cast<uint32_t>(border.Left().GetBorderStyle()),
1887         static_cast<uint32_t>(border.Top().GetBorderStyle()), static_cast<uint32_t>(border.Right().GetBorderStyle()),
1888         static_cast<uint32_t>(border.Bottom().GetBorderStyle()));
1889 }
1890 
1891 #ifndef USE_ROSEN_DRAWING
GetBoxOuterRRect(const Offset & offset)1892 SkRRect RosenDecorationPainter::GetBoxOuterRRect(const Offset& offset)
1893 {
1894     SkRRect outerRRect;
1895     if (decoration_) {
1896         Border border = decoration_->GetBorder();
1897         outerRRect = GetBoxRRect(offset + margin_.GetOffsetInPx(scale_), border, 0.0, true);
1898     } else {
1899         Rect paintSize = paintRect_ + offset;
1900         outerRRect = SkRRect::MakeRect(
1901             SkRect::MakeLTRB(paintSize.Left(), paintSize.Top(), paintSize.Right(), paintSize.Bottom()));
1902     }
1903     return outerRRect;
1904 }
1905 #else
GetBoxOuterRRect(const Offset & offset)1906 RSRoundRect RosenDecorationPainter::GetBoxOuterRRect(const Offset& offset)
1907 {
1908     RSRoundRect outerRRect;
1909     if (decoration_) {
1910         Border border = decoration_->GetBorder();
1911         outerRRect = GetBoxRRect(offset + margin_.GetOffsetInPx(scale_), border, 0.0, true);
1912     } else {
1913         Rect paintSize = paintRect_ + offset;
1914         outerRRect.SetRect(RSRect(paintSize.Left(), paintSize.Top(), paintSize.Right(), paintSize.Bottom()));
1915     }
1916     return outerRRect;
1917 }
1918 #endif
1919 
1920 #ifndef USE_ROSEN_DRAWING
PaintColorAndImage(const Offset & offset,SkCanvas * canvas,SkPaint & paint,RenderContext & renderContext)1921 void RosenDecorationPainter::PaintColorAndImage(
1922     const Offset& offset, SkCanvas* canvas, SkPaint& paint, RenderContext& renderContext)
1923 #else
1924 void RosenDecorationPainter::PaintColorAndImage(
1925     const Offset& offset, RSCanvas* canvas, RSBrush& brush, RenderContext& renderContext)
1926 #endif
1927 {
1928     auto rsNode = static_cast<RosenRenderContext*>(&renderContext)->GetRSNode();
1929     if (!decoration_ || !rsNode) {
1930         return;
1931     }
1932 
1933     // paint backColor
1934     bool paintBgColor = false;
1935 #ifndef USE_ROSEN_DRAWING
1936     paint.setStyle(SkPaint::Style::kFill_Style);
1937 #endif
1938     Color backColor = decoration_->GetBackgroundColor();
1939     Color animationColor = decoration_->GetAnimationColor();
1940     if (backColor != Color::TRANSPARENT) {
1941         rsNode->SetBackgroundColor(backColor.GetValue());
1942         paintBgColor = true;
1943     } else {
1944         rsNode->SetBackgroundColor(Color::TRANSPARENT.GetValue());
1945     }
1946 
1947     if (animationColor != Color::TRANSPARENT) {
1948         rsNode->SetBackgroundColor(animationColor.GetValue());
1949     }
1950 
1951     // paint background image.
1952     RefPtr<ArcBackground> arcBG = decoration_->GetArcBackground();
1953     if (arcBG) {
1954         Color arcColor = arcBG->GetColor();
1955         if (arcColor != Color::TRANSPARENT) {
1956 #ifndef USE_ROSEN_DRAWING
1957             paint.setColor(arcColor.GetValue());
1958             canvas->drawCircle(arcBG->GetCenter().GetX(), arcBG->GetCenter().GetY(), arcBG->GetRadius(), paint);
1959 #else
1960             brush.SetColor(arcColor.GetValue());
1961             canvas->AttachBrush(brush);
1962             RSPoint point(arcBG->GetCenter().GetX(), arcBG->GetCenter().GetY());
1963             canvas->DrawCircle(point, arcBG->GetRadius());
1964             canvas->DetachBrush();
1965 #endif
1966             paintBgColor = true;
1967         }
1968     }
1969     if (paintBgColor) {
1970         return;
1971     }
1972     // paint background image.
1973     if (decoration_->GetImage()) {
1974         PaintImage(offset, renderContext);
1975         return;
1976     }
1977     // paint Gradient color.
1978     if (decoration_->GetGradient().IsValid()) {
1979         PaintGradient(renderContext);
1980     }
1981 }
1982 
1983 #ifndef USE_ROSEN_DRAWING
GetOuterRRect(const Offset & offset,const Border & border)1984 SkRRect RosenDecorationPainter::GetOuterRRect(const Offset& offset, const Border& border)
1985 {
1986     SkRRect rrect;
1987     float topLeftRadiusX = NormalizeToPx(border.TopLeftRadius().GetX());
1988     float topLeftRadiusY = NormalizeToPx(border.TopLeftRadius().GetY());
1989     float topRightRadiusX = NormalizeToPx(border.TopRightRadius().GetX());
1990     float topRightRadiusY = NormalizeToPx(border.TopRightRadius().GetY());
1991     float bottomRightRadiusX = NormalizeToPx(border.BottomRightRadius().GetX());
1992     float bottomRightRadiusY = NormalizeToPx(border.BottomRightRadius().GetY());
1993     float bottomLeftRadiusX = NormalizeToPx(border.BottomLeftRadius().GetX());
1994     float bottomLeftRadiusY = NormalizeToPx(border.BottomLeftRadius().GetY());
1995     SkRect outerRect = SkRect::MakeXYWH(offset.GetX(), offset.GetY(), paintSize_.Width(), paintSize_.Height());
1996     const SkVector outerRadii[] = { SkVector::Make(topLeftRadiusX, topLeftRadiusY),
1997         SkVector::Make(topRightRadiusX, topRightRadiusY), SkVector::Make(bottomRightRadiusX, bottomRightRadiusY),
1998         SkVector::Make(bottomLeftRadiusX, bottomLeftRadiusY) };
1999     rrect.setRectRadii(outerRect, outerRadii);
2000     return rrect;
2001 }
2002 #else
GetOuterRRect(const Offset & offset,const Border & border)2003 RSRoundRect RosenDecorationPainter::GetOuterRRect(const Offset& offset, const Border& border)
2004 {
2005     float topLeftRadiusX = NormalizeToPx(border.TopLeftRadius().GetX());
2006     float topLeftRadiusY = NormalizeToPx(border.TopLeftRadius().GetY());
2007     float topRightRadiusX = NormalizeToPx(border.TopRightRadius().GetX());
2008     float topRightRadiusY = NormalizeToPx(border.TopRightRadius().GetY());
2009     float bottomRightRadiusX = NormalizeToPx(border.BottomRightRadius().GetX());
2010     float bottomRightRadiusY = NormalizeToPx(border.BottomRightRadius().GetY());
2011     float bottomLeftRadiusX = NormalizeToPx(border.BottomLeftRadius().GetX());
2012     float bottomLeftRadiusY = NormalizeToPx(border.BottomLeftRadius().GetY());
2013     RSRect outerRect =
2014         RSRect(offset.GetX(), offset.GetY(), paintSize_.Width() + offset.GetX(), paintSize_.Height() + offset.GetY());
2015     std::vector<RSPoint> outerRadii;
2016     outerRadii.push_back(RSPoint(topLeftRadiusX, topLeftRadiusY));
2017     outerRadii.push_back(RSPoint(topRightRadiusX, topRightRadiusY));
2018     outerRadii.push_back(RSPoint(bottomRightRadiusX, bottomRightRadiusY));
2019     outerRadii.push_back(RSPoint(bottomLeftRadiusX, bottomLeftRadiusY));
2020     return RSRoundRect(outerRect, outerRadii);
2021 }
2022 #endif
2023 
2024 #ifndef USE_ROSEN_DRAWING
GetInnerRRect(const Offset & offset,const Border & border)2025 SkRRect RosenDecorationPainter::GetInnerRRect(const Offset& offset, const Border& border)
2026 {
2027     SkRRect rrect;
2028     float x = offset.GetX();
2029     float y = offset.GetY();
2030     float w = paintSize_.Width();
2031     float h = paintSize_.Height();
2032     float leftW = NormalizeToPx(border.Left().GetWidth());
2033     float topW = NormalizeToPx(border.Top().GetWidth());
2034     float rightW = NormalizeToPx(border.Right().GetWidth());
2035     float bottomW = NormalizeToPx(border.Bottom().GetWidth());
2036     float tlX = NormalizeToPx(border.TopLeftRadius().GetX());
2037     float tlY = NormalizeToPx(border.TopLeftRadius().GetY());
2038     float trX = NormalizeToPx(border.TopRightRadius().GetX());
2039     float trY = NormalizeToPx(border.TopRightRadius().GetY());
2040     float brX = NormalizeToPx(border.BottomRightRadius().GetX());
2041     float brY = NormalizeToPx(border.BottomRightRadius().GetY());
2042     float blX = NormalizeToPx(border.BottomLeftRadius().GetX());
2043     float blY = NormalizeToPx(border.BottomLeftRadius().GetY());
2044     SkRect innerRect = SkRect::MakeXYWH(x + leftW, y + topW, w - rightW - leftW, h - bottomW - topW);
2045     const SkVector innerRadii[] = { SkVector::Make(std::max(0.0f, tlX - leftW), std::max(0.0f, tlY - topW)),
2046         SkVector::Make(std::max(0.0f, trX - rightW), std::max(0.0f, trY - topW)),
2047         SkVector::Make(std::max(0.0f, brX - rightW), std::max(0.0f, brY - bottomW)),
2048         SkVector::Make(std::max(0.0f, blX - leftW), std::max(0.0f, blY - bottomW)) };
2049     rrect.setRectRadii(innerRect, innerRadii);
2050     return rrect;
2051 }
2052 #else
GetInnerRRect(const Offset & offset,const Border & border)2053 RSRoundRect RosenDecorationPainter::GetInnerRRect(const Offset& offset, const Border& border)
2054 {
2055     float x = offset.GetX();
2056     float y = offset.GetY();
2057     float w = paintSize_.Width();
2058     float h = paintSize_.Height();
2059     float leftW = NormalizeToPx(border.Left().GetWidth());
2060     float topW = NormalizeToPx(border.Top().GetWidth());
2061     float rightW = NormalizeToPx(border.Right().GetWidth());
2062     float bottomW = NormalizeToPx(border.Bottom().GetWidth());
2063     float tlX = NormalizeToPx(border.TopLeftRadius().GetX());
2064     float tlY = NormalizeToPx(border.TopLeftRadius().GetY());
2065     float trX = NormalizeToPx(border.TopRightRadius().GetX());
2066     float trY = NormalizeToPx(border.TopRightRadius().GetY());
2067     float brX = NormalizeToPx(border.BottomRightRadius().GetX());
2068     float brY = NormalizeToPx(border.BottomRightRadius().GetY());
2069     float blX = NormalizeToPx(border.BottomLeftRadius().GetX());
2070     float blY = NormalizeToPx(border.BottomLeftRadius().GetY());
2071     RSRect innerRect = RSRect(x + leftW, y + topW, w - rightW + x, h - bottomW + y);
2072     std::vector<RSPoint> innerRadii;
2073     innerRadii.push_back(RSPoint(std::max(0.0f, tlX - leftW), std::max(0.0f, tlY - topW)));
2074     innerRadii.push_back(RSPoint(std::max(0.0f, trX - rightW), std::max(0.0f, trY - topW)));
2075     innerRadii.push_back(RSPoint(std::max(0.0f, brX - rightW), std::max(0.0f, brY - bottomW)));
2076     innerRadii.push_back(RSPoint(std::max(0.0f, blX - leftW), std::max(0.0f, blY - bottomW)));
2077     return RSRoundRect(innerRect, innerRadii);
2078 }
2079 #endif
2080 
2081 #ifndef USE_ROSEN_DRAWING
GetClipRRect(const Offset & offset,const Border & border)2082 SkRRect RosenDecorationPainter::GetClipRRect(const Offset& offset, const Border& border)
2083 {
2084     SkRRect rrect;
2085     float bottomRightRadiusX = NormalizeToPx(border.BottomRightRadius().GetX());
2086     float bottomRightRadiusY = NormalizeToPx(border.BottomRightRadius().GetY());
2087     float bottomLeftRadiusX = NormalizeToPx(border.BottomLeftRadius().GetX());
2088     float bottomLeftRadiusY = NormalizeToPx(border.BottomLeftRadius().GetY());
2089     float topLeftRadiusX = NormalizeToPx(border.TopLeftRadius().GetX());
2090     float topLeftRadiusY = NormalizeToPx(border.TopLeftRadius().GetY());
2091     float topRightRadiusX = NormalizeToPx(border.TopRightRadius().GetX());
2092     float topRightRadiusY = NormalizeToPx(border.TopRightRadius().GetY());
2093     const SkVector outerRadii[] = { SkVector::Make(topLeftRadiusX, topLeftRadiusY),
2094         SkVector::Make(topRightRadiusX, topRightRadiusY), SkVector::Make(bottomRightRadiusX, bottomRightRadiusY),
2095         SkVector::Make(bottomLeftRadiusX, bottomLeftRadiusY) };
2096     float leftW = NormalizeToPx(border.Left().GetWidth());
2097     float topW = NormalizeToPx(border.Top().GetWidth());
2098     float rightW = NormalizeToPx(border.Right().GetWidth());
2099     float bottomW = NormalizeToPx(border.Bottom().GetWidth());
2100     float x = offset.GetX() + leftW / 2.0f;
2101     float y = offset.GetY() + topW / 2.0f;
2102     float w = paintSize_.Width() - (leftW + rightW) / 2.0f;
2103     float h = paintSize_.Height() - (topW + bottomW) / 2.0f;
2104     rrect.setRectRadii(SkRect::MakeXYWH(x, y, w, h), outerRadii);
2105     return rrect;
2106 }
2107 #else
GetClipRRect(const Offset & offset,const Border & border)2108 RSRoundRect RosenDecorationPainter::GetClipRRect(const Offset& offset, const Border& border)
2109 {
2110     float bottomRightRadiusX = NormalizeToPx(border.BottomRightRadius().GetX());
2111     float bottomRightRadiusY = NormalizeToPx(border.BottomRightRadius().GetY());
2112     float bottomLeftRadiusX = NormalizeToPx(border.BottomLeftRadius().GetX());
2113     float bottomLeftRadiusY = NormalizeToPx(border.BottomLeftRadius().GetY());
2114     float topLeftRadiusX = NormalizeToPx(border.TopLeftRadius().GetX());
2115     float topLeftRadiusY = NormalizeToPx(border.TopLeftRadius().GetY());
2116     float topRightRadiusX = NormalizeToPx(border.TopRightRadius().GetX());
2117     float topRightRadiusY = NormalizeToPx(border.TopRightRadius().GetY());
2118     std::vector<RSPoint> outerRadii;
2119     outerRadii.push_back(RSPoint(topLeftRadiusX, topLeftRadiusY));
2120     outerRadii.push_back(RSPoint(topRightRadiusX, topRightRadiusY));
2121     outerRadii.push_back(RSPoint(bottomRightRadiusX, bottomRightRadiusY));
2122     outerRadii.push_back(RSPoint(bottomLeftRadiusX, bottomLeftRadiusY));
2123     float leftW = NormalizeToPx(border.Left().GetWidth());
2124     float topW = NormalizeToPx(border.Top().GetWidth());
2125     float rightW = NormalizeToPx(border.Right().GetWidth());
2126     float bottomW = NormalizeToPx(border.Bottom().GetWidth());
2127     float x = offset.GetX() + leftW / 2.0f;
2128     float y = offset.GetY() + topW / 2.0f;
2129     float w = paintSize_.Width() - (leftW + rightW) / 2.0f;
2130     float h = paintSize_.Height() - (topW + bottomW) / 2.0f;
2131     RSRect outerRect = RSRect(x, y, w + x, h + y);
2132     return RSRoundRect(outerRect, outerRadii);
2133 }
2134 #endif
2135 
2136 #ifndef USE_ROSEN_DRAWING
CanUseFillStyle(const Border & border,SkPaint & paint)2137 bool RosenDecorationPainter::CanUseFillStyle(const Border& border, SkPaint& paint)
2138 #else
2139 bool RosenDecorationPainter::CanUseFillStyle(const Border& border, RSBrush& brush)
2140 #endif
2141 {
2142     if (border.Top().GetBorderStyle() != BorderStyle::SOLID || border.Right().GetBorderStyle() != BorderStyle::SOLID ||
2143         border.Bottom().GetBorderStyle() != BorderStyle::SOLID ||
2144         border.Left().GetBorderStyle() != BorderStyle::SOLID) {
2145         return false;
2146     }
2147     if (border.Left().GetColor() != border.Top().GetColor() || border.Left().GetColor() != border.Right().GetColor() ||
2148         border.Left().GetColor() != border.Bottom().GetColor()) {
2149         return false;
2150     }
2151 #ifndef USE_ROSEN_DRAWING
2152     paint.setStyle(SkPaint::Style::kFill_Style);
2153     paint.setColor(border.Left().GetColor().GetValue());
2154 #else
2155     brush.SetColor(border.Left().GetColor().GetValue());
2156 #endif
2157     return true;
2158 }
2159 
2160 #ifndef USE_ROSEN_DRAWING
CanUsePathRRect(const Border & border,SkPaint & paint)2161 bool RosenDecorationPainter::CanUsePathRRect(const Border& border, SkPaint& paint)
2162 #else
2163 bool RosenDecorationPainter::CanUsePathRRect(const Border& border, RSPen& pen)
2164 #endif
2165 {
2166     if (border.Left().GetBorderStyle() != border.Top().GetBorderStyle() ||
2167         border.Left().GetBorderStyle() != border.Right().GetBorderStyle() ||
2168         border.Left().GetBorderStyle() != border.Bottom().GetBorderStyle()) {
2169         return false;
2170     }
2171     if (border.Left().GetWidth() != border.Top().GetWidth() || border.Left().GetWidth() != border.Right().GetWidth() ||
2172         border.Left().GetWidth() != border.Bottom().GetWidth()) {
2173         return false;
2174     }
2175     if (border.Left().GetColor() != border.Top().GetColor() || border.Left().GetColor() != border.Right().GetColor() ||
2176         border.Left().GetColor() != border.Bottom().GetColor()) {
2177         return false;
2178     }
2179 #ifndef USE_ROSEN_DRAWING
2180     SetBorderStyle(border.Left(), paint, false);
2181 #else
2182     SetBorderStyle(border.Left(), pen, false);
2183 #endif
2184     return true;
2185 }
2186 
CanUseFourLine(const Border & border)2187 bool RosenDecorationPainter::CanUseFourLine(const Border& border)
2188 {
2189     if (border.Left().GetBorderStyle() != border.Top().GetBorderStyle() ||
2190         border.Left().GetBorderStyle() != border.Right().GetBorderStyle() ||
2191         border.Left().GetBorderStyle() != border.Bottom().GetBorderStyle()) {
2192         return false;
2193     }
2194     if (border.Left().GetColor() != border.Top().GetColor() || border.Left().GetColor() != border.Right().GetColor() ||
2195         border.Left().GetColor() != border.Bottom().GetColor()) {
2196         return false;
2197     }
2198     if (border.TopLeftRadius().IsValid() || border.TopRightRadius().IsValid() || border.BottomLeftRadius().IsValid() ||
2199         border.BottomRightRadius().IsValid()) {
2200         return false;
2201     }
2202     return true;
2203 }
2204 
CanUseInnerRRect(const Border & border)2205 bool RosenDecorationPainter::CanUseInnerRRect(const Border& border)
2206 {
2207     if (!border.HasValue()) {
2208         return false;
2209     }
2210     if (border.Top().GetBorderStyle() != BorderStyle::SOLID || border.Right().GetBorderStyle() != BorderStyle::SOLID ||
2211         border.Bottom().GetBorderStyle() != BorderStyle::SOLID ||
2212         border.Left().GetBorderStyle() != BorderStyle::SOLID) {
2213         return false;
2214     }
2215     return true;
2216 }
2217 
2218 #ifndef USE_ROSEN_DRAWING
GetBoxRRect(const Offset & offset,const Border & border,double shrinkFactor,bool isRound)2219 SkRRect RosenDecorationPainter::GetBoxRRect(
2220     const Offset& offset, const Border& border, double shrinkFactor, bool isRound)
2221 {
2222     SkRRect rrect;
2223     SkRect skRect {};
2224     SkVector fRadii[4] = { { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 } };
2225     if (CheckBorderEdgeForRRect(border)) {
2226         BorderEdge borderEdge = border.Left();
2227         double borderWidth = NormalizeToPx(borderEdge.GetWidth());
2228         skRect.setXYWH(SkDoubleToScalar(offset.GetX() + shrinkFactor * borderWidth),
2229             SkDoubleToScalar(offset.GetY() + shrinkFactor * borderWidth),
2230             SkDoubleToScalar(paintSize_.Width() - shrinkFactor * DOUBLE_WIDTH * borderWidth),
2231             SkDoubleToScalar(paintSize_.Height() - shrinkFactor * DOUBLE_WIDTH * borderWidth));
2232         if (isRound) {
2233             fRadii[SkRRect::kUpperLeft_Corner].set(
2234                 SkDoubleToScalar(
2235                     std::max(NormalizeToPx(border.TopLeftRadius().GetX()) - shrinkFactor * borderWidth, 0.0)),
2236                 SkDoubleToScalar(
2237                     std::max(NormalizeToPx(border.TopLeftRadius().GetY()) - shrinkFactor * borderWidth, 0.0)));
2238             fRadii[SkRRect::kUpperRight_Corner].set(
2239                 SkDoubleToScalar(
2240                     std::max(NormalizeToPx(border.TopRightRadius().GetX()) - shrinkFactor * borderWidth, 0.0)),
2241                 SkDoubleToScalar(
2242                     std::max(NormalizeToPx(border.TopRightRadius().GetY()) - shrinkFactor * borderWidth, 0.0)));
2243             fRadii[SkRRect::kLowerRight_Corner].set(
2244                 SkDoubleToScalar(
2245                     std::max(NormalizeToPx(border.BottomRightRadius().GetX()) - shrinkFactor * borderWidth, 0.0)),
2246                 SkDoubleToScalar(
2247                     std::max(NormalizeToPx(border.BottomRightRadius().GetY()) - shrinkFactor * borderWidth, 0.0)));
2248             fRadii[SkRRect::kLowerLeft_Corner].set(
2249                 SkDoubleToScalar(
2250                     std::max(NormalizeToPx(border.BottomLeftRadius().GetX()) - shrinkFactor * borderWidth, 0.0)),
2251                 SkDoubleToScalar(
2252                     std::max(NormalizeToPx(border.BottomLeftRadius().GetY()) - shrinkFactor * borderWidth, 0.0)));
2253         }
2254     } else {
2255         skRect.setXYWH(SkDoubleToScalar(offset.GetX() + shrinkFactor * NormalizeToPx(border.Left().GetWidth())),
2256             SkDoubleToScalar(offset.GetY() + shrinkFactor * NormalizeToPx(border.Top().GetWidth())),
2257             SkDoubleToScalar(
2258                 paintSize_.Width() - shrinkFactor * DOUBLE_WIDTH * NormalizeToPx(border.Right().GetWidth())),
2259             SkDoubleToScalar(paintSize_.Height() - shrinkFactor * (NormalizeToPx(border.Bottom().GetWidth()) +
2260                                                                       NormalizeToPx(border.Top().GetWidth()))));
2261     }
2262     rrect.setRectRadii(skRect, fRadii);
2263     return rrect;
2264 }
2265 #else
GetBoxRRect(const Offset & offset,const Border & border,double shrinkFactor,bool isRound)2266 RSRoundRect RosenDecorationPainter::GetBoxRRect(
2267     const Offset& offset, const Border& border, double shrinkFactor, bool isRound)
2268 {
2269     RSRoundRect rrect;
2270     RSRect rect;
2271     if (CheckBorderEdgeForRRect(border)) {
2272         std::vector<RSPoint> fRadii;
2273         BorderEdge borderEdge = border.Left();
2274         double borderWidth = NormalizeToPx(borderEdge.GetWidth());
2275         rect = RSRect(static_cast<RSScalar>(offset.GetX() + shrinkFactor * borderWidth),
2276             static_cast<RSScalar>(offset.GetY() + shrinkFactor * borderWidth),
2277             static_cast<RSScalar>(paintSize_.Width() - shrinkFactor * borderWidth + offset.GetX()),
2278             static_cast<RSScalar>(paintSize_.Height() - shrinkFactor * borderWidth + offset.GetY()));
2279         if (isRound) {
2280             fRadii.push_back(
2281                 RSPoint(static_cast<RSScalar>(
2282                             std::max(NormalizeToPx(border.TopLeftRadius().GetX()) - shrinkFactor * borderWidth, 0.0)),
2283                     static_cast<RSScalar>(
2284                         std::max(NormalizeToPx(border.TopLeftRadius().GetY()) - shrinkFactor * borderWidth, 0.0))));
2285             fRadii.push_back(
2286                 RSPoint(static_cast<RSScalar>(
2287                             std::max(NormalizeToPx(border.TopRightRadius().GetX()) - shrinkFactor * borderWidth, 0.0)),
2288                     static_cast<RSScalar>(
2289                         std::max(NormalizeToPx(border.TopRightRadius().GetY()) - shrinkFactor * borderWidth, 0.0))));
2290             fRadii.push_back(
2291                 RSPoint(static_cast<RSScalar>(std::max(
2292                             NormalizeToPx(border.BottomRightRadius().GetX()) - shrinkFactor * borderWidth, 0.0)),
2293                     static_cast<RSScalar>(
2294                         std::max(NormalizeToPx(border.BottomRightRadius().GetY()) - shrinkFactor * borderWidth, 0.0))));
2295             fRadii.push_back(
2296                 RSPoint(static_cast<RSScalar>(std::max(
2297                             NormalizeToPx(border.BottomLeftRadius().GetX()) - shrinkFactor * borderWidth, 0.0)),
2298                     static_cast<RSScalar>(
2299                         std::max(NormalizeToPx(border.BottomLeftRadius().GetY()) - shrinkFactor * borderWidth, 0.0))));
2300         }
2301         rrect = RSRoundRect(rect, fRadii);
2302     } else {
2303         rect = RSRect(static_cast<RSScalar>(offset.GetX() + shrinkFactor * NormalizeToPx(border.Left().GetWidth())),
2304             static_cast<RSScalar>(offset.GetY() + shrinkFactor * NormalizeToPx(border.Top().GetWidth())),
2305             static_cast<RSScalar>(paintSize_.Width() -
2306                                   shrinkFactor * DOUBLE_WIDTH * NormalizeToPx(border.Right().GetWidth()) +
2307                                   offset.GetX() + shrinkFactor * NormalizeToPx(border.Left().GetWidth())),
2308             static_cast<RSScalar>(
2309                 paintSize_.Height() -
2310                 shrinkFactor * (NormalizeToPx(border.Bottom().GetWidth()) + NormalizeToPx(border.Top().GetWidth())) +
2311                 offset.GetY() + shrinkFactor * NormalizeToPx(border.Top().GetWidth())));
2312         rrect.SetRect(rect);
2313     }
2314     return rrect;
2315 }
2316 #endif
2317 
2318 #ifndef USE_ROSEN_DRAWING
SetBorderStyle(const BorderEdge & borderEdge,SkPaint & paint,bool useDefaultColor,double spaceBetweenDot,double borderLength)2319 void RosenDecorationPainter::SetBorderStyle(
2320     const BorderEdge& borderEdge, SkPaint& paint, bool useDefaultColor, double spaceBetweenDot, double borderLength)
2321 {
2322     if (borderEdge.HasValue()) {
2323         double width = NormalizeToPx(borderEdge.GetWidth());
2324         uint32_t color = useDefaultColor ? Color::BLACK.GetValue() : borderEdge.GetColor().GetValue();
2325         paint.setStrokeWidth(width);
2326         paint.setColor(color);
2327         paint.setStyle(SkPaint::Style::kStroke_Style);
2328         if (borderEdge.GetBorderStyle() == BorderStyle::DOTTED) {
2329             SkPath dotPath;
2330             if (NearZero(spaceBetweenDot)) {
2331                 spaceBetweenDot = width * 2.0; // 2.0: Double factor.
2332             }
2333             dotPath.addCircle(0.0f, 0.0f, SkDoubleToScalar(width / 2.0)); // 2.0: Average factor.
2334             paint.setPathEffect(
2335                 SkPath1DPathEffect::Make(dotPath, spaceBetweenDot, 0.0, SkPath1DPathEffect::kRotate_Style));
2336         } else if (borderEdge.GetBorderStyle() == BorderStyle::DASHED) {
2337             double addLen = 0.0; // When left < 2 * gap, splits left to gaps.
2338             double delLen = 0.0; // When left > 2 * gap, add one dash and shortening them.
2339             if (!NearZero(borderLength)) {
2340                 double count = borderLength / width;
2341                 double leftLen = fmod((count - DASHED_LINE_LENGTH), (DASHED_LINE_LENGTH + 1));
2342                 if (NearZero(count - DASHED_LINE_LENGTH)) {
2343                     return;
2344                 }
2345                 if (leftLen > DASHED_LINE_LENGTH - 1) {
2346                     delLen = (DASHED_LINE_LENGTH + 1 - leftLen) * width /
2347                              static_cast<int32_t>((count - DASHED_LINE_LENGTH) / (DASHED_LINE_LENGTH + 1) + DEL_NUM);
2348                 } else {
2349                     addLen =
2350                         leftLen * width / static_cast<int32_t>((count - DASHED_LINE_LENGTH) / (DASHED_LINE_LENGTH + 1));
2351                 }
2352             }
2353             const float intervals[] = { width * DASHED_LINE_LENGTH - delLen, width + addLen };
2354             paint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 0.0));
2355         } else {
2356             paint.setPathEffect(nullptr);
2357         }
2358     }
2359 }
2360 #else
SetBorderStyle(const BorderEdge & borderEdge,RSPen & pen,bool useDefaultColor,double spaceBetweenDot,double borderLength)2361 void RosenDecorationPainter::SetBorderStyle(
2362     const BorderEdge& borderEdge, RSPen& pen, bool useDefaultColor, double spaceBetweenDot, double borderLength)
2363 {
2364     if (borderEdge.HasValue()) {
2365         double width = NormalizeToPx(borderEdge.GetWidth());
2366         uint32_t color = useDefaultColor ? Color::BLACK.GetValue() : borderEdge.GetColor().GetValue();
2367         pen.SetWidth(width);
2368         pen.SetColor(color);
2369         if (borderEdge.GetBorderStyle() == BorderStyle::DOTTED) {
2370             RSPath dotPath;
2371             if (NearZero(spaceBetweenDot)) {
2372                 spaceBetweenDot = width * 2.0; // 2.0: Double factor.
2373             }
2374             dotPath.AddCircle(0.0f, 0.0f, static_cast<RSScalar>(width / 2.0)); // 2.0: Average factor.
2375             pen.SetPathEffect(
2376                 RSPathEffect::CreatePathDashEffect(dotPath, spaceBetweenDot, 0.0, RSPathDashStyle::ROTATE));
2377         } else if (borderEdge.GetBorderStyle() == BorderStyle::DASHED) {
2378             double addLen = 0.0; // When left < 2 * gap, splits left to gaps.
2379             double delLen = 0.0; // When left > 2 * gap, add one dash and shortening them.
2380             if (!NearZero(borderLength)) {
2381                 double count = borderLength / width;
2382                 double leftLen = fmod((count - DASHED_LINE_LENGTH), (DASHED_LINE_LENGTH + 1));
2383                 if (NearZero(count - DASHED_LINE_LENGTH)) {
2384                     return;
2385                 }
2386                 if (leftLen > DASHED_LINE_LENGTH - 1) {
2387                     delLen = (DASHED_LINE_LENGTH + 1 - leftLen) * width /
2388                              static_cast<int32_t>((count - DASHED_LINE_LENGTH) / (DASHED_LINE_LENGTH + 1) + DEL_NUM);
2389                 } else {
2390                     addLen =
2391                         leftLen * width / static_cast<int32_t>((count - DASHED_LINE_LENGTH) / (DASHED_LINE_LENGTH + 1));
2392                 }
2393             }
2394             const RSScalar intervals[] = { width * DASHED_LINE_LENGTH - delLen, width + addLen };
2395             pen.SetPathEffect(RSPathEffect::CreateDashPathEffect(intervals, sizeof(intervals) / sizeof(RSScalar), 0.0));
2396         } else {
2397             pen.SetPathEffect(nullptr);
2398         }
2399     }
2400 }
2401 #endif
2402 
2403 #ifndef USE_ROSEN_DRAWING
PaintBorder(const Offset & offset,const Border & border,SkCanvas * canvas,SkPaint & paint)2404 void RosenDecorationPainter::PaintBorder(const Offset& offset, const Border& border, SkCanvas* canvas, SkPaint& paint)
2405 #else
2406 void RosenDecorationPainter::PaintBorder(const Offset& offset, const Border& border, RSCanvas* canvas, RSPen& pen)
2407 #endif
2408 {
2409     float offsetX = offset.GetX();
2410     float offsetY = offset.GetY();
2411     float width = paintSize_.Width();
2412     float height = paintSize_.Height();
2413     float leftW = NormalizeToPx(border.Left().GetWidth());
2414     float topW = NormalizeToPx(border.Top().GetWidth());
2415     float rightW = NormalizeToPx(border.Right().GetWidth());
2416     float bottomW = NormalizeToPx(border.Bottom().GetWidth());
2417     float maxW = std::max(std::max(leftW, topW), std::max(rightW, bottomW));
2418     float x = offset.GetX() + leftW / 2.0f;
2419     float y = offset.GetY() + topW / 2.0f;
2420     float w = std::max(0.0, paintSize_.Width() - (leftW + rightW) / 2.0f);
2421     float h = std::max(0.0, paintSize_.Height() - (topW + bottomW) / 2.0f);
2422     float tlX = std::max(0.0, NormalizeToPx(border.TopLeftRadius().GetX()) - (topW + leftW) / 4.0f);
2423     float tlY = std::max(0.0, NormalizeToPx(border.TopLeftRadius().GetY()) - (topW + leftW) / 4.0f);
2424     float trX = std::max(0.0, NormalizeToPx(border.TopRightRadius().GetX()) - (topW + rightW) / 4.0f);
2425     float trY = std::max(0.0, NormalizeToPx(border.TopRightRadius().GetY()) - (topW + rightW) / 4.0f);
2426     float brX = std::max(0.0, NormalizeToPx(border.BottomRightRadius().GetX()) - (bottomW + rightW) / 4.0f);
2427     float brY = std::max(0.0, NormalizeToPx(border.BottomRightRadius().GetY()) - (bottomW + rightW) / 4.0f);
2428     float blX = std::max(0.0, NormalizeToPx(border.BottomLeftRadius().GetX()) - (bottomW + leftW) / 4.0f);
2429     float blY = std::max(0.0, NormalizeToPx(border.BottomLeftRadius().GetY()) - (bottomW + leftW) / 4.0f);
2430 #ifndef USE_ROSEN_DRAWING
2431     if (border.Top().HasValue() && !NearZero(topW)) {
2432         // Draw Top Border
2433         SetBorderStyle(border.Top(), paint, false);
2434         auto rectStart = SkRect::MakeXYWH(x, y, tlX * 2.0f, tlY * 2.0f);
2435         auto rectEnd = SkRect::MakeXYWH(x + w - trX * 2.0f, y, trX * 2.0f, trY * 2.0f);
2436         SkPath topBorder;
2437         paint.setStrokeWidth(maxW);
2438         if (border.Top().GetBorderStyle() != BorderStyle::DOTTED) {
2439             paint.setStrokeWidth(maxW);
2440         }
2441         if (NearZero(tlX) || NearZero(tlY) || NearZero(trX) || NearZero(trY)) {
2442             canvas->save();
2443         }
2444         if (NearZero(tlX) && !NearZero(leftW)) {
2445             topBorder.moveTo(offsetX, y);
2446             topBorder.lineTo(x, y);
2447             SkPath topClipPath;
2448             topClipPath.moveTo(offsetX - leftW, offsetY - topW);
2449             topClipPath.lineTo(offsetX + leftW * EXTEND, offsetY + topW * EXTEND);
2450             topClipPath.lineTo(offsetX, offsetY + topW * EXTEND);
2451             topClipPath.close();
2452             canvas->clipPath(topClipPath, SkClipOp::kDifference, true);
2453         }
2454         topBorder.arcTo(rectStart, TOP_START, SWEEP_ANGLE, false);
2455         topBorder.arcTo(rectEnd, TOP_END, SWEEP_ANGLE + 0.5f, false);
2456         if (NearZero(trX) && !NearZero(rightW)) {
2457             topBorder.lineTo(offsetX + width, y);
2458             SkPath topClipPath;
2459             topClipPath.moveTo(offsetX + width + rightW, offsetY - topW);
2460             topClipPath.lineTo(offsetX + width - rightW * EXTEND, offsetY + topW * EXTEND);
2461             topClipPath.lineTo(offsetX + width, offsetY + topW * EXTEND);
2462             topClipPath.close();
2463             canvas->clipPath(topClipPath, SkClipOp::kDifference, true);
2464         }
2465         canvas->drawPath(topBorder, paint);
2466         if (NearZero(tlX) || NearZero(tlY) || NearZero(trX) || NearZero(trY)) {
2467             canvas->restore();
2468         }
2469     }
2470     if (border.Right().HasValue() && !NearZero(rightW)) {
2471         // Draw Right Border
2472         SetBorderStyle(border.Right(), paint, false);
2473         auto rectStart = SkRect::MakeXYWH(x + w - trX * 2.0f, y, trX * 2.0f, trY * 2.0f);
2474         auto rectEnd = SkRect::MakeXYWH(x + w - brX * 2.0f, y + h - brY * 2.0f, brX * 2.0f, brY * 2.0f);
2475         SkPath rightBorder;
2476         paint.setStrokeWidth(maxW);
2477         if (border.Right().GetBorderStyle() != BorderStyle::DOTTED) {
2478             paint.setStrokeWidth(maxW);
2479         }
2480         if (NearZero(trX) || NearZero(trY) || NearZero(brX) || NearZero(brY)) {
2481             canvas->save();
2482         }
2483         if (NearZero(trX) && !NearZero(topW)) {
2484             rightBorder.moveTo(offsetX + width - rightW / 2.0f, offsetY);
2485             rightBorder.lineTo(x + w - trX * 2.0f, y);
2486             SkPath rightClipPath;
2487             rightClipPath.moveTo(offsetX + width + rightW, offsetY - topW);
2488             rightClipPath.lineTo(offsetX + width - rightW * EXTEND, offsetY + topW * EXTEND);
2489             rightClipPath.lineTo(offsetX + width - rightW * EXTEND, offsetY);
2490             rightClipPath.close();
2491             canvas->clipPath(rightClipPath, SkClipOp::kDifference, true);
2492         }
2493         rightBorder.arcTo(rectStart, RIGHT_START, SWEEP_ANGLE, false);
2494         rightBorder.arcTo(rectEnd, RIGHT_END, SWEEP_ANGLE + 0.5f, false);
2495         if (NearZero(brX) && !NearZero(bottomW)) {
2496             rightBorder.lineTo(offsetX + width - rightW / 2.0f, offsetY + height);
2497             SkPath rightClipPath;
2498             rightClipPath.moveTo(offsetX + width + rightW, offsetY + height + bottomW);
2499             rightClipPath.lineTo(offsetX + width - rightW * EXTEND, offsetY + height - bottomW * EXTEND);
2500             rightClipPath.lineTo(offsetX + width - rightW * EXTEND, offsetY + height);
2501             rightClipPath.close();
2502             canvas->clipPath(rightClipPath, SkClipOp::kDifference, true);
2503         }
2504         canvas->drawPath(rightBorder, paint);
2505         if (NearZero(trX) || NearZero(trY) || NearZero(brX) || NearZero(brY)) {
2506             canvas->restore();
2507         }
2508     }
2509     if (border.Bottom().HasValue() && !NearZero(bottomW)) {
2510         // Draw Bottom Border
2511         SetBorderStyle(border.Bottom(), paint, false);
2512         auto rectStart = SkRect::MakeXYWH(x + w - brX * 2.0f, y + h - brY * 2.0f, brX * 2.0f, brY * 2.0f);
2513         auto rectEnd = SkRect::MakeXYWH(x, y + h - blY * 2.0f, blX * 2.0f, blY * 2.0f);
2514         SkPath bottomBorder;
2515         if (border.Bottom().GetBorderStyle() != BorderStyle::DOTTED) {
2516             paint.setStrokeWidth(maxW);
2517         }
2518         if (NearZero(brX) || NearZero(brY) || NearZero(blX) || NearZero(blY)) {
2519             canvas->save();
2520         }
2521         if (NearZero(brX) && !NearZero(rightW)) {
2522             bottomBorder.moveTo(offsetX + width, offsetY + height - bottomW / 2.0f);
2523             bottomBorder.lineTo(x + w - brX * 2.0f, y + h - brY * 2.0f);
2524             SkPath bottomClipPath;
2525             bottomClipPath.moveTo(offsetX + width + rightW, offsetY + height + bottomW);
2526             bottomClipPath.lineTo(offsetX + width - rightW * EXTEND, offsetY + height - bottomW * EXTEND);
2527             bottomClipPath.lineTo(offsetX + width, offsetY + height - bottomW * EXTEND);
2528             bottomClipPath.close();
2529             canvas->clipPath(bottomClipPath, SkClipOp::kDifference, true);
2530         }
2531         bottomBorder.arcTo(rectStart, BOTTOM_START, SWEEP_ANGLE, false);
2532         bottomBorder.arcTo(rectEnd, BOTTOM_END, SWEEP_ANGLE + 0.5f, false);
2533         if (NearZero(blX) && !NearZero(leftW)) {
2534             bottomBorder.lineTo(offsetX, offsetY + height - bottomW / 2.0f);
2535             SkPath bottomClipPath;
2536             bottomClipPath.moveTo(offsetX - leftW, offsetY + height + bottomW);
2537             bottomClipPath.lineTo(offsetX + leftW * EXTEND, offsetY + height - bottomW * EXTEND);
2538             bottomClipPath.lineTo(offsetX, offsetY + height - bottomW * EXTEND);
2539             bottomClipPath.close();
2540             canvas->clipPath(bottomClipPath, SkClipOp::kDifference, true);
2541         }
2542         canvas->drawPath(bottomBorder, paint);
2543         if (NearZero(brX) || NearZero(brY) || NearZero(blX) || NearZero(blY)) {
2544             canvas->restore();
2545         }
2546     }
2547     if (border.Left().HasValue() && !NearZero(leftW)) {
2548         // Draw Left Border
2549         SetBorderStyle(border.Left(), paint, false);
2550         auto rectStart = SkRect::MakeXYWH(x, y + h - blY * 2.0f, blX * 2.0f, blY * 2.0f);
2551         auto rectEnd = SkRect::MakeXYWH(x, y, tlX * 2.0f, tlY * 2.0f);
2552         SkPath leftBorder;
2553         if (border.Left().GetBorderStyle() != BorderStyle::DOTTED) {
2554             paint.setStrokeWidth(maxW);
2555         }
2556         if (NearZero(blX) || NearZero(blY) || NearZero(tlX) || NearZero(tlY)) {
2557             canvas->save();
2558         }
2559         if (NearZero(blX) && !NearZero(bottomW)) {
2560             leftBorder.moveTo(offsetX + leftW / 2.0f, offsetY + height);
2561             leftBorder.lineTo(x, y + h - blY * 2.0f);
2562             SkPath leftClipPath;
2563             leftClipPath.moveTo(offsetX - leftW, offsetY + height + bottomW);
2564             leftClipPath.lineTo(offsetX + leftW * EXTEND, offsetY + height - bottomW * EXTEND);
2565             leftClipPath.lineTo(offsetX + leftW * EXTEND, offsetY + height);
2566             leftClipPath.close();
2567             canvas->clipPath(leftClipPath, SkClipOp::kDifference, true);
2568         }
2569         leftBorder.arcTo(rectStart, LEFT_START, SWEEP_ANGLE, false);
2570         leftBorder.arcTo(rectEnd, LEFT_END, SWEEP_ANGLE + 0.5f, false);
2571         if (NearZero(tlX) && !NearZero(topW)) {
2572             leftBorder.lineTo(offsetX + leftW / 2.0f, offsetY);
2573             SkPath topClipPath;
2574             topClipPath.moveTo(offsetX - leftW, offsetY - topW);
2575             topClipPath.lineTo(offsetX + leftW * EXTEND, offsetY + topW * EXTEND);
2576             topClipPath.lineTo(offsetX + leftW * EXTEND, offsetY);
2577             topClipPath.close();
2578             canvas->clipPath(topClipPath, SkClipOp::kDifference, true);
2579         }
2580         canvas->drawPath(leftBorder, paint);
2581         if (NearZero(blX) || NearZero(blY) || NearZero(tlX) || NearZero(tlY)) {
2582             canvas->restore();
2583         }
2584     }
2585 #else
2586     if (border.Top().HasValue() && !NearZero(topW)) {
2587         // Draw Top Border
2588         SetBorderStyle(border.Top(), pen, false);
2589         auto rectStart = RSRect(x, y, tlX * 2.0f + x, tlY * 2.0f + y);
2590         auto rectEnd = RSRect(x + w - trX * 2.0f, y, x + w, trY * 2.0f + y);
2591         RSRecordingPath topBorder;
2592         pen.SetWidth(maxW);
2593         if (border.Top().GetBorderStyle() != BorderStyle::DOTTED) {
2594             pen.SetWidth(maxW);
2595         }
2596         if (NearZero(tlX) || NearZero(tlY) || NearZero(trX) || NearZero(trY)) {
2597             canvas->Save();
2598         }
2599         if (NearZero(tlX) && !NearZero(leftW)) {
2600             topBorder.MoveTo(offsetX, y);
2601             topBorder.LineTo(x, y);
2602             RSRecordingPath topClipPath;
2603             topClipPath.MoveTo(offsetX - leftW, offsetY - topW);
2604             topClipPath.LineTo(offsetX + leftW * EXTEND, offsetY + topW * EXTEND);
2605             topClipPath.LineTo(offsetX, offsetY + topW * EXTEND);
2606             topClipPath.Close();
2607             canvas->ClipPath(topClipPath, RSClipOp::DIFFERENCE, true);
2608         }
2609         topBorder.ArcTo(rectStart.GetLeft(), rectStart.GetTop(), rectStart.GetRight(), rectStart.GetBottom(),
2610             TOP_START, SWEEP_ANGLE);
2611         topBorder.ArcTo(rectEnd.GetLeft(), rectEnd.GetTop(), rectEnd.GetRight(), rectEnd.GetBottom(),
2612             TOP_END, SWEEP_ANGLE + 0.5f);
2613         if (NearZero(trX) && !NearZero(rightW)) {
2614             topBorder.LineTo(offsetX + width, y);
2615             RSRecordingPath topClipPath;
2616             topClipPath.MoveTo(offsetX + width + rightW, offsetY - topW);
2617             topClipPath.LineTo(offsetX + width - rightW * EXTEND, offsetY + topW * EXTEND);
2618             topClipPath.LineTo(offsetX + width, offsetY + topW * EXTEND);
2619             topClipPath.Close();
2620             canvas->ClipPath(topClipPath, RSClipOp::DIFFERENCE, true);
2621         }
2622         canvas->AttachPen(pen);
2623         canvas->DrawPath(topBorder);
2624         if (NearZero(tlX) || NearZero(tlY) || NearZero(trX) || NearZero(trY)) {
2625             canvas->Restore();
2626         }
2627         canvas->DetachPen();
2628     }
2629     if (border.Right().HasValue() && !NearZero(rightW)) {
2630         // Draw Right Border
2631         SetBorderStyle(border.Right(), pen, false);
2632         auto rectStart = RSRect(x + w - trX * 2.0f, y, x + w, trY * 2.0f + y);
2633         auto rectEnd = RSRect(x + w - brX * 2.0f, y + h - brY * 2.0f, x + w, y + h);
2634         RSRecordingPath rightBorder;
2635         pen.SetWidth(maxW);
2636         if (border.Right().GetBorderStyle() != BorderStyle::DOTTED) {
2637             pen.SetWidth(maxW);
2638         }
2639         if (NearZero(trX) || NearZero(trY) || NearZero(brX) || NearZero(brY)) {
2640             canvas->Save();
2641         }
2642         if (NearZero(trX) && !NearZero(topW)) {
2643             rightBorder.MoveTo(offsetX + width - rightW / 2.0f, offsetY);
2644             rightBorder.LineTo(x + w - trX * 2.0f, y);
2645             RSRecordingPath rightClipPath;
2646             rightClipPath.MoveTo(offsetX + width + rightW, offsetY - topW);
2647             rightClipPath.LineTo(offsetX + width - rightW * EXTEND, offsetY + topW * EXTEND);
2648             rightClipPath.LineTo(offsetX + width - rightW * EXTEND, offsetY);
2649             rightClipPath.Close();
2650             canvas->ClipPath(rightClipPath, RSClipOp::DIFFERENCE, true);
2651         }
2652         rightBorder.ArcTo(rectStart.GetLeft(), rectStart.GetTop(), rectStart.GetRight(), rectStart.GetBottom(),
2653             RIGHT_START, SWEEP_ANGLE);
2654         rightBorder.ArcTo(rectEnd.GetLeft(), rectEnd.GetTop(), rectEnd.GetRight(), rectEnd.GetBottom(),
2655             RIGHT_END, SWEEP_ANGLE + 0.5f);
2656         if (NearZero(brX) && !NearZero(bottomW)) {
2657             rightBorder.LineTo(offsetX + width - rightW / 2.0f, offsetY + height);
2658             RSRecordingPath rightClipPath;
2659             rightClipPath.MoveTo(offsetX + width + rightW, offsetY + height + bottomW);
2660             rightClipPath.LineTo(offsetX + width - rightW * EXTEND, offsetY + height - bottomW * EXTEND);
2661             rightClipPath.LineTo(offsetX + width - rightW * EXTEND, offsetY + height);
2662             rightClipPath.Close();
2663             canvas->ClipPath(rightClipPath, RSClipOp::DIFFERENCE, true);
2664         }
2665         canvas->AttachPen(pen);
2666         canvas->DrawPath(rightBorder);
2667         if (NearZero(trX) || NearZero(trY) || NearZero(brX) || NearZero(brY)) {
2668             canvas->Restore();
2669         }
2670         canvas->DetachPen();
2671     }
2672     if (border.Bottom().HasValue() && !NearZero(bottomW)) {
2673         // Draw Bottom Border
2674         SetBorderStyle(border.Bottom(), pen, false);
2675         auto rectStart = RSRect(x + w - brX * 2.0f, y + h - brY * 2.0f, x + w, y + h);
2676         auto rectEnd = RSRect(x, y + h - blY * 2.0f, blX * 2.0f + x, y + h);
2677         RSRecordingPath bottomBorder;
2678         if (border.Bottom().GetBorderStyle() != BorderStyle::DOTTED) {
2679             pen.SetWidth(maxW);
2680         }
2681         if (NearZero(brX) || NearZero(brY) || NearZero(blX) || NearZero(blY)) {
2682             canvas->Save();
2683         }
2684         if (NearZero(brX) && !NearZero(rightW)) {
2685             bottomBorder.MoveTo(offsetX + width, offsetY + height - bottomW / 2.0f);
2686             bottomBorder.LineTo(x + w - brX * 2.0f, y + h - brY * 2.0f);
2687             RSRecordingPath bottomClipPath;
2688             bottomClipPath.MoveTo(offsetX + width + rightW, offsetY + height + bottomW);
2689             bottomClipPath.LineTo(offsetX + width - rightW * EXTEND, offsetY + height - bottomW * EXTEND);
2690             bottomClipPath.LineTo(offsetX + width, offsetY + height - bottomW * EXTEND);
2691             bottomClipPath.Close();
2692             canvas->ClipPath(bottomClipPath, RSClipOp::DIFFERENCE, true);
2693         }
2694         bottomBorder.ArcTo(rectStart.GetLeft(), rectStart.GetTop(), rectStart.GetRight(), rectStart.GetBottom(),
2695             BOTTOM_START, SWEEP_ANGLE);
2696         bottomBorder.ArcTo(rectEnd.GetLeft(), rectEnd.GetTop(), rectEnd.GetRight(), rectEnd.GetBottom(),
2697             BOTTOM_END, SWEEP_ANGLE + 0.5f);
2698         if (NearZero(blX) && !NearZero(leftW)) {
2699             bottomBorder.LineTo(offsetX, offsetY + height - bottomW / 2.0f);
2700             RSRecordingPath bottomClipPath;
2701             bottomClipPath.MoveTo(offsetX - leftW, offsetY + height + bottomW);
2702             bottomClipPath.LineTo(offsetX + leftW * EXTEND, offsetY + height - bottomW * EXTEND);
2703             bottomClipPath.LineTo(offsetX, offsetY + height - bottomW * EXTEND);
2704             bottomClipPath.Close();
2705             canvas->ClipPath(bottomClipPath, RSClipOp::DIFFERENCE, true);
2706         }
2707         canvas->AttachPen(pen);
2708         canvas->DrawPath(bottomBorder);
2709         if (NearZero(brX) || NearZero(brY) || NearZero(blX) || NearZero(blY)) {
2710             canvas->Restore();
2711         }
2712         canvas->DetachPen();
2713     }
2714     if (border.Left().HasValue() && !NearZero(leftW)) {
2715         // Draw Left Border
2716         SetBorderStyle(border.Left(), pen, false);
2717         auto rectStart = RSRect(x, y + h - blY * 2.0f, blX * 2.0f, blY * 2.0f);
2718         auto rectEnd = RSRect(x, y, tlX * 2.0f, tlY * 2.0f);
2719         RSRecordingPath leftBorder;
2720         if (border.Left().GetBorderStyle() != BorderStyle::DOTTED) {
2721             pen.SetWidth(maxW);
2722         }
2723         if (NearZero(blX) || NearZero(blY) || NearZero(tlX) || NearZero(tlY)) {
2724             canvas->Save();
2725         }
2726         if (NearZero(blX) && !NearZero(bottomW)) {
2727             leftBorder.MoveTo(offsetX + leftW / 2.0f, offsetY + height);
2728             leftBorder.LineTo(x, y + h - blY * 2.0f);
2729             RSRecordingPath leftClipPath;
2730             leftClipPath.MoveTo(offsetX - leftW, offsetY + height + bottomW);
2731             leftClipPath.LineTo(offsetX + leftW * EXTEND, offsetY + height - bottomW * EXTEND);
2732             leftClipPath.LineTo(offsetX + leftW * EXTEND, offsetY + height);
2733             leftClipPath.Close();
2734             canvas->ClipPath(leftClipPath, RSClipOp::DIFFERENCE, true);
2735         }
2736         leftBorder.ArcTo(rectStart.GetLeft(), rectStart.GetTop(), rectStart.GetRight(), rectStart.GetBottom(),
2737             LEFT_START, SWEEP_ANGLE);
2738         leftBorder.ArcTo(rectEnd.GetLeft(), rectEnd.GetTop(), rectEnd.GetRight(), rectEnd.GetBottom(),
2739             LEFT_END, SWEEP_ANGLE + 0.5f);
2740         if (NearZero(tlX) && !NearZero(topW)) {
2741             leftBorder.LineTo(offsetX + leftW / 2.0f, offsetY);
2742             RSRecordingPath topClipPath;
2743             topClipPath.MoveTo(offsetX - leftW, offsetY - topW);
2744             topClipPath.LineTo(offsetX + leftW * EXTEND, offsetY + topW * EXTEND);
2745             topClipPath.LineTo(offsetX + leftW * EXTEND, offsetY);
2746             topClipPath.Close();
2747             canvas->ClipPath(topClipPath, RSClipOp::DIFFERENCE, true);
2748         }
2749         canvas->AttachPen(pen);
2750         canvas->DrawPath(leftBorder);
2751         if (NearZero(blX) || NearZero(blY) || NearZero(tlX) || NearZero(tlY)) {
2752             canvas->Restore();
2753         }
2754         canvas->DetachPen();
2755     }
2756 #endif
2757 }
2758 
2759 #ifndef USE_ROSEN_DRAWING
PaintBorderWithLine(const Offset & offset,const Border & border,SkCanvas * canvas,SkPaint & paint)2760 void RosenDecorationPainter::PaintBorderWithLine(
2761     const Offset& offset, const Border& border, SkCanvas* canvas, SkPaint& paint)
2762 #else
2763 void RosenDecorationPainter::PaintBorderWithLine(
2764     const Offset& offset, const Border& border, RSCanvas* canvas, RSPen& pen)
2765 #endif
2766 {
2767     double addLen = 0.5;
2768     if (border.Left().GetBorderStyle() != BorderStyle::DOTTED) {
2769         addLen = 0.0;
2770     }
2771     // paint left border edge.
2772     BorderEdge left = border.Left();
2773     if (left.HasValue()) {
2774         if (NearZero(NormalizeToPx(left.GetWidth()))) {
2775             LOGI("left border width is zero");
2776             return;
2777         }
2778         auto borderLength = paintSize_.Height() - NormalizeToPx(left.GetWidth()) * addLen * 2.0;
2779         int32_t rawNumber = borderLength / (2 * NormalizeToPx(left.GetWidth()));
2780         if (NearZero(rawNumber)) {
2781             LOGI("number of dot is zero");
2782             return;
2783         }
2784 #ifndef USE_ROSEN_DRAWING
2785         SetBorderStyle(left, paint, false, borderLength / rawNumber, borderLength);
2786         canvas->drawLine(offset.GetX() + SK_ScalarHalf * NormalizeToPx(left.GetWidth()),
2787             offset.GetY() + addLen * NormalizeToPx(left.GetWidth()),
2788             offset.GetX() + SK_ScalarHalf * NormalizeToPx(left.GetWidth()), offset.GetY() + paintSize_.Height(), paint);
2789 #else
2790         SetBorderStyle(left, pen, false, borderLength / rawNumber, borderLength);
2791         canvas->AttachPen(pen);
2792         canvas->DrawLine(RSPoint(offset.GetX() + FLOAT_HALF * NormalizeToPx(left.GetWidth()),
2793                              offset.GetY() + addLen * NormalizeToPx(left.GetWidth())),
2794             RSPoint(offset.GetX() + FLOAT_HALF * NormalizeToPx(left.GetWidth()), offset.GetY() + paintSize_.Height()));
2795         canvas->DetachPen();
2796 #endif
2797     }
2798 
2799     // paint bottom border edge.
2800     BorderEdge bottom = border.Bottom();
2801     if (bottom.HasValue()) {
2802         if (NearZero(NormalizeToPx(bottom.GetWidth()))) {
2803             LOGI("bottom border width is zero");
2804             return;
2805         }
2806         auto borderLength = paintSize_.Width() - NormalizeToPx(bottom.GetWidth()) * addLen * 2.0;
2807         int32_t rawNumber = borderLength / (2 * NormalizeToPx(bottom.GetWidth()));
2808         if (NearZero(rawNumber)) {
2809             LOGI("number of dot is zero");
2810             return;
2811         }
2812 #ifndef USE_ROSEN_DRAWING
2813         SetBorderStyle(bottom, paint, false, borderLength / rawNumber, borderLength);
2814         canvas->drawLine(offset.GetX() + addLen * NormalizeToPx(bottom.GetWidth()),
2815             offset.GetY() + paintSize_.Height() - SK_ScalarHalf * NormalizeToPx(bottom.GetWidth()),
2816             offset.GetX() + paintSize_.Width(),
2817             offset.GetY() + paintSize_.Height() - SK_ScalarHalf * NormalizeToPx(bottom.GetWidth()), paint);
2818 #else
2819         SetBorderStyle(bottom, pen, false, borderLength / rawNumber, borderLength);
2820         canvas->AttachPen(pen);
2821         canvas->DrawLine(RSPoint(offset.GetX() + addLen * NormalizeToPx(bottom.GetWidth()),
2822                              offset.GetY() + paintSize_.Height() - FLOAT_HALF * NormalizeToPx(bottom.GetWidth())),
2823             RSPoint(offset.GetX() + paintSize_.Width(),
2824                 offset.GetY() + paintSize_.Height() - FLOAT_HALF * NormalizeToPx(bottom.GetWidth())));
2825         canvas->DetachPen();
2826 #endif
2827     }
2828     // paint right border edge.
2829     BorderEdge right = border.Right();
2830     if (right.HasValue()) {
2831         if (NearZero(NormalizeToPx(right.GetWidth()))) {
2832             LOGI("right border width is zero");
2833             return;
2834         }
2835         auto borderLength = paintSize_.Height() - NormalizeToPx(right.GetWidth()) * addLen * 2.0;
2836         int32_t rawNumber = borderLength / (2 * NormalizeToPx(right.GetWidth()));
2837         if (NearZero(rawNumber)) {
2838             LOGI("number of dot is zero");
2839             return;
2840         }
2841 #ifndef USE_ROSEN_DRAWING
2842         SetBorderStyle(right, paint, false, borderLength / rawNumber, borderLength);
2843         canvas->drawLine(offset.GetX() + paintSize_.Width() - SK_ScalarHalf * NormalizeToPx(right.GetWidth()),
2844             offset.GetY() + paintSize_.Height() - addLen * NormalizeToPx(right.GetWidth()),
2845             offset.GetX() + paintSize_.Width() - SK_ScalarHalf * NormalizeToPx(right.GetWidth()), offset.GetY(), paint);
2846 #else
2847         SetBorderStyle(right, pen, false, borderLength / rawNumber, borderLength);
2848         canvas->AttachPen(pen);
2849         canvas->DrawLine(RSPoint(offset.GetX() + paintSize_.Width() - FLOAT_HALF * NormalizeToPx(right.GetWidth()),
2850                              offset.GetY() + paintSize_.Height() - addLen * NormalizeToPx(right.GetWidth())),
2851             RSPoint(offset.GetX() + paintSize_.Width() - FLOAT_HALF * NormalizeToPx(right.GetWidth()), offset.GetY()));
2852         canvas->DetachPen();
2853 #endif
2854     }
2855     // paint top border edge.
2856     BorderEdge top = border.Top();
2857     if (top.HasValue()) {
2858         if (NearZero(NormalizeToPx(top.GetWidth()))) {
2859             LOGI("top border width is zero");
2860             return;
2861         }
2862         auto borderLength = paintSize_.Width() - NormalizeToPx(top.GetWidth()) * addLen * 2.0;
2863         int32_t rawNumber = borderLength / (2 * NormalizeToPx(top.GetWidth()));
2864         if (NearZero(rawNumber)) {
2865             LOGI("number of dot is zero");
2866             return;
2867         }
2868 #ifndef USE_ROSEN_DRAWING
2869         SetBorderStyle(top, paint, false, borderLength / rawNumber, borderLength);
2870         canvas->drawLine(offset.GetX() + addLen * NormalizeToPx(top.GetWidth()),
2871             offset.GetY() + SK_ScalarHalf * NormalizeToPx(top.GetWidth()), offset.GetX() + paintSize_.Width(),
2872             offset.GetY() + SK_ScalarHalf * NormalizeToPx(top.GetWidth()), paint);
2873 #else
2874         SetBorderStyle(top, pen, false, borderLength / rawNumber, borderLength);
2875         canvas->AttachPen(pen);
2876         canvas->DrawLine(RSPoint(offset.GetX() + addLen * NormalizeToPx(top.GetWidth()),
2877                              offset.GetY() + FLOAT_HALF * NormalizeToPx(top.GetWidth())),
2878             RSPoint(offset.GetX() + paintSize_.Width(), offset.GetY() + FLOAT_HALF * NormalizeToPx(top.GetWidth())));
2879         canvas->DetachPen();
2880 #endif
2881     }
2882 }
2883 
2884 // Add for box-shadow, otherwise using PaintShadow().
PaintBoxShadows(const std::vector<Shadow> & shadows,const std::shared_ptr<RSNode> & rsNode)2885 void RosenDecorationPainter::PaintBoxShadows(const std::vector<Shadow>& shadows, const std::shared_ptr<RSNode>& rsNode)
2886 {
2887     if (!rsNode) {
2888         LOGE("PaintBoxShadows failed, rsNode is null.");
2889         return;
2890     }
2891 
2892     if (!shadows.empty()) {
2893         for (const auto& shadow : shadows) {
2894             if (!shadow.IsValid()) {
2895                 LOGW("The current shadow is not drawn if the shadow is invalid.");
2896                 continue;
2897             }
2898 #ifndef USE_ROSEN_DRAWING
2899             PaintShadow(SkPath(), shadow, rsNode);
2900 #else
2901             PaintShadow(RSRecordingPath(), shadow, rsNode);
2902 #endif
2903         }
2904     } else {
2905         rsNode->SetShadowRadius(0.f);
2906     }
2907 }
2908 
2909 #ifndef USE_ROSEN_DRAWING
PaintShadow(const SkPath & path,const Shadow & shadow,const std::shared_ptr<RSNode> & rsNode)2910 void RosenDecorationPainter::PaintShadow(
2911     const SkPath& path, const Shadow& shadow, const std::shared_ptr<RSNode>& rsNode)
2912 #else
2913 void RosenDecorationPainter::PaintShadow(
2914     const RSPath& path, const Shadow& shadow, const std::shared_ptr<RSNode>& rsNode)
2915 #endif
2916 {
2917     if (!rsNode || !shadow.IsValid()) {
2918         return;
2919     }
2920 #ifndef USE_ROSEN_DRAWING
2921     if (!path.isEmpty()) {
2922 #else
2923     if (path.IsValid()) {
2924 #endif
2925         rsNode->SetShadowPath(Rosen::RSPath::CreateRSPath(path));
2926     }
2927     rsNode->SetShadowColor(shadow.GetColor().GetValue());
2928     rsNode->SetShadowOffsetX(shadow.GetOffset().GetX());
2929     rsNode->SetShadowOffsetY(shadow.GetOffset().GetY());
2930     rsNode->SetShadowMask(shadow.GetShadowType() == ShadowType::BLUR);
2931     if (shadow.GetHardwareAcceleration()) {
2932         rsNode->SetShadowElevation(shadow.GetElevation());
2933     } else {
2934         rsNode->SetShadowRadius(ConvertRadiusToSigma(shadow.GetBlurRadius()));
2935     }
2936 }
2937 
2938 #ifndef USE_ROSEN_DRAWING
2939 void RosenDecorationPainter::PaintShadow(
2940     const SkPath& path, const Shadow& shadow, SkCanvas* canvas, const SkPaint* paint)
2941 {
2942     if (!canvas) {
2943         LOGE("PaintShadow failed, canvas is null.");
2944         return;
2945     }
2946     if (!shadow.IsValid()) {
2947         LOGW("The current shadow is not drawn if the shadow is invalid.");
2948         return;
2949     }
2950     canvas->save();
2951     SkPath skPath = path;
2952     skPath.offset(shadow.GetOffset().GetX(), shadow.GetOffset().GetY());
2953     SkColor spotColor = shadow.GetColor().GetValue();
2954     if (shadow.GetHardwareAcceleration()) {
2955         // PlaneParams represents the coordinates of the component, and here we only need to focus on the elevation
2956         // of the component.
2957         SkPoint3 planeParams = { 0.0f, 0.0f, shadow.GetElevation() };
2958 
2959         // LightPos is the location of a spot light source, which is by default located directly above the center
2960         // of the component.
2961         SkPoint3 lightPos = { skPath.getBounds().centerX(), skPath.getBounds().centerY(), shadow.GetLightHeight() };
2962 
2963         // Current ambient color is not available.
2964         SkColor ambientColor = SkColorSetARGB(0, 0, 0, 0);
2965         SkShadowUtils::DrawShadow(canvas, skPath, planeParams, lightPos, shadow.GetLightRadius(), ambientColor,
2966             spotColor, SkShadowFlags::kTransparentOccluder_ShadowFlag);
2967     } else {
2968         SkPaint ShadowPaint;
2969         ShadowPaint.setColor(spotColor);
2970         ShadowPaint.setAntiAlias(true);
2971         if (paint) {
2972             ShadowPaint.setStyle(paint->getStyle());
2973             ShadowPaint.setStrokeWidth(paint->getStrokeWidth());
2974             ShadowPaint.setStrokeMiter(paint->getStrokeMiter());
2975             ShadowPaint.setStrokeCap(paint->getStrokeCap());
2976             ShadowPaint.setStrokeJoin(paint->getStrokeJoin());
2977             ShadowPaint.setAlphaf(paint->getAlphaf() * ShadowPaint.getAlphaf());
2978         }
2979         ShadowPaint.setMaskFilter(
2980             SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, ConvertRadiusToSigma(shadow.GetBlurRadius())));
2981         canvas->drawPath(skPath, ShadowPaint);
2982     }
2983     canvas->restore();
2984 }
2985 #else
2986 void RosenDecorationPainter::PaintShadow(const RSPath& path, const Shadow& shadow,
2987     RSCanvas* canvas, const RSBrush* brush, const RSPen* pen)
2988 {
2989     if (!canvas) {
2990         LOGE("PaintShadow failed, canvas is null.");
2991         return;
2992     }
2993     if (!shadow.IsValid()) {
2994         LOGW("The current shadow is not drawn if the shadow is invalid.");
2995         return;
2996     }
2997     canvas->Save();
2998     RSRecordingPath drPath = static_cast<const RSRecordingPath&>(path);
2999     drPath.Offset(shadow.GetOffset().GetX(), shadow.GetOffset().GetY());
3000     RSColorQuad spotColor = shadow.GetColor().GetValue();
3001     if (shadow.GetHardwareAcceleration()) {
3002         // PlaneParams represents the coordinates of the component, and here we only need to focus on the elevation
3003         // of the component.
3004         RSPoint3 planeParams = RSPoint3(0.0f, 0.0f, shadow.GetElevation());
3005 
3006         // LightPos is the location of a spot light source, which is by default located directly above the center
3007         // of the component.
3008         auto drRect = drPath.GetBounds();
3009         RSPoint3 lightPos = RSPoint3(drRect.GetLeft() * FLOAT_HALF + drRect.GetRight() * FLOAT_HALF,
3010             drRect.GetTop() * FLOAT_HALF + drRect.GetBottom() * FLOAT_HALF, shadow.GetLightHeight());
3011 
3012         // Current ambient color is not available.
3013         RSColorQuad ambientColor = RSColor::ColorQuadSetARGB(0, 0, 0, 0);
3014         canvas->DrawShadow(drPath, planeParams, lightPos, shadow.GetLightRadius(), ambientColor, spotColor,
3015             RSShadowFlags::TRANSPARENT_OCCLUDER);
3016     } else {
3017         RSFilter filter;
3018         filter.SetMaskFilter(RSRecordingMaskFilter::CreateBlurMaskFilter(
3019             RSBlurType::NORMAL, ConvertRadiusToSigma(shadow.GetBlurRadius())));
3020         if (pen) {
3021             RSPen shadowPen;
3022             shadowPen.SetColor(spotColor);
3023             shadowPen.SetAntiAlias(true);
3024             shadowPen.SetWidth(pen->GetWidth());
3025             shadowPen.SetMiterLimit(pen->GetMiterLimit());
3026             shadowPen.SetCapStyle(pen->GetCapStyle());
3027             shadowPen.SetJoinStyle(pen->GetJoinStyle());
3028             shadowPen.SetAlphaF(pen->GetAlphaF() * shadowPen.GetAlphaF());
3029             shadowPen.SetFilter(filter);
3030             canvas->AttachPen(shadowPen);
3031         }
3032         if (brush) {
3033             RSBrush shadowBrush;
3034             shadowBrush.SetColor(spotColor);
3035             shadowBrush.SetAntiAlias(true);
3036             shadowBrush.SetAlphaF(brush->GetAlphaF() * shadowBrush.GetAlphaF());
3037             shadowBrush.SetFilter(filter);
3038             canvas->AttachBrush(shadowBrush);
3039         }
3040         canvas->DrawPath(drPath);
3041         if (pen) {
3042             canvas->DetachBrush();
3043         }
3044         if (brush) {
3045             canvas->DetachPen();
3046         }
3047     }
3048     canvas->Restore();
3049 }
3050 #endif
3051 
3052 void RosenDecorationPainter::PaintImage(const Offset& offset, RenderContext& context)
3053 {
3054     if (decoration_) {
3055         RefPtr<BackgroundImage> backgroundImage = decoration_->GetImage();
3056         if (backgroundImage && renderImage_) {
3057             renderImage_->RenderWithContext(context, offset);
3058         }
3059     }
3060 }
3061 
3062 #ifndef USE_ROSEN_DRAWING
3063 bool RosenDecorationPainter::GetGradientPaint(SkPaint& paint)
3064 #else
3065 bool RosenDecorationPainter::GetGradientPaint(RSBrush& brush)
3066 #endif
3067 {
3068     Gradient gradient = decoration_->GetGradient();
3069     if (NearZero(paintSize_.Width()) || NearZero(paintSize_.Height()) || !gradient.IsValid()) {
3070         return false;
3071     }
3072 
3073 #ifndef USE_ROSEN_DRAWING
3074 
3075     SkSize skPaintSize = SkSize::Make(paintSize_.Width(), paintSize_.Height());
3076     auto shader = CreateGradientShader(gradient, skPaintSize);
3077     paint.setShader(std::move(shader));
3078 #else
3079     RSSize paintSize = RSSize(static_cast<RSScalar>(paintSize_.Width()), static_cast<RSScalar>(paintSize_.Height()));
3080     auto shader = CreateGradientShader(gradient, paintSize);
3081     brush.SetShaderEffect(shader);
3082 #endif
3083     return true;
3084 }
3085 
3086 void RosenDecorationPainter::PaintGradient(RenderContext& context)
3087 {
3088     Gradient gradient = decoration_->GetGradient();
3089     if (NearZero(paintSize_.Width()) || NearZero(paintSize_.Height())) {
3090         return;
3091     }
3092     if (!gradient.IsValid()) {
3093         return;
3094     }
3095 
3096 #ifndef USE_ROSEN_DRAWING
3097     auto size = SkSize::Make(paintSize_.Width(), paintSize_.Width());
3098 #else
3099     auto size = RSSize(paintSize_.Width(), paintSize_.Width());
3100 #endif
3101     auto shader = CreateGradientShader(gradient, size, dipScale_);
3102 #ifdef OHOS_PLATFORM
3103     auto rsNode = static_cast<RosenRenderContext*>(&context)->GetRSNode();
3104     if (rsNode) {
3105         rsNode->SetBackgroundShader(Rosen::RSShader::CreateRSShader(shader));
3106     }
3107 #endif
3108 }
3109 
3110 #ifndef USE_ROSEN_DRAWING
3111 sk_sp<SkShader> RosenDecorationPainter::CreateGradientShader(const Gradient& gradient, const SkSize& size)
3112 #else
3113 std::shared_ptr<RSShaderEffect> RosenDecorationPainter::CreateGradientShader(
3114     const Gradient& gradient, const RSSize& size)
3115 #endif
3116 {
3117     return CreateGradientShader(gradient, size, dipScale_);
3118 }
3119 
3120 #ifndef USE_ROSEN_DRAWING
3121 sk_sp<SkShader> RosenDecorationPainter::CreateGradientShader(
3122     const Gradient& gradient, const SkSize& size, double dipScale)
3123 #else
3124 std::shared_ptr<RSShaderEffect> RosenDecorationPainter::CreateGradientShader(
3125     const Gradient& gradient, const RSSize& size, double dipScale)
3126 #endif
3127 {
3128     auto ptr = std::make_unique<GradientShader>(gradient);
3129     switch (gradient.GetType()) {
3130         case GradientType::LINEAR:
3131             ptr = LinearGradientShader::CreateLinearGradient(gradient, size);
3132             break;
3133         case GradientType::RADIAL:
3134             ptr = RadialGradientShader::CreateRadialGradient(gradient, size, dipScale);
3135             break;
3136         case GradientType::SWEEP:
3137             ptr = SweepGradientShader::CreateSweepGradient(gradient, size, dipScale);
3138             break;
3139         default:
3140             LOGE("unsupported gradient type.");
3141             break;
3142     }
3143     return ptr->CreateGradientShader();
3144 }
3145 
3146 bool RosenDecorationPainter::CheckBorderEdgeForRRect(const Border& border)
3147 {
3148     double leftWidth = NormalizeToPx(border.Left().GetWidth());
3149     if (NearEqual(leftWidth, NormalizeToPx(border.Top().GetWidth())) &&
3150         NearEqual(leftWidth, NormalizeToPx(border.Right().GetWidth())) &&
3151         NearEqual(leftWidth, NormalizeToPx(border.Bottom().GetWidth()))) {
3152         BorderStyle leftStyle = border.Left().GetBorderStyle();
3153         return leftStyle == border.Top().GetBorderStyle() && leftStyle == border.Right().GetBorderStyle() &&
3154                leftStyle == border.Bottom().GetBorderStyle();
3155     }
3156     return false;
3157 }
3158 
3159 void RosenDecorationPainter::AdjustBorderStyle(Border& border)
3160 {
3161     // if not set border style use default border style solid
3162     if (border.Left().GetBorderStyle() == BorderStyle::NONE) {
3163         border.SetLeftStyle(BorderStyle::SOLID);
3164     }
3165 
3166     if (border.Top().GetBorderStyle() == BorderStyle::NONE) {
3167         border.SetTopStyle(BorderStyle::SOLID);
3168     }
3169 
3170     if (border.Right().GetBorderStyle() == BorderStyle::NONE) {
3171         border.SetRightStyle(BorderStyle::SOLID);
3172     }
3173 
3174     if (border.Bottom().GetBorderStyle() == BorderStyle::NONE) {
3175         border.SetBottomStyle(BorderStyle::SOLID);
3176     }
3177 }
3178 
3179 double RosenDecorationPainter::NormalizeToPx(const Dimension& dimension) const
3180 {
3181     if ((dimension.Unit() == DimensionUnit::VP) || (dimension.Unit() == DimensionUnit::FP)) {
3182         return (dimension.Value() * dipScale_);
3183     }
3184     return dimension.Value();
3185 }
3186 
3187 double RosenDecorationPainter::SliceNormalizePercentToPx(const Dimension& dimension, bool isVertical) const
3188 {
3189     if (dimension.Unit() != DimensionUnit::PERCENT) {
3190         return NormalizeToPx(dimension);
3191     }
3192 #ifndef USE_ROSEN_DRAWING
3193     auto limit = isVertical ? image_->width() : image_->height();
3194 #else
3195     auto limit = isVertical ? image_->GetWidth() : image_->GetHeight();
3196 #endif
3197     return limit * dimension.Value();
3198 }
3199 
3200 double RosenDecorationPainter::WidthNormalizePercentToPx(const Dimension& dimension, bool isVertical) const
3201 {
3202     if (dimension.Unit() != DimensionUnit::PERCENT) {
3203         return NormalizeToPx(dimension);
3204     }
3205     auto limit = isVertical ? paintSize_.Width() : paintSize_.Height();
3206     return limit * dimension.Value();
3207 }
3208 
3209 double RosenDecorationPainter::OutsetNormalizePercentToPx(const Dimension& dimension, bool isVertical) const
3210 {
3211     if (dimension.Unit() != DimensionUnit::PERCENT) {
3212         return NormalizeToPx(dimension);
3213     }
3214     auto limit = isVertical ? paintSize_.Width() : paintSize_.Height();
3215     return limit * dimension.Value();
3216 }
3217 
3218 } // namespace OHOS::Ace
3219