• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "drawable/rs_property_drawable_utils.h"
17 
18 #include "common/rs_optional_trace.h"
19 #include "common/rs_obj_abs_geometry.h"
20 #include "platform/common/rs_log.h"
21 #include "property/rs_properties_painter.h"
22 #include "render/rs_drawing_filter.h"
23 #include "render/rs_kawase_blur_shader_filter.h"
24 #include "render/rs_mesa_blur_shader_filter.h"
25 #include "render/rs_linear_gradient_blur_shader_filter.h"
26 #include "render/rs_magnifier_shader_filter.h"
27 #include "render/rs_material_filter.h"
28 #include "render/rs_color_picker.h"
29 
30 namespace OHOS {
31 namespace Rosen {
32 namespace {
33 constexpr int TRACE_LEVEL_TWO = 2;
34 constexpr int PARAM_DOUBLE = 2;
35 } // namespace
36 
37 std::shared_ptr<Drawing::RuntimeEffect> RSPropertyDrawableUtils::binarizationShaderEffect_ = nullptr;
38 std::shared_ptr<Drawing::RuntimeEffect> RSPropertyDrawableUtils::dynamicDimShaderEffect_ = nullptr;
39 std::shared_ptr<Drawing::RuntimeEffect> RSPropertyDrawableUtils::dynamicBrightnessBlenderEffect_ = nullptr;
40 
RRect2DrawingRRect(const RRect & rr)41 Drawing::RoundRect RSPropertyDrawableUtils::RRect2DrawingRRect(const RRect& rr)
42 {
43     Drawing::Rect rect = Drawing::Rect(
44         rr.rect_.left_, rr.rect_.top_, rr.rect_.left_ + rr.rect_.width_, rr.rect_.top_ + rr.rect_.height_);
45 
46     // set radius for all 4 corner of RRect
47     constexpr uint32_t NUM_OF_CORNERS_IN_RECT = 4;
48     std::vector<Drawing::Point> radii(NUM_OF_CORNERS_IN_RECT);
49     for (uint32_t i = 0; i < NUM_OF_CORNERS_IN_RECT; i++) {
50         radii.at(i).SetX(rr.radius_[i].x_);
51         radii.at(i).SetY(rr.radius_[i].y_);
52     }
53     return { rect, radii };
54 }
55 
Rect2DrawingRect(const RectF & r)56 Drawing::Rect RSPropertyDrawableUtils::Rect2DrawingRect(const RectF& r)
57 {
58     return { r.left_, r.top_, r.left_ + r.width_, r.top_ + r.height_ };
59 }
60 
GetRRectForDrawingBorder(const RSProperties & properties,const std::shared_ptr<RSBorder> & border,const bool & isOutline)61 RRect RSPropertyDrawableUtils::GetRRectForDrawingBorder(
62     const RSProperties& properties, const std::shared_ptr<RSBorder>& border, const bool& isOutline)
63 {
64     if (!border) {
65         return {};
66     }
67 
68     return isOutline ? RRect(properties.GetRRect().rect_.MakeOutset(border->GetWidthFour()), border->GetRadiusFour())
69                      : properties.GetRRect();
70 }
71 
GetInnerRRectForDrawingBorder(const RSProperties & properties,const std::shared_ptr<RSBorder> & border,const bool & isOutline)72 RRect RSPropertyDrawableUtils::GetInnerRRectForDrawingBorder(
73     const RSProperties& properties, const std::shared_ptr<RSBorder>& border, const bool& isOutline)
74 {
75     if (!border) {
76         return {};
77     }
78     return isOutline ? properties.GetRRect() : properties.GetInnerRRect();
79 }
80 
GetColorForShadowSyn(Drawing::Canvas * canvas,Drawing::Path & path,const Color & color,const int & colorStrategy)81 Color RSPropertyDrawableUtils::GetColorForShadowSyn(Drawing::Canvas* canvas, Drawing::Path& path, const Color& color,
82     const int& colorStrategy)
83 {
84     RSColor colorPicked;
85     auto shadowAlpha = color.GetAlpha();
86     auto matrix = canvas->GetTotalMatrix();
87     if (PickColorSyn(canvas, path, matrix, colorPicked, colorStrategy)) {
88         GetDarkColor(colorPicked);
89     } else {
90         shadowAlpha = 0;
91     }
92     return Color(colorPicked.GetRed(), colorPicked.GetGreen(), colorPicked.GetBlue(), shadowAlpha);
93 }
94 
GetShadowRegionImage(Drawing::Canvas * canvas,Drawing::Path & drPath,Drawing::Matrix & matrix)95 std::shared_ptr<Drawing::Image> RSPropertyDrawableUtils::GetShadowRegionImage(Drawing::Canvas* canvas,
96     Drawing::Path& drPath, Drawing::Matrix& matrix)
97 {
98     Drawing::Rect clipBounds = drPath.GetBounds();
99     Drawing::RectI clipIBounds = { static_cast<int>(clipBounds.GetLeft()), static_cast<int>(clipBounds.GetTop()),
100         static_cast<int>(clipBounds.GetRight()), static_cast<int>(clipBounds.GetBottom()) };
101     Drawing::Surface* drSurface = canvas->GetSurface();
102     if (drSurface == nullptr) {
103         ROSEN_LOGE("RSPropertyDrawableUtils::GetShadowRegionImage drSurface is null");
104         return nullptr;
105     }
106     static int deviceWidth = drSurface->Width();
107     static int deviceHeight = drSurface->Height();
108     Drawing::Rect regionRect = {0, 0, clipIBounds.GetWidth(), clipIBounds.GetHeight()};
109     Drawing::Rect regionRectDev;
110     matrix.MapRect(regionRectDev, regionRect);
111     int32_t fLeft = std::clamp(int(regionRectDev.GetLeft()), 0, deviceWidth - 1);
112     int32_t fTop = std::clamp(int(regionRectDev.GetTop()), 0, deviceHeight - 1);
113     int32_t fRight = std::clamp(int(regionRectDev.GetRight()), 0, deviceWidth - 1);
114     int32_t fBottom = std::clamp(int(regionRectDev.GetBottom()), 0, deviceHeight - 1);
115     if (fLeft == fRight || fTop == fBottom) {
116         ROSEN_LOGE("RSPropertyDrawableUtils::GetShadowRegionImage Shadow Rect Invalid");
117         return nullptr;
118     }
119     Drawing::RectI regionBounds = { fLeft, fTop, fRight, fBottom };
120     std::shared_ptr<Drawing::Image> shadowRegionImage = drSurface->GetImageSnapshot(regionBounds);
121     return shadowRegionImage;
122 }
123 
PickColorSyn(Drawing::Canvas * canvas,Drawing::Path & drPath,Drawing::Matrix & matrix,RSColor & colorPicked,const int & colorStrategy)124 bool RSPropertyDrawableUtils::PickColorSyn(Drawing::Canvas* canvas, Drawing::Path& drPath, Drawing::Matrix& matrix,
125     RSColor& colorPicked, const int& colorStrategy)
126 {
127     std::shared_ptr<Drawing::Image> shadowRegionImage = GetShadowRegionImage(canvas, drPath, matrix);
128     if (shadowRegionImage == nullptr) {
129         ROSEN_LOGE("RSPropertyDrawableUtils::PickColorSyn GetImageSnapshot Failed");
130         return false;
131     }
132     auto scaledImage = GpuScaleImage(canvas, shadowRegionImage);
133     if (scaledImage == nullptr) {
134         ROSEN_LOGE("RSPropertyDrawableUtils::PickColorSyn scaledImage is null");
135         return false;
136     }
137     std::shared_ptr<Drawing::Pixmap> dst;
138     const int buffLen = scaledImage->GetWidth() * scaledImage->GetHeight();
139     auto pixelPtr = std::make_unique<uint32_t[]>(buffLen);
140     auto info = scaledImage->GetImageInfo();
141     dst = std::make_shared<Drawing::Pixmap>(info, pixelPtr.get(), info.GetWidth() * info.GetBytesPerPixel());
142     bool flag = scaledImage->ReadPixels(*dst, 0, 0);
143     if (!flag) {
144         ROSEN_LOGE("RSPropertyDrawableUtils::PickColorSyn ReadPixel Failed");
145         return false;
146     }
147     uint32_t errorCode = 0;
148     std::shared_ptr<RSColorPicker> colorPicker = RSColorPicker::CreateColorPicker(dst, errorCode);
149     if (colorPicker == nullptr) {
150         ROSEN_LOGE("RSPropertyDrawableUtils::PickColorSyn colorPicker is null");
151         return false;
152     }
153     if (errorCode != 0) {
154         return false;
155     }
156     Drawing::ColorQuad color;
157     if (colorStrategy == SHADOW_COLOR_STRATEGY::COLOR_STRATEGY_MAIN) {
158         colorPicker->GetLargestProportionColor(color);
159     } else {
160         colorPicker->GetAverageColor(color);
161     }
162     colorPicked = RSColor(Drawing::Color::ColorQuadGetR(color), Drawing::Color::ColorQuadGetG(color),
163         Drawing::Color::ColorQuadGetB(color), Drawing::Color::ColorQuadGetA(color));
164     return true;
165 }
166 
GpuScaleImage(Drawing::Canvas * canvas,const std::shared_ptr<Drawing::Image> image)167 std::shared_ptr<Drawing::Image> RSPropertyDrawableUtils::GpuScaleImage(Drawing::Canvas* canvas,
168     const std::shared_ptr<Drawing::Image> image)
169 {
170     std::string shaderString(R"(
171         uniform shader imageInput;
172 
173         half4 main(float2 xy) {
174             half4 c = imageInput.eval(xy);
175             return half4(c.rgb, 1.0);
176         }
177     )");
178 
179     std::shared_ptr<Drawing::RuntimeEffect> effect = Drawing::RuntimeEffect::CreateForShader(shaderString);
180     if (!effect) {
181         ROSEN_LOGE("RSPropertyDrawableUtils::GpuScaleImage effect is null");
182         return nullptr;
183     }
184 
185     Drawing::SamplingOptions linear(Drawing::FilterMode::LINEAR, Drawing::MipmapMode::NONE);
186     std::shared_ptr<Drawing::RuntimeShaderBuilder> effectBulider =
187         std::make_shared<Drawing::RuntimeShaderBuilder>(effect);
188     Drawing::ImageInfo pcInfo;
189     Drawing::Matrix matrix;
190     matrix.SetScale(1.0, 1.0);
191     if (image->GetWidth() * image->GetHeight() < 10000) { // 10000 = 100 * 100 pixels
192         pcInfo = Drawing::ImageInfo::MakeN32Premul(10, 10); // 10 * 10 pixels
193         matrix.SetScale(10.0 / image->GetWidth(), 10.0 / image->GetHeight()); // 10.0 pixels
194     } else {
195         pcInfo = Drawing::ImageInfo::MakeN32Premul(100, 100); // 100 * 100 pixels
196         matrix.SetScale(100.0 / image->GetWidth(), 100.0 / image->GetHeight());  // 100.0 pixels
197     }
198     effectBulider->SetChild("imageInput", Drawing::ShaderEffect::CreateImageShader(
199         *image, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, linear, matrix));
200     std::shared_ptr<Drawing::Image> tmpColorImg = effectBulider->MakeImage(
201         canvas->GetGPUContext().get(), nullptr, pcInfo, false);
202 
203     return tmpColorImg;
204 }
205 
GetDarkColor(RSColor & color)206 void RSPropertyDrawableUtils::GetDarkColor(RSColor& color)
207 {
208     // convert to lab
209     float minColorRange = 0;
210     float maxColorRange = 255;
211     float R = float(color.GetRed()) / maxColorRange;
212     float G = float(color.GetGreen()) / maxColorRange;
213     float B = float(color.GetBlue()) / maxColorRange;
214 
215     float X = 0.4124 * R + 0.3576 * G + 0.1805 * B;
216     float Y = 0.2126 * R + 0.7152 * G + 0.0722 * B;
217     float Z = 0.0193 * R + 0.1192 * G + 0.9505 * B;
218 
219     float Xn = 0.9505;
220     float Yn = 1.0000;
221     float Zn = 1.0889999;
222     float Fx = (X / Xn) > 0.008856 ? pow((X / Xn), 1.0 / 3) : (7.787 * (X / Xn) + 16.0 / 116);
223     float Fy = (Y / Yn) > 0.008856 ? pow((Y / Yn), 1.0 / 3) : (7.787 * (Y / Yn) + 16.0 / 116);
224     float Fz = (Z / Zn) > 0.008856 ? pow((Z / Zn), 1.0 / 3) : (7.787 * (Z / Zn) + 16.0 / 116);
225     float L = 116 * Fy - 16;
226     float a = 500 * (Fx - Fy);
227     float b = 200 * (Fy - Fz);
228 
229     float standardLightness = 75.0;
230     if (L > standardLightness) {
231         float L1 = standardLightness;
232         float xw = 0.9505;
233         float yw = 1.0000;
234         float zw = 1.0889999;
235 
236         float fy = (L1 + 16) / 116;
237         float fx = fy + (a / 500);
238         float fz = fy - (b / 200);
239 
240         float X1 = xw * ((pow(fx, 3) > 0.008856) ? pow(fx, 3) : ((fx - 16.0 / 116) / 7.787));
241         float Y1 = yw * ((pow(fy, 3) > 0.008856) ? pow(fy, 3) : ((fy - 16.0 / 116) / 7.787));
242         float Z1 = zw * ((pow(fz, 3) > 0.008856) ? pow(fz, 3) : ((fz - 16.0 / 116) / 7.787));
243 
244         float DarkR = 3.2406 * X1 - 1.5372 * Y1 - 0.4986 * Z1;
245         float DarkG = -0.9689 * X1 + 1.8758 * Y1 + 0.0415 * Z1;
246         float DarkB = 0.0557 * X1 - 0.2040 * Y1 + 1.0570 * Z1;
247 
248         DarkR = std::clamp(maxColorRange * DarkR, minColorRange, maxColorRange);
249         DarkG = std::clamp(maxColorRange * DarkG, minColorRange, maxColorRange);
250         DarkB = std::clamp(maxColorRange * DarkB, minColorRange, maxColorRange);
251 
252         color = RSColor(DarkR, DarkG, DarkB, color.GetAlpha());
253     }
254 }
255 
CeilMatrixTrans(Drawing::Canvas * canvas)256 void RSPropertyDrawableUtils::CeilMatrixTrans(Drawing::Canvas* canvas)
257 {
258     // The translation of the matrix is rounded to improve the hit ratio of skia blurfilter cache,
259     // the function <compute_key_and_clip_bounds> in <skia/src/gpu/GrBlurUtil.cpp> for more details.
260     auto matrix = canvas->GetTotalMatrix();
261     matrix.Set(Drawing::Matrix::TRANS_X, std::ceil(matrix.Get(Drawing::Matrix::TRANS_X)));
262     matrix.Set(Drawing::Matrix::TRANS_Y, std::ceil(matrix.Get(Drawing::Matrix::TRANS_Y)));
263     canvas->SetMatrix(matrix);
264 }
265 
DrawFilter(Drawing::Canvas * canvas,const std::shared_ptr<RSFilter> & rsFilter,const std::unique_ptr<RSFilterCacheManager> & cacheManager,const bool isForegroundFilter,bool shouldClearFilteredCache)266 void RSPropertyDrawableUtils::DrawFilter(Drawing::Canvas* canvas,
267     const std::shared_ptr<RSFilter>& rsFilter, const std::unique_ptr<RSFilterCacheManager>& cacheManager,
268     const bool isForegroundFilter, bool shouldClearFilteredCache)
269 {
270     if (!RSSystemProperties::GetBlurEnabled()) {
271         ROSEN_LOGD("RSPropertyDrawableUtils::DrawFilter close blur.");
272         return;
273     }
274     if (rsFilter == nullptr) {
275         ROSEN_LOGE("RSPropertyDrawableUtils::DrawFilter null filter.");
276         return;
277     }
278     if (canvas == nullptr) {
279         ROSEN_LOGE("RSPropertyDrawableUtils::DrawFilter null canvas.");
280         return;
281     }
282 
283     auto filter = std::static_pointer_cast<RSDrawingFilter>(rsFilter);
284     auto clipIBounds = canvas->GetDeviceClipBounds();
285     RS_OPTIONAL_TRACE_NAME("DrawFilter " + rsFilter->GetDescription());
286     RS_OPTIONAL_TRACE_NAME_FMT_LEVEL(TRACE_LEVEL_TWO, "DrawFilter, filterType: %d, %s, bounds: %s",
287         rsFilter->GetFilterType(), rsFilter->GetDetailedDescription().c_str(), clipIBounds.ToString().c_str());
288     g_blurCnt++;
289 
290     auto surface = canvas->GetSurface();
291     if (surface == nullptr) {
292         ROSEN_LOGE("RSPropertyDrawableUtils::DrawFilter surface null");
293         Drawing::Brush brush = filter->GetBrush();
294         Drawing::SaveLayerOps slr(nullptr, &brush, Drawing::SaveLayerOps::Flags::INIT_WITH_PREVIOUS);
295         canvas->SaveLayer(slr);
296         filter->PostProcess(*canvas);
297         return;
298     }
299 
300     auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(canvas);
301     if (paintFilterCanvas == nullptr) {
302         return;
303     }
304     RSAutoCanvasRestore autoCanvasStore(paintFilterCanvas, isForegroundFilter ?
305         RSPaintFilterCanvas::SaveType::kAlpha : RSPaintFilterCanvas::SaveType::kNone);
306     if (isForegroundFilter) {
307         paintFilterCanvas->SetAlpha(1.0);
308     }
309     auto imageClipIBounds = clipIBounds;
310     std::shared_ptr<RSShaderFilter> magnifierShaderFilter =
311         filter->GetShaderFilterWithType(RSShaderFilter::MAGNIFIER);
312     if (magnifierShaderFilter != nullptr) {
313         auto tmpFilter = std::static_pointer_cast<RSMagnifierShaderFilter>(magnifierShaderFilter);
314         auto canvasMatrix = canvas->GetTotalMatrix();
315         tmpFilter->SetMagnifierOffset(canvasMatrix);
316         imageClipIBounds.Offset(tmpFilter->GetMagnifierOffsetX(), tmpFilter->GetMagnifierOffsetY());
317     }
318 
319 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
320     // Optional use cacheManager to draw filter
321     if (!paintFilterCanvas->GetDisableFilterCache() && cacheManager != nullptr && RSProperties::FilterCacheEnabled) {
322         if (cacheManager->GetCachedType() == FilterCacheType::FILTERED_SNAPSHOT) {
323             g_blurCnt--;
324         }
325         std::shared_ptr<RSShaderFilter> rsShaderFilter =
326         filter->GetShaderFilterWithType(RSShaderFilter::LINEAR_GRADIENT_BLUR);
327         if (rsShaderFilter != nullptr) {
328             auto tmpFilter = std::static_pointer_cast<RSLinearGradientBlurShaderFilter>(rsShaderFilter);
329             tmpFilter->IsOffscreenCanvas(true);
330             filter->SetSnapshotOutset(false);
331         }
332         cacheManager->DrawFilter(*paintFilterCanvas, filter,
333             { false, shouldClearFilteredCache });
334         cacheManager->CompactFilterCache(shouldClearFilteredCache); // flag for clear witch cache after drawing
335         return;
336     }
337 #endif
338 
339     std::shared_ptr<RSShaderFilter> rsShaderFilter =
340         filter->GetShaderFilterWithType(RSShaderFilter::LINEAR_GRADIENT_BLUR);
341     if (rsShaderFilter != nullptr) {
342         auto tmpFilter = std::static_pointer_cast<RSLinearGradientBlurShaderFilter>(rsShaderFilter);
343         tmpFilter->IsOffscreenCanvas(true);
344         filter->SetSnapshotOutset(false);
345     }
346 
347     auto imageSnapshot = surface->GetImageSnapshot(imageClipIBounds);
348     if (imageSnapshot == nullptr) {
349         ROSEN_LOGD("RSPropertyDrawableUtils::DrawFilter image null");
350         return;
351     }
352     if (RSSystemProperties::GetImageGpuResourceCacheEnable(imageSnapshot->GetWidth(), imageSnapshot->GetHeight())) {
353         ROSEN_LOGD("RSPropertyDrawableUtils::DrawFilter cache image resource(w:%{public}d, h:%{public}d).",
354             imageSnapshot->GetWidth(), imageSnapshot->GetHeight());
355         imageSnapshot->HintCacheGpuResource();
356     }
357 
358     filter->PreProcess(imageSnapshot);
359     Drawing::AutoCanvasRestore acr(*canvas, true);
360     canvas->ResetMatrix();
361     Drawing::Rect srcRect = Drawing::Rect(0, 0, imageSnapshot->GetWidth(), imageSnapshot->GetHeight());
362     Drawing::Rect dstRect = clipIBounds;
363     filter->DrawImageRect(*canvas, imageSnapshot, srcRect, dstRect);
364     filter->PostProcess(*canvas);
365 }
366 
BeginForegroundFilter(RSPaintFilterCanvas & canvas,const RectF & bounds)367 void RSPropertyDrawableUtils::BeginForegroundFilter(RSPaintFilterCanvas& canvas, const RectF& bounds)
368 {
369     RS_OPTIONAL_TRACE_NAME("RSPropertyDrawableUtils::BeginForegroundFilter");
370     auto surface = canvas.GetSurface();
371     if (!surface) {
372         return;
373     }
374     std::shared_ptr<Drawing::Surface> offscreenSurface = surface->MakeSurface(bounds.width_, bounds.height_);
375     if (!offscreenSurface) {
376         return;
377     }
378     auto offscreenCanvas = std::make_shared<RSPaintFilterCanvas>(offscreenSurface.get());
379     canvas.StoreCanvas();
380     canvas.ReplaceMainScreenData(offscreenSurface, offscreenCanvas);
381     offscreenCanvas->Clear(Drawing::Color::COLOR_TRANSPARENT);
382     canvas.SavePCanvasList();
383     canvas.RemoveAll();
384     canvas.AddCanvas(offscreenCanvas.get());
385 }
386 
DrawForegroundFilter(RSPaintFilterCanvas & canvas,const std::shared_ptr<RSFilter> & rsFilter)387 void RSPropertyDrawableUtils::DrawForegroundFilter(RSPaintFilterCanvas& canvas,
388     const std::shared_ptr<RSFilter>& rsFilter)
389 {
390     RS_OPTIONAL_TRACE_NAME("DrawForegroundFilter restore");
391     auto surface = canvas.GetSurface();
392     std::shared_ptr<Drawing::Image> imageSnapshot = nullptr;
393     if (surface) {
394         imageSnapshot = surface->GetImageSnapshot();
395     } else {
396         ROSEN_LOGD("RSPropertyDrawableUtils::DrawForegroundFilter Surface null");
397     }
398 
399     canvas.RestorePCanvasList();
400     canvas.SwapBackMainScreenData();
401 
402     if (rsFilter == nullptr) {
403         return;
404     }
405 
406     if (imageSnapshot == nullptr) {
407         ROSEN_LOGD("RSPropertyDrawableUtils::DrawForegroundFilter image null");
408         return;
409     }
410     auto foregroundFilter = std::static_pointer_cast<RSDrawingFilterOriginal>(rsFilter);
411     if (foregroundFilter->GetFilterType() == RSFilter::MOTION_BLUR) {
412         if (canvas.GetDisableFilterCache()) {
413             foregroundFilter->DisableMotionBlur(true);
414         } else {
415             foregroundFilter->DisableMotionBlur(false);
416         }
417     }
418 
419     foregroundFilter->DrawImageRect(canvas, imageSnapshot, Drawing::Rect(0, 0, imageSnapshot->GetWidth(),
420         imageSnapshot->GetHeight()), Drawing::Rect(0, 0, imageSnapshot->GetWidth(), imageSnapshot->GetHeight()));
421 }
422 
GetAndResetBlurCnt()423 int RSPropertyDrawableUtils::GetAndResetBlurCnt()
424 {
425     auto blurCnt = g_blurCnt;
426     g_blurCnt = 0;
427     return blurCnt;
428 }
429 
DrawBackgroundEffect(RSPaintFilterCanvas * canvas,const std::shared_ptr<RSFilter> & rsFilter,const std::unique_ptr<RSFilterCacheManager> & cacheManager,bool shouldClearFilteredCache,Drawing::RectI & bounds)430 void RSPropertyDrawableUtils::DrawBackgroundEffect(
431     RSPaintFilterCanvas* canvas, const std::shared_ptr<RSFilter>& rsFilter,
432     const std::unique_ptr<RSFilterCacheManager>& cacheManager, bool shouldClearFilteredCache,
433     Drawing::RectI& bounds)
434 {
435     if (rsFilter == nullptr) {
436         ROSEN_LOGE("RSPropertyDrawableUtils::DrawBackgroundEffect null filter");
437         return;
438     }
439     if (canvas == nullptr) {
440         ROSEN_LOGE("RSPropertyDrawableUtils::DrawBackgroundEffect null canvas");
441         return;
442     }
443     auto surface = canvas->GetSurface();
444     if (surface == nullptr) {
445         ROSEN_LOGE("RSPropertyDrawableUtils::DrawBackgroundEffect surface null");
446         return;
447     }
448     g_blurCnt++;
449     auto clipIBounds = bounds;
450     auto filter = std::static_pointer_cast<RSDrawingFilter>(rsFilter);
451     RS_OPTIONAL_TRACE_NAME("RSPropertyDrawableUtils::DrawBackgroundEffect " + rsFilter->GetDescription());
452     RS_OPTIONAL_TRACE_NAME_FMT_LEVEL(TRACE_LEVEL_TWO, "EffectComponent, %s, bounds: %s",
453         rsFilter->GetDetailedDescription().c_str(), clipIBounds.ToString().c_str());
454 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
455     // Optional use cacheManager to draw filter
456     if (RSProperties::FilterCacheEnabled && cacheManager != nullptr && !canvas->GetDisableFilterCache()) {
457         if (cacheManager->GetCachedType() == FilterCacheType::FILTERED_SNAPSHOT) {
458             g_blurCnt--;
459         }
460         auto&& data = cacheManager->GeneratedCachedEffectData(*canvas, filter, clipIBounds, clipIBounds);
461         cacheManager->CompactFilterCache(shouldClearFilteredCache); // flag for clear witch cache after drawing
462         canvas->SetEffectData(data);
463         return;
464     }
465 #endif
466     auto imageRect = clipIBounds;
467     auto imageSnapshot = surface->GetImageSnapshot(imageRect);
468     if (imageSnapshot == nullptr) {
469         ROSEN_LOGE("RSPropertyDrawableUtils::DrawBackgroundEffect image snapshot null");
470         return;
471     }
472     filter->PreProcess(imageSnapshot);
473     // create a offscreen skSurface
474     std::shared_ptr<Drawing::Surface> offscreenSurface =
475         surface->MakeSurface(imageSnapshot->GetWidth(), imageSnapshot->GetHeight());
476     if (offscreenSurface == nullptr) {
477         ROSEN_LOGE("RSPropertyDrawableUtils::DrawBackgroundEffect offscreenSurface null");
478         return;
479     }
480     RSPaintFilterCanvas offscreenCanvas(offscreenSurface.get());
481     auto clipBounds = Drawing::Rect(0, 0, imageRect.GetWidth(), imageRect.GetHeight());
482     auto imageSnapshotBounds = Drawing::Rect(0, 0, imageSnapshot->GetWidth(), imageSnapshot->GetHeight());
483     filter->DrawImageRect(offscreenCanvas, imageSnapshot, imageSnapshotBounds, clipBounds);
484     filter->PostProcess(offscreenCanvas);
485 
486     auto imageCache = offscreenSurface->GetImageSnapshot();
487     if (imageCache == nullptr) {
488         ROSEN_LOGE("RSPropertyDrawableUtils::DrawBackgroundEffect imageCache snapshot null");
489         return;
490     }
491     auto data = std::make_shared<RSPaintFilterCanvas::CachedEffectData>(std::move(imageCache), std::move(imageRect));
492     canvas->SetEffectData(std::move(data));
493 }
494 
DrawColorFilter(Drawing::Canvas * canvas,const std::shared_ptr<Drawing::ColorFilter> & colorFilter)495 void RSPropertyDrawableUtils::DrawColorFilter(
496     Drawing::Canvas* canvas, const std::shared_ptr<Drawing::ColorFilter>& colorFilter)
497 {
498     if (colorFilter == nullptr) {
499         ROSEN_LOGE("RSPropertyDrawableUtils::DrawColorFilter null colorFilter.");
500         return;
501     }
502 
503     Drawing::Brush brush;
504     brush.SetAntiAlias(true);
505     Drawing::Filter filter;
506     filter.SetColorFilter(colorFilter);
507     brush.SetFilter(filter);
508     auto surface = canvas->GetSurface();
509     if (surface == nullptr) {
510         ROSEN_LOGE("RSPropertyDrawableUtils::DrawColorFilter surface is null");
511         return;
512     }
513     auto clipBounds = canvas->GetLocalClipBounds();
514     Drawing::AutoCanvasRestore acr(*canvas, false);
515     Drawing::SaveLayerOps slo(&clipBounds, &brush, Drawing::SaveLayerOps::Flags::INIT_WITH_PREVIOUS);
516     canvas->SaveLayer(slo);
517 }
518 
DrawLightUpEffect(Drawing::Canvas * canvas,const float lightUpEffectDegree)519 void RSPropertyDrawableUtils::DrawLightUpEffect(Drawing::Canvas* canvas, const float lightUpEffectDegree)
520 {
521     if (!ROSEN_GE(lightUpEffectDegree, 0.0) || !ROSEN_LNE(lightUpEffectDegree, 1.0)) {
522         ROSEN_LOGE(
523             "RSPropertyDrawableUtils::DrawLightUpEffect Invalid lightUpEffectDegree %{public}f", lightUpEffectDegree);
524         return;
525     }
526 
527     Drawing::Surface* surface = canvas->GetSurface();
528     if (surface == nullptr) {
529         ROSEN_LOGE("RSPropertyDrawableUtils::DrawLightUpEffect surface is null");
530         return;
531     }
532 
533     auto clipBounds = canvas->GetDeviceClipBounds();
534     auto image = surface->GetImageSnapshot(clipBounds);
535     if (image == nullptr) {
536         ROSEN_LOGE("RSPropertyDrawableUtils::DrawLightUpEffect image is null");
537         return;
538     }
539 
540     Drawing::Matrix scaleMat;
541     auto imageShader = Drawing::ShaderEffect::CreateImageShader(*image, Drawing::TileMode::CLAMP,
542         Drawing::TileMode::CLAMP, Drawing::SamplingOptions(Drawing::FilterMode::LINEAR), scaleMat);
543     auto shader = Drawing::ShaderEffect::CreateLightUp(lightUpEffectDegree, *imageShader);
544     Drawing::Brush brush;
545     brush.SetShaderEffect(shader);
546     Drawing::AutoCanvasRestore acr(*canvas, true);
547     canvas->ResetMatrix();
548     canvas->Translate(clipBounds.GetLeft(), clipBounds.GetTop());
549     canvas->DrawBackground(brush);
550 }
551 
DrawDynamicDim(Drawing::Canvas * canvas,const float dynamicDimDegree)552 void RSPropertyDrawableUtils::DrawDynamicDim(Drawing::Canvas* canvas, const float dynamicDimDegree)
553 {
554     if (!ROSEN_GE(dynamicDimDegree, 0.0) || !ROSEN_LNE(dynamicDimDegree, 1.0)) {
555         ROSEN_LOGE(
556             "RSPropertyDrawableUtils::DrawDynamicDim Invalid dynamicDimDegree %{public}f", dynamicDimDegree);
557         return;
558     }
559 
560     Drawing::Surface* surface = canvas->GetSurface();
561     if (surface == nullptr) {
562         ROSEN_LOGE("RSPropertyDrawableUtils::DrawDynamicDim surface is null");
563         return;
564     }
565 
566     auto clipBounds = canvas->GetDeviceClipBounds();
567     auto image = surface->GetImageSnapshot(clipBounds);
568     if (image == nullptr) {
569         ROSEN_LOGE("RSPropertyDrawableUtils::DrawDynamicDim image is null");
570         return;
571     }
572 
573     Drawing::Matrix scaleMat;
574     auto imageShader = Drawing::ShaderEffect::CreateImageShader(*image, Drawing::TileMode::CLAMP,
575         Drawing::TileMode::CLAMP, Drawing::SamplingOptions(Drawing::FilterMode::LINEAR), scaleMat);
576     auto shader = MakeDynamicDimShader(dynamicDimDegree, imageShader);
577     if (shader == nullptr) {
578         ROSEN_LOGE("RSPropertyDrawableUtils::DrawDynamicDim shader is null");
579         return;
580     }
581     Drawing::Brush brush;
582     brush.SetShaderEffect(shader);
583     Drawing::AutoCanvasRestore acr(*canvas, true);
584     canvas->ResetMatrix();
585     canvas->Translate(clipBounds.GetLeft(), clipBounds.GetTop());
586     canvas->DrawBackground(brush);
587 }
588 
MakeDynamicDimShader(float dynamicDimDeg,std::shared_ptr<Drawing::ShaderEffect> imageShader)589 std::shared_ptr<Drawing::ShaderEffect> RSPropertyDrawableUtils::MakeDynamicDimShader(
590     float dynamicDimDeg, std::shared_ptr<Drawing::ShaderEffect> imageShader)
591 {
592     static constexpr char prog[] = R"(
593         uniform half dynamicDimDeg;
594         uniform shader imageShader;
595 
596         vec3 rgb2hsv(in vec3 c)
597         {
598             vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
599             vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
600             vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
601             float d = q.x - min(q.w, q.y);
602             float e = 1.0e-10;
603             return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
604         }
605         vec3 hsv2rgb(in vec3 c)
606         {
607             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);
608             return c.z * mix(vec3(1.0), rgb, c.y);
609         }
610         half4 main(float2 coord)
611         {
612             vec3 hsv = rgb2hsv(imageShader.eval(coord).rgb);
613             float value = max(0.8, dynamicDimDeg); // 0.8 is min saturation ratio.
614             hsv.y = hsv.y * (1.75 - value * 0.75); // saturation value [1.0 , 1.15].
615             hsv.z = min(hsv.z * dynamicDimDeg, 1.0);
616             return vec4(hsv2rgb(hsv), 1.0);
617         }
618     )";
619     if (dynamicDimShaderEffect_ == nullptr) {
620         dynamicDimShaderEffect_ = Drawing::RuntimeEffect::CreateForShader(prog);
621         if (dynamicDimShaderEffect_ == nullptr) {
622             ROSEN_LOGE("MakeDynamicDimShader::RuntimeShader effect error\n");
623             return nullptr;
624         }
625     }
626     std::shared_ptr<Drawing::ShaderEffect> children[] = {imageShader};
627     size_t childCount = 1;
628     auto data = std::make_shared<Drawing::Data>();
629     data->BuildWithCopy(&dynamicDimDeg, sizeof(dynamicDimDeg));
630     return dynamicDimShaderEffect_->MakeShader(data, children, childCount, nullptr, false);
631 }
632 
MakeBinarizationShader(float low,float high,float thresholdLow,float thresholdHigh,std::shared_ptr<Drawing::ShaderEffect> imageShader)633 std::shared_ptr<Drawing::ShaderEffect> RSPropertyDrawableUtils::MakeBinarizationShader(
634     float low, float high, float thresholdLow, float thresholdHigh, std::shared_ptr<Drawing::ShaderEffect> imageShader)
635 {
636     static constexpr char prog[] = R"(
637         uniform mediump float ubo_low;
638         uniform mediump float ubo_high;
639         uniform mediump float ubo_thresholdLow;
640         uniform mediump float ubo_thresholdHigh;
641         uniform shader imageShader;
642         mediump vec4 main(vec2 drawing_coord) {
643             mediump vec3 c = imageShader(drawing_coord).rgb;
644             float gray = 0.299 * c.r + 0.587 * c.g + 0.114 * c.b;
645             float lowRes = mix(ubo_high, -1.0, step(ubo_thresholdLow, gray));
646             float highRes = mix(-1.0, ubo_low, step(ubo_thresholdHigh, gray));
647             float midRes = (ubo_thresholdHigh - gray) * (ubo_high - ubo_low) /
648             (ubo_thresholdHigh - ubo_thresholdLow) + ubo_low;
649             float invertedGray = mix(midRes, max(lowRes, highRes), step(-0.5, max(lowRes, highRes)));
650             mediump vec3 invert = vec3(invertedGray);
651             mediump vec4 res = vec4(invert, 1.0);
652             return res;
653         }
654     )";
655     if (binarizationShaderEffect_ == nullptr) {
656         binarizationShaderEffect_ = Drawing::RuntimeEffect::CreateForShader(prog);
657         if (binarizationShaderEffect_ == nullptr) {
658             ROSEN_LOGE("RSPropertyDrawableUtils::MakeBinarizationShader effect error\n");
659             return nullptr;
660         }
661     }
662     std::shared_ptr<Drawing::RuntimeShaderBuilder> builder =
663         std::make_shared<Drawing::RuntimeShaderBuilder>(binarizationShaderEffect_);
664     thresholdHigh = thresholdHigh <= thresholdLow ? thresholdHigh + 1e-6 : thresholdHigh;
665     builder->SetChild("imageShader", imageShader);
666     builder->SetUniform("ubo_low", low);
667     builder->SetUniform("ubo_high", high);
668     builder->SetUniform("ubo_thresholdLow", thresholdLow);
669     builder->SetUniform("ubo_thresholdHigh", thresholdHigh);
670     return builder->MakeShader(nullptr, false);
671 }
672 
MakeDynamicBrightnessBlender(const RSDynamicBrightnessPara & params,float ratio)673 std::shared_ptr<Drawing::Blender> RSPropertyDrawableUtils::MakeDynamicBrightnessBlender(
674     const RSDynamicBrightnessPara& params, float ratio)
675 {
676     if (!RSSystemProperties::GetDynamicBrightnessEnabled()) {
677         return nullptr;
678     }
679 
680     auto builder = MakeDynamicBrightnessBuilder();
681     if (!builder) {
682         ROSEN_LOGE("RSPropertyDrawableUtils::MakeDynamicBrightnessBlender make builder fail");
683         return nullptr;
684     }
685 
686     RS_OPTIONAL_TRACE_NAME("RSPropertyDrawableUtils::MakeDynamicBrightnessBlender");
687     builder->SetUniform("ubo_ratio", ratio);
688     builder->SetUniform("ubo_fract", std::clamp(params.fraction_, 0.0f, 1.0f));
689     builder->SetUniform("ubo_cubic", params.rates_.x_);
690     builder->SetUniform("ubo_quad", params.rates_.y_);
691     builder->SetUniform("ubo_rate", params.rates_.z_);
692     builder->SetUniform("ubo_degree", params.rates_.w_);
693     builder->SetUniform("ubo_baseSat", params.saturation_);
694     builder->SetUniform("ubo_posr", params.posCoeff_.x_);
695     builder->SetUniform("ubo_posg", params.posCoeff_.y_);
696     builder->SetUniform("ubo_posb", params.posCoeff_.z_);
697     builder->SetUniform("ubo_negr", params.negCoeff_.x_);
698     builder->SetUniform("ubo_negg", params.negCoeff_.y_);
699     builder->SetUniform("ubo_negb", params.negCoeff_.z_);
700     return builder->MakeBlender();
701 }
702 
MakeDynamicBrightnessBuilder()703 std::shared_ptr<Drawing::RuntimeBlenderBuilder> RSPropertyDrawableUtils::MakeDynamicBrightnessBuilder()
704 {
705     RS_OPTIONAL_TRACE_NAME("RSPropertyDrawableUtils::MakeDynamicBrightnessBuilder");
706     static constexpr char prog[] = R"(
707         uniform half ubo_ratio;
708         uniform half ubo_fract;
709         uniform half ubo_rate;
710         uniform half ubo_degree;
711         uniform half ubo_cubic;
712         uniform half ubo_quad;
713         uniform half ubo_baseSat;
714         uniform half ubo_posr;
715         uniform half ubo_posg;
716         uniform half ubo_posb;
717         uniform half ubo_negr;
718         uniform half ubo_negg;
719         uniform half ubo_negb;
720 
721         const vec3 baseVec = vec3(0.2412016, 0.6922296, 0.0665688);
722         const float eps = 1e-6;
723         half3 getUnpremulRGB(half4 color) {
724             half factor = 1.0 / (max(ubo_ratio, eps) * max(color.a, eps));
725             return clamp(color.rgb * factor, 0.0, 1.0);
726         }
727         half3 gray(half3 x, half4 coeff) {
728             return coeff.x * x * x * x + coeff.y * x * x + coeff.z * x + coeff.w;
729         }
730         half3 sat(half3 inColor, half n, half3 pos, half3 neg) {
731             half base = dot(inColor, baseVec) * (1.0 - n);
732             half3 delta = base + inColor * n - inColor;
733             half3 posDelta = inColor + delta * pos;
734             half3 negDelta = inColor + delta * neg;
735             half3 test = mix(negDelta, posDelta, step(0, delta));
736             return test;
737         }
738 
739         half4 main(half4 src, half4 dst) {
740             half4 coeff = half4(ubo_cubic, ubo_quad, ubo_rate, ubo_degree);
741             half3 color = gray(getUnpremulRGB(dst), coeff);
742             half3 pos = half3(ubo_posr, ubo_posg, ubo_posb);
743             half3 neg = half3(ubo_negr, ubo_negg, ubo_negb);
744             color = sat(color, ubo_baseSat, pos, neg);
745             color = clamp(color, 0.0, 1.0);
746             color = mix(color, getUnpremulRGB(src), ubo_fract);
747             return half4(mix(dst.rgb, color * ubo_ratio * dst.a, src.a), dst.a);
748         }
749     )";
750     if (dynamicBrightnessBlenderEffect_ == nullptr) {
751         dynamicBrightnessBlenderEffect_ = Drawing::RuntimeEffect::CreateForBlender(prog);
752         if (dynamicBrightnessBlenderEffect_ == nullptr) { return nullptr; }
753     }
754     return std::make_shared<Drawing::RuntimeBlenderBuilder>(dynamicBrightnessBlenderEffect_);
755 }
756 
DrawBinarization(Drawing::Canvas * canvas,const std::optional<Vector4f> & aiInvert)757 void RSPropertyDrawableUtils::DrawBinarization(Drawing::Canvas* canvas, const std::optional<Vector4f>& aiInvert)
758 {
759     if (!aiInvert.has_value()) {
760         ROSEN_LOGE("RSPropertyDrawableUtils::DrawBinarization aiInvert has no value");
761         return;
762     }
763     auto drSurface = canvas->GetSurface();
764     if (drSurface == nullptr) {
765         ROSEN_LOGE("RSPropertyDrawableUtils::DrawBinarization drSurface is null");
766         return;
767     }
768     auto clipBounds = canvas->GetDeviceClipBounds();
769     auto imageSnapshot = drSurface->GetImageSnapshot(clipBounds);
770     if (imageSnapshot == nullptr) {
771         ROSEN_LOGE("RSPropertyDrawableUtils::DrawBinarization image is null");
772         return;
773     }
774     Drawing::Matrix matrix;
775     auto imageShader = Drawing::ShaderEffect::CreateImageShader(*imageSnapshot, Drawing::TileMode::CLAMP,
776         Drawing::TileMode::CLAMP, Drawing::SamplingOptions(Drawing::FilterMode::LINEAR), matrix);
777     float thresholdLow = aiInvert->z_ - aiInvert->w_;
778     float thresholdHigh = aiInvert->z_ + aiInvert->w_;
779     auto shader = MakeBinarizationShader(aiInvert->x_, aiInvert->y_, thresholdLow, thresholdHigh, imageShader);
780     Drawing::Brush brush;
781     brush.SetShaderEffect(shader);
782     brush.SetAntiAlias(true);
783     Drawing::AutoCanvasRestore acr(*canvas, true);
784     canvas->ResetMatrix();
785     canvas->Translate(clipBounds.GetLeft(), clipBounds.GetTop());
786     canvas->DrawBackground(brush);
787 }
788 
DrawPixelStretch(Drawing::Canvas * canvas,const std::optional<Vector4f> & pixelStretch,const RectF & boundsRect,const bool boundsGeoValid,const Drawing::TileMode pixelStretchTileMode)789 void RSPropertyDrawableUtils::DrawPixelStretch(Drawing::Canvas* canvas, const std::optional<Vector4f>& pixelStretch,
790     const RectF& boundsRect, const bool boundsGeoValid, const Drawing::TileMode pixelStretchTileMode)
791 {
792     if (!pixelStretch.has_value()) {
793         ROSEN_LOGE("RSPropertyDrawableUtils::DrawPixelStretch pixelStretch has no value");
794         return;
795     }
796     auto surface = canvas->GetSurface();
797     if (surface == nullptr) {
798         ROSEN_LOGE("RSPropertyDrawableUtils::DrawPixelStretch surface null");
799         return;
800     }
801 
802     /*  Calculates the relative coordinates of the clipbounds
803         with respect to the origin of the current canvas coordinates */
804     Drawing::Matrix worldToLocalMat;
805     if (!canvas->GetTotalMatrix().Invert(worldToLocalMat)) {
806         ROSEN_LOGE("RSPropertyDrawableUtils::DrawPixelStretch get invert matrix failed.");
807     }
808     Drawing::Rect localClipBounds;
809     canvas->Save();
810     canvas->ClipRect(Rect2DrawingRect(boundsRect), Drawing::ClipOp::INTERSECT, false);
811     auto tmpBounds = canvas->GetDeviceClipBounds();
812     RS_OPTIONAL_TRACE_NAME_FMT_LEVEL(TRACE_LEVEL_TWO,
813         "RSPropertyDrawableUtils::DrawPixelStretch, tmpBounds: %s", tmpBounds.ToString().c_str());
814     canvas->Restore();
815     Drawing::Rect clipBounds(
816         tmpBounds.GetLeft(), tmpBounds.GetTop(), tmpBounds.GetRight() - 1, tmpBounds.GetBottom() - 1);
817     Drawing::Rect fClipBounds(clipBounds.GetLeft(), clipBounds.GetTop(), clipBounds.GetRight(), clipBounds.GetBottom());
818 
819     if (!worldToLocalMat.MapRect(localClipBounds, fClipBounds)) {
820         ROSEN_LOGE("RSPropertyDrawableUtils::DrawPixelStretch map rect failed.");
821     }
822     auto bounds = Rect2DrawingRect(boundsRect);
823     if (!bounds.Intersect(localClipBounds)) {
824         ROSEN_LOGE("RSPropertyDrawableUtils::DrawPixelStretch intersect clipbounds failed");
825     }
826 
827     auto scaledBounds = Drawing::Rect(bounds.GetLeft() - pixelStretch->x_, bounds.GetTop() - pixelStretch->y_,
828         bounds.GetRight() + pixelStretch->z_, bounds.GetBottom() + pixelStretch->w_);
829     if (!scaledBounds.IsValid() || !bounds.IsValid() || !clipBounds.IsValid()) {
830         ROSEN_LOGE("RSPropertyDrawableUtils::DrawPixelStretch invalid scaled bounds");
831         return;
832     }
833 
834     Drawing::RectI rectI(static_cast<int>(fClipBounds.GetLeft()), static_cast<int>(fClipBounds.GetTop()),
835         static_cast<int>(fClipBounds.GetRight()), static_cast<int>(fClipBounds.GetBottom()));
836     auto image = surface->GetImageSnapshot(rectI);
837     if (image == nullptr) {
838         ROSEN_LOGE("RSPropertyDrawableUtils::DrawPixelStretch image null");
839         return;
840     }
841 
842     Drawing::Brush brush;
843     Drawing::Matrix inverseMat;
844     Drawing::Matrix rotateMat;
845     if (boundsGeoValid) {
846         auto transMat = canvas->GetTotalMatrix();
847         /* transMat.getSkewY() is the sin of the rotation angle(sin0 = 0,sin90 =1 sin180 = 0,sin270 = -1),
848             if transMat.getSkewY() is not 0 or -1 or 1,the rotation angle is not a multiple of 90,not Stretch*/
849         auto skewY = transMat.Get(Drawing::Matrix::SKEW_Y);
850         if (ROSEN_EQ(skewY, 0.f) || ROSEN_EQ(skewY, 1.f) || ROSEN_EQ(skewY, -1.f)) {
851         } else {
852             ROSEN_LOGD("rotate degree is not 0 or 90 or 180 or 270,return.");
853             return;
854         }
855         rotateMat.SetScale(transMat.Get(Drawing::Matrix::SCALE_X), transMat.Get(Drawing::Matrix::SCALE_Y));
856         rotateMat.Set(Drawing::Matrix::SKEW_X, transMat.Get(Drawing::Matrix::SKEW_X));
857         rotateMat.Set(Drawing::Matrix::SKEW_Y, transMat.Get(Drawing::Matrix::SKEW_Y));
858         rotateMat.PreTranslate(-bounds.GetLeft(), -bounds.GetTop());
859         rotateMat.PostTranslate(bounds.GetLeft(), bounds.GetTop());
860 
861         Drawing::Rect transBounds;
862         rotateMat.MapRect(transBounds, bounds);
863         rotateMat.Set(Drawing::Matrix::TRANS_X, bounds.GetLeft() - transBounds.GetLeft());
864         rotateMat.Set(Drawing::Matrix::TRANS_Y, bounds.GetTop() - transBounds.GetTop());
865         if (!rotateMat.Invert(inverseMat)) {
866             ROSEN_LOGE("RSPropertyDrawableUtils::DrawPixelStretch get invert matrix failed.");
867         }
868     }
869 
870     Drawing::AutoCanvasRestore acr(*canvas, true);
871     canvas->Translate(bounds.GetLeft(), bounds.GetTop());
872     Drawing::SamplingOptions samplingOptions;
873     constexpr static float EPS = 1e-5f;
874     if (pixelStretch->x_ > EPS || pixelStretch->y_ > EPS || pixelStretch->z_ > EPS || pixelStretch->w_ > EPS) {
875         brush.SetShaderEffect(Drawing::ShaderEffect::CreateImageShader(
876             *image, pixelStretchTileMode, pixelStretchTileMode, samplingOptions, inverseMat));
877         canvas->AttachBrush(brush);
878         canvas->DrawRect(Drawing::Rect(-pixelStretch->x_, -pixelStretch->y_,
879             -pixelStretch->x_ + scaledBounds.GetWidth(), -pixelStretch->y_ + scaledBounds.GetHeight()));
880         canvas->DetachBrush();
881     } else {
882         inverseMat.PostScale(
883             scaledBounds.GetWidth() / bounds.GetWidth(), scaledBounds.GetHeight() / bounds.GetHeight());
884         brush.SetShaderEffect(Drawing::ShaderEffect::CreateImageShader(
885             *image, pixelStretchTileMode, pixelStretchTileMode, samplingOptions, inverseMat));
886 
887         canvas->Translate(-pixelStretch->x_, -pixelStretch->y_);
888         canvas->AttachBrush(brush);
889         canvas->DrawRect(Drawing::Rect(pixelStretch->x_, pixelStretch->y_, pixelStretch->x_ + bounds.GetWidth(),
890             pixelStretch->y_ + bounds.GetHeight()));
891         canvas->DetachBrush();
892     }
893 }
894 
CreateShadowPath(const std::shared_ptr<RSPath> rsPath,const std::shared_ptr<RSPath> & clipBounds,const RRect & rrect)895 Drawing::Path RSPropertyDrawableUtils::CreateShadowPath(const std::shared_ptr<RSPath> rsPath,
896     const std::shared_ptr<RSPath>& clipBounds, const RRect& rrect)
897 {
898     Drawing::Path path;
899     if (rsPath && rsPath->GetDrawingPath().IsValid()) {
900         path = rsPath->GetDrawingPath();
901     } else if (clipBounds) {
902         path = clipBounds->GetDrawingPath();
903     } else {
904         path.AddRoundRect(RRect2DrawingRRect(rrect));
905     }
906     return path;
907 }
908 
DrawShadow(Drawing::Canvas * canvas,Drawing::Path & path,const float & offsetX,const float & offsetY,const float & elevation,const bool & isFilled,Color spotColor)909 void RSPropertyDrawableUtils::DrawShadow(Drawing::Canvas* canvas, Drawing::Path& path, const float& offsetX,
910     const float& offsetY, const float& elevation, const bool& isFilled, Color spotColor)
911 {
912     RS_OPTIONAL_TRACE_NAME_FMT_LEVEL(TRACE_LEVEL_TWO,
913         "RSPropertyDrawableUtils::DrawShadow, ShadowElevation: %f, ShadowOffsetX: "
914         "%f, ShadowOffsetY: %f, bounds: %s",
915         elevation, offsetX, offsetY, path.GetBounds().ToString().c_str());
916     Drawing::AutoCanvasRestore acr(*canvas, true);
917     if (RSSystemProperties::IsPhoneType()) {
918         CeilMatrixTrans(canvas);
919     }
920     if (!isFilled) {
921         canvas->ClipPath(path, Drawing::ClipOp::DIFFERENCE, true);
922     }
923     path.Offset(offsetX, offsetY);
924     Drawing::Point3 planeParams = {0.0f, 0.0f, elevation};
925     std::vector<Drawing::Point> pt{{path.GetBounds().GetLeft() + path.GetBounds().GetWidth() / 2,
926         path.GetBounds().GetTop() + path.GetBounds().GetHeight() / 2}};
927     canvas->GetTotalMatrix().MapPoints(pt, pt, 1);
928     Drawing::Point3 lightPos = {pt[0].GetX(), pt[0].GetY(), DEFAULT_LIGHT_HEIGHT};
929     Color ambientColor = Color::FromArgbInt(DEFAULT_AMBIENT_COLOR);
930     ambientColor.MultiplyAlpha(canvas->GetAlpha());
931     spotColor.MultiplyAlpha(canvas->GetAlpha());
932     canvas->DrawShadowStyle(path, planeParams, lightPos, DEFAULT_LIGHT_RADIUS, Drawing::Color(ambientColor.AsArgbInt()),
933         Drawing::Color(spotColor.AsArgbInt()), Drawing::ShadowFlags::TRANSPARENT_OCCLUDER, true);
934 }
935 
DrawShadowMaskFilter(Drawing::Canvas * canvas,Drawing::Path & path,const float & offsetX,const float & offsetY,const float & radius,const bool & isFilled,Color spotColor)936 void RSPropertyDrawableUtils::DrawShadowMaskFilter(Drawing::Canvas* canvas, Drawing::Path& path, const float& offsetX,
937     const float& offsetY, const float& radius, const bool& isFilled, Color spotColor)
938 {
939     RS_OPTIONAL_TRACE_NAME_FMT_LEVEL(TRACE_LEVEL_TWO,
940         "RSPropertyDrawableUtils::DrawShadowMaskFilter, Radius: %f, ShadowOffsetX: "
941         "%f, ShadowOffsetY: %f, bounds: %s",
942         radius, offsetX, offsetY, path.GetBounds().ToString().c_str());
943     Drawing::AutoCanvasRestore acr(*canvas, true);
944     if (!isFilled) {
945         canvas->ClipPath(path, Drawing::ClipOp::DIFFERENCE, true);
946     }
947     path.Offset(offsetX, offsetY);
948     Drawing::Brush brush;
949     brush.SetColor(Drawing::Color::ColorQuadSetARGB(
950         spotColor.GetAlpha(), spotColor.GetRed(), spotColor.GetGreen(), spotColor.GetBlue()));
951     brush.SetAntiAlias(true);
952     Drawing::Filter filter;
953     filter.SetMaskFilter(
954         Drawing::MaskFilter::CreateBlurMaskFilter(Drawing::BlurType::NORMAL, radius));
955     brush.SetFilter(filter);
956     canvas->AttachBrush(brush);
957     canvas->DrawPath(path);
958     canvas->DetachBrush();
959 }
960 
DrawUseEffect(RSPaintFilterCanvas * canvas)961 void RSPropertyDrawableUtils::DrawUseEffect(RSPaintFilterCanvas* canvas)
962 {
963     const auto& effectData = canvas->GetEffectData();
964     if (effectData == nullptr || effectData->cachedImage_ == nullptr || !RSSystemProperties::GetEffectMergeEnabled()) {
965         return;
966     }
967     RS_TRACE_FUNC();
968     Drawing::AutoCanvasRestore acr(*canvas, true);
969     // Align the current coordinate system with the one that the effect data was generated from. In most cases,
970     // the two coordinate systems are the same, so the cachedMatrix_ should be set to identity.
971     canvas->SetMatrix(effectData->cachedMatrix_);
972     auto visibleRect = canvas->GetVisibleRect();
973     visibleRect.Round();
974     auto visibleIRect = Drawing::RectI(
975         static_cast<int>(visibleRect.GetLeft()), static_cast<int>(visibleRect.GetTop()),
976         static_cast<int>(visibleRect.GetRight()), static_cast<int>(visibleRect.GetBottom()));
977     if (!visibleIRect.IsEmpty()) {
978         canvas->ClipIRect(visibleIRect, Drawing::ClipOp::INTERSECT);
979     }
980     Drawing::Brush brush;
981     canvas->AttachBrush(brush);
982     // Draw the cached image in the coordinate system where the effect data is generated. The image content
983     // outside the device clip bounds will be automatically clipped.
984     canvas->DrawImage(*effectData->cachedImage_, static_cast<float>(effectData->cachedRect_.GetLeft()),
985         static_cast<float>(effectData->cachedRect_.GetTop()), Drawing::SamplingOptions());
986     RS_OPTIONAL_TRACE_NAME_FMT("RSPropertyDrawableUtils::DrawUseEffect cachedRect_:%s, DeviceClipBounds:%s, "
987         "IdentityMatrix: %d", effectData->cachedRect_.ToString().c_str(),
988         canvas->GetDeviceClipBounds().ToString().c_str(), effectData->cachedMatrix_.IsIdentity());
989     canvas->DetachBrush();
990 }
991 
IsDangerousBlendMode(int blendMode,int blendApplyType)992 bool RSPropertyDrawableUtils::IsDangerousBlendMode(int blendMode, int blendApplyType)
993 {
994     static const uint32_t fastDangerousBit =
995         (1 << static_cast<int>(Drawing::BlendMode::CLEAR)) +
996         (1 << static_cast<int>(Drawing::BlendMode::SRC_OUT)) +
997         (1 << static_cast<int>(Drawing::BlendMode::DST_OUT)) +
998         (1 << static_cast<int>(Drawing::BlendMode::XOR));
999     static const uint32_t offscreenDangerousBit =
1000         (1 << static_cast<int>(Drawing::BlendMode::CLEAR)) +
1001         (1 << static_cast<int>(Drawing::BlendMode::SRC)) +
1002         (1 << static_cast<int>(Drawing::BlendMode::SRC_IN)) +
1003         (1 << static_cast<int>(Drawing::BlendMode::DST_IN)) +
1004         (1 << static_cast<int>(Drawing::BlendMode::SRC_OUT)) +
1005         (1 << static_cast<int>(Drawing::BlendMode::DST_OUT)) +
1006         (1 << static_cast<int>(Drawing::BlendMode::DST_ATOP)) +
1007         (1 << static_cast<int>(Drawing::BlendMode::XOR)) +
1008         (1 << static_cast<int>(Drawing::BlendMode::MODULATE));
1009     uint32_t tmp = 1 << blendMode;
1010     if (blendApplyType == static_cast<int>(RSColorBlendApplyType::FAST)) {
1011         return tmp & fastDangerousBit;
1012     }
1013     return tmp & offscreenDangerousBit;
1014 }
1015 
BeginBlender(RSPaintFilterCanvas & canvas,std::shared_ptr<Drawing::Blender> blender,int blendModeApplyType,bool isDangerous)1016 void RSPropertyDrawableUtils::BeginBlender(RSPaintFilterCanvas& canvas, std::shared_ptr<Drawing::Blender> blender,
1017     int blendModeApplyType, bool isDangerous)
1018 {
1019     if (isDangerous && !canvas.HasOffscreenLayer()) {
1020         Drawing::SaveLayerOps maskLayerRec(nullptr, nullptr, 0);
1021         canvas.SaveLayer(maskLayerRec);
1022         ROSEN_LOGD("Dangerous offscreen blendmode may produce transparent pixels, add extra offscreen here.");
1023     }
1024 
1025     // fast blender
1026     if (blendModeApplyType == static_cast<int>(RSColorBlendApplyType::FAST)) {
1027         canvas.SetBlender(blender);
1028         return;
1029     }
1030 
1031     // save layer mode
1032     Drawing::Brush blendBrush_;
1033     blendBrush_.SetAlphaF(canvas.GetAlpha());
1034     blendBrush_.SetBlender(blender);
1035     Drawing::SaveLayerOps maskLayerRec(nullptr, &blendBrush_, 0);
1036     canvas.SaveLayer(maskLayerRec);
1037     canvas.SetBlender(nullptr);
1038     canvas.SaveAlpha();
1039     canvas.SetAlpha(1.0f);
1040 }
1041 
EndBlender(RSPaintFilterCanvas & canvas,int blendModeApplyType)1042 void RSPropertyDrawableUtils::EndBlender(RSPaintFilterCanvas& canvas, int blendModeApplyType)
1043 {
1044     // RSRenderNodeDrawable will do other necessary work (restore canvas & env), we only need to restore alpha
1045     if (blendModeApplyType != static_cast<int>(RSColorBlendApplyType::FAST)) {
1046         canvas.RestoreAlpha();
1047     }
1048 }
1049 
CalculateInvertColor(const Color & backgroundColor)1050 Color RSPropertyDrawableUtils::CalculateInvertColor(const Color& backgroundColor)
1051 {
1052     uint32_t a = backgroundColor.GetAlpha();
1053     uint32_t r = 255 - backgroundColor.GetRed(); // 255 max red channel value
1054     uint32_t g = 255 - backgroundColor.GetGreen(); // 255 max green channel value
1055     uint32_t b = 255 - backgroundColor.GetBlue(); // 255 max blue channel value
1056     return Color(r, g, b, a);
1057 }
1058 
GetInvertBackgroundColor(RSPaintFilterCanvas & canvas,bool needClipToBounds,const Vector4f & boundsRect,const Color & backgroundColor)1059 Color RSPropertyDrawableUtils::GetInvertBackgroundColor(RSPaintFilterCanvas& canvas, bool needClipToBounds,
1060     const Vector4f& boundsRect, const Color& backgroundColor)
1061 {
1062     Drawing::AutoCanvasRestore acr(canvas, true);
1063     if (!needClipToBounds) {
1064         RS_LOGI("RSPropertyDrawableUtils::GetInvertBackgroundColor not GetClipToBounds");
1065         Drawing::Rect rect = Drawing::Rect(0, 0, boundsRect.z_, boundsRect.w_);
1066         canvas.ClipRect(rect, Drawing::ClipOp::INTERSECT, false);
1067     }
1068     if (backgroundColor.GetAlpha() == 0xff) { // 0xff = 255, max alpha value
1069         RS_LOGI("RSPropertyDrawableUtils::GetInvertBackgroundColor not alpha");
1070         return RSPropertyDrawableUtils::CalculateInvertColor(backgroundColor);
1071     }
1072     auto imageSnapshot = canvas.GetSurface()->GetImageSnapshot(canvas.GetDeviceClipBounds());
1073     if (imageSnapshot == nullptr) {
1074         RS_LOGI("RSPropertyDrawableUtils::GetInvertBackgroundColor imageSnapshot null");
1075         return Color(0);
1076     }
1077     auto colorPicker = RSPropertiesPainter::CalcAverageColor(imageSnapshot);
1078     return RSPropertyDrawableUtils::CalculateInvertColor(Color(
1079         Drawing::Color::ColorQuadGetR(colorPicker), Drawing::Color::ColorQuadGetG(colorPicker),
1080         Drawing::Color::ColorQuadGetB(colorPicker), Drawing::Color::ColorQuadGetA(colorPicker)));
1081 }
1082 
GetGravityMatrix(const Gravity & gravity,const Drawing::Rect & rect,const float & w,const float & h,Drawing::Matrix & mat)1083 bool RSPropertyDrawableUtils::GetGravityMatrix(const Gravity& gravity, const Drawing::Rect& rect, const float& w,
1084     const float& h, Drawing::Matrix& mat)
1085 {
1086     if (w == rect.GetWidth() && h == rect.GetHeight()) {
1087         return false;
1088     }
1089     mat = Drawing::Matrix();
1090 
1091     switch (gravity) {
1092         case Gravity::CENTER: {
1093             mat.PreTranslate((rect.GetWidth() - w) / PARAM_DOUBLE, (rect.GetHeight() - h) / PARAM_DOUBLE);
1094             return true;
1095         }
1096         case Gravity::TOP: {
1097             mat.PreTranslate((rect.GetWidth() - w) / PARAM_DOUBLE, 0);
1098             return true;
1099         }
1100         case Gravity::BOTTOM: {
1101             mat.PreTranslate((rect.GetWidth() - w) / PARAM_DOUBLE, rect.GetHeight() - h);
1102             return true;
1103         }
1104         case Gravity::LEFT: {
1105             mat.PreTranslate(0, (rect.GetHeight() - h) / PARAM_DOUBLE);
1106             return true;
1107         }
1108         case Gravity::RIGHT: {
1109             mat.PreTranslate(rect.GetWidth() - w, (rect.GetHeight() - h) / PARAM_DOUBLE);
1110             return true;
1111         }
1112         case Gravity::TOP_LEFT: {
1113             return false;
1114         }
1115         case Gravity::TOP_RIGHT: {
1116             mat.PreTranslate(rect.GetWidth() - w, 0);
1117             return true;
1118         }
1119         case Gravity::BOTTOM_LEFT: {
1120             mat.PreTranslate(0, rect.GetHeight() - h);
1121             return true;
1122         }
1123         case Gravity::BOTTOM_RIGHT: {
1124             mat.PreTranslate(rect.GetWidth() - w, rect.GetHeight() - h);
1125             return true;
1126         }
1127         case Gravity::RESIZE: {
1128             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
1129                 return false;
1130             }
1131             mat.PreScale(rect.GetWidth() / w, rect.GetHeight() / h);
1132             return true;
1133         }
1134         case Gravity::RESIZE_ASPECT: {
1135             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
1136                 return false;
1137             }
1138             float scale = std::min(rect.GetWidth() / w, rect.GetHeight() / h);
1139             if (ROSEN_EQ(scale, 0.f)) {
1140                 return false;
1141             }
1142             mat.PreScale(scale, scale);
1143             mat.PreTranslate((rect.GetWidth() / scale - w) / PARAM_DOUBLE,
1144                 (rect.GetHeight() / scale - h) / PARAM_DOUBLE);
1145             return true;
1146         }
1147         case Gravity::RESIZE_ASPECT_TOP_LEFT: {
1148             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
1149                 return false;
1150             }
1151             float scale = std::min(rect.GetWidth() / w, rect.GetHeight() / h);
1152             mat.PreScale(scale, scale);
1153             return true;
1154         }
1155         case Gravity::RESIZE_ASPECT_BOTTOM_RIGHT: {
1156             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
1157                 return false;
1158             }
1159             float scale = std::min(rect.GetWidth() / w, rect.GetHeight() / h);
1160             if (ROSEN_EQ(scale, 0.f)) {
1161                 return false;
1162             }
1163             mat.PreScale(scale, scale);
1164             mat.PreTranslate(rect.GetWidth() / scale - w, rect.GetHeight() / scale - h);
1165             return true;
1166         }
1167         case Gravity::RESIZE_ASPECT_FILL: {
1168             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
1169                 return false;
1170             }
1171             float scale = std::max(rect.GetWidth() / w, rect.GetHeight() / h);
1172             if (ROSEN_EQ(scale, 0.f)) {
1173                 return false;
1174             }
1175             mat.PreScale(scale, scale);
1176             mat.PreTranslate((rect.GetWidth() / scale - w) / PARAM_DOUBLE,
1177                 (rect.GetHeight() / scale - h) / PARAM_DOUBLE);
1178             return true;
1179         }
1180         case Gravity::RESIZE_ASPECT_FILL_TOP_LEFT: {
1181             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
1182                 return false;
1183             }
1184             float scale = std::max(rect.GetWidth() / w, rect.GetHeight() / h);
1185             mat.PreScale(scale, scale);
1186             return true;
1187         }
1188         case Gravity::RESIZE_ASPECT_FILL_BOTTOM_RIGHT: {
1189             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
1190                 return false;
1191             }
1192             float scale = std::max(rect.GetWidth() / w, rect.GetHeight() / h);
1193             if (ROSEN_EQ(scale, 0.f)) {
1194                 return false;
1195             }
1196             mat.PreScale(scale, scale);
1197             mat.PreTranslate(rect.GetWidth() / scale - w, rect.GetHeight() / scale - h);
1198             return true;
1199         }
1200         default: {
1201             ROSEN_LOGE("GetGravityMatrix unknow gravity=[%{public}d]", gravity);
1202             return false;
1203         }
1204     }
1205 }
1206 
DrawFilterWithDRM(Drawing::Canvas * canvas,bool isDark)1207 void RSPropertyDrawableUtils::DrawFilterWithDRM(Drawing::Canvas* canvas, bool isDark)
1208 {
1209     Drawing::Brush brush;
1210     int16_t rgb_light = 235;
1211     int16_t rgb_dark = 80;
1212     int16_t alpha = 245; // give a nearly opaque mask to replace blur effect
1213     RSColor demoColor = RSColor(rgb_light, rgb_light, rgb_light, alpha);
1214     if (isDark) {
1215         demoColor = RSColor(rgb_dark, rgb_dark, rgb_dark, alpha);
1216     }
1217 
1218     float sat = 1.0f;
1219     float brightness = 0.9f;
1220     float normalizedDegree = brightness - sat;
1221     const float brightnessMat[] = {
1222         1.0f,
1223         0.0f,
1224         0.0f,
1225         0.0f,
1226         normalizedDegree,
1227         0.0f,
1228         1.0f,
1229         0.0f,
1230         0.0f,
1231         normalizedDegree,
1232         0.0f,
1233         0.0f,
1234         1.0f,
1235         0.0f,
1236         normalizedDegree,
1237         0.0f,
1238         0.0f,
1239         0.0f,
1240         1.0f,
1241         0.0f,
1242     };
1243     Drawing::ColorMatrix cm;
1244     cm.SetSaturation(sat);
1245     float cmArray[Drawing::ColorMatrix::MATRIX_SIZE];
1246     cm.GetArray(cmArray);
1247     std::shared_ptr<Drawing::ColorFilter> filterCompose =
1248         Drawing::ColorFilter::CreateComposeColorFilter(cmArray, brightnessMat);
1249     auto colorImageFilter = Drawing::ImageFilter::CreateColorFilterImageFilter(*filterCompose, nullptr);
1250     Drawing::Filter filter;
1251     filter.SetImageFilter(colorImageFilter);
1252     brush.SetFilter(filter);
1253     brush.SetColor(demoColor.AsArgbInt());
1254     canvas->DrawBackground(brush);
1255 }
1256 
RSFilterSetPixelStretch(const RSProperties & property,const std::shared_ptr<RSFilter> & filter)1257 bool RSPropertyDrawableUtils::RSFilterSetPixelStretch(const RSProperties& property,
1258     const std::shared_ptr<RSFilter>& filter)
1259 {
1260     if (!filter || !RSSystemProperties::GetMESABlurFuzedEnabled()) {
1261         return false;
1262     }
1263     auto drawingFilter = std::static_pointer_cast<RSDrawingFilter>(filter);
1264     std::shared_ptr<RSShaderFilter> mesaShaderFilter =
1265         drawingFilter->GetShaderFilterWithType(RSShaderFilter::MESA);
1266     if (!mesaShaderFilter) {
1267         return false;
1268     }
1269 
1270     auto& pixelStretch = property.GetPixelStretch();
1271     if (!pixelStretch.has_value()) {
1272         return false;
1273     }
1274 
1275     constexpr static float EPS = 1e-5f;
1276     // The pixel stretch is fuzed only when the stretch factors are negative
1277     if (pixelStretch->x_ > EPS || pixelStretch->y_ > EPS || pixelStretch->z_ > EPS || pixelStretch->w_ > EPS) {
1278         return false;
1279     }
1280 
1281     ROSEN_LOGD("RSPropertyDrawableUtils::DrawPixelStretch fuzed with MESABlur.");
1282     const auto& boundsRect = property.GetBoundsRect();
1283     auto tileMode = property.GetPixelStretchTileMode();
1284     auto pixelStretchParams = std::make_shared<RSPixelStretchParams>(std::abs(pixelStretch->x_),
1285                                                                      std::abs(pixelStretch->y_),
1286                                                                      std::abs(pixelStretch->z_),
1287                                                                      std::abs(pixelStretch->w_),
1288                                                                      tileMode,
1289                                                                      boundsRect.width_, boundsRect.height_);
1290     auto mesaBlurFilter = std::static_pointer_cast<RSMESABlurShaderFilter>(mesaShaderFilter);
1291     mesaBlurFilter->SetPixelStretchParams(pixelStretchParams);
1292     return true;
1293 }
1294 
RSFilterRemovePixelStretch(const std::shared_ptr<RSFilter> & filter)1295 void RSPropertyDrawableUtils::RSFilterRemovePixelStretch(const std::shared_ptr<RSFilter>& filter)
1296 {
1297     if (!filter) {
1298         return;
1299     }
1300     auto drawingFilter = std::static_pointer_cast<RSDrawingFilter>(filter);
1301     std::shared_ptr<RSShaderFilter> mesaShaderFilter =
1302         drawingFilter->GetShaderFilterWithType(RSShaderFilter::MESA);
1303     if (!mesaShaderFilter) {
1304         return;
1305     }
1306 
1307     ROSEN_LOGD("RSPropertyDrawableUtils::remove pixel stretch from the fuzed blur");
1308     auto mesaBlurFilter = std::static_pointer_cast<RSMESABlurShaderFilter>(mesaShaderFilter);
1309     std::shared_ptr<RSPixelStretchParams> pixelStretchParams = nullptr;
1310     mesaBlurFilter->SetPixelStretchParams(pixelStretchParams);
1311     return;
1312 }
1313 } // namespace Rosen
1314 } // namespace OHOS
1315