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