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