• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "property/rs_properties_painter.h"
17 #include "rs_trace.h"
18 
19 #include "common/rs_obj_abs_geometry.h"
20 #include "common/rs_optional_trace.h"
21 #include "pipeline/rs_effect_render_node.h"
22 #include "pipeline/rs_paint_filter_canvas.h"
23 #include "pipeline/rs_root_render_node.h"
24 #include "platform/common/rs_log.h"
25 #include "property/rs_point_light_manager.h"
26 #include "property/rs_properties_def.h"
27 #include "render/rs_blur_filter.h"
28 #include "render/rs_skia_filter.h"
29 #include "render/rs_material_filter.h"
30 #include "platform/common/rs_system_properties.h"
31 
32 #ifdef USE_ROSEN_DRAWING
33 #include <cstdint>
34 #include <algorithm>
35 
36 #include "draw/canvas.h"
37 #include "draw/clip.h"
38 #include "drawing/draw/core_canvas.h"
39 #include "effect/runtime_blender_builder.h"
40 #include "effect/runtime_effect.h"
41 #include "effect/runtime_shader_builder.h"
42 #include "utils/rect.h"
43 #else
44 #include "include/core/SkCanvas.h"
45 #include "include/core/SkColorFilter.h"
46 #include "include/core/SkMaskFilter.h"
47 #include "include/core/SkPaint.h"
48 #include "include/core/SkPoint3.h"
49 #include "include/core/SkRRect.h"
50 #include "include/core/SkSurface.h"
51 #include "include/effects/Sk1DPathEffect.h"
52 #include "include/effects/SkDashPathEffect.h"
53 #include "include/effects/SkGradientShader.h"
54 #include "include/effects/SkLumaColorFilter.h"
55 #include "include/utils/SkShadowUtils.h"
56 #include "include/effects/SkImageFilters.h"
57 #include "include/effects/SkRuntimeEffect.h"
58 #endif
59 #include "src/image/SkImage_Base.h"
60 
61 namespace OHOS {
62 namespace Rosen {
63 namespace {
64 bool g_forceBgAntiAlias = true;
65 constexpr int PARAM_DOUBLE = 2;
66 constexpr float MIN_TRANS_RATIO = 0.0f;
67 constexpr float MAX_TRANS_RATIO = 0.95f;
68 constexpr float MIN_SPOT_RATIO = 1.0f;
69 constexpr float MAX_SPOT_RATIO = 1.95f;
70 constexpr float MAX_AMBIENT_RADIUS = 150.0f;
71 // when the blur radius > SNAPSHOT_OUTSET_BLUR_RADIUS_THRESHOLD,
72 // the snapshot should call outset before blur to shrink by 1px.
73 constexpr static float SNAPSHOT_OUTSET_BLUR_RADIUS_THRESHOLD = 40.0f;
74 } // namespace
75 
76 const bool RSPropertiesPainter::BLUR_ENABLED = RSSystemProperties::GetBlurEnabled();
77 
78 #ifndef USE_ROSEN_DRAWING
79 #else
80 std::shared_ptr<Drawing::RuntimeEffect> RSPropertiesPainter::greyAdjustEffect_ = nullptr;
81 std::shared_ptr<Drawing::RuntimeEffect> RSPropertiesPainter::binarizationShaderEffect_ = nullptr;
82 std::shared_ptr<Drawing::RuntimeEffect> RSPropertiesPainter::lightUpEffectShaderEffect_ = nullptr;
83 std::shared_ptr<Drawing::RuntimeEffect> RSPropertiesPainter::dynamicLightUpBlenderEffect_ = nullptr;
84 #endif
85 
86 #ifndef USE_ROSEN_DRAWING
Rect2SkRect(const RectF & r)87 SkRect RSPropertiesPainter::Rect2SkRect(const RectF& r)
88 {
89     return SkRect::MakeXYWH(r.left_, r.top_, r.width_, r.height_);
90 }
91 #else
Rect2DrawingRect(const RectF & r)92 Drawing::Rect RSPropertiesPainter::Rect2DrawingRect(const RectF& r)
93 {
94     return Drawing::Rect(r.left_, r.top_, r.left_ + r.width_, r.top_ + r.height_);
95 }
96 #endif
97 
98 #ifndef USE_ROSEN_DRAWING
RRect2SkRRect(const RRect & rr)99 SkRRect RSPropertiesPainter::RRect2SkRRect(const RRect& rr)
100 {
101     SkRect rect = SkRect::MakeXYWH(rr.rect_.left_, rr.rect_.top_, rr.rect_.width_, rr.rect_.height_);
102     SkRRect rrect = SkRRect::MakeEmpty();
103 
104     // set radius for all 4 corner of RRect
105     constexpr uint32_t NUM_OF_CORNERS_IN_RECT = 4;
106     SkVector vec[NUM_OF_CORNERS_IN_RECT];
107     for (uint32_t i = 0; i < NUM_OF_CORNERS_IN_RECT; i++) {
108         vec[i].set(rr.radius_[i].x_, rr.radius_[i].y_);
109     }
110 
111     rrect.setRectRadii(rect, vec);
112     return rrect;
113 }
114 #else
RRect2DrawingRRect(const RRect & rr)115 Drawing::RoundRect RSPropertiesPainter::RRect2DrawingRRect(const RRect& rr)
116 {
117     Drawing::Rect rect = Drawing::Rect(
118         rr.rect_.left_, rr.rect_.top_, rr.rect_.left_ + rr.rect_.width_, rr.rect_.top_ + rr.rect_.height_);
119 
120     // set radius for all 4 corner of RRect
121     constexpr uint32_t NUM_OF_CORNERS_IN_RECT = 4;
122     std::vector<Drawing::Point> radii(NUM_OF_CORNERS_IN_RECT);
123     for (uint32_t i = 0; i < NUM_OF_CORNERS_IN_RECT; i++) {
124         radii.at(i).SetX(rr.radius_[i].x_);
125         radii.at(i).SetY(rr.radius_[i].y_);
126     }
127     return Drawing::RoundRect(rect, radii);
128 }
129 #endif
130 
131 #ifndef USE_ROSEN_DRAWING
GetGravityMatrix(Gravity gravity,RectF rect,float w,float h,SkMatrix & mat)132 bool RSPropertiesPainter::GetGravityMatrix(Gravity gravity, RectF rect, float w, float h, SkMatrix& mat)
133 #else
134 bool RSPropertiesPainter::GetGravityMatrix(Gravity gravity, RectF rect, float w, float h, Drawing::Matrix& mat)
135 #endif
136 {
137     if (w == rect.width_ && h == rect.height_) {
138         return false;
139     }
140 #ifndef USE_ROSEN_DRAWING
141     mat.reset();
142 #else
143     mat = Drawing::Matrix();
144 #endif
145 
146     switch (gravity) {
147         case Gravity::CENTER: {
148 #ifndef USE_ROSEN_DRAWING
149             mat.preTranslate((rect.width_ - w) / PARAM_DOUBLE, (rect.height_ - h) / PARAM_DOUBLE);
150 #else
151             mat.PreTranslate((rect.width_ - w) / PARAM_DOUBLE, (rect.height_ - h) / PARAM_DOUBLE);
152 #endif
153             return true;
154         }
155         case Gravity::TOP: {
156 #ifndef USE_ROSEN_DRAWING
157             mat.preTranslate((rect.width_ - w) / PARAM_DOUBLE, 0);
158 #else
159             mat.PreTranslate((rect.width_ - w) / PARAM_DOUBLE, 0);
160 #endif
161             return true;
162         }
163         case Gravity::BOTTOM: {
164 #ifndef USE_ROSEN_DRAWING
165             mat.preTranslate((rect.width_ - w) / PARAM_DOUBLE, rect.height_ - h);
166 #else
167             mat.PreTranslate((rect.width_ - w) / PARAM_DOUBLE, rect.height_ - h);
168 #endif
169             return true;
170         }
171         case Gravity::LEFT: {
172 #ifndef USE_ROSEN_DRAWING
173             mat.preTranslate(0, (rect.height_ - h) / PARAM_DOUBLE);
174 #else
175             mat.PreTranslate(0, (rect.height_ - h) / PARAM_DOUBLE);
176 #endif
177             return true;
178         }
179         case Gravity::RIGHT: {
180 #ifndef USE_ROSEN_DRAWING
181             mat.preTranslate(rect.width_ - w, (rect.height_ - h) / PARAM_DOUBLE);
182 #else
183             mat.PreTranslate(rect.width_ - w, (rect.height_ - h) / PARAM_DOUBLE);
184 #endif
185             return true;
186         }
187         case Gravity::TOP_LEFT: {
188             return false;
189         }
190         case Gravity::TOP_RIGHT: {
191 #ifndef USE_ROSEN_DRAWING
192             mat.preTranslate(rect.width_ - w, 0);
193 #else
194             mat.PreTranslate(rect.width_ - w, 0);
195 #endif
196             return true;
197         }
198         case Gravity::BOTTOM_LEFT: {
199 #ifndef USE_ROSEN_DRAWING
200             mat.preTranslate(0, rect.height_ - h);
201 #else
202             mat.PreTranslate(0, rect.height_ - h);
203 #endif
204             return true;
205         }
206         case Gravity::BOTTOM_RIGHT: {
207 #ifndef USE_ROSEN_DRAWING
208             mat.preTranslate(rect.width_ - w, rect.height_ - h);
209 #else
210             mat.PreTranslate(rect.width_ - w, rect.height_ - h);
211 #endif
212             return true;
213         }
214         case Gravity::RESIZE: {
215             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
216                 return false;
217             }
218 #ifndef USE_ROSEN_DRAWING
219             mat.preScale(rect.width_ / w, rect.height_ / h);
220 #else
221             mat.PreScale(rect.width_ / w, rect.height_ / h);
222 #endif
223             return true;
224         }
225         case Gravity::RESIZE_ASPECT: {
226             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
227                 return false;
228             }
229             float scale = std::min(rect.width_ / w, rect.height_ / h);
230             if (ROSEN_EQ(scale, 0.f)) {
231                 return false;
232             }
233 #ifndef USE_ROSEN_DRAWING
234             mat.preScale(scale, scale);
235             mat.preTranslate((rect.width_ / scale - w) / PARAM_DOUBLE, (rect.height_ / scale - h) / PARAM_DOUBLE);
236 #else
237             mat.PreScale(scale, scale);
238             mat.PreTranslate((rect.width_ / scale - w) / PARAM_DOUBLE, (rect.height_ / scale - h) / PARAM_DOUBLE);
239 #endif
240             return true;
241         }
242         case Gravity::RESIZE_ASPECT_TOP_LEFT: {
243             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
244                 return false;
245             }
246             float scale = std::min(rect.width_ / w, rect.height_ / h);
247 #ifndef USE_ROSEN_DRAWING
248             mat.preScale(scale, scale);
249 #else
250             mat.PreScale(scale, scale);
251 #endif
252             return true;
253         }
254         case Gravity::RESIZE_ASPECT_BOTTOM_RIGHT: {
255             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
256                 return false;
257             }
258             float scale = std::min(rect.width_ / w, rect.height_ / h);
259             if (ROSEN_EQ(scale, 0.f)) {
260                 return false;
261             }
262 #ifndef USE_ROSEN_DRAWING
263             mat.preScale(scale, scale);
264             mat.preTranslate(rect.width_ / scale - w, rect.height_ / scale - h);
265 #else
266             mat.PreScale(scale, scale);
267             mat.PreTranslate(rect.width_ / scale - w, rect.height_ / scale - h);
268 #endif
269             return true;
270         }
271         case Gravity::RESIZE_ASPECT_FILL: {
272             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
273                 return false;
274             }
275             float scale = std::max(rect.width_ / w, rect.height_ / h);
276             if (ROSEN_EQ(scale, 0.f)) {
277                 return false;
278             }
279 #ifndef USE_ROSEN_DRAWING
280             mat.preScale(scale, scale);
281             mat.preTranslate((rect.width_ / scale - w) / PARAM_DOUBLE, (rect.height_ / scale - h) / PARAM_DOUBLE);
282 #else
283             mat.PreScale(scale, scale);
284             mat.PreTranslate((rect.width_ / scale - w) / PARAM_DOUBLE, (rect.height_ / scale - h) / PARAM_DOUBLE);
285 #endif
286             return true;
287         }
288         case Gravity::RESIZE_ASPECT_FILL_TOP_LEFT: {
289             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
290                 return false;
291             }
292             float scale = std::max(rect.width_ / w, rect.height_ / h);
293 #ifndef USE_ROSEN_DRAWING
294             mat.preScale(scale, scale);
295 #else
296             mat.PreScale(scale, scale);
297 #endif
298             return true;
299         }
300         case Gravity::RESIZE_ASPECT_FILL_BOTTOM_RIGHT: {
301             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
302                 return false;
303             }
304             float scale = std::max(rect.width_ / w, rect.height_ / h);
305             if (ROSEN_EQ(scale, 0.f)) {
306                 return false;
307             }
308 #ifndef USE_ROSEN_DRAWING
309             mat.preScale(scale, scale);
310             mat.preTranslate(rect.width_ / scale - w, rect.height_ / scale - h);
311 #else
312             mat.PreScale(scale, scale);
313             mat.PreTranslate(rect.width_ / scale - w, rect.height_ / scale - h);
314 #endif
315             return true;
316         }
317         default: {
318             ROSEN_LOGE("GetGravityMatrix unknow gravity=[%{public}d]", gravity);
319             return false;
320         }
321     }
322 }
323 
324 #ifndef USE_ROSEN_DRAWING
Clip(SkCanvas & canvas,RectF rect,bool isAntiAlias)325 void RSPropertiesPainter::Clip(SkCanvas& canvas, RectF rect, bool isAntiAlias)
326 {
327     // isAntiAlias is false only the method is called in ProcessAnimatePropertyBeforeChildren().
328     canvas.clipRect(Rect2SkRect(rect), isAntiAlias);
329 }
330 #else
Clip(Drawing::Canvas & canvas,RectF rect,bool isAntiAlias)331 void RSPropertiesPainter::Clip(Drawing::Canvas& canvas, RectF rect, bool isAntiAlias)
332 {
333     canvas.ClipRect(Rect2DrawingRect(rect), Drawing::ClipOp::INTERSECT, isAntiAlias);
334 }
335 #endif
336 
337 #ifndef USE_ROSEN_DRAWING
GetShadowDirtyRect(RectI & dirtyShadow,const RSProperties & properties,const RRect * rrect,bool isAbsCoordinate,bool radiusInclude)338 void RSPropertiesPainter::GetShadowDirtyRect(RectI& dirtyShadow, const RSProperties& properties,
339     const RRect* rrect, bool isAbsCoordinate, bool radiusInclude)
340 {
341     // [Planning]: After Skia being updated, we should directly call SkShadowUtils::GetLocalBounds here.
342     if (!properties.IsShadowValid()) {
343         return;
344     }
345     SkPath skPath;
346     if (properties.GetShadowPath() && !properties.GetShadowPath()->GetSkiaPath().isEmpty()) {
347         skPath = properties.GetShadowPath()->GetSkiaPath();
348     } else if (properties.GetClipBounds()) {
349         skPath = properties.GetClipBounds()->GetSkiaPath();
350     } else {
351         if (rrect != nullptr) {
352             skPath.addRRect(RRect2SkRRect(*rrect));
353         } else {
354             skPath.addRRect(RRect2SkRRect(properties.GetRRect()));
355         }
356     }
357     skPath.offset(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
358 
359     SkRect shadowRect = skPath.getBounds();
360     if (properties.GetShadowElevation() > 0.f) {
361         float elevation = properties.GetShadowElevation() + DEFAULT_TRANSLATION_Z;
362 
363         float userTransRatio =
364             (elevation != DEFAULT_LIGHT_HEIGHT) ? elevation / (DEFAULT_LIGHT_HEIGHT - elevation) : MAX_TRANS_RATIO;
365         float transRatio = std::max(MIN_TRANS_RATIO, std::min(userTransRatio, MAX_TRANS_RATIO));
366 
367         float userSpotRatio = (elevation != DEFAULT_LIGHT_HEIGHT)
368                                   ? DEFAULT_LIGHT_HEIGHT / (DEFAULT_LIGHT_HEIGHT - elevation)
369                                   : MAX_SPOT_RATIO;
370         float spotRatio = std::max(MIN_SPOT_RATIO, std::min(userSpotRatio, MAX_SPOT_RATIO));
371 
372         SkRect ambientRect = skPath.getBounds();
373         SkRect spotRect = SkRect::MakeLTRB(ambientRect.left() * spotRatio, ambientRect.top() * spotRatio,
374             ambientRect.right() * spotRatio, ambientRect.bottom() * spotRatio);
375         spotRect.offset(-transRatio * DEFAULT_LIGHT_POSITION_X, -transRatio * DEFAULT_LIGHT_POSITION_Y);
376         spotRect.outset(transRatio * DEFAULT_LIGHT_RADIUS, transRatio * DEFAULT_LIGHT_RADIUS);
377 
378         shadowRect = ambientRect;
379         float ambientBlur = std::min(elevation * 0.5f, MAX_AMBIENT_RADIUS);
380         shadowRect.outset(ambientBlur, ambientBlur);
381         shadowRect.join(spotRect);
382         shadowRect.outset(1, 1);
383     } else {
384         SkPaint paint;
385         paint.setAntiAlias(true);
386         paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, properties.GetShadowRadius()));
387         if (paint.canComputeFastBounds() && radiusInclude) {
388             paint.computeFastBounds(shadowRect, &shadowRect);
389         }
390     }
391 
392     auto geoPtr = (properties.GetBoundsGeometry());
393     SkMatrix matrix = (geoPtr && isAbsCoordinate) ? geoPtr->GetAbsMatrix() : SkMatrix::I();
394     matrix.mapRect(&shadowRect);
395 
396     dirtyShadow.left_ = shadowRect.left();
397     dirtyShadow.top_ = shadowRect.top();
398     dirtyShadow.width_ = shadowRect.width();
399     dirtyShadow.height_ = shadowRect.height();
400 }
401 #else
GetShadowDirtyRect(RectI & dirtyShadow,const RSProperties & properties,const RRect * rrect,bool isAbsCoordinate,bool radiusInclude)402 void RSPropertiesPainter::GetShadowDirtyRect(RectI& dirtyShadow, const RSProperties& properties,
403     const RRect* rrect, bool isAbsCoordinate, bool radiusInclude)
404 {
405     // [Planning]: After Skia being updated, we should directly call SkShadowUtils::GetLocalBounds here.
406     if (!properties.IsShadowValid()) {
407         return;
408     }
409     Drawing::Path path;
410     if (properties.GetShadowPath() && properties.GetShadowPath()->GetDrawingPath().IsValid()) {
411         path = properties.GetShadowPath()->GetDrawingPath();
412     } else if (properties.GetClipBounds()) {
413         path = properties.GetClipBounds()->GetDrawingPath();
414     } else {
415         if (rrect != nullptr) {
416             path.AddRoundRect(RRect2DrawingRRect(*rrect));
417         } else {
418             path.AddRoundRect(RRect2DrawingRRect(properties.GetRRect()));
419         }
420     }
421     path.Offset(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
422 
423     Drawing::Rect shadowRect = path.GetBounds();
424     if (properties.GetShadowElevation() > 0.f) {
425         float elevation = properties.GetShadowElevation() + DEFAULT_TRANSLATION_Z;
426 
427         float userTransRatio =
428             (elevation != DEFAULT_LIGHT_HEIGHT) ? elevation / (DEFAULT_LIGHT_HEIGHT - elevation) : MAX_TRANS_RATIO;
429         float transRatio = std::max(MIN_TRANS_RATIO, std::min(userTransRatio, MAX_TRANS_RATIO));
430 
431         float userSpotRatio = (elevation != DEFAULT_LIGHT_HEIGHT)
432                                   ? DEFAULT_LIGHT_HEIGHT / (DEFAULT_LIGHT_HEIGHT - elevation)
433                                   : MAX_SPOT_RATIO;
434         float spotRatio = std::max(MIN_SPOT_RATIO, std::min(userSpotRatio, MAX_SPOT_RATIO));
435 
436         Drawing::Rect ambientRect = path.GetBounds();
437         Drawing::Rect spotRect = Drawing::Rect(ambientRect.GetLeft() * spotRatio, ambientRect.GetTop() * spotRatio,
438             ambientRect.GetRight() * spotRatio, ambientRect.GetBottom() * spotRatio);
439         spotRect.Offset(-transRatio * DEFAULT_LIGHT_POSITION_X, -transRatio * DEFAULT_LIGHT_POSITION_Y);
440         spotRect.MakeOutset(transRatio * DEFAULT_LIGHT_RADIUS, transRatio * DEFAULT_LIGHT_RADIUS);
441 
442         shadowRect = ambientRect;
443         float ambientBlur = std::min(elevation * 0.5f, MAX_AMBIENT_RADIUS);
444         shadowRect.MakeOutset(ambientBlur, ambientBlur);
445 
446         shadowRect.Join(spotRect);
447         shadowRect.MakeOutset(1, 1);
448     } else {
449         Drawing::Brush brush;
450         brush.SetAntiAlias(true);
451         Drawing::Filter filter;
452         filter.SetMaskFilter(
453             Drawing::MaskFilter::CreateBlurMaskFilter(Drawing::BlurType::NORMAL, properties.GetShadowRadius()));
454         brush.SetFilter(filter);
455         if (brush.CanComputeFastBounds() && radiusInclude) {
456             brush.ComputeFastBounds(shadowRect, &shadowRect);
457         }
458     }
459 
460     auto geoPtr = (properties.GetBoundsGeometry());
461     Drawing::Matrix matrix = (geoPtr && isAbsCoordinate) ? geoPtr->GetAbsMatrix() : Drawing::Matrix();
462     matrix.MapRect(shadowRect, shadowRect);
463 
464     dirtyShadow.left_ = shadowRect.GetLeft();
465     dirtyShadow.top_ = shadowRect.GetTop();
466     dirtyShadow.width_ = shadowRect.GetWidth();
467     dirtyShadow.height_ = shadowRect.GetHeight();
468 }
469 #endif
470 
471 #ifndef USE_ROSEN_DRAWING
DrawShadow(const RSProperties & properties,RSPaintFilterCanvas & canvas,const RRect * rrect)472 void RSPropertiesPainter::DrawShadow(const RSProperties& properties, RSPaintFilterCanvas& canvas, const RRect* rrect)
473 {
474     // skip shadow if not valid or cache is enabled
475     if (properties.IsSpherizeValid() || !properties.IsShadowValid() || properties.GetNeedSkipShadow()
476         canvas.GetCacheType() == RSPaintFilterCanvas::CacheType::ENABLED) {
477         return;
478     }
479 
480     RSAutoCanvasRestore acr(&canvas);
481     SkPath skPath;
482     if (properties.GetShadowPath() && !properties.GetShadowPath()->GetSkiaPath().isEmpty()) {
483         skPath = properties.GetShadowPath()->GetSkiaPath();
484         if (!properties.GetShadowIsFilled()) {
485             canvas.clipPath(skPath, SkClipOp::kDifference, true);
486         }
487     } else if (properties.GetClipBounds()) {
488         skPath = properties.GetClipBounds()->GetSkiaPath();
489         if (!properties.GetShadowIsFilled()) {
490             canvas.clipPath(skPath, SkClipOp::kDifference, true);
491         }
492     } else {
493         if (rrect != nullptr) {
494             skPath.addRRect(RRect2SkRRect(*rrect));
495             if (!properties.GetShadowIsFilled()) {
496                 canvas.clipRRect(RRect2SkRRect(*rrect), SkClipOp::kDifference, true);
497             }
498         } else {
499             skPath.addRRect(RRect2SkRRect(properties.GetRRect()));
500             if (!properties.GetShadowIsFilled()) {
501                 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), SkClipOp::kDifference, true);
502             }
503         }
504     }
505     if (properties.GetShadowMask()) {
506         DrawColorfulShadowInner(properties, canvas, skPath);
507     } else {
508         DrawShadowInner(properties, canvas, skPath);
509     }
510 }
511 #else
DrawShadow(const RSProperties & properties,RSPaintFilterCanvas & canvas,const RRect * rrect)512 void RSPropertiesPainter::DrawShadow(const RSProperties& properties, RSPaintFilterCanvas& canvas, const RRect* rrect)
513 {
514     // skip shadow if not valid or cache is enabled
515     if (properties.IsSpherizeValid() || !properties.IsShadowValid() ||
516         canvas.GetCacheType() == RSPaintFilterCanvas::CacheType::ENABLED) {
517         return;
518     }
519     Drawing::AutoCanvasRestore acr(canvas, true);
520     Drawing::Path path;
521     if (properties.GetShadowPath() && properties.GetShadowPath()->GetDrawingPath().IsValid()) {
522         path = properties.GetShadowPath()->GetDrawingPath();
523         if (!properties.GetShadowIsFilled()) {
524             canvas.ClipPath(path, Drawing::ClipOp::DIFFERENCE, true);
525         }
526     } else if (properties.GetClipBounds()) {
527         path = properties.GetClipBounds()->GetDrawingPath();
528         if (!properties.GetShadowIsFilled()) {
529             canvas.ClipPath(path, Drawing::ClipOp::DIFFERENCE, true);
530         }
531     } else {
532         if (rrect != nullptr) {
533             path.AddRoundRect(RRect2DrawingRRect(*rrect));
534             if (!properties.GetShadowIsFilled()) {
535                 canvas.ClipRoundRect(RRect2DrawingRRect(*rrect), Drawing::ClipOp::DIFFERENCE, true);
536             }
537         } else {
538             path.AddRoundRect(RRect2DrawingRRect(properties.GetRRect()));
539             if (!properties.GetShadowIsFilled()) {
540                 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::DIFFERENCE, true);
541             }
542         }
543     }
544     if (properties.GetShadowMask()) {
545         DrawColorfulShadowInner(properties, canvas, path);
546     } else {
547         DrawShadowInner(properties, canvas, path);
548     }
549 }
550 #endif
551 
552 #ifndef USE_ROSEN_DRAWING
DrawColorfulShadowInner(const RSProperties & properties,RSPaintFilterCanvas & canvas,SkPath & skPath)553 void RSPropertiesPainter::DrawColorfulShadowInner(
554     const RSProperties& properties, RSPaintFilterCanvas& canvas, SkPath& skPath)
555 {
556     // blurRadius calculation is based on the formula in SkShadowUtils::DrawShadow, 0.25f and 128.0f are constants
557     const SkScalar blurRadius =
558         properties.GetShadowElevation() > 0.f
559             ? 0.25f * properties.GetShadowElevation() * (1 + properties.GetShadowElevation() / 128.0f)
560             : properties.GetShadowRadius();
561 
562     // save layer, draw image with clipPath, blur and draw back
563     SkPaint blurPaint;
564     blurPaint.setImageFilter(SkImageFilters::Blur(blurRadius, blurRadius, SkTileMode::kDecal, nullptr));
565     canvas.saveLayer(nullptr, &blurPaint);
566 
567     canvas.translate(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
568 
569     canvas.clipPath(skPath);
570     // draw node content as shadow
571     // [PLANNING]: maybe we should also draw background color / image here, and we should cache the shadow image
572     if (auto node = RSBaseRenderNode::ReinterpretCast<RSCanvasRenderNode>(properties.backref_.lock())) {
573         node->InternalDrawContent(canvas);
574     }
575 }
576 #else
DrawColorfulShadowInner(const RSProperties & properties,RSPaintFilterCanvas & canvas,Drawing::Path & path)577 void RSPropertiesPainter::DrawColorfulShadowInner(
578     const RSProperties& properties, RSPaintFilterCanvas& canvas, Drawing::Path& path)
579 {
580     // blurRadius calculation is based on the formula in Canvas::DrawShadow, 0.25f and 128.0f are constants
581     const Drawing::scalar blurRadius =
582         properties.GetShadowElevation() > 0.f
583             ? 0.25f * properties.GetShadowElevation() * (1 + properties.GetShadowElevation() / 128.0f)
584             : properties.GetShadowRadius();
585 
586     // save layer, draw image with clipPath, blur and draw back
587     Drawing::Brush blurBrush;
588     Drawing::Filter filter;
589     filter.SetImageFilter(Drawing::ImageFilter::CreateBlurImageFilter(
590         blurRadius, blurRadius, Drawing::TileMode::DECAL, nullptr));
591     blurBrush.SetFilter(filter);
592 
593     canvas.SaveLayer({nullptr, &blurBrush});
594 
595     canvas.Translate(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
596 
597     canvas.ClipPath(path, Drawing::ClipOp::INTERSECT, false);
598     // draw node content as shadow
599     // [PLANNING]: maybe we should also draw background color / image here, and we should cache the shadow image
600     if (auto node = RSBaseRenderNode::ReinterpretCast<RSCanvasRenderNode>(properties.backref_.lock())) {
601         node->InternalDrawContent(canvas);
602     }
603 }
604 #endif
605 
GetDarkColor(RSColor & color)606 void RSPropertiesPainter::GetDarkColor(RSColor& color)
607 {
608     // convert to lab
609     float minColorRange = 0;
610     float maxColorRange = 255;
611     float R = float(color.GetRed()) / maxColorRange;
612     float G = float(color.GetGreen()) / maxColorRange;
613     float B = float(color.GetBlue()) / maxColorRange;
614 
615     float X = 0.4124 * R + 0.3576 * G + 0.1805 * B;
616     float Y = 0.2126 * R + 0.7152 * G + 0.0722 * B;
617     float Z = 0.0193 * R + 0.1192 * G + 0.9505 * B;
618 
619     float Xn = 0.9505;
620     float Yn = 1.0000;
621     float Zn = 1.0889999;
622     float Fx = (X / Xn) > 0.008856 ? pow((X / Xn), 1.0 / 3) : (7.787 * (X / Xn) + 16.0 / 116);
623     float Fy = (Y / Yn) > 0.008856 ? pow((Y / Yn), 1.0 / 3) : (7.787 * (Y / Yn) + 16.0 / 116);
624     float Fz = (Z / Zn) > 0.008856 ? pow((Z / Zn), 1.0 / 3) : (7.787 * (Z / Zn) + 16.0 / 116);
625     float L = 116 * Fy - 16;
626     float a = 500 * (Fx - Fy);
627     float b = 200 * (Fy - Fz);
628 
629     float standardLightness = 75.0;
630     if (L > standardLightness) {
631         float L1 = standardLightness;
632         float xw = 0.9505;
633         float yw = 1.0000;
634         float zw = 1.0889999;
635 
636         float fy = (L1 + 16) / 116;
637         float fx = fy + (a / 500);
638         float fz = fy - (b / 200);
639 
640         float X1 = xw * ((pow(fx, 3) > 0.008856) ? pow(fx, 3) : ((fx - 16.0 / 116) / 7.787));
641         float Y1 = yw * ((pow(fy, 3) > 0.008856) ? pow(fy, 3) : ((fy - 16.0 / 116) / 7.787));
642         float Z1 = zw * ((pow(fz, 3) > 0.008856) ? pow(fz, 3) : ((fz - 16.0 / 116) / 7.787));
643 
644         float DarkR = 3.2406 * X1 - 1.5372 * Y1 - 0.4986 * Z1;
645         float DarkG = -0.9689 * X1 + 1.8758 * Y1 + 0.0415 * Z1;
646         float DarkB = 0.0557 * X1 - 0.2040 * Y1 + 1.0570 * Z1;
647 
648         DarkR = std::clamp(maxColorRange * DarkR, minColorRange, maxColorRange);
649         DarkG = std::clamp(maxColorRange * DarkG, minColorRange, maxColorRange);
650         DarkB = std::clamp(maxColorRange * DarkB, minColorRange, maxColorRange);
651 
652         color = RSColor(DarkR, DarkG, DarkB, color.GetAlpha());
653     }
654 }
655 
656 #ifndef USE_ROSEN_DRAWING
PickColor(const RSProperties & properties,RSPaintFilterCanvas & canvas,SkPath & skPath,SkMatrix & matrix,SkIRect & deviceClipBounds,RSColor & colorPicked)657 bool RSPropertiesPainter::PickColor(const RSProperties& properties, RSPaintFilterCanvas& canvas, SkPath& skPath,
658     SkMatrix& matrix, SkIRect& deviceClipBounds, RSColor& colorPicked)
659 {
660     SkRect clipBounds = skPath.getBounds();
661     SkIRect clipIBounds = clipBounds.roundIn();
662     SkSurface* skSurface = canvas.GetSurface();
663     if (skSurface == nullptr) {
664         return false;
665     }
666 
667     auto& colorPickerTask = properties.GetColorPickerCacheTaskShadow();
668     colorPickerTask->SetIsShadow(true);
669     int deviceWidth = 0;
670     int deviceHeight = 0;
671     int deviceClipBoundsW = skSurface->width();
672     int deviceClipBoundsH = skSurface->height();
673     if (!colorPickerTask->GetDeviceSize(deviceWidth, deviceHeight)) {
674         colorPickerTask->SetDeviceSize(deviceClipBoundsW, deviceClipBoundsH);
675         deviceWidth = deviceClipBoundsW;
676         deviceHeight = deviceClipBoundsH;
677     }
678     int32_t fLeft = std::clamp(int(matrix.getTranslateX()), 0, deviceWidth - 1);
679     int32_t fTop = std::clamp(int(matrix.getTranslateY()), 0, deviceHeight - 1);
680     int32_t fRight = std::clamp(int(fLeft + clipIBounds.width()), 0, deviceWidth - 1);
681     int32_t fBottom = std::clamp(int(fTop + clipIBounds.height()), 0, deviceHeight - 1);
682     if (fLeft == fRight || fTop == fBottom) {
683         return false;
684     }
685 
686     SkIRect regionBounds = SkIRect::MakeLTRB(fLeft, fTop, fRight, fBottom);
687     sk_sp<SkImage> shadowRegionImage = skSurface->makeImageSnapshot(regionBounds);
688 
689     if (shadowRegionImage == nullptr) {
690         return false;
691     }
692 
693     // when color picker task resource is waitting for release, use color picked last frame
694     if (colorPickerTask->GetWaitRelease()) {
695         colorPickerTask->GetColorAverage(colorPicked);
696         return true;
697     }
698 
699     if (RSColorPickerCacheTask::PostPartialColorPickerTask(colorPickerTask, shadowRegionImage)
700         && colorPickerTask->GetColor(colorPicked)) {
701         colorPickerTask->GetColorAverage(colorPicked);
702         colorPickerTask->SetStatus(CacheProcessStatus::WAITING);
703         return true;
704     }
705     colorPickerTask->GetColorAverage(colorPicked);
706     return true;
707 }
708 #else
PickColor(const RSProperties & properties,RSPaintFilterCanvas & canvas,Drawing::Path & drPath,Drawing::Matrix & matrix,Drawing::RectI & deviceClipBounds,RSColor & colorPicked)709 bool RSPropertiesPainter::PickColor(const RSProperties& properties, RSPaintFilterCanvas& canvas, Drawing::Path& drPath,
710     Drawing::Matrix& matrix, Drawing::RectI& deviceClipBounds, RSColor& colorPicked)
711 {
712     Drawing::Rect clipBounds = drPath.GetBounds();
713     Drawing::RectI clipIBounds = { static_cast<int>(clipBounds.GetLeft()), static_cast<int>(clipBounds.GetTop()),
714         static_cast<int>(clipBounds.GetRight()), static_cast<int>(clipBounds.GetBottom()) };
715     Drawing::Surface* drSurface = canvas.GetSurface();
716     if (drSurface == nullptr) {
717         return false;
718     }
719 
720     auto& colorPickerTask = properties.GetColorPickerCacheTaskShadow();
721     if (!colorPickerTask) {
722         ROSEN_LOGE("RSPropertiesPainter::PickColor colorPickerTask is null");
723         return false;
724     }
725     colorPickerTask->SetIsShadow(true);
726     int deviceWidth = 0;
727     int deviceHeight = 0;
728     int deviceClipBoundsW = drSurface->Width();
729     int deviceClipBoundsH = drSurface->Height();
730     if (!colorPickerTask->GetDeviceSize(deviceWidth, deviceHeight)) {
731         colorPickerTask->SetDeviceSize(deviceClipBoundsW, deviceClipBoundsH);
732         deviceWidth = deviceClipBoundsW;
733         deviceHeight = deviceClipBoundsH;
734     }
735     int32_t fLeft = std::clamp(int(matrix.Get(Drawing::Matrix::Index::TRANS_X)), 0, deviceWidth - 1);
736     int32_t fTop = std::clamp(int(matrix.Get(Drawing::Matrix::Index::TRANS_Y)), 0, deviceHeight - 1);
737     int32_t fRight = std::clamp(int(fLeft + clipIBounds.GetWidth()), 0, deviceWidth - 1);
738     int32_t fBottom = std::clamp(int(fTop + clipIBounds.GetHeight()), 0, deviceHeight - 1);
739     if (fLeft == fRight || fTop == fBottom) {
740         return false;
741     }
742 
743     Drawing::RectI regionBounds = { fLeft, fTop, fRight, fBottom };
744     std::shared_ptr<Drawing::Image> shadowRegionImage = drSurface->GetImageSnapshot(regionBounds);
745 
746     if (shadowRegionImage == nullptr) {
747         return false;
748     }
749 
750     // when color picker task resource is waitting for release, use color picked last frame
751     if (colorPickerTask->GetWaitRelease()) {
752         colorPickerTask->GetColorAverage(colorPicked);
753         return true;
754     }
755 
756     if (RSColorPickerCacheTask::PostPartialColorPickerTask(colorPickerTask, shadowRegionImage)
757         && colorPickerTask->GetColor(colorPicked)) {
758         colorPickerTask->GetColorAverage(colorPicked);
759         colorPickerTask->SetStatus(CacheProcessStatus::WAITING);
760         return true;
761     }
762     colorPickerTask->GetColorAverage(colorPicked);
763     return true;
764 }
765 #endif
766 
767 #ifndef USE_ROSEN_DRAWING
DrawShadowInner(const RSProperties & properties,RSPaintFilterCanvas & canvas,SkPath & skPath)768 void RSPropertiesPainter::DrawShadowInner(const RSProperties& properties, RSPaintFilterCanvas& canvas, SkPath& skPath)
769 {
770     skPath.offset(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
771     Color spotColor = properties.GetShadowColor();
772     // shadow alpha follow setting
773     auto shadowAlpha = spotColor.GetAlpha();
774     auto deviceClipBounds = canvas.getDeviceClipBounds();
775 
776     // The translation of the matrix is rounded to improve the hit ratio of skia blurfilter cache,
777     // the function <compute_key_and_clip_bounds> in <skia/src/gpu/GrBlurUtil.cpp> for more details.
778     RSAutoCanvasRestore rst(&canvas);
779     auto matrix = canvas.getTotalMatrix();
780     matrix.setTranslateX(std::ceil(matrix.getTranslateX()));
781     matrix.setTranslateY(std::ceil(matrix.getTranslateY()));
782     canvas.setMatrix(matrix);
783 
784     RSColor colorPicked;
785     auto& colorPickerTask = properties.GetColorPickerCacheTaskShadow();
786     if (colorPickerTask != nullptr &&
787         properties.GetShadowColorStrategy() != SHADOW_COLOR_STRATEGY::COLOR_STRATEGY_NONE) {
788         if (PickColor(properties, canvas, skPath, matrix, deviceClipBounds, colorPicked)) {
789             GetDarkColor(colorPicked);
790         } else {
791             shadowAlpha = 0;
792         }
793         if (!colorPickerTask->GetFirstGetColorFinished()) {
794             shadowAlpha = 0;
795         }
796     } else {
797         shadowAlpha = spotColor.GetAlpha();
798         colorPicked = spotColor;
799     }
800 
801     if (properties.GetShadowElevation() > 0.f) {
802         SkPoint3 planeParams = { 0.0f, 0.0f, properties.GetShadowElevation() };
803         SkPoint pt = { skPath.getBounds().centerX(), skPath.getBounds().centerY() };
804         canvas.getTotalMatrix().mapPoints(&pt, 1);
805         SkPoint3 lightPos = {pt.fX, pt.fY, DEFAULT_LIGHT_HEIGHT};
806         Color ambientColor = Color::FromArgbInt(DEFAULT_AMBIENT_COLOR);
807         ambientColor.MultiplyAlpha(canvas.GetAlpha());
808         spotColor.MultiplyAlpha(canvas.GetAlpha());
809         SkShadowUtils::DrawShadow(&canvas, skPath, planeParams, lightPos, DEFAULT_LIGHT_RADIUS,
810             ambientColor.AsArgbInt(), spotColor.AsArgbInt(), SkShadowFlags::kTransparentOccluder_ShadowFlag);
811     } else {
812         SkPaint paint;
813         paint.setColor(SkColorSetARGB(shadowAlpha, colorPicked.GetRed(),
814             colorPicked.GetGreen(), colorPicked.GetBlue()));
815         paint.setAntiAlias(true);
816         paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, properties.GetShadowRadius()));
817         canvas.drawPath(skPath, paint);
818     }
819 }
820 #else
DrawShadowInner(const RSProperties & properties,RSPaintFilterCanvas & canvas,Drawing::Path & path)821 void RSPropertiesPainter::DrawShadowInner(
822     const RSProperties& properties, RSPaintFilterCanvas& canvas, Drawing::Path& path)
823 {
824     path.Offset(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
825     Color spotColor = properties.GetShadowColor();
826     // shadow alpha follow setting
827     auto shadowAlpha = spotColor.GetAlpha();
828     auto deviceClipBounds = canvas.GetDeviceClipBounds();
829 
830     // The translation of the matrix is rounded to improve the hit ratio of skia blurfilter cache,
831     // the function <compute_key_and_clip_bounds> in <skia/src/gpu/GrBlurUtil.cpp> for more details.
832     RSAutoCanvasRestore rst(&canvas);
833     auto matrix = canvas.GetTotalMatrix();
834     matrix.Set(Drawing::Matrix::TRANS_X, std::ceil(matrix.Get(Drawing::Matrix::TRANS_X)));
835     matrix.Set(Drawing::Matrix::TRANS_Y, std::ceil(matrix.Get(Drawing::Matrix::TRANS_Y)));
836     canvas.SetMatrix(matrix);
837 
838     RSColor colorPicked;
839     auto& colorPickerTask = properties.GetColorPickerCacheTaskShadow();
840     if (colorPickerTask != nullptr &&
841         properties.GetShadowColorStrategy() != SHADOW_COLOR_STRATEGY::COLOR_STRATEGY_NONE) {
842         if (PickColor(properties, canvas, path, matrix, deviceClipBounds, colorPicked)) {
843             GetDarkColor(colorPicked);
844         } else {
845             shadowAlpha = 0;
846         }
847         if (!colorPickerTask->GetFirstGetColorFinished()) {
848             shadowAlpha = 0;
849         }
850     } else {
851         shadowAlpha = spotColor.GetAlpha();
852         colorPicked = spotColor;
853     }
854 
855     if (properties.GetShadowElevation() > 0.f) {
856         Drawing::Point3 planeParams = { 0.0f, 0.0f, properties.GetShadowElevation() };
857         std::vector<Drawing::Point> pt{{path.GetBounds().GetLeft() + path.GetBounds().GetWidth() / 2,
858             path.GetBounds().GetTop() + path.GetBounds().GetHeight() / 2}};
859         canvas.GetTotalMatrix().MapPoints(pt, pt, 1);
860         Drawing::Point3 lightPos = {pt[0].GetX(), pt[0].GetY(), DEFAULT_LIGHT_HEIGHT};
861         Color ambientColor = Color::FromArgbInt(DEFAULT_AMBIENT_COLOR);
862         ambientColor.MultiplyAlpha(canvas.GetAlpha());
863         spotColor.MultiplyAlpha(canvas.GetAlpha());
864         canvas.DrawShadow(path, planeParams, lightPos, DEFAULT_LIGHT_RADIUS,
865             Drawing::Color(ambientColor.AsArgbInt()), Drawing::Color(spotColor.AsArgbInt()),
866             Drawing::ShadowFlags::TRANSPARENT_OCCLUDER);
867     } else {
868         Drawing::Brush brush;
869         brush.SetColor(Drawing::Color::ColorQuadSetARGB(
870             shadowAlpha, colorPicked.GetRed(), colorPicked.GetGreen(), colorPicked.GetBlue()));
871         brush.SetAntiAlias(true);
872         Drawing::Filter filter;
873         filter.SetMaskFilter(
874             Drawing::MaskFilter::CreateBlurMaskFilter(Drawing::BlurType::NORMAL, properties.GetShadowRadius()));
875         brush.SetFilter(filter);
876         canvas.AttachBrush(brush);
877         canvas.DrawPath(path);
878         canvas.DetachBrush();
879     }
880 }
881 #endif
882 
883 #ifndef USE_ROSEN_DRAWING
MakeGreyAdjustmentEffect()884 sk_sp<SkRuntimeEffect> RSPropertiesPainter::MakeGreyAdjustmentEffect()
885 {
886     SkString GreyGradationString(R"(
887         uniform shader imageShader;
888         uniform float coefficient1;
889         uniform float coefficient2;
890 
891         float poww(float x, float y) {
892             return (x < 0) ? -pow(-x, y) : pow(x, y);
893         }
894 
895         float calculateT_y(float rgb) {
896             if (rgb > 127.5) { rgb = 255 - rgb; }
897             float b = 38.0;
898             float c = 45.0;
899             float d = 127.5;
900             float A = 106.5;    // 3 * b - 3 * c + d;
901             float B = -93;      // 3 * (c - 2 * b);
902             float C = 114;      // 3 * b;
903             float p = 0.816240163988;                   // (3 * A * C - pow(B, 2)) / (3 * pow(A, 2));
904             float q = -rgb / 106.5 + 0.262253485943;    // -rgb/A - B*C/(3*pow(A,2)) + 2*pow(B,3)/(27*pow(A,3))
905             float s1 = -(q / 2.0);
906             float s2 = sqrt(pow(s1, 2) + pow(p / 3, 3));
907             return poww((s1 + s2), 1.0 / 3) + poww((s1 - s2), 1.0 / 3) - (B / (3 * A));
908         }
909 
910         float calculateGreyAdjustY(float rgb) {
911             float t_r = calculateT_y(rgb);
912             return (rgb < 127.5) ? (rgb + coefficient1 * pow((1 - t_r), 3)) : (rgb - coefficient2 * pow((1 - t_r), 3));
913         }
914 
915         half4 main(float2 coord) {
916             vec3 color = vec3(imageShader.eval(coord).r, imageShader.eval(coord).g, imageShader.eval(coord).b);
917             float Y = (0.299 * color.r + 0.587 * color.g + 0.114 * color.b) * 255;
918             float U = (-0.147 * color.r - 0.289 * color.g + 0.436 * color.b) * 255;
919             float V = (0.615 * color.r - 0.515 * color.g - 0.100 * color.b) * 255;
920             Y = calculateGreyAdjustY(Y);
921             color.r = (Y + 1.14 * V) / 255.0;
922             color.g = (Y - 0.39 * U - 0.58 * V) / 255.0;
923             color.b = (Y + 2.03 * U) / 255.0;
924 
925             return vec4(color, 1.0);
926         }
927     )");
928     if (!greyAdjustEffect_) {
929         auto [greyAdjustEffect, greyAdjustError] = SkRuntimeEffect::MakeForShader(GreyGradationString);
930         if (!greyAdjustEffect) {
931             return nullptr;
932         }
933         greyAdjustEffect_ = std::move(greyAdjustEffect);
934     }
935 
936     return greyAdjustEffect_;
937 }
938 #else
MakeGreyAdjustmentEffect()939 std::shared_ptr<Drawing::RuntimeEffect> RSPropertiesPainter::MakeGreyAdjustmentEffect()
940 {
941     static const std::string GreyGradationString(R"(
942         uniform shader imageShader;
943         uniform float coefficient1;
944         uniform float coefficient2;
945 
946         float poww(float x, float y) {
947             return (x < 0) ? -pow(-x, y) : pow(x, y);
948         }
949 
950         float calculateT_y(float rgb) {
951             if (rgb > 127.5) { rgb = 255 - rgb; }
952             float b = 38.0;
953             float c = 45.0;
954             float d = 127.5;
955             float A = 106.5;    // 3 * b - 3 * c + d;
956             float B = -93;      // 3 * (c - 2 * b);
957             float C = 114;      // 3 * b;
958             float p = 0.816240163988;                   // (3 * A * C - pow(B, 2)) / (3 * pow(A, 2));
959             float q = -rgb / 106.5 + 0.262253485943;    // -rgb/A - B*C/(3*pow(A,2)) + 2*pow(B,3)/(27*pow(A,3))
960             float s1 = -(q / 2.0);
961             float s2 = sqrt(pow(s1, 2) + pow(p / 3, 3));
962             return poww((s1 + s2), 1.0 / 3) + poww((s1 - s2), 1.0 / 3) - (B / (3 * A));
963         }
964 
965         float calculateGreyAdjustY(float rgb) {
966             float t_r = calculateT_y(rgb);
967             return (rgb < 127.5) ? (rgb + coefficient1 * pow((1 - t_r), 3)) : (rgb - coefficient2 * pow((1 - t_r), 3));
968         }
969 
970         half4 main(float2 coord) {
971             vec3 color = vec3(imageShader.eval(coord).r, imageShader.eval(coord).g, imageShader.eval(coord).b);
972             float Y = (0.299 * color.r + 0.587 * color.g + 0.114 * color.b) * 255;
973             float U = (-0.147 * color.r - 0.289 * color.g + 0.436 * color.b) * 255;
974             float V = (0.615 * color.r - 0.515 * color.g - 0.100 * color.b) * 255;
975             Y = calculateGreyAdjustY(Y);
976             color.r = (Y + 1.14 * V) / 255.0;
977             color.g = (Y - 0.39 * U - 0.58 * V) / 255.0;
978             color.b = (Y + 2.03 * U) / 255.0;
979 
980             return vec4(color, 1.0);
981         }
982     )");
983     if (!greyAdjustEffect_) {
984         std::shared_ptr<Drawing::RuntimeEffect> greyAdjustEffect =
985             Drawing::RuntimeEffect::CreateForShader(GreyGradationString);
986         if (!greyAdjustEffect) {
987             return nullptr;
988         }
989         greyAdjustEffect_ = std::move(greyAdjustEffect);
990     }
991 
992     return greyAdjustEffect_;
993 }
994 #endif
995 
996 #ifndef USE_ROSEN_DRAWING
DrawGreyAdjustment(SkCanvas & canvas,const sk_sp<SkImage> & image,const float greyCoef1,const float greyCoef2)997 sk_sp<SkImage> RSPropertiesPainter::DrawGreyAdjustment(SkCanvas& canvas, const sk_sp<SkImage>& image,
998     const float greyCoef1, const float greyCoef2)
999 {
1000     if (image == nullptr) {
1001         ROSEN_LOGE("RSPropertiesPainter::DrawGreyAdjustment image is null");
1002         return nullptr;
1003     }
1004     RS_TRACE_NAME_FMT("RSPropertiesPainter::DrawGreyAdjustment, greyCoef1 is: %f, greyCoef2 is: %f",
1005         greyCoef1, greyCoef2);
1006     auto greyAdjustEffect = MakeGreyAdjustmentEffect();
1007     if (!greyAdjustEffect) {
1008         ROSEN_LOGE("RSPropertiesPainter::DrawGreyAdjustment greyAdjustEffect is null");
1009         return nullptr;
1010     }
1011     SkRuntimeShaderBuilder builder(greyAdjustEffect);
1012     auto imageShader = image->makeShader(SkSamplingOptions(SkFilterMode::kLinear));
1013     builder.child("imageShader") = imageShader;
1014     builder.uniform("coefficient1") = greyCoef1;
1015     builder.uniform("coefficient2") = greyCoef2;
1016 
1017     return builder.makeImage(canvas.recordingContext(), nullptr, image->imageInfo(), false);
1018 }
1019 #else
DrawGreyAdjustment(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> & image,const float greyCoef1,const float greyCoef2)1020 std::shared_ptr<Drawing::Image> RSPropertiesPainter::DrawGreyAdjustment(Drawing::Canvas& canvas,
1021     const std::shared_ptr<Drawing::Image>& image, const float greyCoef1, const float greyCoef2)
1022 {
1023     if (image == nullptr) {
1024         ROSEN_LOGE("RSPropertiesPainter::DrawGreyAdjustment image is null");
1025         return nullptr;
1026     }
1027     RS_TRACE_NAME_FMT("RSPropertiesPainter::DrawGreyAdjustment, greyCoef1 is: %f, greyCoef2 is: %f",
1028         greyCoef1, greyCoef2);
1029     auto greyAdjustEffect = MakeGreyAdjustmentEffect();
1030     if (!greyAdjustEffect) {
1031         ROSEN_LOGE("RSPropertiesPainter::DrawGreyAdjustment greyAdjustEffect is null");
1032         return nullptr;
1033     }
1034     std::shared_ptr<Drawing::RuntimeShaderBuilder> builder =
1035         std::make_shared<Drawing::RuntimeShaderBuilder>(greyAdjustEffect);
1036     Drawing::Matrix matrix;
1037     auto imageShader = Drawing::ShaderEffect::CreateImageShader(*image, Drawing::TileMode::CLAMP,
1038         Drawing::TileMode::CLAMP, Drawing::SamplingOptions(Drawing::FilterMode::LINEAR), matrix);
1039     builder->SetChild("imageShader", imageShader);
1040     builder->SetUniform("coefficient1", greyCoef1);
1041     builder->SetUniform("coefficient2", greyCoef2);
1042     return builder->MakeImage(canvas.GetGPUContext().get(), nullptr, image->GetImageInfo(), false);
1043 }
1044 #endif
1045 
1046 #ifndef USE_ROSEN_DRAWING
DrawFilter(const RSProperties & properties,RSPaintFilterCanvas & canvas,FilterType filterType,const std::optional<SkRect> & rect,const std::shared_ptr<RSFilter> & externalFilter)1047 void RSPropertiesPainter::DrawFilter(const RSProperties& properties, RSPaintFilterCanvas& canvas,
1048     FilterType filterType, const std::optional<SkRect>& rect, const std::shared_ptr<RSFilter>& externalFilter)
1049 #else
1050 void RSPropertiesPainter::DrawFilter(const RSProperties& properties, RSPaintFilterCanvas& canvas,
1051     FilterType filterType, const std::optional<Drawing::Rect>& rect, const std::shared_ptr<RSFilter>& externalFilter)
1052 #endif
1053 {
1054     if (!BLUR_ENABLED) {
1055         ROSEN_LOGD("RSPropertiesPainter::DrawFilter close blur.");
1056         return;
1057     }
1058     // use provided filter if not null
1059     auto& RSFilter = externalFilter ? externalFilter
1060         : ((filterType == FilterType::BACKGROUND_FILTER) ? properties.GetBackgroundFilter() : properties.GetFilter());
1061     if (RSFilter == nullptr) {
1062         return;
1063     }
1064 
1065     bool needSnapshotOutset = true;
1066     if (RSFilter->GetFilterType() == RSFilter::MATERIAL) {
1067         auto material = std::static_pointer_cast<RSMaterialFilter>(RSFilter);
1068         needSnapshotOutset = (material->GetRadius() >= SNAPSHOT_OUTSET_BLUR_RADIUS_THRESHOLD);
1069     }
1070     RS_OPTIONAL_TRACE_NAME("DrawFilter " + RSFilter->GetDescription());
1071     g_blurCnt++;
1072 #ifndef USE_ROSEN_DRAWING
1073     SkAutoCanvasRestore acr(&canvas, true);
1074     if (RSSystemProperties::GetPropertyDrawableEnable()) {
1075         // do nothing
1076     } else if (rect.has_value()) {
1077         canvas.clipRect((*rect), true);
1078     } else if (properties.GetClipBounds() != nullptr) {
1079         canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
1080     } else { // we always do clip for DrawFilter, even if ClipToBounds is false
1081         canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
1082     }
1083 
1084     auto filter = std::static_pointer_cast<RSSkiaFilter>(RSFilter);
1085     filter->SetGreyCoef(properties.GetGreyCoef1(), properties.GetGreyCoef2(), properties.IsGreyAdjustmentValid());
1086     auto skSurface = canvas.GetSurface();
1087     if (skSurface == nullptr) {
1088         ROSEN_LOGD("RSPropertiesPainter::DrawFilter skSurface null");
1089         auto paint = filter->GetPaint();
1090         SkCanvas::SaveLayerRec slr(nullptr, &paint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
1091         canvas.saveLayer(slr);
1092         filter->PostProcess(canvas);
1093         return;
1094     }
1095 #else
1096     Drawing::AutoCanvasRestore acr(canvas, true);
1097     if (RSSystemProperties::GetPropertyDrawableEnable()) {
1098         // do nothing
1099     } else if (rect.has_value()) {
1100         canvas.ClipRect((*rect), Drawing::ClipOp::INTERSECT, true);
1101     } else if (properties.GetClipBounds() != nullptr) {
1102         canvas.ClipPath(properties.GetClipBounds()->GetDrawingPath(), Drawing::ClipOp::INTERSECT, true);
1103     } else { // we always do clip for DrawFilter, even if ClipToBounds is false
1104         canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, true);
1105     }
1106 
1107     auto filter = std::static_pointer_cast<RSDrawingFilter>(RSFilter);
1108     filter->SetGreyCoef(properties.GetGreyCoef1(), properties.GetGreyCoef2(), properties.IsGreyAdjustmentValid());
1109     auto surface = canvas.GetSurface();
1110     if (surface == nullptr) {
1111         ROSEN_LOGD("RSPropertiesPainter::DrawFilter surface null");
1112         Drawing::Brush brush = filter->GetBrush();
1113         Drawing::SaveLayerOps slr(nullptr, &brush, Drawing::SaveLayerOps::Flags::INIT_WITH_PREVIOUS);
1114         canvas.SaveLayer(slr);
1115         filter->PostProcess(canvas);
1116         return;
1117     }
1118 #endif
1119 
1120     // for foreground filter, when do online opacity, rendering result already applied opacity,
1121     // so drawImage should not apply opacity again
1122     RSAutoCanvasRestore autoCanvasRestore(&canvas,
1123         filterType == FilterType::FOREGROUND_FILTER ? RSPaintFilterCanvas::kAlpha : RSPaintFilterCanvas::kNone);
1124     if (filterType == FilterType::FOREGROUND_FILTER) {
1125         canvas.SetAlpha(1.0);
1126     }
1127 
1128 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
1129     // Optional use cacheManager to draw filter
1130     if (auto& cacheManager = properties.GetFilterCacheManager(filterType == FilterType::FOREGROUND_FILTER);
1131         cacheManager != nullptr && !canvas.GetDisableFilterCache()) {
1132         if (filter->GetFilterType() == RSFilter::LINEAR_GRADIENT_BLUR) {
1133             filter->SetBoundsGeometry(properties.GetFrameWidth(), properties.GetFrameHeight());
1134         }
1135         cacheManager->DrawFilter(canvas, filter, needSnapshotOutset);
1136         return;
1137     }
1138 #endif
1139 
1140 #ifndef USE_ROSEN_DRAWING
1141     auto clipIBounds = canvas.getDeviceClipBounds();
1142     auto imageSnapshot = skSurface->makeImageSnapshot(
1143         needSnapshotOutset ? clipIBounds.makeOutset(-1, -1) : clipIBounds);
1144 #else
1145     auto clipIBounds = canvas.GetDeviceClipBounds();
1146     auto imageClipIBounds = clipIBounds;
1147     if (needSnapshotOutset) {
1148         imageClipIBounds.MakeOutset(-1, -1);
1149     }
1150     auto imageSnapshot = surface->GetImageSnapshot(imageClipIBounds);
1151 #endif
1152     if (imageSnapshot == nullptr) {
1153         ROSEN_LOGE("RSPropertiesPainter::DrawFilter image null");
1154         return;
1155     }
1156 #ifndef USE_ROSEN_DRAWING
1157     if (RSSystemProperties::GetImageGpuResourceCacheEnable(imageSnapshot->width(), imageSnapshot->height())) {
1158         ROSEN_LOGD("DrawFilter cache image resource(width:%{public}d, height:%{public}d).",
1159             imageSnapshot->width(), imageSnapshot->height());
1160         as_IB(imageSnapshot)->hintCacheGpuResource();
1161 #else
1162     if (RSSystemProperties::GetImageGpuResourceCacheEnable(imageSnapshot->GetWidth(), imageSnapshot->GetHeight())) {
1163         ROSEN_LOGD("DrawFilter cache image resource(width:%{public}d, height:%{public}d).",
1164             imageSnapshot->GetWidth(), imageSnapshot->GetHeight());
1165         as_IB(imageSnapshot->ExportSkImage().get())->hintCacheGpuResource();
1166 #endif
1167     }
1168 
1169     filter->PreProcess(imageSnapshot);
1170 #ifndef USE_ROSEN_DRAWING
1171     if (filter->GetFilterType() == RSFilter::LINEAR_GRADIENT_BLUR) {
1172         SkMatrix mat = canvas.getTotalMatrix();
1173         filter->SetCanvasChange(mat, skSurface->width(), skSurface->height());
1174         filter->SetBoundsGeometry(properties.GetFrameWidth(), properties.GetFrameHeight());
1175     }
1176 
1177     canvas.resetMatrix();
1178     auto visibleIRect = canvas.GetVisibleRect().round();
1179     if (!visibleIRect.isEmpty()) {
1180         canvas.clipIRect(visibleIRect);
1181     }
1182     filter->DrawImageRect(
1183         canvas, imageSnapshot, SkRect::Make(imageSnapshot->bounds()), SkRect::Make(clipIBounds));
1184 #else
1185     if (filter->GetFilterType() == RSFilter::LINEAR_GRADIENT_BLUR) {
1186         Drawing::Matrix mat = canvas.GetTotalMatrix();
1187         filter->SetCanvasChange(mat, surface->Width(), surface->Height());
1188         filter->SetBoundsGeometry(properties.GetFrameWidth(), properties.GetFrameHeight());
1189     }
1190 
1191     canvas.ResetMatrix();
1192     auto visibleRect = canvas.GetVisibleRect();
1193     visibleRect.Round();
1194     auto visibleIRect = Drawing::RectI(
1195         static_cast<int>(visibleRect.GetLeft()), static_cast<int>(visibleRect.GetTop()),
1196         static_cast<int>(visibleRect.GetRight()), static_cast<int>(visibleRect.GetBottom()));
1197     if (!visibleIRect.IsEmpty()) {
1198         canvas.ClipIRect(visibleIRect, Drawing::ClipOp::INTERSECT);
1199     }
1200     Drawing::Rect srcRect = Drawing::Rect(0, 0, imageSnapshot->GetWidth(), imageSnapshot->GetHeight());
1201     Drawing::Rect dstRect = clipIBounds;
1202     filter->DrawImageRect(canvas, imageSnapshot, srcRect, dstRect);
1203 #endif
1204     filter->PostProcess(canvas);
1205 }
1206 
1207 void RSPropertiesPainter::DrawBackgroundImageAsEffect(const RSProperties& properties, RSPaintFilterCanvas& canvas)
1208 {
1209     RS_TRACE_FUNC();
1210     auto boundsRect = properties.GetBoundsRect();
1211 
1212     // Optional use cacheManager to draw filter, cache is valid, skip drawing background image
1213 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
1214     if (auto& cacheManager = properties.GetFilterCacheManager(false);
1215         cacheManager != nullptr && !canvas.GetDisableFilterCache() && cacheManager->IsCacheValid()) {
1216         // no need to validate parameters, the caller already do it
1217 #ifndef USE_ROSEN_DRAWING
1218         canvas.clipRect(RSPropertiesPainter::Rect2SkRect(boundsRect));
1219         auto filter = std::static_pointer_cast<RSSkiaFilter>(properties.GetBackgroundFilter());
1220 #else
1221         canvas.ClipRect(RSPropertiesPainter::Rect2DrawingRect(boundsRect));
1222         auto filter = std::static_pointer_cast<RSDrawingFilter>(properties.GetBackgroundFilter());
1223 #endif
1224         // extract cache data from cacheManager
1225         auto&& data = cacheManager->GeneratedCachedEffectData(canvas, filter);
1226         canvas.SetEffectData(data);
1227         return;
1228     }
1229 #endif
1230 
1231     auto surface = canvas.GetSurface();
1232     if (!surface) {
1233         ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundImageAsEffect surface null");
1234         return;
1235     }
1236     // create offscreen surface with same size as current surface (PLANNING: use bounds size instead)
1237 #ifndef USE_ROSEN_DRAWING
1238     auto offscreenSurface = surface->makeSurface(surface->width(), surface->height());
1239 #else
1240     auto offscreenSurface = surface->MakeSurface(canvas.GetWidth(), canvas.GetHeight());
1241 #endif
1242     auto offscreenCanvas = std::make_shared<RSPaintFilterCanvas>(offscreenSurface.get());
1243     // copy matrix and other properties to offscreen canvas
1244 #ifndef USE_ROSEN_DRAWING
1245     offscreenCanvas->setMatrix(canvas.getTotalMatrix());
1246 #else
1247     offscreenCanvas->SetMatrix(canvas.GetTotalMatrix());
1248 #endif
1249     offscreenCanvas->CopyConfiguration(canvas);
1250     // draw background onto offscreen canvas
1251     RSPropertiesPainter::DrawBackground(properties, *offscreenCanvas);
1252     // generate effect data
1253     RSPropertiesPainter::DrawBackgroundEffect(properties, *offscreenCanvas);
1254     // extract effect data from offscreen canvas and set to canvas
1255     canvas.SetEffectData(offscreenCanvas->GetEffectData());
1256 }
1257 
1258 void RSPropertiesPainter::DrawBackgroundEffect(
1259     const RSProperties& properties, RSPaintFilterCanvas& canvas)
1260 {
1261     auto& RSFilter = properties.GetBackgroundFilter();
1262     if (RSFilter == nullptr) {
1263         return;
1264     }
1265     g_blurCnt++;
1266     RS_TRACE_NAME("DrawBackgroundEffect " + RSFilter->GetDescription());
1267     auto surface = canvas.GetSurface();
1268     if (surface == nullptr) {
1269         ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundEffect surface null");
1270         return;
1271     }
1272 
1273 #ifndef USE_ROSEN_DRAWING
1274     canvas.save();
1275     canvas.clipRect(Rect2SkRect(properties.GetBoundsRect()));
1276     auto bounds = canvas.getDeviceClipBounds();
1277     canvas.restore();
1278     auto filter = std::static_pointer_cast<RSSkiaFilter>(RSFilter);
1279 #else
1280     canvas.Save();
1281     canvas.ClipRect(Rect2DrawingRect(properties.GetBoundsRect()));
1282     auto bounds = canvas.GetDeviceClipBounds();
1283     canvas.Restore();
1284     auto filter = std::static_pointer_cast<RSDrawingFilter>(RSFilter);
1285 #endif
1286 
1287 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
1288     // Optional use cacheManager to draw filter
1289     if (auto& cacheManager = properties.GetFilterCacheManager(false);
1290         cacheManager != nullptr && !canvas.GetDisableFilterCache()) {
1291         auto node = properties.backref_.lock();
1292         if (node == nullptr) {
1293             ROSEN_LOGE("DrawBackgroundEffect::node is null");
1294             return;
1295         }
1296         auto effectNode = node->ReinterpretCastTo<RSEffectRenderNode>();
1297         if (effectNode == nullptr) {
1298             ROSEN_LOGE("DrawBackgroundEffect::node reinterpret cast failed.");
1299             return;
1300         }
1301         // node is freeze or screen rotating, force cache filterred snapshot.
1302         auto forceCacheFlags = std::make_tuple(false, effectNode->GetRotationChanged());
1303         auto&& data = cacheManager->GeneratedCachedEffectData(canvas, filter, bounds, bounds, forceCacheFlags);
1304         canvas.SetEffectData(data);
1305         return;
1306     }
1307 #endif
1308 
1309     auto imageRect = bounds;
1310 #ifndef USE_ROSEN_DRAWING
1311     auto imageSnapshot = surface->makeImageSnapshot(imageRect);
1312 #else
1313     auto imageSnapshot = surface->GetImageSnapshot(imageRect);
1314 #endif
1315     if (imageSnapshot == nullptr) {
1316         ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundEffect image snapshot null");
1317         return;
1318     }
1319 
1320     filter->PreProcess(imageSnapshot);
1321     // create a offscreen skSurface
1322 #ifndef USE_ROSEN_DRAWING
1323     sk_sp<SkSurface> offscreenSurface = surface->makeSurface(imageSnapshot->imageInfo());
1324     if (offscreenSurface == nullptr) {
1325         ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundEffect offscreenSurface null");
1326         return;
1327     }
1328     RSPaintFilterCanvas offscreenCanvas(offscreenSurface.get());
1329     auto clipBounds = SkRect::MakeIWH(imageRect.width(), imageRect.height());
1330     filter->DrawImageRect(offscreenCanvas, imageSnapshot, SkRect::Make(imageSnapshot->bounds()), clipBounds);
1331     filter->PostProcess(offscreenCanvas);
1332 
1333     auto imageCache = offscreenSurface->makeImageSnapshot();
1334 #else
1335     std::shared_ptr<Drawing::Surface> offscreenSurface =
1336         surface->MakeSurface(imageSnapshot->GetWidth(), imageSnapshot->GetHeight());
1337     if (offscreenSurface == nullptr) {
1338         ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundEffect offscreenSurface null");
1339         return;
1340     }
1341     RSPaintFilterCanvas offscreenCanvas(offscreenSurface.get());
1342     auto clipBounds = Drawing::Rect(0, 0, imageRect.GetWidth(), imageRect.GetHeight());
1343     auto imageSnapshotBounds = Drawing::Rect(0, 0, imageSnapshot->GetWidth(), imageSnapshot->GetHeight());
1344     filter->DrawImageRect(offscreenCanvas, imageSnapshot, imageSnapshotBounds, clipBounds);
1345     filter->PostProcess(offscreenCanvas);
1346 
1347     auto imageCache = offscreenSurface->GetImageSnapshot();
1348 #endif
1349     if (imageCache == nullptr) {
1350         ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundEffect imageCache snapshot null");
1351         return;
1352     }
1353     auto data = std::make_shared<RSPaintFilterCanvas::CachedEffectData>(std::move(imageCache), std::move(imageRect));
1354     canvas.SetEffectData(std::move(data));
1355 }
1356 
1357 void RSPropertiesPainter::ApplyBackgroundEffectFallback(const RSProperties& properties, RSPaintFilterCanvas& canvas)
1358 {
1359     RS_TRACE_FUNC();
1360     auto parentNode = properties.backref_.lock();
1361     while (parentNode && !parentNode->IsInstanceOf<RSEffectRenderNode>()) {
1362         parentNode = parentNode->GetParent().lock();
1363     }
1364     if (!parentNode) {
1365         ROSEN_LOGD("RSPropertiesPainter::ApplyBackgroundEffectFallback: parentNode null, draw filter failed.");
1366         return;
1367     }
1368     auto& filter = parentNode->GetRenderProperties().GetBackgroundFilter();
1369     if (filter == nullptr || !filter->IsValid()) {
1370         ROSEN_LOGD("RSPropertiesPainter::ApplyBackgroundEffectFallback: parent EffectRenderNode has no filter, "
1371                    "draw filter failed.");
1372         return;
1373     }
1374     DrawFilter(properties, canvas, FilterType::BACKGROUND_FILTER, std::nullopt, filter);
1375 }
1376 
1377 void RSPropertiesPainter::ClipVisibleCanvas(const RSProperties& properties, RSPaintFilterCanvas& canvas)
1378 {
1379 #ifndef USE_ROSEN_DRAWING
1380     if (RSSystemProperties::GetPropertyDrawableEnable()) {
1381         // do nothing
1382     } else if (properties.GetClipBounds() != nullptr) {
1383         canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
1384     } else { // we always do clip for ApplyBackgroundEffect, even if ClipToBounds is false
1385         canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
1386     }
1387     canvas.resetMatrix();
1388     auto visibleIRect = canvas.GetVisibleRect().round();
1389     if (!visibleIRect.isEmpty()) {
1390         canvas.clipIRect(visibleIRect);
1391     }
1392 #else
1393     if (RSSystemProperties::GetPropertyDrawableEnable()) {
1394         // do nothing
1395     } else if (properties.GetClipBounds() != nullptr) {
1396         canvas.ClipPath(properties.GetClipBounds()->GetDrawingPath(), Drawing::ClipOp::INTERSECT, true);
1397     } else { // we always do clip for ApplyBackgroundEffect, even if ClipToBounds is false
1398         canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, true);
1399     }
1400     canvas.ResetMatrix();
1401     auto visibleRect = canvas.GetVisibleRect();
1402     visibleRect.Round();
1403     auto visibleIRect = Drawing::RectI(
1404         static_cast<int>(visibleRect.GetLeft()), static_cast<int>(visibleRect.GetTop()),
1405         static_cast<int>(visibleRect.GetRight()), static_cast<int>(visibleRect.GetBottom()));
1406     if (!visibleIRect.IsEmpty()) {
1407         canvas.ClipIRect(visibleIRect, Drawing::ClipOp::INTERSECT);
1408     }
1409 #endif
1410 }
1411 
1412 void RSPropertiesPainter::ApplyBackgroundEffect(const RSProperties& properties, RSPaintFilterCanvas& canvas)
1413 {
1414     const auto& effectData = canvas.GetEffectData();
1415     if (effectData == nullptr || effectData->cachedImage_ == nullptr
1416         || !RSSystemProperties::GetEffectMergeEnabled()) {
1417         // no effectData available, draw background filter in fallback method
1418         ROSEN_LOGD("RSPropertiesPainter::ApplyBackgroundEffect: effectData null, try fallback method.");
1419         ApplyBackgroundEffectFallback(properties, canvas);
1420         return;
1421     }
1422     RS_TRACE_FUNC();
1423 #ifndef USE_ROSEN_DRAWING
1424     SkAutoCanvasRestore acr(&canvas, true);
1425     ClipVisibleCanvas(properties, canvas);
1426     SkPaint defaultPaint;
1427     // dstRect: canvas clip region
1428     auto dstRect = SkRect::Make(canvas.getDeviceClipBounds());
1429     // srcRect: map dstRect onto cache coordinate
1430     auto srcRect = dstRect.makeOffset(-effectData->cachedRect_.left(), -effectData->cachedRect_.top());
1431     canvas.drawImageRect(effectData->cachedImage_, srcRect, dstRect, SkSamplingOptions(), &defaultPaint,
1432         SkCanvas::kFast_SrcRectConstraint);
1433 #else
1434     Drawing::AutoCanvasRestore acr(canvas, true);
1435     ClipVisibleCanvas(properties, canvas);
1436     Drawing::Brush brush;
1437     canvas.AttachBrush(brush);
1438     // dstRect: canvas clip region
1439     Drawing::Rect dstRect = canvas.GetDeviceClipBounds();
1440     // srcRect: map dstRect onto cache coordinate
1441     Drawing::Rect srcRect = dstRect;
1442     srcRect.Offset(-effectData->cachedRect_.GetLeft(), -effectData->cachedRect_.GetTop());
1443     canvas.DrawImageRect(*effectData->cachedImage_, srcRect, dstRect,
1444                          Drawing::SamplingOptions(), Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
1445     canvas.DetachBrush();
1446 #endif
1447 }
1448 
1449 void RSPropertiesPainter::DrawPixelStretch(const RSProperties& properties, RSPaintFilterCanvas& canvas)
1450 {
1451     auto& pixelStretch = properties.GetPixelStretch();
1452     if (!pixelStretch.has_value()) {
1453         return;
1454     }
1455 #ifndef USE_ROSEN_DRAWING
1456     auto skSurface = canvas.GetSurface();
1457     if (skSurface == nullptr) {
1458         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch skSurface null");
1459         return;
1460     }
1461 
1462     canvas.save();
1463     auto bounds = RSPropertiesPainter::Rect2SkRect(properties.GetBoundsRect());
1464     canvas.clipRect(bounds);
1465     auto clipBounds = canvas.getDeviceClipBounds();
1466     clipBounds.setXYWH(clipBounds.left(), clipBounds.top(), clipBounds.width() - 1, clipBounds.height() - 1);
1467     canvas.restore();
1468 
1469     /* Calculates the relative coordinates of the clipbounds
1470         with respect to the origin of the current canvas coordinates */
1471     SkMatrix worldToLocalMat;
1472     if (!canvas.getTotalMatrix().invert(&worldToLocalMat)) {
1473         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch get invert matrix failed.");
1474     }
1475     SkRect localClipBounds;
1476     SkRect fClipBounds = SkRect::MakeXYWH(clipBounds.x(), clipBounds.y(), clipBounds.width(), clipBounds.height());
1477     if (!worldToLocalMat.mapRect(&localClipBounds, fClipBounds)) {
1478         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch map rect failed.");
1479     }
1480 
1481     if (!bounds.intersect(localClipBounds)) {
1482         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch intersect clipbounds failed");
1483     }
1484 
1485     auto scaledBounds = SkRect::MakeLTRB(bounds.left() - pixelStretch->x_, bounds.top() - pixelStretch->y_,
1486         bounds.right() + pixelStretch->z_, bounds.bottom() + pixelStretch->w_);
1487     if (scaledBounds.isEmpty() || bounds.isEmpty() || clipBounds.isEmpty()) {
1488         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch invalid scaled bounds");
1489         return;
1490     }
1491 
1492     auto image = skSurface->makeImageSnapshot(clipBounds);
1493     if (image == nullptr) {
1494         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch image null");
1495         return;
1496     }
1497 
1498     SkPaint paint;
1499     SkMatrix inverseMat, rotateMat;
1500     auto boundsGeo = (properties.GetBoundsGeometry());
1501     if (boundsGeo && !boundsGeo->IsEmpty()) {
1502         auto transMat = canvas.getTotalMatrix();
1503         /* transMat.getSkewY() is the sin of the rotation angle(sin0 = 0,sin90 =1 sin180 = 0,sin270 = -1),
1504             if transMat.getSkewY() is not 0 or -1 or 1,the rotation angle is not a multiple of 90,not Stretch*/
1505         if (ROSEN_EQ(transMat.getSkewY(), 0.f) || ROSEN_EQ(transMat.getSkewY(), 1.f) ||
1506             ROSEN_EQ(transMat.getSkewY(), -1.f)) {
1507         } else {
1508             ROSEN_LOGD("rotate degree is not 0 or 90 or 180 or 270,return.");
1509             return;
1510         }
1511         rotateMat.setScale(transMat.getScaleX(), transMat.getScaleY());
1512         rotateMat.setSkewX(transMat.getSkewX());
1513         rotateMat.setSkewY(transMat.getSkewY());
1514         rotateMat.preTranslate(-bounds.x(), -bounds.y());
1515         rotateMat.postTranslate(bounds.x(), bounds.y());
1516 
1517         SkRect transBounds = rotateMat.mapRect(bounds);
1518 
1519         rotateMat.setTranslateX(bounds.x() - transBounds.x());
1520         rotateMat.setTranslateY(bounds.y() - transBounds.y());
1521         if (!rotateMat.invert(&inverseMat)) {
1522             ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch get invert matrix failed.");
1523         }
1524     }
1525 
1526     canvas.save();
1527     canvas.translate(bounds.x(), bounds.y());
1528 
1529     // NOTE: Ensure that EPS is consistent with rs_properties.cpp
1530     constexpr static float EPS = 1e-5f;
1531     if (pixelStretch->x_ > EPS || pixelStretch->y_ > EPS || pixelStretch->z_ > EPS || pixelStretch->w_ > EPS) {
1532         paint.setShader(image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions(), &inverseMat));
1533         canvas.drawRect(
1534             SkRect::MakeXYWH(-pixelStretch->x_, -pixelStretch->y_, scaledBounds.width(), scaledBounds.height()), paint);
1535     } else {
1536         inverseMat.postScale(scaledBounds.width() / bounds.width(), scaledBounds.height() / bounds.height());
1537         paint.setShader(image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions(), &inverseMat));
1538         canvas.translate(-pixelStretch->x_, -pixelStretch->y_);
1539         canvas.drawRect(SkRect::MakeXYWH(pixelStretch->x_, pixelStretch->y_, bounds.width(), bounds.height()), paint);
1540     }
1541     canvas.restore();
1542 }
1543 #else
1544     auto surface = canvas.GetSurface();
1545     if (surface == nullptr) {
1546         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch surface null");
1547         return;
1548     }
1549 
1550     canvas.Save();
1551     auto bounds = RSPropertiesPainter::Rect2DrawingRect(properties.GetBoundsRect());
1552     canvas.ClipRect(bounds, Drawing::ClipOp::INTERSECT, false);
1553     auto tmpBounds = canvas.GetDeviceClipBounds();
1554     Drawing::Rect clipBounds(
1555         tmpBounds.GetLeft(), tmpBounds.GetTop(), tmpBounds.GetRight() - 1, tmpBounds.GetBottom() - 1);
1556     canvas.Restore();
1557 
1558     /*  Calculates the relative coordinates of the clipbounds
1559         with respect to the origin of the current canvas coordinates */
1560     Drawing::Matrix worldToLocalMat;
1561     if (!canvas.GetTotalMatrix().Invert(worldToLocalMat)) {
1562         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch get invert matrix failed.");
1563     }
1564     Drawing::Rect localClipBounds;
1565     Drawing::Rect fClipBounds(clipBounds.GetLeft(), clipBounds.GetTop(), clipBounds.GetRight(),
1566         clipBounds.GetBottom());
1567     if (!worldToLocalMat.MapRect(localClipBounds, fClipBounds)) {
1568         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch map rect failed.");
1569     }
1570 
1571     if (!bounds.Intersect(localClipBounds)) {
1572         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch intersect clipbounds failed");
1573     }
1574 
1575     auto scaledBounds = Drawing::Rect(bounds.GetLeft() - pixelStretch->x_, bounds.GetTop() - pixelStretch->y_,
1576         bounds.GetRight() + pixelStretch->z_, bounds.GetBottom() + pixelStretch->w_);
1577     if (!scaledBounds.IsValid() || !bounds.IsValid() || !clipBounds.IsValid()) {
1578         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch invalid scaled bounds");
1579         return;
1580     }
1581 
1582     Drawing::RectI rectI(static_cast<int>(fClipBounds.GetLeft()), static_cast<int>(fClipBounds.GetTop()),
1583         static_cast<int>(fClipBounds.GetRight()), static_cast<int>(fClipBounds.GetBottom()));
1584     auto image = surface->GetImageSnapshot(rectI);
1585     if (image == nullptr) {
1586         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch image null");
1587         return;
1588     }
1589 
1590     Drawing::Brush brush;
1591     Drawing::Matrix inverseMat, rotateMat;
1592     auto boundsGeo = (properties.GetBoundsGeometry());
1593     if (boundsGeo && !boundsGeo->IsEmpty()) {
1594         auto transMat = canvas.GetTotalMatrix();
1595         /* transMat.getSkewY() is the sin of the rotation angle(sin0 = 0,sin90 =1 sin180 = 0,sin270 = -1),
1596             if transMat.getSkewY() is not 0 or -1 or 1,the rotation angle is not a multiple of 90,not Stretch*/
1597         auto skewY = transMat.Get(Drawing::Matrix::SKEW_Y);
1598         if (ROSEN_EQ(skewY, 0.f) || ROSEN_EQ(skewY, 1.f) ||
1599             ROSEN_EQ(skewY, -1.f)) {
1600         } else {
1601             ROSEN_LOGD("rotate degree is not 0 or 90 or 180 or 270,return.");
1602             return;
1603         }
1604         rotateMat.SetScale(transMat.Get(Drawing::Matrix::SCALE_X), transMat.Get(Drawing::Matrix::SCALE_Y));
1605         rotateMat.Set(Drawing::Matrix::SKEW_X, transMat.Get(Drawing::Matrix::SKEW_X));
1606         rotateMat.Set(Drawing::Matrix::SKEW_Y, transMat.Get(Drawing::Matrix::SKEW_Y));
1607         rotateMat.PreTranslate(-bounds.GetLeft(), -bounds.GetTop());
1608         rotateMat.PostTranslate(bounds.GetLeft(), bounds.GetTop());
1609 
1610         Drawing::Rect transBounds;
1611         rotateMat.MapRect(transBounds, bounds);
1612         rotateMat.Set(Drawing::Matrix::TRANS_X, bounds.GetLeft() - transBounds.GetLeft());
1613         rotateMat.Set(Drawing::Matrix::TRANS_Y, bounds.GetTop() - transBounds.GetTop());
1614         if (!rotateMat.Invert(inverseMat)) {
1615             ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch get invert matrix failed.");
1616         }
1617     }
1618 
1619     canvas.Save();
1620     canvas.Translate(bounds.GetLeft(), bounds.GetTop());
1621     Drawing::SamplingOptions samplingOptions;
1622     constexpr static float EPS = 1e-5f;
1623     if (pixelStretch->x_ > EPS || pixelStretch->y_ > EPS || pixelStretch->z_ > EPS || pixelStretch->w_ > EPS) {
1624         brush.SetShaderEffect(Drawing::ShaderEffect::CreateImageShader(
1625             *image, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, samplingOptions, inverseMat));
1626         canvas.AttachBrush(brush);
1627         canvas.DrawRect(Drawing::Rect(-pixelStretch->x_, -pixelStretch->y_,
1628             -pixelStretch->x_ + scaledBounds.GetWidth(), -pixelStretch->y_ + scaledBounds.GetHeight()));
1629         canvas.DetachBrush();
1630     } else {
1631         inverseMat.PostScale(scaledBounds.GetWidth() / bounds.GetWidth(), scaledBounds.GetHeight() / bounds.GetHeight());
1632         brush.SetShaderEffect(Drawing::ShaderEffect::CreateImageShader(
1633             *image, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, samplingOptions, inverseMat));
1634 
1635         canvas.Translate(-pixelStretch->x_, -pixelStretch->y_);
1636         canvas.AttachBrush(brush);
1637         canvas.DrawRect(Drawing::Rect(pixelStretch->x_, pixelStretch->y_,
1638             pixelStretch->x_ + bounds.GetWidth(), pixelStretch->y_ + bounds.GetHeight()));
1639         canvas.DetachBrush();
1640     }
1641     canvas.Restore();
1642 }
1643 #endif
1644 
1645 #ifndef USE_ROSEN_DRAWING
CalcAverageColor(sk_sp<SkImage> imageSnapshot)1646 SkColor RSPropertiesPainter::CalcAverageColor(sk_sp<SkImage> imageSnapshot)
1647 {
1648     // create a 1x1 SkPixmap
1649     uint32_t pixel[1] = { 0 };
1650     auto single_pixel_info = SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
1651     SkPixmap single_pixel(single_pixel_info, pixel, single_pixel_info.bytesPerPixel());
1652 
1653     // resize snapshot to 1x1 to calculate average color
1654     // kMedium_SkFilterQuality will do bilerp + mipmaps for down-scaling, we can easily get average color
1655     imageSnapshot->scalePixels(single_pixel, SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear));
1656     // convert color format and return average color
1657     return SkColor4f::FromBytes_RGBA(pixel[0]).toSkColor();
1658 }
1659 #else
CalcAverageColor(std::shared_ptr<Drawing::Image> imageSnapshot)1660 Drawing::ColorQuad RSPropertiesPainter::CalcAverageColor(std::shared_ptr<Drawing::Image> imageSnapshot)
1661 {
1662     // create a 1x1 SkPixmap
1663     uint32_t pixel[1] = { 0 };
1664     auto single_pixel_info = SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
1665     SkPixmap single_pixel(single_pixel_info, pixel, single_pixel_info.bytesPerPixel());
1666 
1667     // resize snapshot to 1x1 to calculate average color
1668     // kMedium_SkFilterQuality will do bilerp + mipmaps for down-scaling, we can easily get average color
1669     imageSnapshot->ExportSkImage()->scalePixels(
1670         single_pixel, SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear));
1671     // convert color format and return average color
1672     return SkColor4f::FromBytes_RGBA(pixel[0]).toSkColor();
1673 }
1674 #endif
1675 
GetAndResetBlurCnt()1676 int RSPropertiesPainter::GetAndResetBlurCnt()
1677 {
1678     auto blurCnt = g_blurCnt;
1679     g_blurCnt = 0;
1680     return blurCnt;
1681 }
1682 
DrawBackground(const RSProperties & properties,RSPaintFilterCanvas & canvas,bool isAntiAlias,bool isSurfaceView)1683 void RSPropertiesPainter::DrawBackground(const RSProperties& properties, RSPaintFilterCanvas& canvas,
1684     bool isAntiAlias, bool isSurfaceView)
1685 {
1686     // only disable antialias when background is rect and g_forceBgAntiAlias is false
1687     bool antiAlias = g_forceBgAntiAlias || !properties.GetCornerRadius().IsZero();
1688     // clip
1689 #ifndef USE_ROSEN_DRAWING
1690     if (properties.GetClipBounds() != nullptr) {
1691         canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), antiAlias);
1692     } else if (properties.GetClipToBounds()) {
1693         // In NEW_SKIA version, L476 code will cause crash if the second parameter is true.
1694         // so isAntiAlias is false only the method is called in ProcessAnimatePropertyBeforeChildren().
1695         if (properties.GetCornerRadius().IsZero()) {
1696             canvas.clipRect(Rect2SkRect(properties.GetBoundsRect()), isAntiAlias);
1697         } else {
1698             canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), antiAlias);
1699         }
1700     } else if (properties.GetClipToRRect()) {
1701         canvas.clipRRect(RRect2SkRRect(properties.GetClipRRect()), antiAlias);
1702     }
1703     // paint backgroundColor
1704     SkPaint paint;
1705     paint.setAntiAlias(antiAlias);
1706     auto bgColor = properties.GetBackgroundColor();
1707     if (bgColor != RgbPalette::Transparent() && !isSurfaceView) {
1708         paint.setColor(bgColor.AsArgbInt());
1709         canvas.drawRRect(RRect2SkRRect(properties.GetInnerRRect()), paint);
1710     }
1711     if (const auto& bgShader = properties.GetBackgroundShader()) {
1712         SkAutoCanvasRestore acr(&canvas, true);
1713         canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), antiAlias);
1714         paint.setShader(bgShader->GetSkShader());
1715         canvas.drawPaint(paint);
1716     }
1717     if (const auto& bgImage = properties.GetBgImage()) {
1718         SkAutoCanvasRestore acr(&canvas, true);
1719         canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), antiAlias);
1720         auto boundsRect = Rect2SkRect(properties.GetBoundsRect());
1721         bgImage->SetDstRect(properties.GetBgImageRect());
1722         bgImage->CanvasDrawImage(canvas, boundsRect, SkSamplingOptions(), paint, true);
1723     }
1724 #else
1725     if (properties.GetClipBounds() != nullptr) {
1726         auto& path = properties.GetClipBounds()->GetDrawingPath();
1727         canvas.ClipPath(path, Drawing::ClipOp::INTERSECT, antiAlias);
1728     } else if (properties.GetClipToBounds()) {
1729         if (properties.GetCornerRadius().IsZero()) {
1730             canvas.ClipRect(Rect2DrawingRect(properties.GetBoundsRect()), Drawing::ClipOp::INTERSECT, isAntiAlias);
1731         } else {
1732             canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, antiAlias);
1733         }
1734     } else if (properties.GetClipToRRect()) {
1735         canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetClipRRect()), Drawing::ClipOp::INTERSECT, antiAlias);
1736     }
1737     // paint backgroundColor
1738     Drawing::Brush brush;
1739     brush.SetAntiAlias(antiAlias);
1740     auto bgColor = properties.GetBackgroundColor();
1741     if (bgColor != RgbPalette::Transparent() && !isSurfaceView) {
1742         brush.SetColor(Drawing::Color(bgColor.AsArgbInt()));
1743         canvas.AttachBrush(brush);
1744         canvas.DrawRoundRect(RRect2DrawingRRect(properties.GetRRect()));
1745         canvas.DetachBrush();
1746     }
1747     if (const auto& bgShader = properties.GetBackgroundShader()) {
1748         Drawing::AutoCanvasRestore acr(canvas, true);
1749         canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, antiAlias);
1750         auto shaderEffect = bgShader->GetDrawingShader();
1751         brush.SetShaderEffect(shaderEffect);
1752         canvas.DrawBackground(brush);
1753     }
1754     if (const auto& bgImage = properties.GetBgImage()) {
1755         Drawing::AutoCanvasRestore acr(canvas, true);
1756         canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, antiAlias);
1757         auto boundsRect = Rect2DrawingRect(properties.GetBoundsRect());
1758         bgImage->SetDstRect(properties.GetBgImageRect());
1759         canvas.AttachBrush(brush);
1760         bgImage->CanvasDrawImage(canvas, boundsRect, Drawing::SamplingOptions(), true);
1761         canvas.DetachBrush();
1762     }
1763 #endif
1764 }
1765 
SetBgAntiAlias(bool forceBgAntiAlias)1766 void RSPropertiesPainter::SetBgAntiAlias(bool forceBgAntiAlias)
1767 {
1768     g_forceBgAntiAlias = forceBgAntiAlias;
1769 }
1770 
GetBgAntiAlias()1771 bool RSPropertiesPainter::GetBgAntiAlias()
1772 {
1773     return g_forceBgAntiAlias;
1774 }
1775 
1776 #ifndef USE_ROSEN_DRAWING
DrawFrame(const RSProperties & properties,RSPaintFilterCanvas & canvas,DrawCmdListPtr & cmds)1777 void RSPropertiesPainter::DrawFrame(const RSProperties& properties, RSPaintFilterCanvas& canvas, DrawCmdListPtr& cmds)
1778 {
1779     if (cmds == nullptr) {
1780         return;
1781     }
1782     SkMatrix mat;
1783     if (GetGravityMatrix(
1784             properties.GetFrameGravity(), properties.GetFrameRect(), cmds->GetWidth(), cmds->GetHeight(), mat)) {
1785         canvas.concat(mat);
1786     }
1787     auto frameRect = Rect2SkRect(properties.GetFrameRect());
1788     cmds->Playback(canvas, &frameRect);
1789 }
1790 #else
DrawFrame(const RSProperties & properties,RSPaintFilterCanvas & canvas,Drawing::DrawCmdListPtr & cmds)1791 void RSPropertiesPainter::DrawFrame(
1792     const RSProperties& properties, RSPaintFilterCanvas& canvas, Drawing::DrawCmdListPtr& cmds)
1793 {
1794     if (cmds == nullptr) {
1795         return;
1796     }
1797     Drawing::Matrix mat;
1798     if (GetGravityMatrix(
1799             properties.GetFrameGravity(), properties.GetFrameRect(), cmds->GetWidth(), cmds->GetHeight(), mat)) {
1800         canvas.ConcatMatrix(mat);
1801     }
1802     auto frameRect = Rect2DrawingRect(properties.GetFrameRect());
1803     cmds->Playback(canvas, &frameRect);
1804 }
1805 #endif
1806 
GetRRectForDrawingBorder(const RSProperties & properties,const std::shared_ptr<RSBorder> & border,const bool & isOutline)1807 RRect RSPropertiesPainter::GetRRectForDrawingBorder(const RSProperties& properties,
1808     const std::shared_ptr<RSBorder>& border, const bool& isOutline)
1809 {
1810     if (!border) {
1811         return RRect();
1812     }
1813 
1814     return isOutline ?
1815         RRect(properties.GetRRect().rect_.MakeOutset(border->GetWidthFour()), border->GetRadiusFour()) :
1816         properties.GetRRect();
1817 }
1818 
GetInnerRRectForDrawingBorder(const RSProperties & properties,const std::shared_ptr<RSBorder> & border,const bool & isOutline)1819 RRect RSPropertiesPainter::GetInnerRRectForDrawingBorder(const RSProperties& properties,
1820     const std::shared_ptr<RSBorder>& border, const bool& isOutline)
1821 {
1822     if (!border) {
1823         return RRect();
1824     }
1825     return isOutline ? properties.GetRRect() : properties.GetInnerRRect();
1826 }
1827 
1828 #ifndef USE_ROSEN_DRAWING
1829 static std::shared_ptr<SkRuntimeShaderBuilder> phongShaderBuilder;
1830 
GetPhongShaderBuilder()1831 const std::shared_ptr<SkRuntimeShaderBuilder>& RSPropertiesPainter::GetPhongShaderBuilder()
1832 {
1833     if (phongShaderBuilder) {
1834         return phongShaderBuilder;
1835     }
1836     sk_sp<SkRuntimeEffect> lightEffect_;
1837     SkString lightString(R"(
1838         uniform mat4 lightPos;
1839         uniform mat4 viewPos;
1840         uniform vec4 specularStrength;
1841 
1842         half4 main(float2 fragCoord) {
1843             vec3 lightColor = vec3(1.0, 1.0, 1.0);
1844             float ambientStrength = 0.0;
1845             vec3 diffuseColor = vec3(1.0, 1.0, 1.0);
1846             float diffuseStrength = 0.0;
1847             vec3 specularColor = vec3(1.0, 1.0, 1.0);
1848             float shininess = 8.0;
1849             half4 fragColor;
1850             vec4 NormalMap = vec4(0.0, 0.0, 1.0, 0.0);
1851             // ambient
1852             vec4 ambient = lightColor.rgb1 * ambientStrength;
1853             vec3 norm = normalize(NormalMap.rgb);
1854 
1855             for (int i = 0; i < 4; i++) {
1856                 if (abs(specularStrength[i]) > 0.01) {
1857                     vec3 lightDir = normalize(vec3(lightPos[i].xy - fragCoord, lightPos[i].z));
1858                     float diff = max(dot(norm, lightDir), 0.0);
1859                     vec4 diffuse = diff * lightColor.rgb1;
1860                     vec3 viewDir = normalize(vec3(viewPos[i].xy - fragCoord, viewPos[i].z)); // view vector
1861                     vec3 halfwayDir = normalize(lightDir + viewDir); // half vector
1862                     float spec = pow(max(dot(norm, halfwayDir), 0.0), shininess); // exponential relationship of angle
1863                     vec4 specular = lightColor.rgb1 * spec; // multiply color of incident light
1864                     vec4 o = ambient + diffuse * diffuseStrength * diffuseColor.rgb1; // diffuse reflection
1865                     fragColor = fragColor + o + specular * specularStrength[i] * specularColor.rgb1;
1866                 }
1867             }
1868             return half4(fragColor);
1869         }
1870     )");
1871     auto [lightEffect, error] = SkRuntimeEffect::MakeForShader(lightString);
1872     if (!lightEffect) {
1873         ROSEN_LOGE("light effect errro: %{public}s", error.c_str());
1874         return phongShaderBuilder;
1875     }
1876     lightEffect_ = std::move(lightEffect);
1877     phongShaderBuilder = std::make_shared<SkRuntimeShaderBuilder>(lightEffect_);
1878     return phongShaderBuilder;
1879 }
1880 #else
1881 static std::shared_ptr<Drawing::RuntimeShaderBuilder> phongShaderBuilder = nullptr;
1882 
GetPhongShaderBuilder()1883 const std::shared_ptr<Drawing::RuntimeShaderBuilder>& RSPropertiesPainter::GetPhongShaderBuilder()
1884 {
1885     if (phongShaderBuilder) {
1886         return phongShaderBuilder;
1887     }
1888     std::shared_ptr<Drawing::RuntimeEffect> lightEffect_;
1889     std::string lightString(R"(
1890         uniform mat4 lightPos;
1891         uniform mat4 viewPos;
1892         uniform vec4 specularStrength;
1893 
1894         half4 main(float2 fragCoord) {
1895             vec3 lightColor = vec3(1.0, 1.0, 1.0);
1896             float ambientStrength = 0.0;
1897             vec3 diffuseColor = vec3(1.0, 1.0, 1.0);
1898             float diffuseStrength = 0.0;
1899             vec3 specularColor = vec3(1.0, 1.0, 1.0);
1900             float shininess = 8.0;
1901             half4 fragColor;
1902             vec4 NormalMap = vec4(0.0, 0.0, 1.0, 0.0);
1903             // ambient
1904             vec4 ambient = lightColor.rgb1 * ambientStrength;
1905             vec3 norm = normalize(NormalMap.rgb);
1906 
1907             for (int i = 0; i < 4; i++) {
1908                 if (abs(specularStrength[i]) > 0.01) {
1909                     vec3 lightDir = normalize(vec3(lightPos[i].xy - fragCoord, lightPos[i].z));
1910                     float diff = max(dot(norm, lightDir), 0.0);
1911                     vec4 diffuse = diff * lightColor.rgb1;
1912                     vec3 viewDir = normalize(vec3(viewPos[i].xy - fragCoord, viewPos[i].z)); // view vector
1913                     vec3 halfwayDir = normalize(lightDir + viewDir); // half vector
1914                     float spec = pow(max(dot(norm, halfwayDir), 0.0), shininess); // exponential relationship of angle
1915                     vec4 specular = lightColor.rgb1 * spec; // multiply color of incident light
1916                     vec4 o = ambient + diffuse * diffuseStrength * diffuseColor.rgb1; // diffuse reflection
1917                     fragColor = fragColor + o + specular * specularStrength[i] * specularColor.rgb1;
1918                 }
1919             }
1920             return half4(fragColor);
1921         }
1922     )");
1923     std::shared_ptr<Drawing::RuntimeEffect> lightEffect = Drawing::RuntimeEffect::CreateForShader(lightString);
1924     if (!lightEffect) {
1925         ROSEN_LOGE("light effect error");
1926         return phongShaderBuilder;
1927     }
1928     lightEffect_ = std::move(lightEffect);
1929     phongShaderBuilder = std::make_shared<Drawing::RuntimeShaderBuilder>(lightEffect_);
1930     return phongShaderBuilder;
1931 }
1932 #endif
1933 
1934 #ifndef USE_ROSEN_DRAWING
DrawLight(const RSProperties & properties,SkCanvas & canvas)1935 void RSPropertiesPainter::DrawLight(const RSProperties& properties, SkCanvas& canvas)
1936 #else
1937 void RSPropertiesPainter::DrawLight(const RSProperties& properties, Drawing::Canvas& canvas)
1938 #endif
1939 {
1940     auto lightBuilder = GetPhongShaderBuilder();
1941     if (!lightBuilder) {
1942         return;
1943     }
1944     const auto& lightSources = properties.GetIlluminated()->GetLightSources();
1945     if (lightSources.empty()) {
1946         ROSEN_LOGD("RSPropertiesPainter::DrawLight lightSourceList is empty!");
1947         return;
1948     }
1949     const auto& geoPtr = (properties.GetBoundsGeometry());
1950     if (!geoPtr || geoPtr->IsEmpty()) {
1951         return;
1952     }
1953     DrawLightInner(properties, canvas, lightBuilder, lightSources, geoPtr);
1954 }
1955 
1956 #ifndef USE_ROSEN_DRAWING
DrawLightInner(const RSProperties & properties,SkCanvas & canvas,std::shared_ptr<SkRuntimeShaderBuilder> & lightBuilder,const std::unordered_set<std::shared_ptr<RSLightSource>> & lightSources,const std::shared_ptr<RSObjAbsGeometry> & geoPtr)1957 void RSPropertiesPainter::DrawLightInner(const RSProperties& properties, SkCanvas& canvas,
1958     std::shared_ptr<SkRuntimeShaderBuilder>& lightBuilder,
1959     const std::unordered_set<std::shared_ptr<RSLightSource>>& lightSources,
1960     const std::shared_ptr<RSObjAbsGeometry>& geoPtr)
1961 {
1962     auto iter = lightSources.begin();
1963     auto cnt = 0;
1964     SkM44 lightPositionMatrix;
1965     SkM44 viewPosMatrix;
1966     SkV4 lightIntensityV4;
1967     constexpr int MAX_LIGHT_SOUCES = 4;
1968     while (iter != lightSources.end() && cnt < MAX_LIGHT_SOUCES) {
1969         auto lightPos = RSPointLightManager::Instance()->CalculateLightPosForIlluminated((*iter), geoPtr);
1970         auto lightIntensity = (*iter)->GetLightIntensity();
1971         auto lightPositionV4 = SkV4 { lightPos.x_, lightPos.y_, lightPos.z_, lightPos.w_ };
1972         auto viewPosV4 = SkV4 { lightPos.x_, lightPos.y_, lightPos.z_, lightPos.w_ };
1973         lightIntensityV4[cnt] = lightIntensity;
1974         lightPositionMatrix.setCol(cnt, lightPositionV4);
1975         viewPosMatrix.setCol(cnt, viewPosV4);
1976         iter++;
1977         cnt++;
1978     }
1979     lightBuilder->uniform("lightPos") = lightPositionMatrix;
1980     lightBuilder->uniform("viewPos") = viewPosMatrix;
1981     SkPaint paint;
1982     paint.setAntiAlias(true);
1983     auto illuminatedType = properties.GetIlluminated()->GetIlluminatedType();
1984     ROSEN_LOGD("RSPropertiesPainter::DrawLight illuminatedType:%{public}d", illuminatedType);
1985     if (illuminatedType == IlluminatedType::CONTENT) {
1986         DrawContentLight(properties, canvas, lightBuilder, paint, lightIntensityV4);
1987     } else if (illuminatedType == IlluminatedType::BORDER) {
1988         DrawBorderLight(properties, canvas, lightBuilder, paint, lightIntensityV4);
1989     } else if (illuminatedType == IlluminatedType::BORDER_CONTENT) {
1990         DrawContentLight(properties, canvas, lightBuilder, paint, lightIntensityV4);
1991         DrawBorderLight(properties, canvas, lightBuilder, paint, lightIntensityV4);
1992     }
1993 }
1994 #else
DrawLightInner(const RSProperties & properties,Drawing::Canvas & canvas,std::shared_ptr<Drawing::RuntimeShaderBuilder> & lightBuilder,const std::unordered_set<std::shared_ptr<RSLightSource>> & lightSources,const std::shared_ptr<RSObjAbsGeometry> & geoPtr)1995 void RSPropertiesPainter::DrawLightInner(const RSProperties& properties, Drawing::Canvas& canvas,
1996     std::shared_ptr<Drawing::RuntimeShaderBuilder>& lightBuilder,
1997     const std::unordered_set<std::shared_ptr<RSLightSource>>& lightSources,
1998     const std::shared_ptr<RSObjAbsGeometry>& geoPtr)
1999 {
2000     auto iter = lightSources.begin();
2001     auto cnt = 0;
2002     Drawing::Matrix44 lightPositionMatrix;
2003     Drawing::Matrix44 viewPosMatrix;
2004     Vector4f lightIntensityV4;
2005     constexpr int MAX_LIGHT_SOUCES = 4;
2006     while (iter != lightSources.end() && cnt < MAX_LIGHT_SOUCES) {
2007         auto lightPos = RSPointLightManager::Instance()->CalculateLightPosForIlluminated((*iter), geoPtr);
2008         auto lightIntensity = (*iter)->GetLightIntensity();
2009         lightIntensityV4[cnt] = lightIntensity;
2010         lightPositionMatrix.SetCol(cnt, lightPos.x_, lightPos.y_, lightPos.z_, lightPos.w_);
2011         viewPosMatrix.SetCol(cnt, lightPos.x_, lightPos.y_, lightPos.z_, lightPos.w_);
2012         iter++;
2013         cnt++;
2014     }
2015     lightBuilder->SetUniform("lightPos", lightPositionMatrix);
2016     lightBuilder->SetUniform("viewPos", viewPosMatrix);
2017     Drawing::Pen pen;
2018     Drawing::Brush brush;
2019     pen.SetAntiAlias(true);
2020     brush.SetAntiAlias(true);
2021     auto illuminatedType = properties.GetIlluminated()->GetIlluminatedType();
2022     ROSEN_LOGD("RSPropertiesPainter::DrawLight illuminatedType:%{public}d", illuminatedType);
2023     if (illuminatedType == IlluminatedType::CONTENT) {
2024         DrawContentLight(properties, canvas, lightBuilder, brush, lightIntensityV4);
2025     } else if (illuminatedType == IlluminatedType::BORDER) {
2026         DrawBorderLight(properties, canvas, lightBuilder, pen, lightIntensityV4);
2027     } else if (illuminatedType == IlluminatedType::BORDER_CONTENT) {
2028         DrawContentLight(properties, canvas, lightBuilder, brush, lightIntensityV4);
2029         DrawBorderLight(properties, canvas, lightBuilder, pen, lightIntensityV4);
2030     }
2031 }
2032 #endif
2033 
2034 #ifndef USE_ROSEN_DRAWING
DrawContentLight(const RSProperties & properties,SkCanvas & canvas,std::shared_ptr<SkRuntimeShaderBuilder> & lightBuilder,SkPaint & paint,SkV4 & lightIntensity)2035 void RSPropertiesPainter::DrawContentLight(const RSProperties& properties, SkCanvas& canvas,
2036     std::shared_ptr<SkRuntimeShaderBuilder>& lightBuilder, SkPaint& paint, SkV4& lightIntensity)
2037 #else
2038 void RSPropertiesPainter::DrawContentLight(const RSProperties& properties, Drawing::Canvas& canvas,
2039     std::shared_ptr<Drawing::RuntimeShaderBuilder>& lightBuilder, Drawing::Brush& brush, Vector4f& lightIntensity)
2040 #endif
2041 {
2042     // content light
2043 #ifndef USE_ROSEN_DRAWING
2044     sk_sp<SkShader> shader;
2045 #else
2046     std::shared_ptr<Drawing::ShaderEffect> shader;
2047 #endif
2048     auto contentStrength = lightIntensity * 0.3f;
2049 #ifndef USE_ROSEN_DRAWING
2050     lightBuilder->uniform("specularStrength") = contentStrength;
2051     shader = lightBuilder->makeShader(nullptr, false);
2052     paint.setShader(shader);
2053     canvas.drawRRect(RRect2SkRRect(properties.GetRRect()), paint);
2054 #else
2055     lightBuilder->SetUniformVec4("specularStrength", contentStrength.x_,
2056         contentStrength.y_, contentStrength.z_, contentStrength.w_);
2057     shader = lightBuilder->MakeShader(nullptr, false);
2058     brush.SetShaderEffect(shader);
2059     canvas.AttachBrush(brush);
2060     canvas.DrawRoundRect(RRect2DrawingRRect(properties.GetRRect()));
2061     canvas.DetachBrush();
2062 #endif
2063 }
2064 
2065 #ifndef USE_ROSEN_DRAWING
DrawBorderLight(const RSProperties & properties,SkCanvas & canvas,std::shared_ptr<SkRuntimeShaderBuilder> & lightBuilder,SkPaint & paint,SkV4 & lightIntensity)2066 void RSPropertiesPainter::DrawBorderLight(const RSProperties& properties, SkCanvas& canvas,
2067     std::shared_ptr<SkRuntimeShaderBuilder>& lightBuilder, SkPaint& paint, SkV4& lightIntensity)
2068 #else
2069 void RSPropertiesPainter::DrawBorderLight(const RSProperties& properties, Drawing::Canvas& canvas,
2070     std::shared_ptr<Drawing::RuntimeShaderBuilder>& lightBuilder, Drawing::Pen& pen, Vector4f& lightIntensity)
2071 #endif
2072 {
2073     // border light
2074 #ifndef USE_ROSEN_DRAWING
2075     sk_sp<SkShader> shader;
2076 #else
2077     std::shared_ptr<Drawing::ShaderEffect> shader;
2078 #endif
2079 #ifndef USE_ROSEN_DRAWING
2080     lightBuilder->uniform("specularStrength") = lightIntensity;
2081     shader = lightBuilder->makeShader(nullptr, false);
2082     paint.setShader(shader);
2083     float borderWidth = std::ceil(properties.GetIlluminatedBorderWidth());
2084     paint.setStrokeWidth(borderWidth);
2085     paint.setStyle(SkPaint::Style::kStroke_Style);
2086 #else
2087     lightBuilder->SetUniformVec4("specularStrength", lightIntensity.x_,
2088         lightIntensity.y_, lightIntensity.z_, lightIntensity.w_);
2089     shader = lightBuilder->MakeShader(nullptr, false);
2090     pen.SetShaderEffect(shader);
2091     float borderWidth = std::ceil(properties.GetIlluminatedBorderWidth());
2092     pen.SetWidth(borderWidth);
2093 #endif
2094     auto borderRect = properties.GetRRect().rect_;
2095     float borderRadius = properties.GetRRect().radius_[0].x_;
2096     auto borderRRect = RRect(RectF(borderRect.left_ + borderWidth / 2.0f, borderRect.top_ + borderWidth / 2.0f,
2097         borderRect.width_ - borderWidth, borderRect.height_ - borderWidth),
2098         borderRadius - borderWidth / 2.0f, borderRadius - borderWidth / 2.0f);
2099 #ifndef USE_ROSEN_DRAWING
2100     canvas.drawRRect(RRect2SkRRect(borderRRect), paint);
2101 #else
2102     canvas.AttachPen(pen);
2103     canvas.DrawRoundRect(RRect2DrawingRRect(borderRRect));
2104     canvas.DetachPen();
2105 #endif
2106 }
2107 
2108 #ifndef USE_ROSEN_DRAWING
DrawBorderBase(const RSProperties & properties,SkCanvas & canvas,const std::shared_ptr<RSBorder> & border,const bool & isOutline)2109 void RSPropertiesPainter::DrawBorderBase(const RSProperties& properties, SkCanvas& canvas,
2110     const std::shared_ptr<RSBorder>& border, const bool& isOutline)
2111 {
2112     if (!border || !border->HasBorder()) {
2113         return;
2114     }
2115 
2116     SkPaint paint;
2117     paint.setAntiAlias(true);
2118     if (border->ApplyFillStyle(paint)) {
2119         auto skRRect = RRect2SkRRect(GetRRectForDrawingBorder(
2120             properties, border, isOutline));
2121         auto innerSkRRect = RRect2SkRRect(GetInnerRRectForDrawingBorder(
2122             properties, border, isOutline));
2123         canvas.drawDRRect(skRRect, innerSkRRect, paint);
2124     } else {
2125         bool isZero = isOutline ? border->GetRadiusFour().IsZero() : properties.GetCornerRadius().IsZero();
2126         if (isZero && border->ApplyFourLine(paint)) {
2127             RectF rectf = isOutline ?
2128                 properties.GetBoundsRect().MakeOutset(border->GetWidthFour()) : properties.GetBoundsRect();
2129             border->PaintFourLine(canvas, paint, rectf);
2130         } else if (border->ApplyPathStyle(paint)) {
2131             auto borderWidth = border->GetWidth();
2132             RRect rrect = GetRRectForDrawingBorder(properties, border, isOutline);
2133             rrect.rect_.width_ -= borderWidth;
2134             rrect.rect_.height_ -= borderWidth;
2135             rrect.rect_.Move(borderWidth / PARAM_DOUBLE, borderWidth / PARAM_DOUBLE);
2136             SkPath borderPath;
2137             borderPath.addRRect(RRect2SkRRect(rrect));
2138             canvas.drawPath(borderPath, paint);
2139         } else {
2140             SkAutoCanvasRestore acr(&canvas, true);
2141             auto rrect = RRect2SkRRect(GetRRectForDrawingBorder(
2142                 properties, border, isOutline));
2143             canvas.clipRRect(rrect, true);
2144             auto innerSkRRect = RRect2SkRRect(GetInnerRRectForDrawingBorder(
2145                 properties, border, isOutline));
2146             canvas.clipRRect(innerSkRRect, SkClipOp::kDifference, true);
2147             paint.setStyle(SkPaint::Style::kStroke_Style);
2148             SkPoint center = { innerSkRRect.rect().centerX(), innerSkRRect.rect().centerY() };
2149             border->PaintTopPath(canvas, paint, rrect, center);
2150             border->PaintRightPath(canvas, paint, rrect, center);
2151             border->PaintBottomPath(canvas, paint, rrect, center);
2152             border->PaintLeftPath(canvas, paint, rrect, center);
2153         }
2154     }
2155 }
2156 #else
DrawBorderBase(const RSProperties & properties,Drawing::Canvas & canvas,const std::shared_ptr<RSBorder> & border,const bool & isOutline)2157 void RSPropertiesPainter::DrawBorderBase(const RSProperties& properties, Drawing::Canvas& canvas,
2158     const std::shared_ptr<RSBorder>& border, const bool& isOutline)
2159 {
2160     if (!border || !border->HasBorder()) {
2161         return;
2162     }
2163 
2164     Drawing::Brush brush;
2165     Drawing::Pen pen;
2166     brush.SetAntiAlias(true);
2167     pen.SetAntiAlias(true);
2168     if (border->ApplyFillStyle(brush)) {
2169         auto roundRect = RRect2DrawingRRect(GetRRectForDrawingBorder(properties, border, isOutline));
2170         auto innerRoundRect = RRect2DrawingRRect(GetInnerRRectForDrawingBorder(
2171             properties, border, isOutline));
2172         canvas.AttachBrush(brush);
2173         canvas.DrawNestedRoundRect(roundRect, innerRoundRect);
2174         canvas.DetachBrush();
2175     } else {
2176         bool isZero = isOutline ? border->GetRadiusFour().IsZero() : properties.GetCornerRadius().IsZero();
2177         if (isZero && border->ApplyFourLine(pen)) {
2178             RectF rectf = isOutline ?
2179                 properties.GetBoundsRect().MakeOutset(border->GetWidthFour()) : properties.GetBoundsRect();
2180             border->PaintFourLine(canvas, pen, rectf);
2181         } else if (border->ApplyPathStyle(pen)) {
2182             auto borderWidth = border->GetWidth();
2183             RRect rrect = GetRRectForDrawingBorder(properties, border, isOutline);
2184             rrect.rect_.width_ -= borderWidth;
2185             rrect.rect_.height_ -= borderWidth;
2186             rrect.rect_.Move(borderWidth / PARAM_DOUBLE, borderWidth / PARAM_DOUBLE);
2187             Drawing::Path borderPath;
2188             borderPath.AddRoundRect(RRect2DrawingRRect(rrect));
2189             canvas.AttachPen(pen);
2190             canvas.DrawPath(borderPath);
2191             canvas.DetachPen();
2192         } else {
2193             Drawing::AutoCanvasRestore acr(canvas, true);
2194             auto rrect = RRect2DrawingRRect(GetRRectForDrawingBorder(properties, border, isOutline));
2195             canvas.ClipRoundRect(rrect, Drawing::ClipOp::INTERSECT, true);
2196             auto innerRoundRect = RRect2DrawingRRect(GetInnerRRectForDrawingBorder(
2197                 properties, border, isOutline));
2198             canvas.ClipRoundRect(innerRoundRect, Drawing::ClipOp::DIFFERENCE, true);
2199             Drawing::scalar centerX = innerRoundRect.GetRect().GetLeft() + innerRoundRect.GetRect().GetWidth() / 2;
2200             Drawing::scalar centerY = innerRoundRect.GetRect().GetTop() + innerRoundRect.GetRect().GetHeight() / 2;
2201             Drawing::Point center = { centerX, centerY };
2202             auto rect = rrect.GetRect();
2203             Drawing::SaveLayerOps slr(&rect, nullptr);
2204             canvas.SaveLayer(slr);
2205             border->PaintTopPath(canvas, pen, rrect, center);
2206             border->PaintRightPath(canvas, pen, rrect, center);
2207             border->PaintBottomPath(canvas, pen, rrect, center);
2208             border->PaintLeftPath(canvas, pen, rrect, center);
2209         }
2210     }
2211 }
2212 #endif
2213 
2214 #ifndef USE_ROSEN_DRAWING
DrawBorder(const RSProperties & properties,SkCanvas & canvas)2215 void RSPropertiesPainter::DrawBorder(const RSProperties& properties, SkCanvas& canvas)
2216 #else
2217 void RSPropertiesPainter::DrawBorder(const RSProperties& properties, Drawing::Canvas& canvas)
2218 #endif
2219 {
2220     auto border = properties.GetBorder();
2221     if (border && border->HasBorder()) {
2222         DrawBorderBase(properties, canvas, border, false);
2223     }
2224 }
2225 
GetOutlineDirtyRect(RectI & dirtyOutline,const RSProperties & properties,const bool & isAbsCoordinate)2226 void RSPropertiesPainter::GetOutlineDirtyRect(RectI& dirtyOutline,
2227     const RSProperties& properties, const bool& isAbsCoordinate)
2228 {
2229     auto outline = properties.GetOutline();
2230     if (!outline || !outline->HasBorder()) {
2231         return;
2232     }
2233 
2234     auto geoPtr = properties.GetBoundsGeometry();
2235 #ifndef USE_ROSEN_DRAWING
2236     SkMatrix matrix = (geoPtr && isAbsCoordinate) ? geoPtr->GetAbsMatrix() : SkMatrix::I();
2237     auto skRect = Rect2SkRect(GetRRectForDrawingBorder(properties, outline, true).rect_);
2238     matrix.MapRect(&skRect);
2239     dirtyOutline.left_ = std::floor(skRect.left());
2240     dirtyOutline.top_ = std::floor(skRect.top());
2241     dirtyOutline.width_ = std::ceil(skRect.width()) + PARAM_DOUBLE;
2242     dirtyOutline.height_ = std::ceil(skRect.height()) + PARAM_DOUBLE;
2243 #else
2244     Drawing::Matrix matrix = (geoPtr && isAbsCoordinate) ? geoPtr->GetAbsMatrix() : Drawing::Matrix();
2245     auto drawingRect = Rect2DrawingRect(GetRRectForDrawingBorder(properties, outline, true).rect_);
2246     matrix.MapRect(drawingRect, drawingRect);
2247     dirtyOutline.left_ = std::floor(drawingRect.GetLeft());
2248     dirtyOutline.top_ = std::floor(drawingRect.GetTop());
2249     dirtyOutline.width_ = std::ceil(drawingRect.GetWidth()) + PARAM_DOUBLE;
2250     dirtyOutline.height_ = std::ceil(drawingRect.GetHeight()) + PARAM_DOUBLE;
2251 #endif
2252 }
2253 
2254 #ifndef USE_ROSEN_DRAWING
DrawOutline(const RSProperties & properties,SkCanvas & canvas)2255 void RSPropertiesPainter::DrawOutline(const RSProperties& properties, SkCanvas& canvas)
2256 #else
2257 void RSPropertiesPainter::DrawOutline(const RSProperties& properties, Drawing::Canvas& canvas)
2258 #endif
2259 {
2260     auto outline = properties.GetOutline();
2261     if (outline && outline->HasBorder()) {
2262         DrawBorderBase(properties, canvas, outline, true);
2263     }
2264 }
2265 
2266 #ifndef USE_ROSEN_DRAWING
DrawForegroundColor(const RSProperties & properties,SkCanvas & canvas)2267 void RSPropertiesPainter::DrawForegroundColor(const RSProperties& properties, SkCanvas& canvas)
2268 {
2269     auto bgColor = properties.GetForegroundColor();
2270     if (bgColor == RgbPalette::Transparent()) {
2271         return;
2272     }
2273     // clip
2274     if (properties.GetClipBounds() != nullptr) {
2275         canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
2276     } else if (properties.GetClipToBounds()) {
2277         canvas.clipRect(Rect2SkRect(properties.GetBoundsRect()), true);
2278     } else if (properties.GetClipToRRect()) {
2279         canvas.clipRRect(RRect2SkRRect(properties.GetClipRRect()), true);
2280     }
2281 
2282     SkPaint paint;
2283     paint.setColor(bgColor.AsArgbInt());
2284     paint.setAntiAlias(true);
2285     canvas.drawRRect(RRect2SkRRect(properties.GetRRect()), paint);
2286 }
2287 #else
DrawForegroundColor(const RSProperties & properties,Drawing::Canvas & canvas)2288 void RSPropertiesPainter::DrawForegroundColor(const RSProperties& properties, Drawing::Canvas& canvas)
2289 {
2290     auto bgColor = properties.GetForegroundColor();
2291     if (bgColor == RgbPalette::Transparent()) {
2292         return;
2293     }
2294     // clip
2295     if (properties.GetClipBounds() != nullptr) {
2296         canvas.ClipPath(properties.GetClipBounds()->GetDrawingPath(), Drawing::ClipOp::INTERSECT, true);
2297     } else if (properties.GetClipToBounds()) {
2298         canvas.ClipRect(Rect2DrawingRect(properties.GetBoundsRect()), Drawing::ClipOp::INTERSECT, true);
2299     } else if (properties.GetClipToRRect()) {
2300         canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetClipRRect()), Drawing::ClipOp::INTERSECT, true);
2301     }
2302 
2303     Drawing::Brush brush;
2304     brush.SetColor(Drawing::Color(bgColor.AsArgbInt()));
2305     brush.SetAntiAlias(true);
2306     canvas.AttachBrush(brush);
2307     canvas.DrawRoundRect(RRect2DrawingRRect(properties.GetRRect()));
2308     canvas.DetachBrush();
2309 }
2310 #endif
2311 
2312 #ifndef USE_ROSEN_DRAWING
DrawMask(const RSProperties & properties,SkCanvas & canvas,SkRect maskBounds)2313 void RSPropertiesPainter::DrawMask(const RSProperties& properties, SkCanvas& canvas, SkRect maskBounds)
2314 {
2315     std::shared_ptr<RSMask> mask = properties.GetMask();
2316     if (mask == nullptr) {
2317         return;
2318     }
2319     if (mask->IsSvgMask() && !mask->GetSvgDom() && !mask->GetSvgPicture()) {
2320         ROSEN_LOGD("RSPropertiesPainter::DrawMask not has Svg Mask property");
2321         return;
2322     }
2323 
2324     canvas.save();
2325     canvas.saveLayer(maskBounds, nullptr);
2326     int tmpLayer = canvas.getSaveCount();
2327 
2328     SkPaint maskfilter;
2329     auto filter = SkColorFilters::Compose(SkLumaColorFilter::Make(), SkColorFilters::SRGBToLinearGamma());
2330     maskfilter.setColorFilter(filter);
2331     canvas.saveLayer(maskBounds, &maskfilter);
2332     if (mask->IsSvgMask()) {
2333         SkAutoCanvasRestore maskSave(&canvas, true);
2334         canvas.translate(maskBounds.fLeft + mask->GetSvgX(), maskBounds.fTop + mask->GetSvgY());
2335         canvas.scale(mask->GetScaleX(), mask->GetScaleY());
2336         if (mask->GetSvgDom()) {
2337             mask->GetSvgDom()->render(&canvas);
2338         } else if (mask->GetSvgPicture()) {
2339             canvas.drawPicture(mask->GetSvgPicture());
2340         }
2341     } else if (mask->IsGradientMask()) {
2342         SkAutoCanvasRestore maskSave(&canvas, true);
2343         canvas.translate(maskBounds.fLeft, maskBounds.fTop);
2344         SkRect skRect = SkRect::MakeIWH(maskBounds.fRight - maskBounds.fLeft, maskBounds.fBottom - maskBounds.fTop);
2345         canvas.drawRect(skRect, mask->GetMaskPaint());
2346     } else if (mask->IsPathMask()) {
2347         SkAutoCanvasRestore maskSave(&canvas, true);
2348         canvas.translate(maskBounds.fLeft, maskBounds.fTop);
2349         canvas.drawPath(mask->GetMaskPath(), mask->GetMaskPaint());
2350     }
2351 
2352     // back to mask layer
2353     canvas.restoreToCount(tmpLayer);
2354     // create content layer
2355     SkPaint maskPaint;
2356     maskPaint.setBlendMode(SkBlendMode::kSrcIn);
2357     canvas.saveLayer(maskBounds, &maskPaint);
2358     canvas.clipRect(maskBounds, true);
2359 }
2360 #else
DrawMask(const RSProperties & properties,Drawing::Canvas & canvas,Drawing::Rect maskBounds)2361 void RSPropertiesPainter::DrawMask(const RSProperties& properties, Drawing::Canvas& canvas, Drawing::Rect maskBounds)
2362 {
2363     std::shared_ptr<RSMask> mask = properties.GetMask();
2364     if (mask == nullptr) {
2365         return;
2366     }
2367     if (mask->IsSvgMask() && !mask->GetSvgDom() && !mask->GetSvgPicture()) {
2368         ROSEN_LOGD("RSPropertiesPainter::DrawMask not has Svg Mask property");
2369         return;
2370     }
2371 
2372     canvas.Save();
2373     Drawing::SaveLayerOps slr(&maskBounds, nullptr);
2374     canvas.SaveLayer(slr);
2375     int tmpLayer = canvas.GetSaveCount();
2376 
2377     Drawing::Brush maskfilter;
2378     Drawing::Filter filter;
2379     filter.SetColorFilter(Drawing::ColorFilter::CreateComposeColorFilter(
2380         *(Drawing::ColorFilter::CreateLumaColorFilter()), *(Drawing::ColorFilter::CreateSrgbGammaToLinear())));
2381     maskfilter.SetFilter(filter);
2382     Drawing::SaveLayerOps slrMask(&maskBounds, &maskfilter);
2383     canvas.SaveLayer(slrMask);
2384     if (mask->IsSvgMask()) {
2385         Drawing::AutoCanvasRestore maskSave(canvas, true);
2386         canvas.Translate(maskBounds.GetLeft() + mask->GetSvgX(), maskBounds.GetTop() + mask->GetSvgY());
2387         canvas.Scale(mask->GetScaleX(), mask->GetScaleY());
2388         if (mask->GetSvgDom()) {
2389             canvas.DrawSVGDOM(mask->GetSvgDom());
2390         } else if (mask->GetSvgPicture()) {
2391             canvas.DrawPicture(*mask->GetSvgPicture());
2392         }
2393     } else if (mask->IsGradientMask()) {
2394         Drawing::AutoCanvasRestore maskSave(canvas, true);
2395         canvas.Translate(maskBounds.GetLeft(), maskBounds.GetTop());
2396         Drawing::Rect rect = Drawing::Rect(
2397             0, 0, maskBounds.GetWidth(), maskBounds.GetHeight());
2398         canvas.AttachBrush(mask->GetMaskBrush());
2399         canvas.DrawRect(rect);
2400         canvas.DetachBrush();
2401     } else if (mask->IsPathMask()) {
2402         Drawing::AutoCanvasRestore maskSave(canvas, true);
2403         canvas.Translate(maskBounds.GetLeft(), maskBounds.GetTop());
2404         canvas.AttachBrush(mask->GetMaskBrush());
2405         canvas.AttachPen(mask->GetMaskPen());
2406         canvas.DrawPath(*mask->GetMaskPath());
2407         canvas.DetachBrush();
2408         canvas.DetachPen();
2409     }
2410 
2411     // back to mask layer
2412     canvas.RestoreToCount(tmpLayer);
2413     // create content layer
2414     Drawing::Brush maskPaint;
2415     maskPaint.SetBlendMode(Drawing::BlendMode::SRC_IN);
2416     Drawing::SaveLayerOps slrContent(&maskBounds, &maskPaint);
2417     canvas.SaveLayer(slrContent);
2418     canvas.ClipRect(maskBounds, Drawing::ClipOp::INTERSECT, true);
2419 }
2420 #endif
2421 
2422 #ifndef USE_ROSEN_DRAWING
DrawMask(const RSProperties & properties,SkCanvas & canvas)2423 void RSPropertiesPainter::DrawMask(const RSProperties& properties, SkCanvas& canvas)
2424 {
2425     SkRect maskBounds = Rect2SkRect(properties.GetBoundsRect());
2426     DrawMask(properties, canvas, maskBounds);
2427 }
2428 #else
DrawMask(const RSProperties & properties,Drawing::Canvas & canvas)2429 void RSPropertiesPainter::DrawMask(const RSProperties& properties, Drawing::Canvas& canvas)
2430 {
2431     Drawing::Rect maskBounds = Rect2DrawingRect(properties.GetBoundsRect());
2432     DrawMask(properties, canvas, maskBounds);
2433 }
2434 #endif
2435 
2436 #ifndef USE_ROSEN_DRAWING
GetCmdsClipRect(DrawCmdListPtr & cmds)2437 RectF RSPropertiesPainter::GetCmdsClipRect(DrawCmdListPtr& cmds)
2438 {
2439 #if defined(RS_ENABLE_DRIVEN_RENDER)
2440     RectF clipRect;
2441     if (cmds == nullptr) {
2442         return clipRect;
2443     }
2444     SkRect rect;
2445     cmds->CheckClipRect(rect);
2446     clipRect = { rect.left(), rect.top(), rect.width(), rect.height() };
2447     return clipRect;
2448 #else
2449     return RectF { 0.0f, 0.0f, 0.0f, 0.0f };
2450 #endif
2451 }
2452 #else
GetCmdsClipRect(Drawing::DrawCmdListPtr & cmds)2453 RectF RSPropertiesPainter::GetCmdsClipRect(Drawing::DrawCmdListPtr& cmds)
2454 {
2455     ROSEN_LOGE("Drawing Unsupport RSPropertiesPainter::GetCmdsClipRect");
2456     return RectF { 0.0f, 0.0f, 0.0f, 0.0f };
2457 }
2458 #endif
2459 
2460 #ifndef USE_ROSEN_DRAWING
DrawFrameForDriven(const RSProperties & properties,RSPaintFilterCanvas & canvas,DrawCmdListPtr & cmds)2461 void RSPropertiesPainter::DrawFrameForDriven(const RSProperties& properties, RSPaintFilterCanvas& canvas,
2462                                              DrawCmdListPtr& cmds)
2463 #else
2464 void RSPropertiesPainter::DrawFrameForDriven(const RSProperties& properties, RSPaintFilterCanvas& canvas,
2465                                              Drawing::DrawCmdListPtr& cmds)
2466 #endif
2467 {
2468 #if defined(RS_ENABLE_DRIVEN_RENDER)
2469     if (cmds == nullptr) {
2470         return;
2471     }
2472 #ifndef USE_ROSEN_DRAWING
2473     SkMatrix mat;
2474     if (GetGravityMatrix(
2475             properties.GetFrameGravity(), properties.GetFrameRect(), cmds->GetWidth(), cmds->GetHeight(), mat)) {
2476         canvas.concat(mat);
2477     }
2478     auto frameRect = Rect2SkRect(properties.GetFrameRect());
2479 #else
2480     Rosen::Drawing::Matrix mat;
2481     if (GetGravityMatrix(
2482             properties.GetFrameGravity(), properties.GetFrameRect(), cmds->GetWidth(), cmds->GetHeight(), mat)) {
2483         canvas.ConcatMatrix(mat);
2484     }
2485     auto frameRect = Rect2DrawingRect(properties.GetFrameRect());
2486 #endif
2487     // temporary solution for driven content clip
2488 #ifndef USE_ROSEN_DRAWING
2489     cmds->ReplaceDrivenCmds();
2490     cmds->Playback(canvas, &frameRect);
2491     cmds->RestoreOriginCmdsForDriven();
2492 #else
2493     cmds->Playback(canvas, &frameRect);
2494 #endif
2495 #endif
2496 }
2497 
2498 #ifndef USE_ROSEN_DRAWING
DrawSpherize(const RSProperties & properties,RSPaintFilterCanvas & canvas,const sk_sp<SkSurface> & spherizeSurface)2499 void RSPropertiesPainter::DrawSpherize(const RSProperties& properties, RSPaintFilterCanvas& canvas,
2500     const sk_sp<SkSurface>& spherizeSurface)
2501 {
2502     if (spherizeSurface == nullptr) {
2503         return;
2504     }
2505     SkAutoCanvasRestore acr(&canvas, true);
2506     float canvasWidth = properties.GetBoundsRect().GetWidth();
2507     float canvasHeight = properties.GetBoundsRect().GetHeight();
2508     if (spherizeSurface->width() == 0 || spherizeSurface->height() == 0) {
2509         return;
2510     }
2511     canvas.scale(canvasWidth / spherizeSurface->width(), canvasHeight / spherizeSurface->height());
2512 
2513     auto imageSnapshot = spherizeSurface->makeImageSnapshot();
2514     if (imageSnapshot == nullptr) {
2515         ROSEN_LOGE("RSPropertiesPainter::DrawCachedSpherizeSurface image  is null");
2516         return;
2517     }
2518 
2519     SkPaint paint;
2520     paint.setBlendMode(SkBlendMode::kSrcOver);
2521     paint.setShader(imageSnapshot->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions()));
2522 
2523     float width = imageSnapshot->width();
2524     float height = imageSnapshot->height();
2525     float degree = properties.GetSpherize();
2526     bool isWidthGreater = width > height;
2527     ROSEN_LOGI("RSPropertiesPainter::DrawCachedSpherizeSurface spherize degree [%{public}f]", degree);
2528 
2529     const SkPoint texCoords[4] = {
2530         {0.0f, 0.0f}, {width, 0.0f}, {width, height}, {0.0f, height}
2531     };
2532     float offsetSquare = 0.f;
2533     if (isWidthGreater) {
2534         offsetSquare = (width - height) * degree / 2.0; // half of the change distance
2535         width = width - (width - height) * degree;
2536     } else {
2537         offsetSquare = (height - width) * degree / 2.0; // half of the change distance
2538         height = height - (height - width) * degree;
2539     }
2540 
2541     float segmentWidthOne = width / 3.0;
2542     float segmentWidthTwo = width / 3.0 * 2.0;
2543     float segmentHeightOne = height / 3.0;
2544     float segmentHeightTwo = height / 3.0 * 2.0;
2545     float offsetSphereWidth = width / 6 * degree;
2546     float offsetSphereHeight = height / 6  * degree;
2547 
2548     SkPoint ctrlPoints[12] = {
2549         // top edge control points
2550         {0.0f, 0.0f}, {segmentWidthOne, 0.0f}, {segmentWidthTwo, 0.0f}, {width, 0.0f},
2551         // right edge control points
2552         {width, segmentHeightOne}, {width, segmentHeightTwo},
2553         // bottom edge control points
2554         {width, height}, {segmentWidthTwo, height}, {segmentWidthOne, height}, {0.0f, height},
2555         // left edge control points
2556         {0.0f, segmentHeightTwo}, {0.0f, segmentHeightOne}
2557     };
2558     ctrlPoints[0].offset(offsetSphereWidth, offsetSphereHeight); // top left control point
2559     ctrlPoints[3].offset(-offsetSphereWidth, offsetSphereHeight); // top right control point
2560     ctrlPoints[6].offset(-offsetSphereWidth, -offsetSphereHeight); // bottom right control point
2561     ctrlPoints[9].offset(offsetSphereWidth, -offsetSphereHeight); // bottom left control point
2562     if (isWidthGreater) {
2563         SkPoint::Offset(ctrlPoints, SK_ARRAY_COUNT(ctrlPoints), offsetSquare, 0);
2564     } else {
2565         SkPoint::Offset(ctrlPoints, SK_ARRAY_COUNT(ctrlPoints), 0, offsetSquare);
2566     }
2567     SkPath path;
2568     path.moveTo(ctrlPoints[0]);
2569     path.cubicTo(ctrlPoints[1], ctrlPoints[2], ctrlPoints[3]); // upper edge
2570     path.cubicTo(ctrlPoints[4], ctrlPoints[5], ctrlPoints[6]); // right edge
2571     path.cubicTo(ctrlPoints[7], ctrlPoints[8], ctrlPoints[9]); // bottom edge
2572     path.cubicTo(ctrlPoints[10], ctrlPoints[11], ctrlPoints[0]); // left edge
2573     canvas.clipPath(path, true);
2574     canvas.drawPatch(ctrlPoints, nullptr, texCoords, SkBlendMode::kSrcOver, paint);
2575 }
2576 #else
DrawSpherize(const RSProperties & properties,RSPaintFilterCanvas & canvas,const std::shared_ptr<Drawing::Surface> & spherizeSurface)2577 void RSPropertiesPainter::DrawSpherize(const RSProperties& properties, RSPaintFilterCanvas& canvas,
2578     const std::shared_ptr<Drawing::Surface>& spherizeSurface)
2579 {
2580     if (spherizeSurface == nullptr) {
2581         return;
2582     }
2583     if (spherizeSurface->Width() == 0 || spherizeSurface->Height() == 0) {
2584         return;
2585     }
2586     Drawing::AutoCanvasRestore acr(canvas, true);
2587     float canvasWidth = properties.GetBoundsRect().GetWidth();
2588     float canvasHeight = properties.GetBoundsRect().GetHeight();
2589 
2590     auto imageSnapshot = spherizeSurface->GetImageSnapshot();
2591     if (imageSnapshot == nullptr) {
2592         ROSEN_LOGE("RSPropertiesPainter::DrawCachedSpherizeSurface image is null");
2593         return;
2594     }
2595     int imageWidth = imageSnapshot->GetWidth();
2596     int imageHeight = imageSnapshot->GetHeight();
2597     if (imageWidth == 0 || imageHeight == 0) {
2598         return;
2599     }
2600     canvas.Scale(canvasWidth / imageWidth, canvasHeight / imageHeight);
2601 
2602     float width = imageWidth;
2603     float height = imageHeight;
2604     float degree = properties.GetSpherize();
2605     bool isWidthGreater = width > height;
2606     ROSEN_LOGI("RSPropertiesPainter::DrawCachedSpherizeSurface spherize degree [%{public}f]", degree);
2607 
2608     Drawing::Brush brush;
2609     brush.SetBlendMode(Drawing::BlendMode::SRC_OVER);
2610     Drawing::SamplingOptions samplingOptions;
2611     Drawing::Matrix scaleMat;
2612     brush.SetShaderEffect(Drawing::ShaderEffect::CreateImageShader(
2613         *imageSnapshot, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, samplingOptions, scaleMat));
2614     canvas.AttachBrush(brush);
2615 
2616     const Drawing::Point texCoords[4] = {
2617         {0.0f, 0.0f}, {width, 0.0f}, {width, height}, {0.0f, height}
2618     };
2619     float offsetSquare = 0.f;
2620     if (isWidthGreater) {
2621         offsetSquare = (width - height) * degree / 2.0; // half of the change distance
2622         width = width - (width - height) * degree;
2623     } else {
2624         offsetSquare = (height - width) * degree / 2.0; // half of the change distance
2625         height = height - (height - width) * degree;
2626     }
2627 
2628     float segmentWidthOne = width / 3.0;
2629     float segmentWidthTwo = width / 3.0 * 2.0;
2630     float segmentHeightOne = height / 3.0;
2631     float segmentHeightTwo = height / 3.0 * 2.0;
2632     float offsetSphereWidth = width / 6 * degree;
2633     float offsetSphereHeight = height / 6  * degree;
2634 
2635     const int PointNum = 12;
2636     Drawing::Point ctrlPoints[PointNum] = {
2637         // top edge control points
2638         {0.0f, 0.0f}, {segmentWidthOne, 0.0f}, {segmentWidthTwo, 0.0f}, {width, 0.0f},
2639         // right edge control points
2640         {width, segmentHeightOne}, {width, segmentHeightTwo},
2641         // bottom edge control points
2642         {width, height}, {segmentWidthTwo, height}, {segmentWidthOne, height}, {0.0f, height},
2643         // left edge control points
2644         {0.0f, segmentHeightTwo}, {0.0f, segmentHeightOne}
2645     };
2646     ctrlPoints[0].Offset(offsetSphereWidth, offsetSphereHeight); // top left control point
2647     ctrlPoints[3].Offset(-offsetSphereWidth, offsetSphereHeight); // top right control point
2648     ctrlPoints[6].Offset(-offsetSphereWidth, -offsetSphereHeight); // bottom right control point
2649     ctrlPoints[9].Offset(offsetSphereWidth, -offsetSphereHeight); // bottom left control point
2650     if (isWidthGreater) {
2651         for (int i = 0; i < PointNum; ++i) {
2652             ctrlPoints[i].Offset(offsetSquare, 0);
2653         }
2654     } else {
2655         for (int i = 0; i < PointNum; ++i) {
2656             ctrlPoints[i].Offset(0, offsetSquare);
2657         }
2658     }
2659     Drawing::Path path;
2660     path.MoveTo(ctrlPoints[0].GetX(), ctrlPoints[0].GetY());
2661     path.CubicTo(ctrlPoints[1], ctrlPoints[2], ctrlPoints[3]); // upper edge
2662     path.CubicTo(ctrlPoints[4], ctrlPoints[5], ctrlPoints[6]); // right edge
2663     path.CubicTo(ctrlPoints[7], ctrlPoints[8], ctrlPoints[9]); // bottom edge
2664     path.CubicTo(ctrlPoints[10], ctrlPoints[11], ctrlPoints[0]); // left edge
2665     canvas.ClipPath(path, Drawing::ClipOp::INTERSECT, true);
2666     canvas.DrawPatch(ctrlPoints, nullptr, texCoords, Drawing::BlendMode::SRC_OVER);
2667     canvas.DetachBrush();
2668 }
2669 #endif
2670 
DrawColorFilter(const RSProperties & properties,RSPaintFilterCanvas & canvas)2671 void RSPropertiesPainter::DrawColorFilter(const RSProperties& properties, RSPaintFilterCanvas& canvas)
2672 {
2673     // if useEffect defined, use color filter from parent EffectView.
2674     auto& colorFilter = properties.GetColorFilter();
2675     if (colorFilter == nullptr) {
2676         return;
2677     }
2678 #ifndef USE_ROSEN_DRAWING
2679     SkAutoCanvasRestore acr(&canvas, true);
2680     canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
2681     SkPaint paint;
2682     paint.setAntiAlias(true);
2683     paint.setColorFilter(colorFilter);
2684     auto skSurface = canvas.GetSurface();
2685     if (skSurface == nullptr) {
2686         ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter skSurface is null");
2687         return;
2688     }
2689     auto clipBounds = canvas.getDeviceClipBounds();
2690     auto imageSnapshot = skSurface->makeImageSnapshot(clipBounds);
2691     if (imageSnapshot == nullptr) {
2692         ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter image is null");
2693         return;
2694     }
2695     as_IB(imageSnapshot)->hintCacheGpuResource();
2696     canvas.resetMatrix();
2697     SkSamplingOptions options(SkFilterMode::kNearest, SkMipmapMode::kNone);
2698     canvas.drawImageRect(imageSnapshot, SkRect::Make(clipBounds), options, &paint);
2699 #else
2700     Drawing::AutoCanvasRestore acr(canvas, true);
2701     canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, true);
2702     Drawing::Brush brush;
2703     brush.SetAntiAlias(true);
2704     Drawing::Filter filter;
2705     filter.SetColorFilter(colorFilter);
2706     brush.SetFilter(filter);
2707     auto surface = canvas.GetSurface();
2708     if (surface == nullptr) {
2709         ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter surface is null");
2710         return;
2711     }
2712     auto clipBounds = canvas.GetDeviceClipBounds();
2713     auto imageSnapshot = surface->GetImageSnapshot(clipBounds);
2714     if (imageSnapshot == nullptr) {
2715         ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter image is null");
2716         return;
2717     }
2718     as_IB(imageSnapshot->ExportSkImage().get())->hintCacheGpuResource();
2719     canvas.ResetMatrix();
2720     Drawing::SamplingOptions options(Drawing::FilterMode::NEAREST, Drawing::MipmapMode::NONE);
2721     canvas.AttachBrush(brush);
2722     canvas.DrawImageRect(*imageSnapshot, clipBounds, options);
2723     canvas.DetachBrush();
2724 #endif
2725 }
2726 
2727 #ifndef USE_ROSEN_DRAWING
DrawBinarizationShader(const RSProperties & properties,RSPaintFilterCanvas & canvas)2728 void RSPropertiesPainter::DrawBinarizationShader(const RSProperties& properties, RSPaintFilterCanvas& canvas)
2729 {
2730     SkAutoCanvasRestore acr(&canvas, true);
2731     canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
2732     auto skSurface = canvas.GetSurface();
2733     if (skSurface == nullptr) {
2734         ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter skSurface is null");
2735         return;
2736     }
2737     auto clipBounds = canvas.getDeviceClipBounds();
2738     auto imageSnapshot = skSurface->makeImageSnapshot(clipBounds);
2739     if (imageSnapshot == nullptr) {
2740         ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter image is null");
2741         return;
2742     }
2743     auto& aiInvert = properties.GetAiInvert();
2744     auto imageShader = imageSnapshot->makeShader(SkSamplingOptions(SkFilterMode::kLinear));
2745     float thresholdLow = aiInvert->z_ - aiInvert->w_;
2746     float thresholdHigh = aiInvert->z_ + aiInvert->w_;
2747     auto shader = MakeBinarizationShader(
2748         aiInvert->x_, aiInvert->y_, thresholdLow, thresholdHigh, imageShader);
2749     SkPaint paint;
2750     paint.setShader(shader);
2751     paint.setAntiAlias(true);
2752     canvas.resetMatrix();
2753     canvas.translate(clipBounds.left(), clipBounds.top());
2754     canvas.drawPaint(paint);
2755 }
2756 #else
DrawBinarizationShader(const RSProperties & properties,RSPaintFilterCanvas & canvas)2757 void RSPropertiesPainter::DrawBinarizationShader(const RSProperties& properties, RSPaintFilterCanvas& canvas)
2758 {
2759     Drawing::AutoCanvasRestore acr(canvas, true);
2760     canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, true);
2761     auto drSurface = canvas.GetSurface();
2762     if (drSurface == nullptr) {
2763         ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter drSurface is null");
2764         return;
2765     }
2766     auto clipBounds = canvas.GetDeviceClipBounds();
2767     auto imageSnapshot = drSurface->GetImageSnapshot(clipBounds);
2768     if (imageSnapshot == nullptr) {
2769         ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter image is null");
2770         return;
2771     }
2772     auto& aiInvert = properties.GetAiInvert();
2773     Drawing::Matrix matrix;
2774     auto imageShader = Drawing::ShaderEffect::CreateImageShader(*imageSnapshot, Drawing::TileMode::CLAMP,
2775         Drawing::TileMode::CLAMP, Drawing::SamplingOptions(Drawing::FilterMode::LINEAR), matrix);
2776     float thresholdLow = aiInvert->z_ - aiInvert->w_;
2777     float thresholdHigh = aiInvert->z_ + aiInvert->w_;
2778     auto shader = MakeBinarizationShader(
2779         aiInvert->x_, aiInvert->y_, thresholdLow, thresholdHigh, imageShader);
2780     Drawing::Brush brush;
2781     brush.SetShaderEffect(shader);
2782     brush.SetAntiAlias(true);
2783     canvas.ResetMatrix();
2784     canvas.Translate(clipBounds.GetLeft(), clipBounds.GetTop());
2785     canvas.DrawBackground(brush);
2786 }
2787 #endif
2788 
2789 #ifndef USE_ROSEN_DRAWING
MakeBinarizationShader(float low,float high,float thresholdLow,float thresholdHigh,sk_sp<SkShader> imageShader)2790 sk_sp<SkShader> RSPropertiesPainter::MakeBinarizationShader(float low, float high, float thresholdLow,
2791     float thresholdHigh, sk_sp<SkShader> imageShader)
2792 {
2793     static constexpr char prog[] = R"(
2794         uniform half low;
2795         uniform half high;
2796         uniform half thresholdLow;
2797         uniform half thresholdHigh;
2798         uniform shader imageShader;
2799 
2800         half4 main(float2 coord) {
2801             half3 c = imageShader.eval(float2(coord.x, coord.y)).rgb;
2802             float gray = 0.299 * c.r + 0.587 * c.g + 0.114 * c.b;
2803             float lowRes = mix(high, -1.0, step(thresholdLow, gray));
2804             float highRes = mix(-1.0, low, step(thresholdHigh, gray));
2805             float midRes = (thresholdHigh - gray) * (high - low) / (thresholdHigh - thresholdLow) + low;
2806             float invertedGray = mix(midRes, max(lowRes, highRes), step(-0.5, max(lowRes, highRes)));
2807             half3 invert = half3(invertedGray);
2808             return half4(invert, 1.0);
2809         }
2810     )";
2811     auto [effect, err] = SkRuntimeEffect::MakeForShader(SkString(prog));
2812     if (!effect) {
2813         ROSEN_LOGE("MakeBinarizationShader::RuntimeShader effect error: %{public}s\n", err.c_str());
2814         return nullptr;
2815     }
2816     SkRuntimeShaderBuilder builder(effect);
2817     // aviod zero-divide in shader
2818     thresholdHigh = thresholdHigh <= thresholdLow ? thresholdHigh + 1e-6 : thresholdHigh;
2819     builder.child("imageShader") = imageShader;
2820     builder.uniform("low") = low;
2821     builder.uniform("high") = high;
2822     builder.uniform("thresholdLow") = thresholdLow;
2823     builder.uniform("thresholdHigh") = thresholdHigh;
2824     return builder.makeShader(nullptr, false);
2825 }
2826 #else
MakeBinarizationShader(float low,float high,float thresholdLow,float thresholdHigh,std::shared_ptr<Drawing::ShaderEffect> imageShader)2827 std::shared_ptr<Drawing::ShaderEffect> RSPropertiesPainter::MakeBinarizationShader(float low, float high,
2828     float thresholdLow, float thresholdHigh,
2829     std::shared_ptr<Drawing::ShaderEffect> imageShader)
2830 {
2831     static constexpr char prog[] = R"(
2832         uniform half low;
2833         uniform half high;
2834         uniform half thresholdLow;
2835         uniform half thresholdHigh;
2836         uniform shader imageShader;
2837 
2838         half4 main(float2 coord) {
2839             half3 c = imageShader.eval(float2(coord.x, coord.y)).rgb;
2840             float gray = 0.299 * c.r + 0.587 * c.g + 0.114 * c.b;
2841             float lowRes = mix(high, -1.0, step(thresholdLow, gray));
2842             float highRes = mix(-1.0, low, step(thresholdHigh, gray));
2843             float midRes = (thresholdHigh - gray) * (high - low) / (thresholdHigh - thresholdLow) + low;
2844             float invertedGray = mix(midRes, max(lowRes, highRes), step(-0.5, max(lowRes, highRes)));
2845             half3 invert = half3(invertedGray);
2846             return half4(invert, 1.0);
2847         }
2848     )";
2849     if (binarizationShaderEffect_ == nullptr) {
2850         binarizationShaderEffect_ = Drawing::RuntimeEffect::CreateForShader(prog);
2851         if (binarizationShaderEffect_ == nullptr) {
2852             ROSEN_LOGE("MakeBinarizationShader::RuntimeShader effect error\n");
2853             return nullptr;
2854         }
2855     }
2856     std::shared_ptr<Drawing::RuntimeShaderBuilder> builder =
2857         std::make_shared<Drawing::RuntimeShaderBuilder>(binarizationShaderEffect_);
2858     // aviod zero-divide in shader
2859     thresholdHigh = thresholdHigh <= thresholdLow ? thresholdHigh + 1e-6 : thresholdHigh;
2860     builder->SetChild("imageShader", imageShader);
2861     builder->SetUniform("low", low);
2862     builder->SetUniform("high", high);
2863     builder->SetUniform("thresholdLow", thresholdLow);
2864     builder->SetUniform("thresholdHigh", thresholdHigh);
2865     return builder->MakeShader(nullptr, false);
2866 }
2867 #endif
2868 
DrawLightUpEffect(const RSProperties & properties,RSPaintFilterCanvas & canvas)2869 void RSPropertiesPainter::DrawLightUpEffect(const RSProperties& properties, RSPaintFilterCanvas& canvas)
2870 {
2871 #ifndef USE_ROSEN_DRAWING
2872     SkSurface* skSurface = canvas.GetSurface();
2873     if (skSurface == nullptr) {
2874         ROSEN_LOGD("RSPropertiesPainter::DrawLightUpEffect skSurface is null");
2875         return;
2876     }
2877     SkAutoCanvasRestore acr(&canvas, true);
2878     if (properties.GetClipBounds() != nullptr) {
2879         canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
2880     } else {
2881         canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
2882     }
2883 
2884     auto clipBounds = canvas.getDeviceClipBounds();
2885     auto image = skSurface->makeImageSnapshot(clipBounds);
2886     if (image == nullptr) {
2887         ROSEN_LOGE("RSPropertiesPainter::DrawLightUpEffect image is null");
2888         return;
2889     }
2890     auto imageShader = image->makeShader(SkSamplingOptions(SkFilterMode::kLinear));
2891     auto shader = MakeLightUpEffectShader(properties.GetLightUpEffect(), imageShader);
2892     SkPaint paint;
2893     paint.setShader(shader);
2894     canvas.resetMatrix();
2895     canvas.translate(clipBounds.left(), clipBounds.top());
2896     canvas.drawPaint(paint);
2897 #else
2898     Drawing::Surface* surface = canvas.GetSurface();
2899     if (surface == nullptr) {
2900         ROSEN_LOGD("RSPropertiesPainter::DrawLightUpEffect surface is null");
2901         return;
2902     }
2903     Drawing::AutoCanvasRestore acr(canvas, true);
2904     if (properties.GetClipBounds() != nullptr) {
2905         canvas.ClipPath(properties.GetClipBounds()->GetDrawingPath(), Drawing::ClipOp::INTERSECT, true);
2906     } else {
2907         canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, true);
2908     }
2909 
2910     auto clipBounds = canvas.GetDeviceClipBounds();
2911     auto image = surface->GetImageSnapshot(clipBounds);
2912     if (image == nullptr) {
2913         ROSEN_LOGE("RSPropertiesPainter::DrawLightUpEffect image is null");
2914         return;
2915     }
2916     Drawing::Matrix scaleMat;
2917     auto imageShader = Drawing::ShaderEffect::CreateImageShader(
2918         *image, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP,
2919         Drawing::SamplingOptions(Drawing::FilterMode::LINEAR), scaleMat);
2920     auto shader = MakeLightUpEffectShader(properties.GetLightUpEffect(), imageShader);
2921     Drawing::Brush brush;
2922     brush.SetShaderEffect(shader);
2923     canvas.ResetMatrix();
2924     canvas.Translate(clipBounds.GetLeft(), clipBounds.GetTop());
2925     canvas.DrawBackground(brush);
2926 #endif
2927 }
2928 
2929 #ifndef USE_ROSEN_DRAWING
MakeLightUpEffectShader(float lightUpDeg,sk_sp<SkShader> imageShader)2930 sk_sp<SkShader> RSPropertiesPainter::MakeLightUpEffectShader(float lightUpDeg, sk_sp<SkShader> imageShader)
2931 #else
2932 std::shared_ptr<Drawing::ShaderEffect> RSPropertiesPainter::MakeLightUpEffectShader(
2933     float lightUpDeg, std::shared_ptr<Drawing::ShaderEffect> imageShader)
2934 #endif
2935 {
2936     static constexpr char prog[] = R"(
2937         uniform half lightUpDeg;
2938         uniform shader imageShader;
2939         vec3 rgb2hsv(in vec3 c)
2940         {
2941             vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
2942             vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
2943             vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
2944             float d = q.x - min(q.w, q.y);
2945             float e = 1.0e-10;
2946             return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
2947         }
2948         vec3 hsv2rgb(in vec3 c)
2949         {
2950             vec3 rgb = clamp(abs(mod(c.x * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0);
2951             return c.z * mix(vec3(1.0), rgb, c.y);
2952         }
2953         half4 main(float2 coord)
2954         {
2955             vec3 hsv = rgb2hsv(imageShader.eval(coord).rgb);
2956             float satUpper = clamp(hsv.y * 1.2, 0.0, 1.0);
2957             hsv.y = mix(satUpper, hsv.y, lightUpDeg);
2958             hsv.z += lightUpDeg - 1.0;
2959             return vec4(hsv2rgb(hsv), 1.0);
2960         }
2961     )";
2962 #ifndef USE_ROSEN_DRAWING
2963     auto [effect, err] = SkRuntimeEffect::MakeForShader(SkString(prog));
2964     sk_sp<SkShader> children[] = {imageShader};
2965     size_t childCount = 1;
2966     return effect->makeShader(SkData::MakeWithCopy(
2967         &lightUpDeg, sizeof(lightUpDeg)), children, childCount, nullptr, false);
2968 #else
2969     if (lightUpEffectShaderEffect_ == nullptr) {
2970         lightUpEffectShaderEffect_ = Drawing::RuntimeEffect::CreateForShader(prog);
2971         if (lightUpEffectShaderEffect_ == nullptr) {
2972             return nullptr;
2973         }
2974     }
2975     std::shared_ptr<Drawing::ShaderEffect> children[] = {imageShader};
2976     size_t childCount = 1;
2977     auto data = std::make_shared<Drawing::Data>();
2978     data->BuildWithCopy(&lightUpDeg, sizeof(lightUpDeg));
2979     return lightUpEffectShaderEffect_->MakeShader(data, children, childCount, nullptr, false);
2980 #endif
2981 }
2982 
DrawDynamicLightUp(const RSProperties & properties,RSPaintFilterCanvas & canvas)2983 void RSPropertiesPainter::DrawDynamicLightUp(const RSProperties& properties, RSPaintFilterCanvas& canvas)
2984 {
2985 #ifndef USE_ROSEN_DRAWING
2986     SkAutoCanvasRestore acr(&canvas, true);
2987     if (RSSystemProperties::GetPropertyDrawableEnable()) {
2988         // do nothing
2989     } else if (properties.GetClipBounds() != nullptr) {
2990         canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
2991     } else {
2992         canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
2993     }
2994 
2995     auto blender = MakeDynamicLightUpBlender(properties.GetDynamicLightUpRate().value() * canvas.GetAlpha(),
2996         properties.GetDynamicLightUpDegree().value() * canvas.GetAlpha());
2997     SkPaint paint;
2998     paint.setBlender(blender);
2999     canvas.drawPaint(paint);
3000 #else
3001     Drawing::Surface* surface = canvas.GetSurface();
3002     if (surface == nullptr) {
3003         ROSEN_LOGD("RSPropertiesPainter::DrawDynamicLightUp surface is null");
3004         return;
3005     }
3006     Drawing::AutoCanvasRestore acr(canvas, true);
3007     if (RSSystemProperties::GetPropertyDrawableEnable()) {
3008         // do nothing
3009     } else if (properties.GetClipBounds() != nullptr) {
3010         canvas.ClipPath(properties.GetClipBounds()->GetDrawingPath(), Drawing::ClipOp::INTERSECT, true);
3011     } else {
3012         canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, true);
3013     }
3014 
3015     auto blender = MakeDynamicLightUpBlender(properties.GetDynamicLightUpRate().value() * canvas.GetAlpha(),
3016         properties.GetDynamicLightUpDegree().value() * canvas.GetAlpha());
3017     Drawing::Brush brush;
3018     brush.SetBlender(blender);
3019     canvas.DrawBackground(brush);
3020 #endif
3021 }
3022 
3023 #ifndef USE_ROSEN_DRAWING
MakeDynamicLightUpBlender(float dynamicLightUpRate,float dynamicLightUpDeg)3024 sk_sp<SkBlender> RSPropertiesPainter::MakeDynamicLightUpBlender(
3025     float dynamicLightUpRate, float dynamicLightUpDeg)
3026 #else
3027 std::shared_ptr<Drawing::Blender> RSPropertiesPainter::MakeDynamicLightUpBlender(
3028     float dynamicLightUpRate, float dynamicLightUpDeg)
3029 #endif
3030 {
3031 #ifndef USE_ROSEN_DRAWING
3032     static constexpr char prog[] = R"(
3033         uniform half dynamicLightUpRate;
3034         uniform half dynamicLightUpDeg;
3035 
3036         vec4 main(vec4 src, vec4 dst) {
3037             float x = 0.299 * dst.r + 0.587 * dst.g + 0.114 * dst.b;
3038             float y = (0 - dynamicLightUpRate) * x + dynamicLightUpDeg;
3039             float R = clamp((dst.r + y), 0.0, 1.0);
3040             float G = clamp((dst.g + y), 0.0, 1.0);
3041             float B = clamp((dst.b + y), 0.0, 1.0);
3042             return vec4(R, G, B, 1.0);
3043         }
3044     )";
3045 
3046     auto [effect, err] = SkRuntimeEffect::MakeForBlender(SkString(prog));
3047     if (!effect) {
3048         ROSEN_LOGE("MakeDynamicLightUpBlender::RuntimeBlender effect error: %{public}s\n", err.c_str());
3049         return nullptr;
3050     }
3051     SkRuntimeBlendBuilder builder(effect);
3052     builder.uniform("dynamicLightUpRate") = dynamicLightUpRate;
3053     builder.uniform("dynamicLightUpDeg") = dynamicLightUpDeg;
3054     return builder.makeBlender();
3055 #else
3056     static constexpr char prog[] = R"(
3057         uniform half dynamicLightUpRate;
3058         uniform half dynamicLightUpDeg;
3059         uniform shader imageShader;
3060 
3061         vec4 main(vec4 src, vec4 dst) {
3062             float x = 0.299 * dst.r + 0.587 * dst.g + 0.114 * dst.b;
3063             float y = (0 - dynamicLightUpRate) * x + dynamicLightUpDeg;
3064             float R = clamp((dst.r + y), 0.0, 1.0);
3065             float G = clamp((dst.g + y), 0.0, 1.0);
3066             float B = clamp((dst.b + y), 0.0, 1.0);
3067             return vec4(R, G, B, 1.0);
3068         }
3069     )";
3070     if (dynamicLightUpBlenderEffect_ == nullptr) {
3071         dynamicLightUpBlenderEffect_ = Drawing::RuntimeEffect::CreateForBlender(prog);
3072         if (dynamicLightUpBlenderEffect_ == nullptr) {
3073             ROSEN_LOGE("MakeDynamicLightUpBlender::MakeDynamicLightUpBlender effect error!\n");
3074             return nullptr;
3075         }
3076     }
3077     std::shared_ptr<Drawing::RuntimeBlenderBuilder> builder =
3078         std::make_shared<Drawing::RuntimeBlenderBuilder>(dynamicLightUpBlenderEffect_);
3079     builder->SetUniform("dynamicLightUpRate", dynamicLightUpRate);
3080     builder->SetUniform("dynamicLightUpDeg", dynamicLightUpDeg);
3081     return builder->MakeBlender();
3082 #endif
3083 }
3084 
DrawParticle(const RSProperties & properties,RSPaintFilterCanvas & canvas)3085 void RSPropertiesPainter::DrawParticle(const RSProperties& properties, RSPaintFilterCanvas& canvas)
3086 {
3087     const auto& particleVector = properties.GetParticles();
3088     if (particleVector.GetParticleSize() == 0) {
3089         return;
3090     }
3091     const auto& particles = particleVector.GetParticleVector();
3092     auto bounds = properties.GetDrawRegion();
3093     for (const auto& particle : particles) {
3094         if (particle != nullptr && particle->IsAlive()) {
3095             // Get particle properties
3096             auto position = particle->GetPosition();
3097             float opacity = particle->GetOpacity();
3098             float scale = particle->GetScale();
3099             if (!(bounds->Intersect(position.x_, position.y_)) || opacity <= 0.f || scale <= 0.f) {
3100                 continue;
3101             }
3102             auto particleType = particle->GetParticleType();
3103 #ifndef USE_ROSEN_DRAWING
3104             SkPaint paint;
3105             paint.setAntiAlias(true);
3106             paint.setAlphaf(opacity);
3107             auto clipBounds = SkRect::MakeXYWH(bounds->left_, bounds->top_, bounds->width_, bounds->height_);
3108             canvas.clipRect(clipBounds, true);
3109 #else
3110             Drawing::Brush brush;
3111             brush.SetAntiAlias(true);
3112             brush.SetAlphaF(opacity);
3113             auto clipBounds = Drawing::Rect(
3114                 bounds->left_, bounds->top_, bounds->left_ + bounds->width_, bounds->top_ + bounds->height_);
3115             canvas.ClipRect(clipBounds, Drawing::ClipOp::INTERSECT, true);
3116 #endif
3117 
3118             if (particleType == ParticleType::POINTS) {
3119                 auto radius = particle->GetRadius();
3120                 Color color = particle->GetColor();
3121                 auto alpha = color.GetAlpha();
3122                 color.SetAlpha(alpha * opacity);
3123 #ifndef USE_ROSEN_DRAWING
3124                 paint.setColor(color.AsArgbInt());
3125                 canvas.drawCircle(position.x_, position.y_, radius * scale, paint);
3126 #else
3127                 brush.SetColor(color.AsArgbInt());
3128                 canvas.AttachBrush(brush);
3129                 canvas.DrawCircle(Drawing::Point(position.x_, position.y_), radius * scale);
3130                 canvas.DetachBrush();
3131 #endif
3132             } else {
3133                 auto imageSize = particle->GetImageSize();
3134                 auto image = particle->GetImage();
3135                 float left = position.x_;
3136                 float top = position.y_;
3137                 float right = position.x_ + imageSize.x_ * scale;
3138                 float bottom = position.y_ + imageSize.y_ * scale;
3139 #ifndef USE_ROSEN_DRAWING
3140                 canvas.save();
3141                 canvas.translate(position.x_, position.y_);
3142                 canvas.rotate(particle->GetSpin(), imageSize.x_ * scale / 2.f, imageSize.y_ * scale / 2.f);
3143 #else
3144                 canvas.Save();
3145                 canvas.Translate(position.x_, position.y_);
3146                 canvas.Rotate(particle->GetSpin(), imageSize.x_ * scale / 2.f, imageSize.y_ * scale / 2.f);
3147 #endif
3148                 RectF destRect(left, top, right, bottom);
3149                 image->SetDstRect(destRect);
3150                 image->SetScale(scale);
3151                 image->SetImageRepeat(0);
3152 #ifndef USE_ROSEN_DRAWING
3153                 SkRect rect { left, top, right, bottom };
3154                 image->CanvasDrawImage(canvas, rect, SkSamplingOptions(), paint, false);
3155                 canvas.restore();
3156 #else
3157                 Drawing::Rect rect { left, top, right, bottom };
3158                 canvas.AttachBrush(brush);
3159                 image->CanvasDrawImage(canvas, rect, Drawing::SamplingOptions(), false);
3160                 canvas.DetachBrush();
3161                 canvas.Restore();
3162 #endif
3163             }
3164         }
3165     }
3166 }
3167 
BeginBlendMode(RSPaintFilterCanvas & canvas,const RSProperties & properties)3168 void RSPropertiesPainter::BeginBlendMode(RSPaintFilterCanvas& canvas, const RSProperties& properties)
3169 {
3170     auto blendMode = properties.GetColorBlendMode();
3171     int blendModeApplyType = properties.GetColorBlendApplyType();
3172 
3173     if (blendMode == 0) {
3174         // no blend
3175         return;
3176     }
3177 
3178 #ifndef USE_ROSEN_DRAWING
3179     canvas.save();
3180     canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
3181 #else
3182     canvas.Save();
3183     canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, true);
3184 #endif
3185 
3186     // fast blend mode
3187     if (blendModeApplyType == static_cast<int>(RSColorBlendApplyType::FAST)) {
3188         canvas.SaveBlendMode();
3189         canvas.SetBlendMode({ blendMode - 1 }); // map blendMode to SkBlendMode
3190         return;
3191     }
3192 
3193     // save layer mode
3194 #ifndef USE_ROSEN_DRAWING
3195     auto matrix = canvas.getTotalMatrix();
3196     matrix.setTranslateX(std::ceil(matrix.getTranslateX()));
3197     matrix.setTranslateY(std::ceil(matrix.getTranslateY()));
3198     canvas.setMatrix(matrix);
3199     SkPaint blendPaint_;
3200     blendPaint_.setAlphaf(canvas.GetAlpha());
3201     blendPaint_.setBlendMode(static_cast<SkBlendMode>(blendMode - 1)); // map blendMode to SkBlendMode
3202     canvas.saveLayer(nullptr, &blendPaint_);
3203 #else
3204     auto matrix = canvas.GetTotalMatrix();
3205     matrix.Set(Drawing::Matrix::TRANS_X, std::ceil(matrix.Get(Drawing::Matrix::TRANS_X)));
3206     matrix.Set(Drawing::Matrix::TRANS_Y, std::ceil(matrix.Get(Drawing::Matrix::TRANS_Y)));
3207     canvas.SetMatrix(matrix);
3208     Drawing::Brush blendBrush_;
3209     blendBrush_.SetAlphaF(canvas.GetAlpha());
3210     blendBrush_.SetBlendMode(static_cast<Drawing::BlendMode>(blendMode - 1)); // map blendMode to Drawing::BlendMode
3211     Drawing::SaveLayerOps maskLayerRec(nullptr, &blendBrush_, 0);
3212     canvas.SaveLayer(maskLayerRec);
3213 #endif
3214     canvas.SaveBlendMode();
3215     canvas.SetBlendMode(std::nullopt);
3216     canvas.SaveAlpha();
3217     canvas.SetAlpha(1.0f);
3218 }
3219 
EndBlendMode(RSPaintFilterCanvas & canvas,const RSProperties & properties)3220 void RSPropertiesPainter::EndBlendMode(RSPaintFilterCanvas& canvas, const RSProperties& properties)
3221 {
3222     auto blendMode = properties.GetColorBlendMode();
3223     int blendModeApplyType = properties.GetColorBlendApplyType();
3224 
3225     if (blendMode == 0) {
3226         // no blend
3227         return;
3228     }
3229 
3230     if (blendModeApplyType == static_cast<int>(RSColorBlendApplyType::FAST)) {
3231         canvas.RestoreBlendMode();
3232     } else {
3233         canvas.RestoreBlendMode();
3234         canvas.RestoreAlpha();
3235 #ifndef USE_ROSEN_DRAWING
3236         canvas.restore();
3237 #else
3238         canvas.Restore();
3239 #endif
3240     }
3241 #ifndef USE_ROSEN_DRAWING
3242         canvas.restore();
3243 #else
3244         canvas.Restore();
3245 #endif
3246 }
3247 } // namespace Rosen
3248 } // namespace OHOS
3249