• 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 
18 #include "common/rs_optional_trace.h"
19 #include "common/rs_obj_abs_geometry.h"
20 #include "common/rs_vector2.h"
21 #include "pipeline/rs_draw_cmd_list.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 "render/rs_blur_filter.h"
26 #include "render/rs_image.h"
27 #include "render/rs_mask.h"
28 #include "render/rs_path.h"
29 #include "render/rs_shader.h"
30 #include "render/rs_skia_filter.h"
31 #include "animation/rs_render_particle.h"
32 
33 #ifdef USE_ROSEN_DRAWING
34 #include <cstdint>
35 
36 #include "draw/canvas.h"
37 #include "draw/clip.h"
38 #include "drawing/draw/core_canvas.h"
39 #include "recording/recording_path.h"
40 #include "recording/recording_shader_effect.h"
41 #include "utils/rect.h"
42 #else
43 #include "include/core/SkCanvas.h"
44 #include "include/core/SkColorFilter.h"
45 #include "include/core/SkMaskFilter.h"
46 #include "include/core/SkPaint.h"
47 #include "include/core/SkPoint3.h"
48 #include "include/core/SkRRect.h"
49 #include "include/core/SkSurface.h"
50 #include "include/effects/Sk1DPathEffect.h"
51 #include "include/effects/SkDashPathEffect.h"
52 #include "include/effects/SkGradientShader.h"
53 #include "include/effects/SkLumaColorFilter.h"
54 #include "include/utils/SkShadowUtils.h"
55 #include "src/image/SkImage_Base.h"
56 #ifdef NEW_SKIA
57 #include "include/effects/SkImageFilters.h"
58 #include "include/effects/SkRuntimeEffect.h"
59 #else
60 #include "include/effects/SkBlurImageFilter.h"
61 #endif
62 #endif
63 
64 namespace OHOS {
65 namespace Rosen {
66 namespace {
67 bool g_forceBgAntiAlias = true;
68 constexpr int PARAM_DOUBLE = 2;
69 constexpr float MIN_TRANS_RATIO = 0.0f;
70 constexpr float MAX_TRANS_RATIO = 0.95f;
71 constexpr float MIN_SPOT_RATIO = 1.0f;
72 constexpr float MAX_SPOT_RATIO = 1.95f;
73 constexpr float MAX_AMBIENT_RADIUS = 150.0f;
74 const bool BLUR_ENABLED = RSSystemProperties::GetBlurEnabled();
75 #ifndef USE_ROSEN_DRAWING
76 constexpr static float FLOAT_ZERO_THRESHOLD = 0.001f;
77 constexpr static uint8_t DIRECTION_NUM = 4;
78 #endif
79 } // namespace
80 
81 #ifndef USE_ROSEN_DRAWING
Rect2SkRect(const RectF & r)82 SkRect RSPropertiesPainter::Rect2SkRect(const RectF& r)
83 {
84     return SkRect::MakeXYWH(r.left_, r.top_, r.width_, r.height_);
85 }
86 #else
Rect2DrawingRect(const RectF & r)87 Drawing::Rect RSPropertiesPainter::Rect2DrawingRect(const RectF& r)
88 {
89     return Drawing::Rect(r.left_, r.top_, r.left_ + r.width_, r.top_ + r.height_);
90 }
91 #endif
92 
93 #ifndef USE_ROSEN_DRAWING
RRect2SkRRect(const RRect & rr)94 SkRRect RSPropertiesPainter::RRect2SkRRect(const RRect& rr)
95 {
96     SkRect rect = SkRect::MakeXYWH(rr.rect_.left_, rr.rect_.top_, rr.rect_.width_, rr.rect_.height_);
97     SkRRect rrect = SkRRect::MakeEmpty();
98 
99     // set radius for all 4 corner of RRect
100     constexpr uint32_t NUM_OF_CORNERS_IN_RECT = 4;
101     SkVector vec[NUM_OF_CORNERS_IN_RECT];
102     for (uint32_t i = 0; i < NUM_OF_CORNERS_IN_RECT; i++) {
103         vec[i].set(rr.radius_[i].x_, rr.radius_[i].y_);
104     }
105 
106     rrect.setRectRadii(rect, vec);
107     return rrect;
108 }
109 #else
RRect2DrawingRRect(const RRect & rr)110 Drawing::RoundRect RSPropertiesPainter::RRect2DrawingRRect(const RRect& rr)
111 {
112     Drawing::Rect rect = Drawing::Rect(
113         rr.rect_.left_, rr.rect_.top_, rr.rect_.left_ + rr.rect_.width_, rr.rect_.top_ + rr.rect_.height_);
114 
115     // set radius for all 4 corner of RRect
116     constexpr uint32_t NUM_OF_CORNERS_IN_RECT = 4;
117     std::vector<Drawing::Point> radii(NUM_OF_CORNERS_IN_RECT);
118     for (uint32_t i = 0; i < NUM_OF_CORNERS_IN_RECT; i++) {
119         radii.at(i).SetX(rr.radius_[i].x_);
120         radii.at(i).SetY(rr.radius_[i].y_);
121     }
122     return Drawing::RoundRect(rect, radii);
123 }
124 #endif
125 
126 #ifndef USE_ROSEN_DRAWING
GetGravityMatrix(Gravity gravity,RectF rect,float w,float h,SkMatrix & mat)127 bool RSPropertiesPainter::GetGravityMatrix(Gravity gravity, RectF rect, float w, float h, SkMatrix& mat)
128 {
129     if (w == rect.width_ && h == rect.height_) {
130         return false;
131     }
132     mat.reset();
133     switch (gravity) {
134         case Gravity::CENTER: {
135             mat.preTranslate((rect.width_ - w) / PARAM_DOUBLE, (rect.height_ - h) / PARAM_DOUBLE);
136             return true;
137         }
138         case Gravity::TOP: {
139             mat.preTranslate((rect.width_ - w) / PARAM_DOUBLE, 0);
140             return true;
141         }
142         case Gravity::BOTTOM: {
143             mat.preTranslate((rect.width_ - w) / PARAM_DOUBLE, rect.height_ - h);
144             return true;
145         }
146         case Gravity::LEFT: {
147             mat.preTranslate(0, (rect.height_ - h) / PARAM_DOUBLE);
148             return true;
149         }
150         case Gravity::RIGHT: {
151             mat.preTranslate(rect.width_ - w, (rect.height_ - h) / PARAM_DOUBLE);
152             return true;
153         }
154         case Gravity::TOP_LEFT: {
155             return false;
156         }
157         case Gravity::TOP_RIGHT: {
158             mat.preTranslate(rect.width_ - w, 0);
159             return true;
160         }
161         case Gravity::BOTTOM_LEFT: {
162             mat.preTranslate(0, rect.height_ - h);
163             return true;
164         }
165         case Gravity::BOTTOM_RIGHT: {
166             mat.preTranslate(rect.width_ - w, rect.height_ - h);
167             return true;
168         }
169         case Gravity::RESIZE: {
170             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
171                 return false;
172             }
173             mat.preScale(rect.width_ / w, rect.height_ / h);
174             return true;
175         }
176         case Gravity::RESIZE_ASPECT: {
177             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
178                 return false;
179             }
180             float scale = std::min(rect.width_ / w, rect.height_ / h);
181             if (ROSEN_EQ(scale, 0.f)) {
182                 return false;
183             }
184             mat.preScale(scale, scale);
185             mat.preTranslate((rect.width_ / scale - w) / PARAM_DOUBLE, (rect.height_ / scale - h) / PARAM_DOUBLE);
186             return true;
187         }
188         case Gravity::RESIZE_ASPECT_TOP_LEFT: {
189             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
190                 return false;
191             }
192             float scale = std::min(rect.width_ / w, rect.height_ / h);
193             mat.preScale(scale, scale);
194             return true;
195         }
196         case Gravity::RESIZE_ASPECT_BOTTOM_RIGHT: {
197             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
198                 return false;
199             }
200             float scale = std::min(rect.width_ / w, rect.height_ / h);
201             if (ROSEN_EQ(scale, 0.f)) {
202                 return false;
203             }
204             mat.preScale(scale, scale);
205             mat.preTranslate(rect.width_ / scale - w, rect.height_ / scale - h);
206             return true;
207         }
208         case Gravity::RESIZE_ASPECT_FILL: {
209             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
210                 return false;
211             }
212             float scale = std::max(rect.width_ / w, rect.height_ / h);
213             if (ROSEN_EQ(scale, 0.f)) {
214                 return false;
215             }
216             mat.preScale(scale, scale);
217             mat.preTranslate((rect.width_ / scale - w) / PARAM_DOUBLE, (rect.height_ / scale - h) / PARAM_DOUBLE);
218             return true;
219         }
220         case Gravity::RESIZE_ASPECT_FILL_TOP_LEFT: {
221             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
222                 return false;
223             }
224             float scale = std::max(rect.width_ / w, rect.height_ / h);
225             mat.preScale(scale, scale);
226             return true;
227         }
228         case Gravity::RESIZE_ASPECT_FILL_BOTTOM_RIGHT: {
229             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
230                 return false;
231             }
232             float scale = std::max(rect.width_ / w, rect.height_ / h);
233             if (ROSEN_EQ(scale, 0.f)) {
234                 return false;
235             }
236             mat.preScale(scale, scale);
237             mat.preTranslate(rect.width_ / scale - w, rect.height_ / scale - h);
238             return true;
239         }
240         default: {
241             ROSEN_LOGE("GetGravityMatrix unknow gravity=[%d]", gravity);
242             return false;
243         }
244     }
245 }
246 #else
GetGravityMatrix(Gravity gravity,RectF rect,float w,float h,Drawing::Matrix & mat)247 bool RSPropertiesPainter::GetGravityMatrix(Gravity gravity, RectF rect, float w, float h, Drawing::Matrix& mat)
248 {
249     if (w == rect.width_ && h == rect.height_) {
250         return false;
251     }
252     mat = Drawing::Matrix();
253     switch (gravity) {
254         case Gravity::CENTER: {
255             mat.PreTranslate((rect.width_ - w) / PARAM_DOUBLE, (rect.height_ - h) / PARAM_DOUBLE);
256             return true;
257         }
258         case Gravity::TOP: {
259             mat.PreTranslate((rect.width_ - w) / PARAM_DOUBLE, 0);
260             return true;
261         }
262         case Gravity::BOTTOM: {
263             mat.PreTranslate((rect.width_ - w) / PARAM_DOUBLE, rect.height_ - h);
264             return true;
265         }
266         case Gravity::LEFT: {
267             mat.PreTranslate(0, (rect.height_ - h) / PARAM_DOUBLE);
268             return true;
269         }
270         case Gravity::RIGHT: {
271             mat.PreTranslate(rect.width_ - w, (rect.height_ - h) / PARAM_DOUBLE);
272             return true;
273         }
274         case Gravity::TOP_LEFT: {
275             return false;
276         }
277         case Gravity::TOP_RIGHT: {
278             mat.PreTranslate(rect.width_ - w, 0);
279             return true;
280         }
281         case Gravity::BOTTOM_LEFT: {
282             mat.PreTranslate(0, rect.height_ - h);
283             return true;
284         }
285         case Gravity::BOTTOM_RIGHT: {
286             mat.PreTranslate(rect.width_ - w, rect.height_ - h);
287             return true;
288         }
289         case Gravity::RESIZE: {
290             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
291                 return false;
292             }
293             mat.PreScale(rect.width_ / w, rect.height_ / h);
294             return true;
295         }
296         case Gravity::RESIZE_ASPECT: {
297             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
298                 return false;
299             }
300             float scale = std::min(rect.width_ / w, rect.height_ / h);
301             if (ROSEN_EQ(scale, 0.f)) {
302                 return false;
303             }
304             mat.PreScale(scale, scale);
305             mat.PreTranslate((rect.width_ / scale - w) / PARAM_DOUBLE, (rect.height_ / scale - h) / PARAM_DOUBLE);
306             return true;
307         }
308         case Gravity::RESIZE_ASPECT_TOP_LEFT: {
309             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
310                 return false;
311             }
312             float scale = std::min(rect.width_ / w, rect.height_ / h);
313             mat.PreScale(scale, scale);
314             return true;
315         }
316         case Gravity::RESIZE_ASPECT_BOTTOM_RIGHT: {
317             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
318                 return false;
319             }
320             float scale = std::min(rect.width_ / w, rect.height_ / h);
321             if (ROSEN_EQ(scale, 0.f)) {
322                 return false;
323             }
324             mat.PreScale(scale, scale);
325             mat.PreTranslate(rect.width_ / scale - w, rect.height_ / scale - h);
326             return true;
327         }
328         case Gravity::RESIZE_ASPECT_FILL: {
329             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
330                 return false;
331             }
332             float scale = std::max(rect.width_ / w, rect.height_ / h);
333             if (ROSEN_EQ(scale, 0.f)) {
334                 return false;
335             }
336             mat.PreScale(scale, scale);
337             mat.PreTranslate((rect.width_ / scale - w) / PARAM_DOUBLE, (rect.height_ / scale - h) / PARAM_DOUBLE);
338             return true;
339         }
340         case Gravity::RESIZE_ASPECT_FILL_TOP_LEFT: {
341             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
342                 return false;
343             }
344             float scale = std::max(rect.width_ / w, rect.height_ / h);
345             mat.PreScale(scale, scale);
346             return true;
347         }
348         case Gravity::RESIZE_ASPECT_FILL_BOTTOM_RIGHT: {
349             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
350                 return false;
351             }
352             float scale = std::max(rect.width_ / w, rect.height_ / h);
353             if (ROSEN_EQ(scale, 0.f)) {
354                 return false;
355             }
356             mat.PreScale(scale, scale);
357             mat.PreTranslate(rect.width_ / scale - w, rect.height_ / scale - h);
358             return true;
359         }
360         default: {
361             ROSEN_LOGE("GetGravityMatrix unknow gravity=[%d]", gravity);
362             return false;
363         }
364     }
365 }
366 #endif
367 
368 #ifndef USE_ROSEN_DRAWING
Clip(SkCanvas & canvas,RectF rect,bool isAntiAlias)369 void RSPropertiesPainter::Clip(SkCanvas& canvas, RectF rect, bool isAntiAlias)
370 {
371     // isAntiAlias is false only the method is called in ProcessAnimatePropertyBeforeChildren().
372     canvas.clipRect(Rect2SkRect(rect), isAntiAlias);
373 }
374 #else
Clip(Drawing::Canvas & canvas,RectF rect,bool isAntiAlias)375 void RSPropertiesPainter::Clip(Drawing::Canvas& canvas, RectF rect, bool isAntiAlias)
376 {
377     canvas.ClipRect(Rect2DrawingRect(rect), Drawing::ClipOp::INTERSECT, isAntiAlias);
378 }
379 #endif
380 
381 #ifndef USE_ROSEN_DRAWING
GetShadowDirtyRect(RectI & dirtyShadow,const RSProperties & properties,const RRect * rrect,bool isAbsCoordinate)382 void RSPropertiesPainter::GetShadowDirtyRect(RectI& dirtyShadow, const RSProperties& properties,
383     const RRect* rrect, bool isAbsCoordinate)
384 {
385     // [Planning]: After Skia being updated, we should directly call SkShadowUtils::GetLocalBounds here.
386     if (!properties.IsShadowValid()) {
387         return;
388     }
389     SkPath skPath;
390     if (properties.GetShadowPath() && !properties.GetShadowPath()->GetSkiaPath().isEmpty()) {
391         skPath = properties.GetShadowPath()->GetSkiaPath();
392     } else if (properties.GetClipBounds()) {
393         skPath = properties.GetClipBounds()->GetSkiaPath();
394     } else {
395         if (rrect != nullptr) {
396             skPath.addRRect(RRect2SkRRect(*rrect));
397         } else {
398             skPath.addRRect(RRect2SkRRect(properties.GetRRect()));
399         }
400     }
401     skPath.offset(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
402 
403     SkRect shadowRect = skPath.getBounds();
404     if (properties.shadow_->GetHardwareAcceleration()) {
405         if (properties.GetShadowElevation() <= 0.f) {
406             return;
407         }
408         float elevation = properties.GetShadowElevation() + DEFAULT_TRANSLATION_Z;
409 
410         float userTransRatio =
411             (elevation != DEFAULT_LIGHT_HEIGHT) ? elevation / (DEFAULT_LIGHT_HEIGHT - elevation) : MAX_TRANS_RATIO;
412         float transRatio = std::max(MIN_TRANS_RATIO, std::min(userTransRatio, MAX_TRANS_RATIO));
413 
414         float userSpotRatio = (elevation != DEFAULT_LIGHT_HEIGHT)
415                                   ? DEFAULT_LIGHT_HEIGHT / (DEFAULT_LIGHT_HEIGHT - elevation)
416                                   : MAX_SPOT_RATIO;
417         float spotRatio = std::max(MIN_SPOT_RATIO, std::min(userSpotRatio, MAX_SPOT_RATIO));
418 
419         SkRect ambientRect = skPath.getBounds();
420         SkRect spotRect = SkRect::MakeLTRB(ambientRect.left() * spotRatio, ambientRect.top() * spotRatio,
421             ambientRect.right() * spotRatio, ambientRect.bottom() * spotRatio);
422         spotRect.offset(-transRatio * DEFAULT_LIGHT_POSITION_X, -transRatio * DEFAULT_LIGHT_POSITION_Y);
423         spotRect.outset(transRatio * DEFAULT_LIGHT_RADIUS, transRatio * DEFAULT_LIGHT_RADIUS);
424 
425         shadowRect = ambientRect;
426         float ambientBlur = std::min(elevation * 0.5f, MAX_AMBIENT_RADIUS);
427         shadowRect.outset(ambientBlur, ambientBlur);
428         shadowRect.join(spotRect);
429         shadowRect.outset(1, 1);
430     } else {
431         SkPaint paint;
432         paint.setAntiAlias(true);
433         paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, properties.GetShadowRadius()));
434         if (paint.canComputeFastBounds()) {
435             paint.computeFastBounds(shadowRect, &shadowRect);
436         }
437     }
438 
439     auto geoPtr = (properties.GetBoundsGeometry());
440     SkMatrix matrix = (geoPtr && isAbsCoordinate) ? geoPtr->GetAbsMatrix() : SkMatrix::I();
441     matrix.mapRect(&shadowRect);
442 
443     dirtyShadow.left_ = shadowRect.left();
444     dirtyShadow.top_ = shadowRect.top();
445     dirtyShadow.width_ = shadowRect.width();
446     dirtyShadow.height_ = shadowRect.height();
447 }
448 #else
GetShadowDirtyRect(RectI & dirtyShadow,const RSProperties & properties,const RRect * rrect,bool isAbsCoordinate)449 void RSPropertiesPainter::GetShadowDirtyRect(RectI& dirtyShadow, const RSProperties& properties,
450     const RRect* rrect, bool isAbsCoordinate)
451 {
452     // [Planning]: After Skia being updated, we should directly call SkShadowUtils::GetLocalBounds here.
453     if (!properties.IsShadowValid()) {
454         return;
455     }
456     Drawing::Path path;
457     if (properties.GetShadowPath() && !properties.GetShadowPath()->GetDrawingPath().IsValid()) {
458         path = properties.GetShadowPath()->GetDrawingPath();
459     } else if (properties.GetClipBounds()) {
460         path = properties.GetClipBounds()->GetDrawingPath();
461     } else {
462         if (rrect != nullptr) {
463             path.AddRoundRect(RRect2DrawingRRect(*rrect));
464         } else {
465             path.AddRoundRect(RRect2DrawingRRect(properties.GetRRect()));
466         }
467     }
468     path.Offset(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
469 
470     Drawing::Rect shadowRect = path.GetBounds();
471     if (properties.shadow_->GetHardwareAcceleration()) {
472         if (properties.GetShadowElevation() <= 0.f) {
473             return;
474         }
475         float elevation = properties.GetShadowElevation() + DEFAULT_TRANSLATION_Z;
476 
477         float userTransRatio =
478             (elevation != DEFAULT_LIGHT_HEIGHT) ? elevation / (DEFAULT_LIGHT_HEIGHT - elevation) : MAX_TRANS_RATIO;
479         float transRatio = std::max(MIN_TRANS_RATIO, std::min(userTransRatio, MAX_TRANS_RATIO));
480 
481         float userSpotRatio = (elevation != DEFAULT_LIGHT_HEIGHT)
482                                   ? DEFAULT_LIGHT_HEIGHT / (DEFAULT_LIGHT_HEIGHT - elevation)
483                                   : MAX_SPOT_RATIO;
484         float spotRatio = std::max(MIN_SPOT_RATIO, std::min(userSpotRatio, MAX_SPOT_RATIO));
485 
486         Drawing::Rect ambientRect = path.GetBounds();
487         Drawing::Rect spotRect = Drawing::Rect(ambientRect.GetLeft() * spotRatio, ambientRect.GetTop() * spotRatio,
488             ambientRect.GetRight() * spotRatio, ambientRect.GetBottom() * spotRatio);
489         spotRect.Offset(-transRatio * DEFAULT_LIGHT_POSITION_X, -transRatio * DEFAULT_LIGHT_POSITION_Y);
490         // spotRect outset (transRatio * DEFAULT_LIGHT_RADIUS, transRatio * DEFAULT_LIGHT_RADIUS)
491         spotRect.SetLeft(spotRect.GetLeft() - transRatio * DEFAULT_LIGHT_RADIUS);
492         spotRect.SetTop(spotRect.GetTop() - transRatio * DEFAULT_LIGHT_RADIUS);
493         spotRect.SetRight(spotRect.GetRight() + transRatio * DEFAULT_LIGHT_RADIUS);
494         spotRect.SetBottom(spotRect.GetBottom() + transRatio * DEFAULT_LIGHT_RADIUS);
495 
496         shadowRect = ambientRect;
497         std::min(elevation * 0.5f, MAX_AMBIENT_RADIUS);
498         float ambientBlur = std::min(elevation * 0.5f, MAX_AMBIENT_RADIUS);
499         // shadowRect outset (ambientBlur, ambientBlur)
500         shadowRect.SetLeft(shadowRect.GetLeft() - ambientBlur);
501         shadowRect.SetTop(shadowRect.GetTop() - ambientBlur);
502         shadowRect.SetRight(shadowRect.GetRight() + ambientBlur);
503         shadowRect.SetBottom(shadowRect.GetBottom() + ambientBlur);
504 
505         shadowRect.Join(spotRect);
506         // shadowRect outset (1, 1)
507         shadowRect.SetLeft(shadowRect.GetLeft() - 1);
508         shadowRect.SetTop(shadowRect.GetTop() - 1);
509         shadowRect.SetRight(shadowRect.GetRight() + 1);
510         shadowRect.SetBottom(shadowRect.GetBottom() + 1);
511     } else {
512         Drawing::Brush brush;
513         brush.SetAntiAlias(true);
514         Drawing::Filter filter;
515         filter.SetMaskFilter(
516             Drawing::MaskFilter::CreateBlurMaskFilter(Drawing::BlurType::NORMAL, properties.GetShadowRadius()));
517         brush.SetFilter(filter);
518     }
519 
520     auto geoPtr = (properties.GetBoundsGeometry());
521     Drawing::Matrix matrix = geoPtr ? geoPtr->GetAbsMatrix() : Drawing::Matrix();
522     matrix.MapRect(shadowRect, shadowRect);
523 
524     dirtyShadow.left_ = shadowRect.GetLeft();
525     dirtyShadow.top_ = shadowRect.GetTop();
526     dirtyShadow.width_ = shadowRect.GetWidth();
527     dirtyShadow.height_ = shadowRect.GetHeight();
528 }
529 #endif
530 
531 #ifndef USE_ROSEN_DRAWING
DrawShadow(const RSProperties & properties,RSPaintFilterCanvas & canvas,const RRect * rrect,bool isLeashWindow)532 void RSPropertiesPainter::DrawShadow(const RSProperties& properties,
533     RSPaintFilterCanvas& canvas, const RRect* rrect, bool isLeashWindow)
534 {
535     // skip shadow if not valid or cache is enabled
536     if (properties.IsSpherizeValid() || !properties.IsShadowValid() ||
537         canvas.GetCacheType() == RSPaintFilterCanvas::CacheType::ENABLED) {
538         return;
539     }
540     RSAutoCanvasRestore acr(&canvas);
541     SkPath skPath;
542     if (properties.GetShadowPath() && !properties.GetShadowPath()->GetSkiaPath().isEmpty()) {
543         skPath = properties.GetShadowPath()->GetSkiaPath();
544         if (!isLeashWindow) {
545             canvas.clipPath(skPath, SkClipOp::kDifference, true);
546         }
547     } else if (properties.GetClipBounds()) {
548         skPath = properties.GetClipBounds()->GetSkiaPath();
549         if (!isLeashWindow) {
550             canvas.clipPath(skPath, SkClipOp::kDifference, true);
551         }
552     } else {
553         if (rrect != nullptr) {
554             skPath.addRRect(RRect2SkRRect(*rrect));
555             if (!isLeashWindow) {
556                 canvas.clipRRect(RRect2SkRRect(*rrect), SkClipOp::kDifference, true);
557             }
558         } else {
559             skPath.addRRect(RRect2SkRRect(properties.GetRRect()));
560             if (!isLeashWindow) {
561                 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), SkClipOp::kDifference, true);
562             }
563         }
564     }
565     if (properties.GetShadowMask()) {
566         DrawColorfulShadowInner(properties, canvas, skPath);
567     } else {
568         DrawShadowInner(properties, canvas, skPath);
569     }
570 }
571 #else
DrawShadow(const RSProperties & properties,RSPaintFilterCanvas & canvas,const RRect * rrect,bool isLeashWindow)572 void RSPropertiesPainter::DrawShadow(const RSProperties& properties,
573     RSPaintFilterCanvas& canvas, const RRect* rrect, bool isLeashWindow)
574 {
575     // skip shadow if not valid or cache is enabled
576     //Todo isCacheEnabled
577     if (properties.IsSpherizeValid() || !properties.IsShadowValid()) {
578         return;
579     }
580     Drawing::AutoCanvasRestore acr(canvas, true);
581     Drawing::Path path;
582     if (properties.GetShadowPath() && !properties.GetShadowPath()->GetDrawingPath().IsValid()) {
583         path = properties.GetShadowPath()->GetDrawingPath();
584         if (!isLeashWindow) {
585             canvas.ClipPath(path, Drawing::ClipOp::DIFFERENCE, true);
586         }
587     } else if (properties.GetClipBounds()) {
588         path = properties.GetClipBounds()->GetDrawingPath();
589         if (!isLeashWindow) {
590             canvas.ClipPath(path, Drawing::ClipOp::DIFFERENCE, true);
591         }
592     } else {
593         if (rrect != nullptr) {
594             path.AddRoundRect(RRect2DrawingRRect(*rrect));
595             if (!isLeashWindow) {
596                 canvas.ClipRoundRect(RRect2DrawingRRect(*rrect), Drawing::ClipOp::DIFFERENCE, true);
597             }
598         } else {
599             path.AddRoundRect(RRect2DrawingRRect(properties.GetRRect()));
600             if (!isLeashWindow) {
601                 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::DIFFERENCE, true);
602             }
603         }
604     }
605     if (properties.GetShadowMask()) {
606         DrawColorfulShadowInner(properties, canvas, path);
607     } else {
608         DrawShadowInner(properties, canvas, path);
609     }
610 }
611 #endif
612 
613 #ifndef USE_ROSEN_DRAWING
DrawColorfulShadowInner(const RSProperties & properties,RSPaintFilterCanvas & canvas,SkPath & skPath)614 void RSPropertiesPainter::DrawColorfulShadowInner(
615     const RSProperties& properties, RSPaintFilterCanvas& canvas, SkPath& skPath)
616 {
617     // blurRadius calculation is based on the formula in SkShadowUtils::DrawShadow, 0.25f and 128.0f are constants
618     const SkScalar blurRadius =
619         properties.shadow_->GetHardwareAcceleration()
620             ? 0.25f * properties.GetShadowElevation() * (1 + properties.GetShadowElevation() / 128.0f)
621             : properties.GetShadowRadius();
622 
623     // save layer, draw image with clipPath, blur and draw back
624     SkPaint blurPaint;
625 #ifdef NEW_SKIA
626     blurPaint.setImageFilter(SkImageFilters::Blur(blurRadius, blurRadius, SkTileMode::kDecal, nullptr));
627 #else
628     blurPaint.setImageFilter(SkBlurImageFilter::Make(blurRadius, blurRadius, SkTileMode::kDecal, nullptr));
629 #endif
630     canvas.saveLayer(nullptr, &blurPaint);
631 
632     canvas.translate(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
633 
634     canvas.clipPath(skPath);
635     // draw node content as shadow
636     // [PLANNING]: maybe we should also draw background color / image here, and we should cache the shadow image
637     if (auto node = RSBaseRenderNode::ReinterpretCast<RSCanvasRenderNode>(properties.backref_.lock())) {
638         node->InternalDrawContent(canvas);
639     }
640 }
641 #else
DrawColorfulShadowInner(const RSProperties & properties,RSPaintFilterCanvas & canvas,Drawing::Path & path)642 void RSPropertiesPainter::DrawColorfulShadowInner(
643     const RSProperties& properties, RSPaintFilterCanvas& canvas, Drawing::Path& path)
644 {
645     // blurRadius calculation is based on the formula in Canvas::DrawShadow, 0.25f and 128.0f are constants
646     const Drawing::scalar blurRadius =
647         properties.shadow_->GetHardwareAcceleration()
648             ? 0.25f * properties.GetShadowElevation() * (1 + properties.GetShadowElevation() / 128.0f)
649             : properties.GetShadowRadius();
650 
651     // save layer, draw image with clipPath, blur and draw back
652     Drawing::Brush blurBrush;
653     Drawing::Filter filter;
654     filter.SetImageFilter(Drawing::ImageFilter::CreateBlurImageFilter(
655         blurRadius, blurRadius, Drawing::TileMode::DECAL, nullptr));
656     blurBrush.SetFilter(filter);
657 
658     canvas.SaveLayer({nullptr, &blurBrush});
659 
660     canvas.Translate(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
661 
662     canvas.ClipPath(path, Drawing::ClipOp::INTERSECT, false);
663     // draw node content as shadow
664     // [PLANNING]: maybe we should also draw background color / image here, and we should cache the shadow image
665     if (auto node = RSBaseRenderNode::ReinterpretCast<RSCanvasRenderNode>(properties.backref_.lock())) {
666         node->InternalDrawContent(canvas);
667     }
668 }
669 #endif
670 
671 #ifndef USE_ROSEN_DRAWING
DrawShadowInner(const RSProperties & properties,RSPaintFilterCanvas & canvas,SkPath & skPath)672 void RSPropertiesPainter::DrawShadowInner(const RSProperties& properties, RSPaintFilterCanvas& canvas, SkPath& skPath)
673 {
674     skPath.offset(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
675     Color spotColor = properties.GetShadowColor();
676 
677     // The translation of the matrix is rounded to improve the hit ratio of skia blurfilter cache,
678     // the function <compute_key_and_clip_bounds> in <skia/src/gpu/GrBlurUtil.cpp> for more details.
679     RSAutoCanvasRestore rst(&canvas);
680     auto matrix = canvas.getTotalMatrix();
681     matrix.setTranslateX(std::ceil(matrix.getTranslateX()));
682     matrix.setTranslateY(std::ceil(matrix.getTranslateY()));
683     // Round the scaleX/scaleY to 2 decimal places.
684     matrix.setScaleX(std::round(matrix.getScaleX() * 100) / 100);
685     matrix.setScaleY(std::round(matrix.getScaleY() * 100) / 100);
686     canvas.setMatrix(matrix);
687 
688     if (properties.shadow_->GetHardwareAcceleration()) {
689         if (properties.GetShadowElevation() <= 0.f) {
690             return;
691         }
692         SkPoint3 planeParams = { 0.0f, 0.0f, properties.GetShadowElevation() };
693         SkPoint3 lightPos = { canvas.getTotalMatrix().getTranslateX() + skPath.getBounds().centerX(),
694             canvas.getTotalMatrix().getTranslateY() + skPath.getBounds().centerY(), DEFAULT_LIGHT_HEIGHT };
695         Color ambientColor = Color::FromArgbInt(DEFAULT_AMBIENT_COLOR);
696         ambientColor.MultiplyAlpha(canvas.GetAlpha());
697         spotColor.MultiplyAlpha(canvas.GetAlpha());
698         SkShadowUtils::DrawShadow(&canvas, skPath, planeParams, lightPos, DEFAULT_LIGHT_RADIUS,
699             ambientColor.AsArgbInt(), spotColor.AsArgbInt(), SkShadowFlags::kTransparentOccluder_ShadowFlag);
700     } else {
701         SkPaint paint;
702         paint.setColor(spotColor.AsArgbInt());
703         paint.setAntiAlias(true);
704         paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, properties.GetShadowRadius()));
705         canvas.drawPath(skPath, paint);
706     }
707 }
708 #else
DrawShadowInner(const RSProperties & properties,RSPaintFilterCanvas & canvas,Drawing::Path & path)709 void RSPropertiesPainter::DrawShadowInner(
710     const RSProperties& properties, RSPaintFilterCanvas& canvas, Drawing::Path& path)
711 {
712     path.Offset(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
713     Color spotColor = properties.GetShadowColor();
714     if (properties.shadow_->GetHardwareAcceleration()) {
715         if (properties.GetShadowElevation() <= 0.f) {
716             return;
717         }
718         Drawing::Point3 planeParams = { 0.0f, 0.0f, properties.GetShadowElevation() };
719         Drawing::scalar centerX = path.GetBounds().GetLeft() + path.GetBounds().GetWidth() / 2;
720         Drawing::scalar centerY = path.GetBounds().GetTop() + path.GetBounds().GetHeight() / 2;
721         Drawing::Point3 lightPos = {
722             canvas.GetTotalMatrix().Get(Drawing::Matrix::TRANS_X) + centerX,
723             canvas.GetTotalMatrix().Get(Drawing::Matrix::TRANS_X) + centerY, DEFAULT_LIGHT_HEIGHT };
724         Color ambientColor = Color::FromArgbInt(DEFAULT_AMBIENT_COLOR);
725         ambientColor.MultiplyAlpha(canvas.GetAlpha());
726         spotColor.MultiplyAlpha(canvas.GetAlpha());
727         canvas.DrawShadow(path, planeParams, lightPos, DEFAULT_LIGHT_RADIUS,
728             Drawing::Color(ambientColor.AsArgbInt()), Drawing::Color(spotColor.AsArgbInt()),
729             Drawing::ShadowFlags::TRANSPARENT_OCCLUDER);
730     } else {
731         Drawing::Brush brush;
732         brush.SetColor(Drawing::Color(spotColor.AsArgbInt()));
733         brush.SetAntiAlias(true);
734         Drawing::Filter filter;
735         filter.SetMaskFilter(
736             Drawing::MaskFilter::CreateBlurMaskFilter(Drawing::BlurType::NORMAL, properties.GetShadowRadius()));
737         brush.SetFilter(filter);
738         canvas.AttachBrush(brush);
739         canvas.DrawPath(path);
740         canvas.DetachBrush();
741     }
742 }
743 #endif
744 
745 #ifndef USE_ROSEN_DRAWING
746 #ifdef NEW_SKIA
GetGradientDirectionPoints(SkPoint (& pts)[2],const SkRect & clipBounds,GradientDirection direction)747 bool RSPropertiesPainter::GetGradientDirectionPoints(
748     SkPoint (&pts)[2], const SkRect& clipBounds, GradientDirection direction)
749 {
750     switch (direction) {
751         case GradientDirection::BOTTOM: {
752             pts[0].set(clipBounds.width() / 2, 0); // 2 represents middle of width;
753             pts[1].set(clipBounds.width() / 2, clipBounds.height()); // 2 represents middle of width;
754             break;
755         }
756         case GradientDirection::TOP: {
757             pts[0].set(clipBounds.width() / 2, clipBounds.height()); // 2 represents middle of width;
758             pts[1].set(clipBounds.width() / 2, 0); // 2 represents middle of width;
759             break;
760         }
761         case GradientDirection::RIGHT: {
762             pts[0].set(0, clipBounds.height() / 2); // 2 represents middle of height;
763             pts[1].set(clipBounds.width(), clipBounds.height() / 2); // 2 represents middle of height;
764             break;
765         }
766         case GradientDirection::LEFT: {
767             pts[0].set(clipBounds.width(), clipBounds.height() / 2); // 2 represents middle of height;
768             pts[1].set(0, clipBounds.height() / 2); // 2 represents middle of height;
769             break;
770         }
771         case GradientDirection::RIGHT_BOTTOM: {
772             pts[0].set(0, 0);
773             pts[1].set(clipBounds.width(), clipBounds.height());
774             break;
775         }
776         case GradientDirection::LEFT_TOP: {
777             pts[0].set(clipBounds.width(), clipBounds.height());
778             pts[1].set(0, 0);
779             break;
780         }
781         case GradientDirection::LEFT_BOTTOM: {
782             pts[0].set(clipBounds.width(), 0);
783             pts[1].set(0, clipBounds.height());
784             break;
785         }
786         case GradientDirection::RIGHT_TOP: {
787             pts[0].set(0, clipBounds.height());
788             pts[1].set(clipBounds.width(), 0);
789             break;
790         }
791         default: {
792             return false;
793         }
794     }
795     return true;
796 }
TransformGradientBlurDirection(uint8_t & direction,const uint8_t directionBias)797 void RSPropertiesPainter::TransformGradientBlurDirection(uint8_t& direction, const uint8_t directionBias)
798 {
799     if (direction == static_cast<uint8_t>(GradientDirection::LEFT_BOTTOM)) {
800         direction += 2; // 2 is used to transtorm diagnal direction.
801     } else if (direction == static_cast<uint8_t>(GradientDirection::RIGHT_TOP) ||
802                     direction == static_cast<uint8_t>(GradientDirection::RIGHT_BOTTOM)) {
803         direction -= 1; // 1 is used to transtorm diagnal direction.
804     }
805     if (direction <= static_cast<uint8_t>(GradientDirection::BOTTOM)) {
806         if (direction < directionBias) {
807             direction += DIRECTION_NUM;
808         }
809         direction -= directionBias;
810     } else {
811         direction -= DIRECTION_NUM;
812         if (direction < directionBias) {
813             direction += DIRECTION_NUM;
814         }
815         direction -= directionBias;
816         direction += DIRECTION_NUM;
817     }
818     if (direction == static_cast<uint8_t>(GradientDirection::RIGHT_BOTTOM)) {
819         direction -= 2; // 2 is used to restore diagnal direction.
820     } else if (direction == static_cast<uint8_t>(GradientDirection::LEFT_BOTTOM) ||
821                         direction == static_cast<uint8_t>(GradientDirection::RIGHT_TOP)) {
822         direction += 1; // 1 is used to restore diagnal direction.
823     }
824 }
825 
MakeAlphaGradientShader(const SkRect & clipBounds,const std::shared_ptr<RSLinearGradientBlurPara> & para,uint8_t directionBias)826 sk_sp<SkShader> RSPropertiesPainter::MakeAlphaGradientShader(
827     const SkRect& clipBounds, const std::shared_ptr<RSLinearGradientBlurPara>& para, uint8_t directionBias)
828 {
829     std::vector<SkColor> c;
830     std::vector<SkScalar> p;
831     SkPoint pts[2];
832     uint8_t direction = static_cast<uint8_t>(para->direction_);
833     if (directionBias != 0) {
834         TransformGradientBlurDirection(direction, directionBias);
835     }
836     bool result = GetGradientDirectionPoints(
837         pts, clipBounds, static_cast<GradientDirection>(direction));
838     if (!result) {
839         return nullptr;
840     }
841     uint8_t ColorMax = 255;
842     uint8_t ColorMin = 0;
843     if (para->fractionStops_[0].second > 0.01) {  // 0.01 represents the fraction bias
844         c.emplace_back(SkColorSetARGB(ColorMin, ColorMax, ColorMax, ColorMax));
845         p.emplace_back(para->fractionStops_[0].second - 0.01); // 0.01 represents the fraction bias
846     }
847     for (size_t i = 0; i < para->fractionStops_.size(); i++) {
848         c.emplace_back(SkColorSetARGB(
849             static_cast<uint8_t>(para->fractionStops_[i].first * ColorMax), ColorMax, ColorMax, ColorMax));
850         p.emplace_back(para->fractionStops_[i].second);
851     }
852     // 0.01 represents the fraction bias
853     if (para->fractionStops_[para->fractionStops_.size() - 1].second < (1 - 0.01)) {
854         c.emplace_back(SkColorSetARGB(ColorMin, ColorMax, ColorMax, ColorMax));
855         // 0.01 represents the fraction bias
856         p.emplace_back(para->fractionStops_[para->fractionStops_.size() - 1].second + 0.01);
857     }
858     auto shader = SkGradientShader::MakeLinear(pts, &c[0], &p[0], p.size(), SkTileMode::kClamp);
859     return shader;
860 }
861 
MakeHorizontalMeanBlurShader(float radiusIn,sk_sp<SkShader> shader,sk_sp<SkShader> gradientShader)862 sk_sp<SkShader> RSPropertiesPainter::MakeHorizontalMeanBlurShader(
863     float radiusIn, sk_sp<SkShader> shader, sk_sp<SkShader> gradientShader)
864 {
865     const char* prog = R"(
866         uniform half r;
867         uniform shader imageShader;
868         uniform shader gradientShader;
869         half4 meanFilter(float2 coord, half radius)
870         {
871             half4 sum = vec4(0.0);
872             half div = 0;
873             for (half x = -30.0; x < 30.0; x += 1.0) {
874                 if (x > radius) {
875                     break;
876                 }
877                 if (abs(x) < radius) {
878                     div += 1;
879                     sum += imageShader.eval(coord + float2(x, 0));
880                 }
881             }
882             return half4(sum.xyz / div, 1.0);
883         }
884         half4 main(float2 coord)
885         {
886             if (abs(gradientShader.eval(coord).a - 0) < 0.001) {
887                 return imageShader.eval(coord);
888             }
889             float val = clamp(r * gradientShader.eval(coord).a, 1.0, r);
890             return meanFilter(coord, val);
891         }
892     )";
893     auto [effect, err] = SkRuntimeEffect::MakeForShader(SkString(prog));
894     sk_sp<SkShader> children[] = {shader, gradientShader};
895     size_t childCount = 2;
896     return effect->makeShader(SkData::MakeWithCopy(
897         &radiusIn, sizeof(radiusIn)), children, childCount, nullptr, false);
898 }
899 
MakeVerticalMeanBlurShader(float radiusIn,sk_sp<SkShader> shader,sk_sp<SkShader> gradientShader)900 sk_sp<SkShader> RSPropertiesPainter::MakeVerticalMeanBlurShader(
901     float radiusIn, sk_sp<SkShader> shader, sk_sp<SkShader> gradientShader)
902 {
903     const char* prog = R"(
904         uniform half r;
905         uniform shader imageShader;
906         uniform shader gradientShader;
907         half4 meanFilter(float2 coord, half radius)
908         {
909             half4 sum = vec4(0.0);
910             half div = 0;
911             for (half y = -30.0; y < 30.0; y += 1.0) {
912                 if (y > radius) {
913                     break;
914                 }
915                 if (abs(y) < radius) {
916                     div += 1;
917                     sum += imageShader.eval(coord + float2(0, y));
918                 }
919             }
920             return half4(sum.xyz / div, 1.0);
921         }
922         half4 main(float2 coord)
923         {
924             if (abs(gradientShader.eval(coord).a - 0) < 0.001) {
925                 return imageShader.eval(coord);
926             }
927             float val = clamp(r * gradientShader.eval(coord).a, 1.0, r);
928             return meanFilter(coord, val);
929         }
930     )";
931     auto [effect, err] = SkRuntimeEffect::MakeForShader(SkString(prog));
932     sk_sp<SkShader> children[] = {shader, gradientShader};
933     size_t childCount = 2;
934     return effect->makeShader(SkData::MakeWithCopy(
935         &radiusIn, sizeof(radiusIn)), children, childCount, nullptr, false);
936 }
937 
DrawHorizontalLinearGradientBlur(SkSurface * skSurface,RSPaintFilterCanvas & canvas,float radius,sk_sp<SkShader> alphaGradientShader,const SkIRect & clipIPadding)938 void RSPropertiesPainter::DrawHorizontalLinearGradientBlur(SkSurface* skSurface, RSPaintFilterCanvas& canvas,
939     float radius, sk_sp<SkShader> alphaGradientShader, const SkIRect& clipIPadding)
940 {
941     auto image = skSurface->makeImageSnapshot(clipIPadding);
942     if (image == nullptr) {
943         return;
944     }
945     auto imageShader = image->makeShader(SkSamplingOptions(SkFilterMode::kLinear));
946     auto shader = MakeHorizontalMeanBlurShader(radius, imageShader, alphaGradientShader);
947     SkPaint paint;
948     paint.setShader(shader);
949     canvas.drawRect(SkRect::Make(clipIPadding.makeOffset(-clipIPadding.left(), -clipIPadding.top())), paint);
950 }
951 
DrawVerticalLinearGradientBlur(SkSurface * skSurface,RSPaintFilterCanvas & canvas,float radius,sk_sp<SkShader> alphaGradientShader,const SkIRect & clipIPadding)952 void RSPropertiesPainter::DrawVerticalLinearGradientBlur(SkSurface* skSurface, RSPaintFilterCanvas& canvas,
953     float radius, sk_sp<SkShader> alphaGradientShader, const SkIRect& clipIPadding)
954 {
955     auto image = skSurface->makeImageSnapshot(clipIPadding);
956     if (image == nullptr) {
957         return;
958     }
959     auto imageShader = image->makeShader(SkSamplingOptions(SkFilterMode::kLinear));
960     auto shader = MakeVerticalMeanBlurShader(radius, imageShader, alphaGradientShader);
961     SkPaint paint;
962     paint.setShader(shader);
963     canvas.drawRect(SkRect::Make(clipIPadding.makeOffset(-clipIPadding.left(), -clipIPadding.top())), paint);
964 }
965 
CalcDirectionBias(const SkMatrix & mat)966 uint8_t RSPropertiesPainter::CalcDirectionBias(const SkMatrix& mat)
967 {
968     uint8_t directionBias = 0;
969     // 1 and 3 represents rotate matrix's index
970     if ((mat.get(1) > FLOAT_ZERO_THRESHOLD) && (mat.get(3) < (0 - FLOAT_ZERO_THRESHOLD))) {
971         directionBias = 1; // 1 represents rotate 90 degree
972     // 0 and 4 represents rotate matrix's index
973     } else if ((mat.get(0) < (0 - FLOAT_ZERO_THRESHOLD)) && (mat.get(4) < (0 - FLOAT_ZERO_THRESHOLD))) {
974         directionBias = 2; // 2 represents rotate 180 degree
975     // 1 and 3 represents rotate matrix's index
976     } else if ((mat.get(1) < (0 - FLOAT_ZERO_THRESHOLD)) && (mat.get(3) > FLOAT_ZERO_THRESHOLD)) {
977         directionBias = 3; // 3 represents rotate 270 degree
978     }
979     return directionBias;
980 }
981 #endif
982 #endif
983 
984 #ifndef USE_ROSEN_DRAWING
DrawLinearGradientBlurFilter(const RSProperties & properties,RSPaintFilterCanvas & canvas,const std::optional<SkRect> & rect)985 void RSPropertiesPainter::DrawLinearGradientBlurFilter(
986     const RSProperties& properties, RSPaintFilterCanvas& canvas, const std::optional<SkRect>& rect)
987 {
988     const auto& para = properties.GetLinearGradientBlurPara();
989     if (para == nullptr || para->blurRadius_ <= 0) {
990         return;
991     }
992 #ifdef NEW_SKIA
993     SkSurface* skSurface = canvas.GetSurface();
994     if (skSurface == nullptr) {
995         return;
996     }
997     SkAutoCanvasRestore acr(&canvas, true);
998     if (rect.has_value()) {
999         canvas.clipRect((*rect), true);
1000     } else if (properties.GetClipBounds() != nullptr) {
1001         canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
1002     } else { // we always do clip for DrawLinearGradientBlurFilter, even if ClipToBounds is false
1003         canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
1004     }
1005 
1006     auto clipBounds = canvas.getDeviceClipBounds();
1007     auto clipIPadding = clipBounds.makeOutset(-1, -1);
1008     SkMatrix mat = canvas.getTotalMatrix();
1009     uint8_t directionBias = CalcDirectionBias(mat);
1010 
1011     auto alphaGradientShader = MakeAlphaGradientShader(SkRect::Make(clipIPadding), para, directionBias);
1012     if (alphaGradientShader == nullptr) {
1013         ROSEN_LOGE("RSPropertiesPainter::DrawLinearGradientBlurFilter alphaGradientShader null");
1014         return;
1015     }
1016     float radius = para->blurRadius_ / 2;
1017     canvas.resetMatrix();
1018     canvas.translate(clipIPadding.left(), clipIPadding.top());
1019 
1020     DrawHorizontalLinearGradientBlur(skSurface, canvas, radius, alphaGradientShader, clipIPadding);
1021     DrawVerticalLinearGradientBlur(skSurface, canvas, radius, alphaGradientShader, clipIPadding);
1022     DrawHorizontalLinearGradientBlur(skSurface, canvas, radius, alphaGradientShader, clipIPadding);
1023     DrawVerticalLinearGradientBlur(skSurface, canvas, radius, alphaGradientShader, clipIPadding);
1024 #endif
1025 }
1026 #else
DrawLinearGradientBlurFilter(const RSProperties & properties,RSPaintFilterCanvas & canvas,const std::optional<Drawing::Rect> & rect)1027 void RSPropertiesPainter::DrawLinearGradientBlurFilter(
1028     const RSProperties& properties, RSPaintFilterCanvas& canvas, const std::optional<Drawing::Rect>& rect)
1029 {
1030 }
1031 #endif
1032 
1033 
1034 #ifndef USE_ROSEN_DRAWING
DrawFilter(const RSProperties & properties,RSPaintFilterCanvas & canvas,FilterType filterType,const std::optional<SkRect> & rect)1035 void RSPropertiesPainter::DrawFilter(const RSProperties& properties, RSPaintFilterCanvas& canvas,
1036     FilterType filterType, const std::optional<SkRect>& rect)
1037 {
1038     if (!BLUR_ENABLED) {
1039         ROSEN_LOGD("RSPropertiesPainter::DrawFilter close blur.");
1040         return;
1041     }
1042     auto& RSFilter =
1043         (filterType == FilterType::BACKGROUND_FILTER) ? properties.GetBackgroundFilter() : properties.GetFilter();
1044     if (RSFilter == nullptr || !RSFilter->IsValid()) {
1045         return;
1046     }
1047 #ifdef NEW_SKIA
1048     RS_OPTIONAL_TRACE_BEGIN("DrawFilter " + RSFilter->GetDescription());
1049     g_blurCnt++;
1050     SkAutoCanvasRestore acr(&canvas, true);
1051     if (rect.has_value()) {
1052         canvas.clipRect((*rect), true);
1053     } else if (properties.GetClipBounds() != nullptr) {
1054         canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
1055     } else { // we always do clip for DrawFilter, even if ClipToBounds is false
1056         canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
1057     }
1058 
1059     auto filter = std::static_pointer_cast<RSSkiaFilter>(RSFilter);
1060     auto skSurface = canvas.GetSurface();
1061     if (skSurface == nullptr) {
1062         ROSEN_LOGD("RSPropertiesPainter::DrawFilter skSurface null");
1063         auto paint = filter->GetPaint();
1064         SkCanvas::SaveLayerRec slr(nullptr, &paint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
1065         canvas.saveLayer(slr);
1066         filter->PostProcess(canvas);
1067         RS_OPTIONAL_TRACE_END();
1068         return;
1069     }
1070 
1071     // for foreground filter, when do online opacity, rendering result already applied opacity,
1072     // so drawImage should not apply opacity again
1073     RSAutoCanvasRestore autoCanvasRestore(&canvas,
1074         filterType == FilterType::FOREGROUND_FILTER ? RSAutoCanvasRestore::kAlpha : RSAutoCanvasRestore::kNone);
1075     if (filterType == FilterType::FOREGROUND_FILTER) {
1076         canvas.SetAlpha(1.0);
1077     }
1078 
1079     // Optional use cacheManager to draw filter
1080     if (auto& cacheManager = properties.GetFilterCacheManager(filterType == FilterType::FOREGROUND_FILTER)) {
1081         cacheManager->DrawFilter(canvas, filter);
1082         RS_OPTIONAL_TRACE_END();
1083         return;
1084     }
1085 
1086     auto clipIBounds = canvas.getDeviceClipBounds();
1087     auto imageSnapshot = skSurface->makeImageSnapshot(clipIBounds);
1088     if (imageSnapshot == nullptr) {
1089         ROSEN_LOGE("RSPropertiesPainter::DrawFilter image null");
1090         RS_OPTIONAL_TRACE_END();
1091         return;
1092     }
1093     if (RSSystemProperties::GetImageGpuResourceCacheEnable(imageSnapshot->width(), imageSnapshot->height())) {
1094         ROSEN_LOGD("DrawFilter cache image resource(width:%d, height:%d).",
1095             imageSnapshot->width(), imageSnapshot->height());
1096         as_IB(imageSnapshot)->hintCacheGpuResource();
1097     }
1098 
1099     filter->PreProcess(imageSnapshot);
1100     canvas.resetMatrix();
1101     auto visibleIRect = canvas.GetVisibleRect().round();
1102     if (!visibleIRect.isEmpty()) {
1103         canvas.clipIRect(visibleIRect);
1104     }
1105     filter->DrawImageRect(
1106         canvas, imageSnapshot, SkRect::Make(imageSnapshot->bounds().makeOutset(-1, -1)), SkRect::Make(clipIBounds));
1107     filter->PostProcess(canvas);
1108     RS_OPTIONAL_TRACE_END();
1109 #endif
1110 }
1111 #else
DrawFilter(const RSProperties & properties,RSPaintFilterCanvas & canvas,FilterType filterType,const std::optional<Drawing::Rect> & rect)1112 void RSPropertiesPainter::DrawFilter(const RSProperties& properties, RSPaintFilterCanvas& canvas,
1113     FilterType filterType, const std::optional<Drawing::Rect>& rect)
1114 {
1115     auto& RSFilter =
1116         (filterType == FilterType::BACKGROUND_FILTER) ? properties.GetBackgroundFilter() : properties.GetFilter();
1117     if (RSFilter == nullptr || !RSFilter->IsValid()) {
1118         return;
1119     }
1120     RS_TRACE_NAME("DrawFilter " + RSFilter->GetDescription());
1121     g_blurCnt++;
1122     Drawing::AutoCanvasRestore acr(canvas, true);
1123     if (rect.has_value()) {
1124         canvas.ClipRect((*rect), Drawing::ClipOp::INTERSECT, true);
1125     } else if (properties.GetClipBounds() != nullptr) {
1126         canvas.ClipPath(properties.GetClipBounds()->GetDrawingPath(), Drawing::ClipOp::INTERSECT, true);
1127     } else {
1128         canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, true);
1129     }
1130     auto filter = std::static_pointer_cast<RSDrawingFilter>(RSFilter);
1131     auto surface = canvas.GetSurface();
1132     if (surface == nullptr) {
1133         ROSEN_LOGD("RSPropertiesPainter::DrawFilter surface null");
1134         auto brush = filter->GetBrush();
1135         Drawing::SaveLayerOps slr(nullptr, &brush, Drawing::SaveLayerOps::Flags::INIT_WITH_PREVIOUS);
1136         canvas.SaveLayer(slr);
1137         filter->PostProcess(canvas);
1138         return;
1139     }
1140 
1141     // for foreground filter, when do online opacity, rendering result already applied opacity,
1142     // so drawImage should not apply opacity again
1143     RSAutoCanvasRestore autoCanvasRestore(&canvas,
1144         filterType == FilterType::FOREGROUND_FILTER ? RSAutoCanvasRestore::kAlpha : RSAutoCanvasRestore::kNone);
1145     if (filterType == FilterType::FOREGROUND_FILTER) {
1146         canvas.SetAlpha(1.0);
1147     }
1148 
1149     auto clipIBounds = canvas.GetDeviceClipBounds();
1150     auto clipIPadding = Drawing::RectI(clipIBounds.GetLeft() + 1, clipIBounds.GetTop() + 1,
1151         clipIBounds.GetRight() - 1, clipIBounds.GetBottom() - 1);
1152     auto imageSnapshot = surface->GetImageSnapshot(clipIPadding);
1153     if (imageSnapshot == nullptr) {
1154         ROSEN_LOGE("RSPropertiesPainter::DrawFilter image null");
1155         return;
1156     }
1157     filter->PreProcess(imageSnapshot);
1158     canvas.ResetMatrix();
1159     auto visibleRect = canvas.GetVisibleRect();
1160     auto visibleIRect = Drawing::RectI(visibleRect.GetLeft(), visibleRect.GetTop(),
1161         visibleRect.GetRight(), visibleRect.GetBottom());
1162     if (visibleIRect.Intersect(clipIBounds)) {
1163         auto clipRect = Drawing::Rect(visibleIRect.GetLeft(), visibleIRect.GetTop(),
1164             visibleIRect.GetRight(), visibleIRect.GetBottom());
1165         canvas.ClipRect(clipRect, Drawing::ClipOp::INTERSECT, false);
1166         auto srcRect = Drawing::Rect(visibleIRect.GetLeft() + 1, visibleIRect.GetTop() + 1,
1167             visibleIRect.GetRight() - 1, visibleIRect.GetBottom() - 1);
1168         srcRect.Offset(-clipIPadding.GetLeft(), -clipIPadding.GetTop());
1169         filter->DrawImageRect(canvas, imageSnapshot, srcRect, clipRect);
1170     } else {
1171         auto srcRect = Drawing::Rect(0, 0, clipIPadding.GetWidth(), clipIPadding.GetHeight());
1172         auto dstRect = Drawing::Rect(clipIBounds.GetLeft(), clipIBounds.GetTop(),
1173             clipIBounds.GetRight(), clipIBounds.GetBottom());
1174         filter->DrawImageRect(canvas, imageSnapshot, srcRect, dstRect);
1175     }
1176     filter->PostProcess(canvas);
1177 }
1178 #endif
1179 
1180 #ifndef USE_ROSEN_DRAWING
DrawBackgroundEffect(const RSProperties & properties,RSPaintFilterCanvas & canvas,const SkIRect & rect)1181 void RSPropertiesPainter::DrawBackgroundEffect(
1182     const RSProperties& properties, RSPaintFilterCanvas& canvas, const SkIRect& rect)
1183 {
1184     auto& RSFilter = properties.GetBackgroundFilter();
1185     if (RSFilter == nullptr || !RSFilter->IsValid()) {
1186         return;
1187     }
1188     auto filter = std::static_pointer_cast<RSSkiaFilter>(RSFilter);
1189     RS_TRACE_NAME("DrawBackgroundEffect " + filter->GetDescription());
1190     auto skSurface = canvas.GetSurface();
1191     if (skSurface == nullptr) {
1192         ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundEffect skSurface null");
1193         return;
1194     }
1195     g_blurCnt++;
1196 
1197     // Optional use cacheManager to draw filter
1198     if (auto& cacheManager = properties.GetFilterCacheManager(false)) {
1199         // the input rect is in global coordinate, so we need to save/reset matrix before clip
1200         SkAutoCanvasRestore acr(&canvas, true);
1201         canvas.resetMatrix();
1202 #ifdef NEW_SKIA
1203         canvas.clipIRect(rect);
1204 #endif
1205         auto data = cacheManager->GeneratedCachedEffectData(canvas, filter);
1206         canvas.SetEffectData(data);
1207         return;
1208     }
1209 
1210     SkIRect imageRect = SkIRect::MakeWH(skSurface->width(), skSurface->height());
1211     imageRect.intersect(rect);
1212     auto imageSnapshot = skSurface->makeImageSnapshot(imageRect);
1213     if (imageSnapshot == nullptr) {
1214         ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundEffect image snapshot null");
1215         return;
1216     }
1217 
1218     filter->PreProcess(imageSnapshot);
1219     // create a offscreen skSurface
1220     sk_sp<SkSurface> offscreenSurface = skSurface->makeSurface(imageSnapshot->imageInfo());
1221     if (offscreenSurface == nullptr) {
1222         ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundEffect offscreenSurface null");
1223         return;
1224     }
1225     RSPaintFilterCanvas offscreenCanvas(offscreenSurface.get());
1226     auto clipBounds = SkRect::MakeIWH(imageRect.width(), imageRect.height());
1227     filter->DrawImageRect(offscreenCanvas, imageSnapshot, SkRect::Make(imageSnapshot->bounds()), clipBounds);
1228     filter->PostProcess(offscreenCanvas);
1229 
1230     auto imageCache = offscreenSurface->makeImageSnapshot();
1231     if (imageCache == nullptr) {
1232         ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundEffect imageCache snapshot null");
1233         return;
1234     }
1235     CachedEffectData data = { imageCache, imageRect };
1236     canvas.SetEffectData(data);
1237 }
1238 #else
DrawBackgroundEffect(const RSProperties & properties,RSPaintFilterCanvas & canvas,const Drawing::RectI & rect)1239 void RSPropertiesPainter::DrawBackgroundEffect(
1240     const RSProperties& properties, RSPaintFilterCanvas& canvas, const Drawing::RectI& rect)
1241 {
1242 }
1243 #endif
1244 
ApplyBackgroundEffect(const RSProperties & properties,RSPaintFilterCanvas & canvas)1245 void RSPropertiesPainter::ApplyBackgroundEffect(const RSProperties& properties, RSPaintFilterCanvas& canvas)
1246 {
1247 #ifndef USE_ROSEN_DRAWING
1248     RS_TRACE_NAME("ApplyBackgroundEffect");
1249     SkAutoCanvasRestore acr(&canvas, true);
1250     if (properties.GetClipBounds() != nullptr) {
1251         canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
1252     } else { // we always do clip for ApplyBackgroundEffect, even if ClipToBounds is false
1253         canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
1254     }
1255     canvas.resetMatrix();
1256     auto visibleIRect = canvas.GetVisibleRect().round();
1257     #ifdef NEW_SKIA
1258     if (!visibleIRect.isEmpty()) {
1259         canvas.clipIRect(visibleIRect);
1260     }
1261     #endif
1262 
1263     const auto& [bgImage, imageIRect, unused] = canvas.GetEffectData();
1264     if (bgImage == nullptr) {
1265         ROSEN_LOGE("RSPropertiesPainter::ApplyBackgroundEffect bgImage null");
1266         return;
1267     }
1268     SkPaint defaultPaint;
1269     // dstRect: canvas clip region
1270     auto dstRect = SkRect::Make(canvas.getDeviceClipBounds());
1271     // srcRect: map dstRect onto cache coordinate
1272     auto srcRect = dstRect.makeOffset(-imageIRect.left(), -imageIRect.top());
1273 #ifdef NEW_SKIA
1274     canvas.drawImageRect(
1275         bgImage, srcRect, dstRect, SkSamplingOptions(), &defaultPaint, SkCanvas::kStrict_SrcRectConstraint);
1276 #else
1277     auto clipIBounds = canvas.getDeviceClipBounds();
1278     auto clipIPadding = clipIBounds.makeOutset(-1, -1);
1279     canvas.drawImageRect(bgImage, SkRect::Make(clipIPadding.makeOffset(-imageIRect.left(), -imageIRect.top())),
1280         SkRect::Make(clipIPadding), &defaultPaint);
1281 #endif
1282 #endif
1283 }
1284 
DrawForegroundEffect(const RSProperties & properties,RSPaintFilterCanvas & canvas)1285 void RSPropertiesPainter::DrawForegroundEffect(const RSProperties& properties, RSPaintFilterCanvas& canvas)
1286 {
1287 #ifndef USE_ROSEN_DRAWING
1288     const auto& data = canvas.GetEffectData();
1289     if (data.childrenPath_.isEmpty()) {
1290         return;
1291     }
1292     auto& colorFilter = properties.GetColorFilter();
1293     if (colorFilter == nullptr) {
1294         return;
1295     }
1296     RS_TRACE_NAME("DrawForegroundEffect");
1297     SkAutoCanvasRestore acr(&canvas, true);
1298     canvas.resetMatrix();
1299     canvas.clipPath(data.childrenPath_, true);
1300     SkPaint paint;
1301     paint.setAntiAlias(true);
1302     paint.setColorFilter(colorFilter);
1303     auto pathBounds = data.childrenPath_.getBounds();
1304     SkCanvas::SaveLayerRec slr(&pathBounds, &paint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
1305     canvas.saveLayer(slr);
1306 #endif
1307 }
1308 
1309 #ifndef USE_ROSEN_DRAWING
DrawPixelStretch(const RSProperties & properties,RSPaintFilterCanvas & canvas)1310 void RSPropertiesPainter::DrawPixelStretch(const RSProperties& properties, RSPaintFilterCanvas& canvas)
1311 {
1312     auto& pixelStretch = properties.GetPixelStretch();
1313     if (!pixelStretch.has_value()) {
1314         return;
1315     }
1316 
1317     auto skSurface = canvas.GetSurface();
1318     if (skSurface == nullptr) {
1319         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch skSurface null");
1320         return;
1321     }
1322 
1323     canvas.save();
1324     auto bounds = RSPropertiesPainter::Rect2SkRect(properties.GetBoundsRect());
1325     canvas.clipRect(bounds);
1326     auto clipBounds = canvas.getDeviceClipBounds();
1327     clipBounds.setXYWH(clipBounds.left(), clipBounds.top(), clipBounds.width() - 1, clipBounds.height() - 1);
1328     canvas.restore();
1329 
1330     /* Calculates the relative coordinates of the clipbounds
1331         with respect to the origin of the current canvas coordinates */
1332     SkMatrix worldToLocalMat;
1333     if (!canvas.getTotalMatrix().invert(&worldToLocalMat)) {
1334         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch get invert matrix failed.");
1335     }
1336     SkRect localClipBounds;
1337     SkRect fClipBounds = SkRect::MakeXYWH(clipBounds.x(), clipBounds.y(), clipBounds.width(), clipBounds.height());
1338     if (!worldToLocalMat.mapRect(&localClipBounds, fClipBounds)) {
1339         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch map rect failed.");
1340     }
1341 
1342     if (!bounds.intersect(localClipBounds)) {
1343         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch intersect clipbounds failed");
1344     }
1345 
1346     auto scaledBounds = SkRect::MakeLTRB(bounds.left() - pixelStretch->x_, bounds.top() - pixelStretch->y_,
1347         bounds.right() + pixelStretch->z_, bounds.bottom() + pixelStretch->w_);
1348     if (scaledBounds.isEmpty() || bounds.isEmpty() || clipBounds.isEmpty()) {
1349         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch invalid scaled bounds");
1350         return;
1351     }
1352 
1353     auto image = skSurface->makeImageSnapshot(clipBounds);
1354     if (image == nullptr) {
1355         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch image null");
1356         return;
1357     }
1358 
1359     SkPaint paint;
1360     SkMatrix inverseMat, scaleMat;
1361     auto boundsGeo = (properties.GetBoundsGeometry());
1362     if (boundsGeo && !boundsGeo->IsEmpty()) {
1363         if (!canvas.getTotalMatrix().invert(&inverseMat)) {
1364             ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch get inverse matrix failed.");
1365         }
1366         scaleMat.setScale(inverseMat.getScaleX(), inverseMat.getScaleY());
1367     }
1368 
1369     canvas.save();
1370     canvas.translate(bounds.x(), bounds.y());
1371     if (pixelStretch->x_ < 0) {
1372 #ifdef NEW_SKIA
1373         paint.setShader(image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions(), &scaleMat));
1374 #else
1375         paint.setShader(image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, &scaleMat));
1376 #endif
1377         canvas.drawRect(
1378             SkRect::MakeXYWH(-pixelStretch->x_, -pixelStretch->y_, scaledBounds.width(), scaledBounds.height()), paint);
1379     } else {
1380         scaleMat.setScale(scaledBounds.width() / bounds.width() * scaleMat.getScaleX(),
1381             scaledBounds.height() / bounds.height() * scaleMat.getScaleY());
1382 #ifdef NEW_SKIA
1383         paint.setShader(image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions(), &scaleMat));
1384 #else
1385         paint.setShader(image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, &scaleMat));
1386 #endif
1387         canvas.translate(-pixelStretch->x_, -pixelStretch->y_);
1388         canvas.drawRect(SkRect::MakeXYWH(pixelStretch->x_, pixelStretch->y_, bounds.width(), bounds.height()), paint);
1389     }
1390     canvas.restore();
1391 }
1392 #else
DrawPixelStretch(const RSProperties & properties,RSPaintFilterCanvas & canvas)1393 void RSPropertiesPainter::DrawPixelStretch(const RSProperties& properties, RSPaintFilterCanvas& canvas)
1394 {
1395     if (!properties.IsPixelStretchValid() && !properties.IsPixelStretchPercentValid()) {
1396         return;
1397     }
1398 
1399     auto surface = canvas.GetSurface();
1400     if (surface == nullptr) {
1401         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch surface null");
1402         return;
1403     }
1404 
1405     canvas.Save();
1406     auto bounds = RSPropertiesPainter::Rect2DrawingRect(properties.GetBoundsRect());
1407     canvas.ClipRect(bounds, Drawing::ClipOp::INTERSECT, false);
1408     auto tmpBounds = canvas.GetDeviceClipBounds();
1409     Drawing::Rect clipBounds(
1410         tmpBounds.GetLeft(), tmpBounds.GetTop(), tmpBounds.GetWidth() - 1, tmpBounds.GetHeight() - 1);
1411     canvas.Restore();
1412 
1413     /*  Calculates the relative coordinates of the clipbounds
1414         with respect to the origin of the current canvas coordinates */
1415     Drawing::Matrix worldToLocalMat;
1416     if (!canvas.GetTotalMatrix().Invert(worldToLocalMat)) {
1417         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch get invert matrix failed.");
1418     }
1419     Drawing::Rect localClipBounds;
1420     Drawing::Rect fClipBounds(clipBounds.GetLeft(), clipBounds.GetTop(), clipBounds.GetWidth(),
1421         clipBounds.GetBottom());
1422     if (!worldToLocalMat.MapRect(localClipBounds, fClipBounds)) {
1423         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch map rect failed.");
1424     }
1425 
1426     if (!bounds.Intersect(localClipBounds)) {
1427         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch intersect clipbounds failed");
1428     }
1429 
1430     auto scaledBounds = Drawing::Rect(bounds.GetLeft() - stretchSize.x_, bounds.GetTop() - stretchSize.y_,
1431         bounds.GetRight() + stretchSize.z_, bounds.GetBottom() + stretchSize.w_);
1432     if (!scaledBounds.IsValid() || !bounds.IsValid() || !clipBounds.IsValid()) {
1433         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch invalid scaled bounds");
1434         return;
1435     }
1436 
1437     Drawing::RectI rectI(static_cast<int>(fClipBounds.GetLeft()), static_cast<int>(fClipBounds.GetTop()),
1438         static_cast<int>(fClipBounds.GetRight()), static_cast<int>(fClipBounds.GetBottom()));
1439     auto image = surface->GetImageSnapshot(rectI);
1440     if (image == nullptr) {
1441         ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch image null");
1442         return;
1443     }
1444 
1445     Drawing::Brush brush;
1446     Drawing::Matrix inverseMat, scaleMat;
1447     auto boundsGeo = (properties.GetBoundsGeometry());
1448     if (boundsGeo && !boundsGeo->IsEmpty()) {
1449         if (!canvas.GetTotalMatrix().Invert(inverseMat)) {
1450             ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch get inverse matrix failed.");
1451         }
1452         scaleMat.Set(Drawing::Matrix::SCALE_X, inverseMat.Get(Drawing::Matrix::SCALE_X));
1453         scaleMat.Set(Drawing::Matrix::SCALE_Y, inverseMat.Get(Drawing::Matrix::SCALE_Y));
1454     }
1455 
1456     canvas.Save();
1457     canvas.Translate(bounds.GetLeft(), bounds.GetTop());
1458     Drawing::SamplingOptions samplingOptions;
1459     if (properties.IsPixelStretchExpanded()) {
1460         brush.SetShaderEffect(Drawing::ShaderEffect::CreateImageShader(
1461             *image, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, samplingOptions, scaleMat));
1462         canvas.AttachBrush(brush);
1463         canvas.DrawRect(Drawing::Rect(-stretchSize.x_, -stretchSize.y_,
1464             -stretchSize.x_ + scaledBounds.GetWidth(), -stretchSize.y_ + scaledBounds.GetHeight()));
1465         canvas.DetachBrush();
1466     } else {
1467         scaleMat.Scale(
1468             scaledBounds.GetWidth() / bounds.GetWidth(), scaledBounds.GetHeight() / bounds.GetHeight(), 0, 0);
1469         brush.SetShaderEffect(Drawing::ShaderEffect::CreateImageShader(
1470             *image, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, samplingOptions, scaleMat));
1471 
1472         canvas.Translate(-stretchSize.x_, -stretchSize.y_);
1473         canvas.AttachBrush(brush);
1474         canvas.DrawRect(Drawing::Rect(
1475             stretchSize.x_, stretchSize.y_, stretchSize.x_ + bounds.GetWidth(), stretchSize.y_ + bounds.GetHeight()));
1476         canvas.DetachBrush();
1477     }
1478     canvas.Restore();
1479 }
1480 #endif
1481 
1482 #ifndef USE_ROSEN_DRAWING
CalcAverageColor(sk_sp<SkImage> imageSnapshot)1483 SkColor RSPropertiesPainter::CalcAverageColor(sk_sp<SkImage> imageSnapshot)
1484 {
1485     // create a 1x1 SkPixmap
1486     uint32_t pixel[1] = { 0 };
1487     auto single_pixel_info = SkImageInfo::MakeN32Premul(1, 1);
1488     SkPixmap single_pixel(single_pixel_info, pixel, single_pixel_info.bytesPerPixel());
1489 
1490     // resize snapshot to 1x1 to calculate average color
1491     // kMedium_SkFilterQuality will do bilerp + mipmaps for down-scaling, we can easily get average color
1492 #ifdef NEW_SKIA
1493     imageSnapshot->scalePixels(single_pixel, SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear));
1494 #else
1495     imageSnapshot->scalePixels(single_pixel, SkFilterQuality::kMedium_SkFilterQuality);
1496 #endif
1497     // convert color format and return average color
1498     return SkColor4f::FromBytes_RGBA(pixel[0]).toSkColor();
1499 }
1500 #else
CalcAverageColor(std::shared_ptr<Drawing::Image> imageSnapshot)1501 Drawing::ColorQuad RSPropertiesPainter::CalcAverageColor(std::shared_ptr<Drawing::Image> imageSnapshot)
1502 {
1503     // create a 1x1 SkPixmap
1504     return Drawing::ColorQuad();
1505 }
1506 #endif
1507 
GetAndResetBlurCnt()1508 int RSPropertiesPainter::GetAndResetBlurCnt()
1509 {
1510     auto blurCnt = g_blurCnt;
1511     g_blurCnt = 0;
1512     return blurCnt;
1513 }
1514 
DrawBackground(const RSProperties & properties,RSPaintFilterCanvas & canvas,bool isAntiAlias)1515 void RSPropertiesPainter::DrawBackground(const RSProperties& properties, RSPaintFilterCanvas& canvas, bool isAntiAlias)
1516 {
1517     // only disable antialias when background is rect and g_forceBgAntiAlias is false
1518     bool antiAlias = g_forceBgAntiAlias || !properties.GetCornerRadius().IsZero();
1519     // clip
1520 #ifndef USE_ROSEN_DRAWING
1521     if (properties.GetClipBounds() != nullptr) {
1522         canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), antiAlias);
1523     } else if (properties.GetClipToBounds()) {
1524         // In NEW_SKIA version, L476 code will cause crash if the second parameter is true.
1525         // so isAntiAlias is false only the method is called in ProcessAnimatePropertyBeforeChildren().
1526 #ifdef NEW_SKIA
1527         if (properties.GetCornerRadius().IsZero()) {
1528             canvas.clipRect(Rect2SkRect(properties.GetBoundsRect()), isAntiAlias);
1529         } else {
1530             canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), antiAlias);
1531         }
1532 #else
1533         canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), antiAlias);
1534 #endif
1535     } else if (properties.GetClipToRRect()) {
1536         canvas.clipRRect(RRect2SkRRect(properties.GetClipRRect()), antiAlias);
1537     }
1538     // paint backgroundColor
1539     SkPaint paint;
1540     paint.setAntiAlias(antiAlias);
1541     auto bgColor = properties.GetBackgroundColor();
1542     if (bgColor != RgbPalette::Transparent()) {
1543         paint.setColor(bgColor.AsArgbInt());
1544         canvas.drawRRect(RRect2SkRRect(properties.GetInnerRRect()), paint);
1545     }
1546     if (const auto& bgShader = properties.GetBackgroundShader()) {
1547         SkAutoCanvasRestore acr(&canvas, true);
1548         canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), antiAlias);
1549         paint.setShader(bgShader->GetSkShader());
1550         canvas.drawPaint(paint);
1551     }
1552     if (const auto& bgImage = properties.GetBgImage()) {
1553         SkAutoCanvasRestore acr(&canvas, true);
1554         canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), antiAlias);
1555         auto boundsRect = Rect2SkRect(properties.GetBoundsRect());
1556         bgImage->SetDstRect(properties.GetBgImageRect());
1557 #ifdef NEW_SKIA
1558         bgImage->CanvasDrawImage(canvas, boundsRect, SkSamplingOptions(), paint, true);
1559 #else
1560         bgImage->CanvasDrawImage(canvas, boundsRect, paint, true);
1561 #endif
1562     }
1563 #else
1564     if (properties.GetClipBounds() != nullptr) {
1565         auto& path = properties.GetClipBounds()->GetDrawingPath();
1566         if (path.GetDrawingType() == Drawing::DrawingType::RECORDING) {
1567             auto clipPath = static_cast<const Drawing::RecordingPath&>(path).GetCmdList()->Playback();
1568             canvas.ClipPath(*clipPath, Drawing::ClipOp::INTERSECT, antiAlias);
1569         } else {
1570             canvas.ClipPath(path, Drawing::ClipOp::INTERSECT, antiAlias);
1571         }
1572     } else if (properties.GetClipToBounds()) {
1573         if (properties.GetCornerRadius().IsZero()) {
1574             canvas.ClipRect(Rect2DrawingRect(properties.GetBoundsRect()), Drawing::ClipOp::INTERSECT, isAntiAlias);
1575         } else {
1576             canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, antiAlias);
1577         }
1578     } else if (properties.GetClipToRRect()) {
1579         canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetClipRRect()), Drawing::ClipOp::INTERSECT, antiAlias);
1580     }
1581     // paint backgroundColor
1582     Drawing::Brush brush;
1583     brush.SetAntiAlias(antiAlias);
1584     auto bgColor = properties.GetBackgroundColor();
1585     if (bgColor != RgbPalette::Transparent()) {
1586         brush.SetColor(Drawing::Color(bgColor.AsArgbInt()));
1587         canvas.AttachBrush(brush);
1588         canvas.DrawRoundRect(RRect2DrawingRRect(properties.GetRRect()));
1589         canvas.DetachBrush();
1590     }
1591     if (const auto& bgShader = properties.GetBackgroundShader()) {
1592         canvas.Save();
1593         canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, antiAlias);
1594         auto shaderEffect = bgShader->GetDrawingShader();
1595         if (shaderEffect && shaderEffect->GetDrawingType() == Drawing::DrawingType::RECORDING) {
1596             auto shader =
1597                 std::static_pointer_cast<Drawing::RecordingShaderEffect>(shaderEffect)->GetCmdList()->Playback();
1598             brush.SetShaderEffect(shader);
1599         } else {
1600             brush.SetShaderEffect(shaderEffect);
1601         }
1602         canvas.DrawBackground(brush);
1603         canvas.Restore();
1604     }
1605     if (const auto& bgImage = properties.GetBgImage()) {
1606         canvas.Save();
1607         canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, antiAlias);
1608         auto boundsRect = Rect2DrawingRect(properties.GetBoundsRect());
1609         bgImage->SetDstRect(properties.GetBgImageRect());
1610         canvas.AttachBrush(brush);
1611         bgImage->CanvasDrawImage(canvas, boundsRect, true);
1612         canvas.DetachBrush();
1613         canvas.Restore();
1614     }
1615 #endif
1616 }
1617 
SetBgAntiAlias(bool forceBgAntiAlias)1618 void RSPropertiesPainter::SetBgAntiAlias(bool forceBgAntiAlias)
1619 {
1620     g_forceBgAntiAlias = forceBgAntiAlias;
1621 }
1622 
GetBgAntiAlias()1623 bool RSPropertiesPainter::GetBgAntiAlias()
1624 {
1625     return g_forceBgAntiAlias;
1626 }
1627 
1628 #ifndef USE_ROSEN_DRAWING
DrawFrame(const RSProperties & properties,RSPaintFilterCanvas & canvas,DrawCmdListPtr & cmds)1629 void RSPropertiesPainter::DrawFrame(const RSProperties& properties, RSPaintFilterCanvas& canvas, DrawCmdListPtr& cmds)
1630 {
1631     if (cmds == nullptr) {
1632         return;
1633     }
1634     SkMatrix mat;
1635     if (GetGravityMatrix(
1636             properties.GetFrameGravity(), properties.GetFrameRect(), cmds->GetWidth(), cmds->GetHeight(), mat)) {
1637         canvas.concat(mat);
1638     }
1639     auto frameRect = Rect2SkRect(properties.GetFrameRect());
1640     cmds->Playback(canvas, &frameRect);
1641 }
1642 #else
DrawFrame(const RSProperties & properties,RSPaintFilterCanvas & canvas,Drawing::DrawCmdListPtr & cmds)1643 void RSPropertiesPainter::DrawFrame(
1644     const RSProperties& properties, RSPaintFilterCanvas& canvas, Drawing::DrawCmdListPtr& cmds)
1645 {
1646     if (cmds == nullptr) {
1647         return;
1648     }
1649     Drawing::Matrix mat;
1650     if (GetGravityMatrix(
1651             properties.GetFrameGravity(), properties.GetFrameRect(), cmds->GetWidth(), cmds->GetHeight(), mat)) {
1652         canvas.ConcatMatrix(mat);
1653     }
1654     auto frameRect = Rect2DrawingRect(properties.GetFrameRect());
1655     cmds->Playback(canvas, &frameRect);
1656 }
1657 #endif
1658 
1659 #ifndef USE_ROSEN_DRAWING
DrawBorder(const RSProperties & properties,SkCanvas & canvas)1660 void RSPropertiesPainter::DrawBorder(const RSProperties& properties, SkCanvas& canvas)
1661 {
1662     auto border = properties.GetBorder();
1663     if (!border || !border->HasBorder()) {
1664         return;
1665     }
1666     SkPaint paint;
1667     paint.setAntiAlias(true);
1668     if (border->ApplyFillStyle(paint)) {
1669         canvas.drawDRRect(RRect2SkRRect(properties.GetRRect()), RRect2SkRRect(properties.GetInnerRRect()), paint);
1670     } else if (properties.GetCornerRadius().IsZero() && border->ApplyFourLine(paint)) {
1671         RectF rect = properties.GetBoundsRect();
1672         border->PaintFourLine(canvas, paint, rect);
1673     } else if (border->ApplyPathStyle(paint)) {
1674         auto borderWidth = border->GetWidth();
1675         RRect rrect = properties.GetRRect();
1676         rrect.rect_.width_ -= borderWidth;
1677         rrect.rect_.height_ -= borderWidth;
1678         rrect.rect_.Move(borderWidth / PARAM_DOUBLE, borderWidth / PARAM_DOUBLE);
1679         SkPath borderPath;
1680         borderPath.addRRect(RRect2SkRRect(rrect));
1681         canvas.drawPath(borderPath, paint);
1682     } else {
1683         SkAutoCanvasRestore acr(&canvas, true);
1684         canvas.clipRRect(RRect2SkRRect(properties.GetInnerRRect()), SkClipOp::kDifference, true);
1685         SkRRect rrect = RRect2SkRRect(properties.GetRRect());
1686         paint.setStyle(SkPaint::Style::kStroke_Style);
1687         border->PaintTopPath(canvas, paint, rrect);
1688         border->PaintRightPath(canvas, paint, rrect);
1689         border->PaintBottomPath(canvas, paint, rrect);
1690         border->PaintLeftPath(canvas, paint, rrect);
1691     }
1692 }
1693 #else
DrawBorder(const RSProperties & properties,Drawing::Canvas & canvas)1694 void RSPropertiesPainter::DrawBorder(const RSProperties& properties, Drawing::Canvas& canvas)
1695 {
1696     auto border = properties.GetBorder();
1697     if (!border || !border->HasBorder()) {
1698         return;
1699     }
1700     Drawing::Pen pen;
1701     Drawing::Brush brush;
1702     pen.SetAntiAlias(true);
1703     brush.SetAntiAlias(true);
1704     if (properties.GetCornerRadius().IsZero() && border->ApplyFourLine(pen)) {
1705         RectF rect = properties.GetBoundsRect();
1706         border->PaintFourLine(canvas, pen, rect);
1707     } else if (border->ApplyFillStyle(brush)) {
1708         canvas.AttachBrush(brush);
1709         canvas.DrawNestedRoundRect(
1710             RRect2DrawingRRect(properties.GetRRect()), RRect2DrawingRRect(properties.GetInnerRRect()));
1711         canvas.DetachBrush();
1712     } else if (border->ApplyPathStyle(pen)) {
1713         auto borderWidth = border->GetWidth();
1714         RRect rrect = properties.GetRRect();
1715         rrect.rect_.width_ -= borderWidth;
1716         rrect.rect_.height_ -= borderWidth;
1717         rrect.rect_.Move(borderWidth / PARAM_DOUBLE, borderWidth / PARAM_DOUBLE);
1718         Drawing::Path borderPath;
1719         borderPath.AddRoundRect(RRect2DrawingRRect(rrect));
1720         canvas.AttachPen(pen);
1721         canvas.DrawPath(borderPath);
1722         canvas.DetachPen();
1723     } else {
1724         Drawing::AutoCanvasRestore acr(canvas, true);
1725         canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetInnerRRect()), Drawing::ClipOp::DIFFERENCE, true);
1726         Drawing::RoundRect rrect = RRect2DrawingRRect(properties.GetRRect());
1727         border->PaintTopPath(canvas, pen, rrect);
1728         border->PaintRightPath(canvas, pen, rrect);
1729         border->PaintBottomPath(canvas, pen, rrect);
1730         border->PaintLeftPath(canvas, pen, rrect);
1731     }
1732 }
1733 #endif
1734 
1735 #ifndef USE_ROSEN_DRAWING
DrawForegroundColor(const RSProperties & properties,SkCanvas & canvas)1736 void RSPropertiesPainter::DrawForegroundColor(const RSProperties& properties, SkCanvas& canvas)
1737 {
1738     auto bgColor = properties.GetForegroundColor();
1739     if (bgColor == RgbPalette::Transparent()) {
1740         return;
1741     }
1742     // clip
1743     if (properties.GetClipBounds() != nullptr) {
1744         canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
1745     } else if (properties.GetClipToBounds()) {
1746         canvas.clipRect(Rect2SkRect(properties.GetBoundsRect()), true);
1747     } else if (properties.GetClipToRRect()) {
1748         canvas.clipRRect(RRect2SkRRect(properties.GetClipRRect()), true);
1749     }
1750 
1751     SkPaint paint;
1752     paint.setColor(bgColor.AsArgbInt());
1753     paint.setAntiAlias(true);
1754     canvas.drawRRect(RRect2SkRRect(properties.GetRRect()), paint);
1755 }
1756 #else
DrawForegroundColor(const RSProperties & properties,Drawing::Canvas & canvas)1757 void RSPropertiesPainter::DrawForegroundColor(const RSProperties& properties, Drawing::Canvas& canvas)
1758 {
1759     auto bgColor = properties.GetForegroundColor();
1760     if (bgColor == RgbPalette::Transparent()) {
1761         return;
1762     }
1763     // clip
1764     if (properties.GetClipBounds() != nullptr) {
1765         canvas.ClipPath(properties.GetClipBounds()->GetDrawingPath(), Drawing::ClipOp::INTERSECT, true);
1766     } else if (properties.GetClipToBounds()) {
1767         canvas.ClipRect(Rect2DrawingRect(properties.GetBoundsRect()), Drawing::ClipOp::INTERSECT, true);
1768     }
1769 
1770     Drawing::Brush brush;
1771     brush.SetColor(Drawing::Color(bgColor.AsArgbInt()));
1772     brush.SetAntiAlias(true);
1773     canvas.AttachBrush(brush);
1774     canvas.DrawRoundRect(RRect2DrawingRRect(properties.GetRRect()));
1775     canvas.DetachBrush();
1776 }
1777 #endif
1778 
1779 #ifndef USE_ROSEN_DRAWING
DrawMask(const RSProperties & properties,SkCanvas & canvas,SkRect maskBounds)1780 void RSPropertiesPainter::DrawMask(const RSProperties& properties, SkCanvas& canvas, SkRect maskBounds)
1781 {
1782     std::shared_ptr<RSMask> mask = properties.GetMask();
1783     if (mask == nullptr) {
1784         return;
1785     }
1786     if (mask->IsSvgMask() && !mask->GetSvgDom() && !mask->GetSvgPicture()) {
1787         ROSEN_LOGD("RSPropertiesPainter::DrawMask not has Svg Mask property");
1788         return;
1789     }
1790 
1791     canvas.save();
1792     canvas.saveLayer(maskBounds, nullptr);
1793     int tmpLayer = canvas.getSaveCount();
1794 
1795     SkPaint maskfilter;
1796     auto filter = SkColorFilters::Compose(SkLumaColorFilter::Make(), SkColorFilters::SRGBToLinearGamma());
1797     maskfilter.setColorFilter(filter);
1798     canvas.saveLayer(maskBounds, &maskfilter);
1799     if (mask->IsSvgMask()) {
1800         SkAutoCanvasRestore maskSave(&canvas, true);
1801         canvas.translate(maskBounds.fLeft + mask->GetSvgX(), maskBounds.fTop + mask->GetSvgY());
1802         canvas.scale(mask->GetScaleX(), mask->GetScaleY());
1803         if (mask->GetSvgDom()) {
1804             mask->GetSvgDom()->render(&canvas);
1805         } else if (mask->GetSvgPicture()) {
1806             canvas.drawPicture(mask->GetSvgPicture());
1807         }
1808     } else if (mask->IsGradientMask()) {
1809         SkAutoCanvasRestore maskSave(&canvas, true);
1810         canvas.translate(maskBounds.fLeft, maskBounds.fTop);
1811         SkRect skRect = SkRect::MakeIWH(maskBounds.fRight - maskBounds.fLeft, maskBounds.fBottom - maskBounds.fTop);
1812         canvas.drawRect(skRect, mask->GetMaskPaint());
1813     } else if (mask->IsPathMask()) {
1814         SkAutoCanvasRestore maskSave(&canvas, true);
1815         canvas.translate(maskBounds.fLeft, maskBounds.fTop);
1816         canvas.drawPath(mask->GetMaskPath(), mask->GetMaskPaint());
1817     }
1818 
1819     // back to mask layer
1820     canvas.restoreToCount(tmpLayer);
1821     // create content layer
1822     SkPaint maskPaint;
1823     maskPaint.setBlendMode(SkBlendMode::kSrcIn);
1824     canvas.saveLayer(maskBounds, &maskPaint);
1825     canvas.clipRect(maskBounds, true);
1826 }
1827 #else
DrawMask(const RSProperties & properties,Drawing::Canvas & canvas,Drawing::Rect maskBounds)1828 void RSPropertiesPainter::DrawMask(const RSProperties& properties, Drawing::Canvas& canvas, Drawing::Rect maskBounds)
1829 {
1830     std::shared_ptr<RSMask> mask = properties.GetMask();
1831     if (mask == nullptr) {
1832         return;
1833     }
1834     if (mask->IsSvgMask() && !mask->GetSvgDom() && !mask->GetSvgPicture()) {
1835         ROSEN_LOGD("RSPropertiesPainter::DrawMask not has Svg Mask property");
1836         return;
1837     }
1838 
1839     canvas.Save();
1840     Drawing::SaveLayerOps slr(&maskBounds, nullptr);
1841     canvas.SaveLayer(slr);
1842     int tmpLayer = canvas.GetSaveCount();
1843 
1844     Drawing::Brush maskfilter;
1845     Drawing::Filter filter;
1846     filter.SetColorFilter(Drawing::ColorFilter::CreateComposeColorFilter(
1847         *(Drawing::ColorFilter::CreateLumaColorFilter()), *(Drawing::ColorFilter::CreateSrgbGammaToLinear())));
1848     maskfilter.SetFilter(filter);
1849     Drawing::SaveLayerOps slrMask(&maskBounds, &maskfilter);
1850     canvas.SaveLayer(slrMask);
1851     if (mask->IsSvgMask()) {
1852         Drawing::AutoCanvasRestore maskSave(canvas, true);
1853         canvas.Translate(maskBounds.GetLeft() + mask->GetSvgX(), maskBounds.GetTop() + mask->GetSvgY());
1854         canvas.Scale(mask->GetScaleX(), mask->GetScaleY());
1855         if (mask->GetSvgDom()) {
1856             canvas.DrawSVGDOM(mask->GetSvgDom());
1857         } else if (mask->GetSvgPicture()) {
1858             canvas.DrawPicture(*mask->GetSvgPicture());
1859         }
1860     } else if (mask->IsGradientMask()) {
1861         Drawing::AutoCanvasRestore maskSave(canvas, true);
1862         canvas.Translate(maskBounds.GetLeft(), maskBounds.GetTop());
1863         Drawing::Rect rect = Drawing::Rect(
1864             0, 0, maskBounds.GetRight() - maskBounds.GetLeft(), maskBounds.GetBottom() - maskBounds.GetTop());
1865         canvas.AttachBrush(mask->GetMaskBrush());
1866         canvas.DrawRect(rect);
1867         canvas.DetachBrush();
1868     } else if (mask->IsPathMask()) {
1869         Drawing::AutoCanvasRestore maskSave(canvas, true);
1870         canvas.Translate(maskBounds.GetLeft(), maskBounds.GetTop());
1871         canvas.AttachBrush(mask->GetMaskBrush());
1872         canvas.DrawPath(mask->GetMaskPath());
1873         canvas.DetachBrush();
1874     }
1875 
1876     // back to mask layer
1877     canvas.RestoreToCount(tmpLayer);
1878     // create content layer
1879     Drawing::Brush maskPaint;
1880     maskPaint.SetBlendMode(Drawing::BlendMode::SRC_IN);
1881     Drawing::SaveLayerOps slrContent(&maskBounds, &maskPaint);
1882     canvas.SaveLayer(slrContent);
1883     canvas.ClipRect(maskBounds, Drawing::ClipOp::INTERSECT, true);
1884 }
1885 #endif
1886 
1887 #ifndef USE_ROSEN_DRAWING
DrawMask(const RSProperties & properties,SkCanvas & canvas)1888 void RSPropertiesPainter::DrawMask(const RSProperties& properties, SkCanvas& canvas)
1889 {
1890     SkRect maskBounds = Rect2SkRect(properties.GetBoundsRect());
1891     DrawMask(properties, canvas, maskBounds);
1892 }
1893 #else
DrawMask(const RSProperties & properties,Drawing::Canvas & canvas)1894 void RSPropertiesPainter::DrawMask(const RSProperties& properties, Drawing::Canvas& canvas)
1895 {
1896     Drawing::Rect maskBounds = Rect2DrawingRect(properties.GetBoundsRect());
1897     DrawMask(properties, canvas, maskBounds);
1898 }
1899 #endif
1900 
1901 #ifndef USE_ROSEN_DRAWING
GetCmdsClipRect(DrawCmdListPtr & cmds)1902 RectF RSPropertiesPainter::GetCmdsClipRect(DrawCmdListPtr& cmds)
1903 #else
1904 RectF RSPropertiesPainter::GetCmdsClipRect(Drawing::DrawCmdListPtr& cmds)
1905 #endif
1906 {
1907 #if defined(RS_ENABLE_DRIVEN_RENDER) && defined(RS_ENABLE_GL)
1908     RectF clipRect;
1909     if (cmds == nullptr) {
1910         return clipRect;
1911     }
1912 #ifndef USE_ROSEN_DRAWING
1913     SkRect rect;
1914     cmds->CheckClipRect(rect);
1915     clipRect = { rect.left(), rect.top(), rect.width(), rect.height() };
1916 #else
1917     Drawing::Rect rect;
1918     cmds->CheckClipRect(rect);
1919     clipRect = { rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight() };
1920 #endif
1921     return clipRect;
1922 #else
1923     return RectF { 0.0f, 0.0f, 0.0f, 0.0f };
1924 #endif
1925 }
1926 
1927 #ifndef USE_ROSEN_DRAWING
DrawFrameForDriven(const RSProperties & properties,RSPaintFilterCanvas & canvas,DrawCmdListPtr & cmds)1928 void RSPropertiesPainter::DrawFrameForDriven(const RSProperties& properties, RSPaintFilterCanvas& canvas,
1929                                              DrawCmdListPtr& cmds)
1930 #else
1931 void RSPropertiesPainter::DrawFrameForDriven(const RSProperties& properties, RSPaintFilterCanvas& canvas,
1932                                              Drawing::DrawCmdListPtr& cmds)
1933 #endif
1934 {
1935 #if defined(RS_ENABLE_DRIVEN_RENDER) && defined(RS_ENABLE_GL)
1936     if (cmds == nullptr) {
1937         return;
1938     }
1939 #ifndef USE_ROSEN_DRAWING
1940     SkMatrix mat;
1941     if (GetGravityMatrix(
1942             properties.GetFrameGravity(), properties.GetFrameRect(), cmds->GetWidth(), cmds->GetHeight(), mat)) {
1943         canvas.concat(mat);
1944     }
1945     auto frameRect = Rect2SkRect(properties.GetFrameRect());
1946 #else
1947     Rosen::Drawing::Matrix mat;
1948     if (GetGravityMatrix(
1949             properties.GetFrameGravity(), properties.GetFrameRect(), cmds->GetWidth(), cmds->GetHeight(), mat)) {
1950         canvas.ConcatMatrix(mat);
1951     }
1952     auto frameRect = Rect2DrawingRect(properties.GetFrameRect());
1953 #endif
1954     // temporary solution for driven content clip
1955     cmds->ReplaceDrivenCmds();
1956     cmds->Playback(canvas, &frameRect);
1957     cmds->RestoreOriginCmdsForDriven();
1958 #endif
1959 }
1960 
1961 #ifndef USE_ROSEN_DRAWING
DrawSpherize(const RSProperties & properties,RSPaintFilterCanvas & canvas,const sk_sp<SkSurface> & spherizeSurface)1962 void RSPropertiesPainter::DrawSpherize(const RSProperties& properties, RSPaintFilterCanvas& canvas,
1963     const sk_sp<SkSurface>& spherizeSurface)
1964 {
1965     if (spherizeSurface == nullptr) {
1966         return;
1967     }
1968     SkAutoCanvasRestore acr(&canvas, true);
1969     float canvasWidth = properties.GetBoundsRect().GetWidth();
1970     float canvasHeight = properties.GetBoundsRect().GetHeight();
1971     if (spherizeSurface->width() == 0 || spherizeSurface->height() == 0) {
1972         return;
1973     }
1974     canvas.scale(canvasWidth / spherizeSurface->width(), canvasHeight / spherizeSurface->height());
1975 
1976     auto imageSnapshot = spherizeSurface->makeImageSnapshot();
1977     if (imageSnapshot == nullptr) {
1978         ROSEN_LOGE("RSPropertiesPainter::DrawCachedSpherizeSurface image  is null");
1979         return;
1980     }
1981 
1982     SkPaint paint;
1983     paint.setBlendMode(SkBlendMode::kSrcOver);
1984 #ifdef NEW_SKIA
1985     paint.setShader(imageSnapshot->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions()));
1986 #else
1987     paint.setShader(imageSnapshot->makeShader(SkTileMode::kClamp, SkTileMode::kClamp));
1988 #endif
1989 
1990     float width = imageSnapshot->width();
1991     float height = imageSnapshot->height();
1992     float degree = properties.GetSpherize();
1993     bool isWidthGreater = width > height;
1994     ROSEN_LOGI("RSPropertiesPainter::DrawCachedSpherizeSurface spherize degree [%f]", degree);
1995 
1996     const SkPoint texCoords[4] = {
1997         {0.0f, 0.0f}, {width, 0.0f}, {width, height}, {0.0f, height}
1998     };
1999     float offsetSquare = 0.f;
2000     if (isWidthGreater) {
2001         offsetSquare = (width - height) * degree / 2.0; // half of the change distance
2002         width = width - (width - height) * degree;
2003     } else {
2004         offsetSquare = (height - width) * degree / 2.0; // half of the change distance
2005         height = height - (height - width) * degree;
2006     }
2007 
2008     float segmentWidthOne = width / 3.0;
2009     float segmentWidthTwo = width / 3.0 * 2.0;
2010     float segmentHeightOne = height / 3.0;
2011     float segmentHeightTwo = height / 3.0 * 2.0;
2012     float offsetSphereWidth = width / 6 * degree;
2013     float offsetSphereHeight = height / 6  * degree;
2014 
2015     SkPoint ctrlPoints[12] = {
2016         // top edge control points
2017         {0.0f, 0.0f}, {segmentWidthOne, 0.0f}, {segmentWidthTwo, 0.0f}, {width, 0.0f},
2018         // right edge control points
2019         {width, segmentHeightOne}, {width, segmentHeightTwo},
2020         // bottom edge control points
2021         {width, height}, {segmentWidthTwo, height}, {segmentWidthOne, height}, {0.0f, height},
2022         // left edge control points
2023         {0.0f, segmentHeightTwo}, {0.0f, segmentHeightOne}
2024     };
2025     ctrlPoints[0].offset(offsetSphereWidth, offsetSphereHeight); // top left control point
2026     ctrlPoints[3].offset(-offsetSphereWidth, offsetSphereHeight); // top right control point
2027     ctrlPoints[6].offset(-offsetSphereWidth, -offsetSphereHeight); // bottom right control point
2028     ctrlPoints[9].offset(offsetSphereWidth, -offsetSphereHeight); // bottom left control point
2029     if (isWidthGreater) {
2030         SkPoint::Offset(ctrlPoints, SK_ARRAY_COUNT(ctrlPoints), offsetSquare, 0);
2031     } else {
2032         SkPoint::Offset(ctrlPoints, SK_ARRAY_COUNT(ctrlPoints), 0, offsetSquare);
2033     }
2034     SkPath path;
2035     path.moveTo(ctrlPoints[0]);
2036     path.cubicTo(ctrlPoints[1], ctrlPoints[2], ctrlPoints[3]); // upper edge
2037     path.cubicTo(ctrlPoints[4], ctrlPoints[5], ctrlPoints[6]); // right edge
2038     path.cubicTo(ctrlPoints[7], ctrlPoints[8], ctrlPoints[9]); // bottom edge
2039     path.cubicTo(ctrlPoints[10], ctrlPoints[11], ctrlPoints[0]); // left edge
2040     canvas.clipPath(path, true);
2041     canvas.drawPatch(ctrlPoints, nullptr, texCoords, SkBlendMode::kSrcOver, paint);
2042 }
2043 #else
DrawSpherize(const RSProperties & properties,RSPaintFilterCanvas & canvas,const std::shared_ptr<Drawing::Surface> & spherizeSurface)2044 void RSPropertiesPainter::DrawSpherize(const RSProperties& properties, RSPaintFilterCanvas& canvas,
2045     const std::shared_ptr<Drawing::Surface>& spherizeSurface)
2046 {
2047 }
2048 #endif
2049 
DrawColorFilter(const RSProperties & properties,RSPaintFilterCanvas & canvas)2050 void RSPropertiesPainter::DrawColorFilter(const RSProperties& properties, RSPaintFilterCanvas& canvas)
2051 {
2052     // if useEffect defined, use color filter from parent EffectView.
2053     auto& colorFilter = properties.GetColorFilter();
2054     if (colorFilter == nullptr) {
2055         return;
2056     }
2057 #ifndef USE_ROSEN_DRAWING
2058     SkAutoCanvasRestore acr(&canvas, true);
2059     canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
2060     SkPaint paint;
2061     paint.setAntiAlias(true);
2062     paint.setColorFilter(colorFilter);
2063     auto skSurface = canvas.GetSurface();
2064     if (skSurface == nullptr) {
2065         ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter skSurface is null");
2066         return;
2067     }
2068     auto clipBounds = canvas.getDeviceClipBounds();
2069     auto imageSnapshot = skSurface->makeImageSnapshot(clipBounds);
2070     if (imageSnapshot == nullptr) {
2071         ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter image is null");
2072         return;
2073     }
2074     SkSamplingOptions options;
2075     canvas.drawImageRect(imageSnapshot, Rect2SkRect(properties.GetBoundsRect()), options, &paint);
2076 #endif
2077 }
2078 
DrawLightUpEffect(const RSProperties & properties,RSPaintFilterCanvas & canvas)2079 void RSPropertiesPainter::DrawLightUpEffect(const RSProperties& properties, RSPaintFilterCanvas& canvas)
2080 {
2081 #ifndef USE_ROSEN_DRAWING
2082 #ifdef NEW_SKIA
2083     SkSurface* skSurface = canvas.GetSurface();
2084     if (skSurface == nullptr) {
2085         ROSEN_LOGD("RSPropertiesPainter::DrawLightUpEffect skSurface is null");
2086         return;
2087     }
2088     SkAutoCanvasRestore acr(&canvas, true);
2089     if (properties.GetClipBounds() != nullptr) {
2090         canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
2091     } else {
2092         canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
2093     }
2094 
2095     auto clipBounds = canvas.getDeviceClipBounds();
2096     auto image = skSurface->makeImageSnapshot(clipBounds);
2097     if (image == nullptr) {
2098         ROSEN_LOGE("RSPropertiesPainter::DrawLightUpEffect image is null");
2099         return;
2100     }
2101     auto imageShader = image->makeShader(SkSamplingOptions(SkFilterMode::kLinear));
2102     auto shader = MakeLightUpEffectShader(properties.GetLightUpEffect(), imageShader);
2103     SkPaint paint;
2104     paint.setShader(shader);
2105     canvas.resetMatrix();
2106     canvas.translate(clipBounds.left(), clipBounds.top());
2107     canvas.drawPaint(paint);
2108 #endif
2109 #endif
2110 }
2111 
2112 #ifndef USE_ROSEN_DRAWING
2113 #ifdef NEW_SKIA
MakeLightUpEffectShader(float lightUpDeg,sk_sp<SkShader> imageShader)2114 sk_sp<SkShader> RSPropertiesPainter::MakeLightUpEffectShader(float lightUpDeg, sk_sp<SkShader> imageShader)
2115 {
2116     static constexpr char prog[] = R"(
2117         uniform half lightUpDeg;
2118         uniform shader imageShader;
2119         vec3 rgb2hsv(in vec3 c)
2120         {
2121             vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
2122             vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
2123             vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
2124             float d = q.x - min(q.w, q.y);
2125             float e = 1.0e-10;
2126             return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
2127         }
2128         vec3 hsv2rgb(in vec3 c)
2129         {
2130             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);
2131             return c.z * mix(vec3(1.0), rgb, c.y);
2132         }
2133         half4 main(float2 coord)
2134         {
2135             vec3 hsv = rgb2hsv(imageShader.eval(coord).rgb);
2136             float satUpper = clamp(hsv.y * 1.2, 0.0, 1.0);
2137             hsv.y = mix(satUpper, hsv.y, lightUpDeg);
2138             hsv.z += lightUpDeg - 1.0;
2139             return vec4(hsv2rgb(hsv), 1.0);
2140         }
2141     )";
2142     auto [effect, err] = SkRuntimeEffect::MakeForShader(SkString(prog));
2143     sk_sp<SkShader> children[] = {imageShader};
2144     size_t childCount = 1;
2145     return effect->makeShader(SkData::MakeWithCopy(
2146         &lightUpDeg, sizeof(lightUpDeg)), children, childCount, nullptr, false);
2147 }
2148 #endif
2149 #endif
2150 
DrawDynamicLightUp(const RSProperties & properties,RSPaintFilterCanvas & canvas)2151 void RSPropertiesPainter::DrawDynamicLightUp(const RSProperties& properties, RSPaintFilterCanvas& canvas)
2152 {
2153 #ifndef USE_ROSEN_DRAWING
2154 #ifdef NEW_SKIA
2155     SkSurface* skSurface = canvas.GetSurface();
2156     if (skSurface == nullptr) {
2157         ROSEN_LOGD("RSPropertiesPainter::DrawDynamicLightUp skSurface is null");
2158         return;
2159     }
2160     SkAutoCanvasRestore acr(&canvas, true);
2161     if (properties.GetClipBounds() != nullptr) {
2162         canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
2163     } else {
2164         canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
2165     }
2166 
2167     auto clipBounds = canvas.getDeviceClipBounds();
2168     auto image = skSurface->makeImageSnapshot(clipBounds);
2169     if (image == nullptr) {
2170         ROSEN_LOGE("RSPropertiesPainter::DrawDynamicLightUp image is null");
2171         return;
2172     }
2173     auto imageShader = image->makeShader(SkSamplingOptions(SkFilterMode::kLinear));
2174     auto shader = MakeDynamicLightUpShader(
2175         properties.GetDynamicLightUpRate().value(), properties.GetDynamicLightUpDegree().value(), imageShader);
2176     SkPaint paint;
2177     paint.setShader(shader);
2178     canvas.resetMatrix();
2179     canvas.translate(clipBounds.left(), clipBounds.top());
2180     canvas.drawPaint(paint);
2181 #endif
2182 #endif
2183 }
2184 
2185 #ifndef USE_ROSEN_DRAWING
2186 #ifdef NEW_SKIA
MakeDynamicLightUpShader(float dynamicLightUpRate,float dynamicLightUpDeg,sk_sp<SkShader> imageShader)2187 sk_sp<SkShader> RSPropertiesPainter::MakeDynamicLightUpShader(
2188     float dynamicLightUpRate, float dynamicLightUpDeg, sk_sp<SkShader> imageShader)
2189 {
2190     static constexpr char prog[] = R"(
2191         uniform half dynamicLightUpRate;
2192         uniform half dynamicLightUpDeg;
2193         uniform shader imageShader;
2194 
2195         half4 main(float2 coord) {
2196             vec3 c = vec3(imageShader.eval(coord).r * 255,
2197                 imageShader.eval(coord).g * 255, imageShader.eval(coord).b * 255);
2198             float x = 0.299 * c.r + 0.587 * c.g + 0.114 * c.b;
2199             float y = (0 - dynamicLightUpRate) * x + dynamicLightUpDeg * 255;
2200             float R = clamp((c.r + y) / 255, 0.0, 1.0);
2201             float G = clamp((c.g + y) / 255, 0.0, 1.0);
2202             float B = clamp((c.b + y) / 255, 0.0, 1.0);
2203             return vec4(R, G, B, 1.0);
2204         }
2205     )";
2206     auto [effect, err] = SkRuntimeEffect::MakeForShader(SkString(prog));
2207     if (!effect) {
2208         ROSEN_LOGE("MakeDynamicLightUpShader::RuntimeShader effect error: %s\n", err.c_str());
2209         return nullptr;
2210     }
2211     SkRuntimeShaderBuilder builder(effect);
2212     builder.child("imageShader") = imageShader;
2213     builder.uniform("dynamicLightUpRate") = dynamicLightUpRate;
2214     builder.uniform("dynamicLightUpDeg") = dynamicLightUpDeg;
2215     return builder.makeShader(nullptr, false);
2216 }
2217 #endif
2218 #endif
2219 
DrawParticle(const RSProperties & properties,RSPaintFilterCanvas & canvas)2220 void RSPropertiesPainter::DrawParticle(const RSProperties& properties, RSPaintFilterCanvas& canvas)
2221 {
2222     auto particleVector = properties.GetParticles();
2223     if (particleVector.GetParticleSize() == 0) {
2224         return;
2225     }
2226     auto particles = particleVector.GetParticleVector();
2227     auto bounds = properties.GetDrawRegion();
2228     for (size_t i = 0; i < particles.size(); i++) {
2229         if (particles[i] != nullptr && particles[i]->IsAlive()) {
2230             // Get particle properties
2231             auto position = particles[i]->GetPosition();
2232             float opacity = particles[i]->GetOpacity();
2233             float scale = particles[i]->GetScale();
2234             if (!(bounds->Intersect(position.x_, position.y_)) || opacity <= 0.f || scale <= 0.f) {
2235                 continue;
2236             }
2237             auto particleType = particles[i]->GetParticleType();
2238 #ifndef USE_ROSEN_DRAWING
2239             SkPaint paint;
2240             paint.setAntiAlias(true);
2241             paint.setAlphaf(opacity);
2242             auto clipBounds = SkRect::MakeXYWH(bounds->left_, bounds->top_, bounds->width_, bounds->height_);
2243             canvas.clipRect(clipBounds, true);
2244 #else
2245             Drawing::Brush brush;
2246             brush.SetAntiAlias(true);
2247             brush.SetAlphaF(opacity);
2248             auto clipBounds = Drawing::Rect(
2249                 bounds->left_, bounds->top_, bounds->left_ + bounds->width_, bounds->top_ + bounds->height_);
2250             canvas.ClipRect(clipBounds, Drawing::ClipOp::INTERSECT, true);
2251 #endif
2252 
2253             if (particleType == ParticleType::POINTS) {
2254                 auto radius = particles[i]->GetRadius();
2255                 Color color = particles[i]->GetColor();
2256                 auto alpha = color.GetAlpha();
2257                 color.SetAlpha(alpha * opacity);
2258 #ifndef USE_ROSEN_DRAWING
2259                 paint.setColor(color.AsArgbInt());
2260                 canvas.drawCircle(position.x_, position.y_, radius * scale, paint);
2261 #else
2262                 brush.SetColor(color.AsArgbInt());
2263                 canvas.AttachBrush(brush);
2264                 canvas.DrawCircle(Drawing::Point(position.x_, position.y_), radius);
2265                 canvas.DetachBrush();
2266 #endif
2267             } else {
2268                 auto imageSize = particles[i]->GetImageSize();
2269                 auto image = particles[i]->GetImage();
2270                 float left = position.x_;
2271                 float top = position.y_;
2272                 float right = position.x_ + imageSize.x_ * scale;
2273                 float bottom = position.y_ + imageSize.y_ * scale;
2274                 canvas.save();
2275                 canvas.translate(position.x_, position.y_);
2276 #ifndef USE_ROSEN_DRAWING
2277                 canvas.rotate(particles[i]->GetSpin(), imageSize.x_ * scale / 2.f, imageSize.y_ * scale / 2.f);
2278 #else
2279                 canvas.Save();
2280                 canvas.Translate(position.x_, position.y_);
2281                 canvas.Rotate(particles[i]->GetSpin(), imageSize.x_ * scale / 2.f, imageSize.y_ * scale / 2.f);
2282 #endif
2283                 RectF destRect(left, top, right, bottom);
2284                 image->SetDstRect(destRect);
2285                 image->SetScale(scale);
2286                 image->SetImageRepeat(0);
2287 #ifndef USE_ROSEN_DRAWING
2288                 SkRect rect { left, top, right, bottom };
2289 #ifdef NEW_SKIA
2290                 image->CanvasDrawImage(canvas, rect, SkSamplingOptions(), paint, false);
2291                 canvas.restore();
2292 #else
2293                 image->CanvasDrawImage(canvas, rect, paint, false);
2294                 canvas.restore();
2295 #endif
2296 #else
2297                 Drawing::Rect rect { fLeft, ftop, fRight, fBottom };
2298                 canvas.AttachBrush(brush);
2299                 image->CanvasDrawImage(canvas, rect, false);
2300                 canvas.DetachBrush();
2301                 canvas.Restore();
2302 #endif
2303             }
2304         }
2305     }
2306 }
2307 
2308 } // namespace Rosen
2309 } // namespace OHOS
2310