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