• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "drawable/rs_property_drawable_utils.h"
17 
18 #include "common/rs_optional_trace.h"
19 #include "common/rs_obj_abs_geometry.h"
20 #include "platform/common/rs_log.h"
21 #include "property/rs_properties_painter.h"
22 #include "render/rs_drawing_filter.h"
23 #include "render/rs_kawase_blur_shader_filter.h"
24 #include "render/rs_mesa_blur_shader_filter.h"
25 #include "render/rs_linear_gradient_blur_shader_filter.h"
26 #include "render/rs_magnifier_shader_filter.h"
27 #include "render/rs_material_filter.h"
28 #include "render/rs_color_picker.h"
29 #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 
534     auto blender = MakeLightUpEffectBlender(lightUpEffectDegree);
535     Drawing::Brush brush;
536     brush.SetBlender(blender);
537     canvas->DrawBackground(brush);
538 }
539 
MakeLightUpEffectBlender(const float lightUpDeg)540 std::shared_ptr<Drawing::Blender> RSPropertyDrawableUtils::MakeLightUpEffectBlender(const float lightUpDeg)
541 {
542     static constexpr char prog[] = R"(
543         uniform half lightUpDeg;
544 
545         vec3 rgb2hsv(in vec3 c)
546         {
547             vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
548             vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
549             vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
550             float d = q.x - min(q.w, q.y);
551             float e = 1.0e-10;
552             return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
553         }
554         vec3 hsv2rgb(in vec3 c)
555         {
556             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);
557             return c.z * mix(vec3(1.0), rgb, c.y);
558         }
559         vec4 main(vec4 drawing_src, vec4 drawing_dst) {
560             drawing_dst = max(drawing_dst, 0.0);
561             vec3 c = vec3(drawing_dst.r, drawing_dst.g, drawing_dst.b);
562             vec3 hsv = rgb2hsv(c);
563             float satUpper = clamp(hsv.y * 1.2, 0.0, 1.0);
564             hsv.y = mix(satUpper, hsv.y, lightUpDeg);
565             hsv.z += lightUpDeg - 1.0;
566             hsv.z = max(hsv.z, 0.0);
567             return vec4(hsv2rgb(hsv), drawing_dst.a);
568         }
569     )";
570     if (lightUpEffectBlender_ == nullptr) {
571         lightUpEffectBlender_ = Drawing::RuntimeEffect::CreateForBlender(prog);
572         if (lightUpEffectBlender_ == nullptr) {
573             return nullptr;
574         }
575     }
576     auto builder = std::make_shared<Drawing::RuntimeBlenderBuilder>(lightUpEffectBlender_);
577     builder->SetUniform("lightUpDeg", lightUpDeg);
578     return builder->MakeBlender();
579 }
580 
DrawDynamicDim(Drawing::Canvas * canvas,const float dynamicDimDegree)581 void RSPropertyDrawableUtils::DrawDynamicDim(Drawing::Canvas* canvas, const float dynamicDimDegree)
582 {
583     if (!ROSEN_GE(dynamicDimDegree, 0.0) || !ROSEN_LNE(dynamicDimDegree, 1.0)) {
584         ROSEN_LOGE(
585             "RSPropertyDrawableUtils::DrawDynamicDim Invalid dynamicDimDegree %{public}f", dynamicDimDegree);
586         return;
587     }
588 
589     Drawing::Surface* surface = canvas->GetSurface();
590     if (surface == nullptr) {
591         ROSEN_LOGE("RSPropertyDrawableUtils::DrawDynamicDim surface is null");
592         return;
593     }
594 
595     auto clipBounds = canvas->GetDeviceClipBounds();
596     auto image = surface->GetImageSnapshot(clipBounds, false);
597     if (image == nullptr) {
598         ROSEN_LOGE("RSPropertyDrawableUtils::DrawDynamicDim image is null");
599         return;
600     }
601 
602     Drawing::Matrix scaleMat;
603     auto imageShader = Drawing::ShaderEffect::CreateImageShader(*image, Drawing::TileMode::CLAMP,
604         Drawing::TileMode::CLAMP, Drawing::SamplingOptions(Drawing::FilterMode::LINEAR), scaleMat);
605     auto shader = MakeDynamicDimShader(dynamicDimDegree, imageShader);
606     if (shader == nullptr) {
607         ROSEN_LOGE("RSPropertyDrawableUtils::DrawDynamicDim shader is null");
608         return;
609     }
610     Drawing::Brush brush;
611     brush.SetShaderEffect(shader);
612     Drawing::AutoCanvasRestore acr(*canvas, true);
613     canvas->ResetMatrix();
614     canvas->Translate(clipBounds.GetLeft(), clipBounds.GetTop());
615     canvas->DrawBackground(brush);
616 }
617 
MakeDynamicDimShader(float dynamicDimDeg,std::shared_ptr<Drawing::ShaderEffect> imageShader)618 std::shared_ptr<Drawing::ShaderEffect> RSPropertyDrawableUtils::MakeDynamicDimShader(
619     float dynamicDimDeg, std::shared_ptr<Drawing::ShaderEffect> imageShader)
620 {
621     static constexpr char prog[] = R"(
622         uniform half dynamicDimDeg;
623         uniform shader imageShader;
624 
625         vec3 rgb2hsv(in vec3 c)
626         {
627             vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
628             vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
629             vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
630             float d = q.x - min(q.w, q.y);
631             float e = 1.0e-10;
632             return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
633         }
634         vec3 hsv2rgb(in vec3 c)
635         {
636             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);
637             return c.z * mix(vec3(1.0), rgb, c.y);
638         }
639         half4 main(float2 coord)
640         {
641             vec3 hsv = rgb2hsv(imageShader.eval(coord).rgb);
642             float value = max(0.8, dynamicDimDeg); // 0.8 is min saturation ratio.
643             hsv.y = hsv.y * (1.75 - value * 0.75); // saturation value [1.0 , 1.15].
644             hsv.z = min(hsv.z * dynamicDimDeg, 1.0);
645             return vec4(hsv2rgb(hsv), 1.0);
646         }
647     )";
648     if (dynamicDimShaderEffect_ == nullptr) {
649         dynamicDimShaderEffect_ = Drawing::RuntimeEffect::CreateForShader(prog);
650         if (dynamicDimShaderEffect_ == nullptr) {
651             ROSEN_LOGE("MakeDynamicDimShader::RuntimeShader effect error\n");
652             return nullptr;
653         }
654     }
655     std::shared_ptr<Drawing::ShaderEffect> children[] = {imageShader};
656     size_t childCount = 1;
657     auto data = std::make_shared<Drawing::Data>();
658     data->BuildWithCopy(&dynamicDimDeg, sizeof(dynamicDimDeg));
659     return dynamicDimShaderEffect_->MakeShader(data, children, childCount, nullptr, false);
660 }
661 
MakeBinarizationShader(float low,float high,float thresholdLow,float thresholdHigh,std::shared_ptr<Drawing::ShaderEffect> imageShader)662 std::shared_ptr<Drawing::ShaderEffect> RSPropertyDrawableUtils::MakeBinarizationShader(
663     float low, float high, float thresholdLow, float thresholdHigh, std::shared_ptr<Drawing::ShaderEffect> imageShader)
664 {
665     static constexpr char prog[] = R"(
666         uniform mediump float ubo_low;
667         uniform mediump float ubo_high;
668         uniform mediump float ubo_thresholdLow;
669         uniform mediump float ubo_thresholdHigh;
670         uniform shader imageShader;
671         mediump vec4 main(vec2 drawing_coord) {
672             mediump vec3 c = imageShader(drawing_coord).rgb;
673             float gray = 0.299 * c.r + 0.587 * c.g + 0.114 * c.b;
674             float lowRes = mix(ubo_high, -1.0, step(ubo_thresholdLow, gray));
675             float highRes = mix(-1.0, ubo_low, step(ubo_thresholdHigh, gray));
676             float midRes = (ubo_thresholdHigh - gray) * (ubo_high - ubo_low) /
677             (ubo_thresholdHigh - ubo_thresholdLow) + ubo_low;
678             float invertedGray = mix(midRes, max(lowRes, highRes), step(-0.5, max(lowRes, highRes)));
679             mediump vec3 invert = vec3(invertedGray);
680             mediump vec4 res = vec4(invert, 1.0);
681             return res;
682         }
683     )";
684     if (binarizationShaderEffect_ == nullptr) {
685         binarizationShaderEffect_ = Drawing::RuntimeEffect::CreateForShader(prog);
686         if (binarizationShaderEffect_ == nullptr) {
687             ROSEN_LOGE("RSPropertyDrawableUtils::MakeBinarizationShader effect error\n");
688             return nullptr;
689         }
690     }
691     std::shared_ptr<Drawing::RuntimeShaderBuilder> builder =
692         std::make_shared<Drawing::RuntimeShaderBuilder>(binarizationShaderEffect_);
693     thresholdHigh = thresholdHigh <= thresholdLow ? thresholdHigh + 1e-6 : thresholdHigh;
694     builder->SetChild("imageShader", imageShader);
695     builder->SetUniform("ubo_low", low);
696     builder->SetUniform("ubo_high", high);
697     builder->SetUniform("ubo_thresholdLow", thresholdLow);
698     builder->SetUniform("ubo_thresholdHigh", thresholdHigh);
699     return builder->MakeShader(nullptr, false);
700 }
701 
MakeDynamicBrightnessBlender(const RSDynamicBrightnessPara & params,float ratio)702 std::shared_ptr<Drawing::Blender> RSPropertyDrawableUtils::MakeDynamicBrightnessBlender(
703     const RSDynamicBrightnessPara& params, float ratio)
704 {
705     if (!RSSystemProperties::GetDynamicBrightnessEnabled()) {
706         return nullptr;
707     }
708 
709     auto builder = MakeDynamicBrightnessBuilder();
710     if (!builder) {
711         ROSEN_LOGE("RSPropertyDrawableUtils::MakeDynamicBrightnessBlender make builder fail");
712         return nullptr;
713     }
714 
715     RS_OPTIONAL_TRACE_NAME("RSPropertyDrawableUtils::MakeDynamicBrightnessBlender");
716     builder->SetUniform("ubo_ratio", ratio);
717     builder->SetUniform("ubo_fract", std::clamp(params.fraction_, 0.0f, 1.0f));
718     builder->SetUniform("ubo_cubic", params.rates_.x_);
719     builder->SetUniform("ubo_quad", params.rates_.y_);
720     builder->SetUniform("ubo_rate", params.rates_.z_);
721     builder->SetUniform("ubo_degree", params.rates_.w_);
722     builder->SetUniform("ubo_baseSat", params.saturation_);
723     builder->SetUniform("ubo_posr", params.posCoeff_.x_);
724     builder->SetUniform("ubo_posg", params.posCoeff_.y_);
725     builder->SetUniform("ubo_posb", params.posCoeff_.z_);
726     builder->SetUniform("ubo_negr", params.negCoeff_.x_);
727     builder->SetUniform("ubo_negg", params.negCoeff_.y_);
728     builder->SetUniform("ubo_negb", params.negCoeff_.z_);
729     return builder->MakeBlender();
730 }
731 
MakeDynamicBrightnessBuilder()732 std::shared_ptr<Drawing::RuntimeBlenderBuilder> RSPropertyDrawableUtils::MakeDynamicBrightnessBuilder()
733 {
734     RS_OPTIONAL_TRACE_NAME("RSPropertyDrawableUtils::MakeDynamicBrightnessBuilder");
735     static constexpr char prog[] = R"(
736         uniform half ubo_ratio;
737         uniform half ubo_fract;
738         uniform half ubo_rate;
739         uniform half ubo_degree;
740         uniform half ubo_cubic;
741         uniform half ubo_quad;
742         uniform half ubo_baseSat;
743         uniform half ubo_posr;
744         uniform half ubo_posg;
745         uniform half ubo_posb;
746         uniform half ubo_negr;
747         uniform half ubo_negg;
748         uniform half ubo_negb;
749 
750         const vec3 baseVec = vec3(0.2412016, 0.6922296, 0.0665688);
751         const float eps = 1e-6;
752         half3 getUnpremulRGB(half4 color) {
753             half factor = 1.0 / (max(ubo_ratio, eps) * max(color.a, eps));
754             return clamp(color.rgb * factor, 0.0, 1.0);
755         }
756         half3 gray(half3 x, half4 coeff) {
757             return coeff.x * x * x * x + coeff.y * x * x + coeff.z * x + coeff.w;
758         }
759         half3 sat(half3 inColor, half n, half3 pos, half3 neg) {
760             half base = dot(inColor, baseVec) * (1.0 - n);
761             half3 delta = base + inColor * n - inColor;
762             half3 posDelta = inColor + delta * pos;
763             half3 negDelta = inColor + delta * neg;
764             half3 test = mix(negDelta, posDelta, step(0, delta));
765             return test;
766         }
767 
768         half4 main(half4 src, half4 dst) {
769             half4 coeff = half4(ubo_cubic, ubo_quad, ubo_rate, ubo_degree);
770             half3 color = gray(getUnpremulRGB(dst), coeff);
771             half3 pos = half3(ubo_posr, ubo_posg, ubo_posb);
772             half3 neg = half3(ubo_negr, ubo_negg, ubo_negb);
773             color = sat(color, ubo_baseSat, pos, neg);
774             color = clamp(color, 0.0, 1.0);
775             color = mix(color, getUnpremulRGB(src), ubo_fract);
776             return half4(mix(dst.rgb, color * ubo_ratio * dst.a, src.a), dst.a);
777         }
778     )";
779     if (dynamicBrightnessBlenderEffect_ == nullptr) {
780         dynamicBrightnessBlenderEffect_ = Drawing::RuntimeEffect::CreateForBlender(prog);
781         if (dynamicBrightnessBlenderEffect_ == nullptr) { return nullptr; }
782     }
783     return std::make_shared<Drawing::RuntimeBlenderBuilder>(dynamicBrightnessBlenderEffect_);
784 }
785 
DrawBinarization(Drawing::Canvas * canvas,const std::optional<Vector4f> & aiInvert)786 void RSPropertyDrawableUtils::DrawBinarization(Drawing::Canvas* canvas, const std::optional<Vector4f>& aiInvert)
787 {
788     if (!aiInvert.has_value()) {
789         ROSEN_LOGE("RSPropertyDrawableUtils::DrawBinarization aiInvert has no value");
790         return;
791     }
792     auto drSurface = canvas->GetSurface();
793     if (drSurface == nullptr) {
794         ROSEN_LOGE("RSPropertyDrawableUtils::DrawBinarization drSurface is null");
795         return;
796     }
797     auto clipBounds = canvas->GetDeviceClipBounds();
798     auto imageSnapshot = drSurface->GetImageSnapshot(clipBounds);
799     if (imageSnapshot == nullptr) {
800         ROSEN_LOGE("RSPropertyDrawableUtils::DrawBinarization image is null");
801         return;
802     }
803     Drawing::Matrix matrix;
804     auto imageShader = Drawing::ShaderEffect::CreateImageShader(*imageSnapshot, Drawing::TileMode::CLAMP,
805         Drawing::TileMode::CLAMP, Drawing::SamplingOptions(Drawing::FilterMode::LINEAR), matrix);
806     float thresholdLow = aiInvert->z_ - aiInvert->w_;
807     float thresholdHigh = aiInvert->z_ + aiInvert->w_;
808     auto shader = MakeBinarizationShader(aiInvert->x_, aiInvert->y_, thresholdLow, thresholdHigh, imageShader);
809     Drawing::Brush brush;
810     brush.SetShaderEffect(shader);
811     brush.SetAntiAlias(true);
812     Drawing::AutoCanvasRestore acr(*canvas, true);
813     canvas->ResetMatrix();
814     canvas->Translate(clipBounds.GetLeft(), clipBounds.GetTop());
815     canvas->DrawBackground(brush);
816 }
817 
DrawPixelStretch(Drawing::Canvas * canvas,const std::optional<Vector4f> & pixelStretch,const RectF & boundsRect,const bool boundsGeoValid,const Drawing::TileMode pixelStretchTileMode)818 void RSPropertyDrawableUtils::DrawPixelStretch(Drawing::Canvas* canvas, const std::optional<Vector4f>& pixelStretch,
819     const RectF& boundsRect, const bool boundsGeoValid, const Drawing::TileMode pixelStretchTileMode)
820 {
821     if (!pixelStretch.has_value()) {
822         ROSEN_LOGD("RSPropertyDrawableUtils::DrawPixelStretch pixelStretch has no value");
823         return;
824     }
825     if (std::isinf(pixelStretch->x_) || std::isinf(pixelStretch->y_) ||
826         std::isinf(pixelStretch->z_) || std::isinf(pixelStretch->w_)) {
827         ROSEN_LOGD("RSPropertyDrawableUtils::DrawPixelStretch skip original pixelStretch");
828         return;
829     }
830     auto surface = canvas->GetSurface();
831     if (surface == nullptr) {
832         ROSEN_LOGE("RSPropertyDrawableUtils::DrawPixelStretch surface null");
833         return;
834     }
835 
836     /*  Calculates the relative coordinates of the clipbounds
837         with respect to the origin of the current canvas coordinates */
838     Drawing::Matrix worldToLocalMat;
839     if (!canvas->GetTotalMatrix().Invert(worldToLocalMat)) {
840         ROSEN_LOGE("RSPropertyDrawableUtils::DrawPixelStretch get invert matrix failed.");
841     }
842     Drawing::Rect localClipBounds;
843     canvas->Save();
844     canvas->ClipRect(Rect2DrawingRect(boundsRect), Drawing::ClipOp::INTERSECT, false);
845     auto tmpBounds = canvas->GetDeviceClipBounds();
846     RS_OPTIONAL_TRACE_NAME_FMT_LEVEL(TRACE_LEVEL_TWO,
847         "RSPropertyDrawableUtils::DrawPixelStretch, tmpBounds: %s", tmpBounds.ToString().c_str());
848     canvas->Restore();
849     Drawing::Rect clipBounds(
850         tmpBounds.GetLeft(), tmpBounds.GetTop(), tmpBounds.GetRight() - 1, tmpBounds.GetBottom() - 1);
851     Drawing::Rect fClipBounds(clipBounds.GetLeft(), clipBounds.GetTop(), clipBounds.GetRight(), clipBounds.GetBottom());
852 
853     if (!worldToLocalMat.MapRect(localClipBounds, fClipBounds)) {
854         ROSEN_LOGE("RSPropertyDrawableUtils::DrawPixelStretch map rect failed.");
855     }
856     auto bounds = Rect2DrawingRect(boundsRect);
857     if (!bounds.Intersect(localClipBounds)) {
858         ROSEN_LOGE("RSPropertyDrawableUtils::DrawPixelStretch intersect clipbounds failed");
859     }
860 
861     auto scaledBounds = Drawing::Rect(bounds.GetLeft() - pixelStretch->x_, bounds.GetTop() - pixelStretch->y_,
862         bounds.GetRight() + pixelStretch->z_, bounds.GetBottom() + pixelStretch->w_);
863     if (!scaledBounds.IsValid() || !bounds.IsValid() || !clipBounds.IsValid()) {
864         ROSEN_LOGE("RSPropertyDrawableUtils::DrawPixelStretch invalid scaled bounds");
865         return;
866     }
867 
868     Drawing::RectI rectI(static_cast<int>(fClipBounds.GetLeft()), static_cast<int>(fClipBounds.GetTop()),
869         static_cast<int>(fClipBounds.GetRight()), static_cast<int>(fClipBounds.GetBottom()));
870     auto image = surface->GetImageSnapshot(rectI);
871     if (image == nullptr) {
872         ROSEN_LOGE("RSPropertyDrawableUtils::DrawPixelStretch image null");
873         return;
874     }
875 
876     Drawing::Brush brush;
877     Drawing::Matrix inverseMat;
878     Drawing::Matrix rotateMat;
879     if (boundsGeoValid) {
880         auto transMat = canvas->GetTotalMatrix();
881         /* transMat.getSkewY() is the sin of the rotation angle(sin0 = 0,sin90 =1 sin180 = 0,sin270 = -1),
882             if transMat.getSkewY() is not 0 or -1 or 1,the rotation angle is not a multiple of 90,not Stretch*/
883         auto skewY = transMat.Get(Drawing::Matrix::SKEW_Y);
884         if (ROSEN_EQ(skewY, 0.f) || ROSEN_EQ(skewY, 1.f) || ROSEN_EQ(skewY, -1.f)) {
885         } else {
886             ROSEN_LOGD("rotate degree is not 0 or 90 or 180 or 270,return.");
887             return;
888         }
889         rotateMat.SetScale(transMat.Get(Drawing::Matrix::SCALE_X), transMat.Get(Drawing::Matrix::SCALE_Y));
890         rotateMat.Set(Drawing::Matrix::SKEW_X, transMat.Get(Drawing::Matrix::SKEW_X));
891         rotateMat.Set(Drawing::Matrix::SKEW_Y, transMat.Get(Drawing::Matrix::SKEW_Y));
892         rotateMat.PreTranslate(-bounds.GetLeft(), -bounds.GetTop());
893         rotateMat.PostTranslate(bounds.GetLeft(), bounds.GetTop());
894 
895         Drawing::Rect transBounds;
896         rotateMat.MapRect(transBounds, bounds);
897         rotateMat.Set(Drawing::Matrix::TRANS_X, bounds.GetLeft() - transBounds.GetLeft());
898         rotateMat.Set(Drawing::Matrix::TRANS_Y, bounds.GetTop() - transBounds.GetTop());
899         if (!rotateMat.Invert(inverseMat)) {
900             ROSEN_LOGE("RSPropertyDrawableUtils::DrawPixelStretch get invert matrix failed.");
901         }
902     }
903 
904     Drawing::AutoCanvasRestore acr(*canvas, true);
905     canvas->Translate(bounds.GetLeft(), bounds.GetTop());
906     Drawing::SamplingOptions samplingOptions;
907     constexpr static float EPS = 1e-5f;
908     if (pixelStretch->x_ > EPS || pixelStretch->y_ > EPS || pixelStretch->z_ > EPS || pixelStretch->w_ > EPS) {
909         brush.SetShaderEffect(Drawing::ShaderEffect::CreateImageShader(
910             *image, pixelStretchTileMode, pixelStretchTileMode, samplingOptions, inverseMat));
911         canvas->AttachBrush(brush);
912         canvas->DrawRect(Drawing::Rect(-pixelStretch->x_, -pixelStretch->y_,
913             -pixelStretch->x_ + scaledBounds.GetWidth(), -pixelStretch->y_ + scaledBounds.GetHeight()));
914         canvas->DetachBrush();
915     } else {
916         inverseMat.PostScale(
917             scaledBounds.GetWidth() / bounds.GetWidth(), scaledBounds.GetHeight() / bounds.GetHeight());
918         brush.SetShaderEffect(Drawing::ShaderEffect::CreateImageShader(
919             *image, pixelStretchTileMode, pixelStretchTileMode, samplingOptions, inverseMat));
920 
921         canvas->Translate(-pixelStretch->x_, -pixelStretch->y_);
922         canvas->AttachBrush(brush);
923         canvas->DrawRect(Drawing::Rect(pixelStretch->x_, pixelStretch->y_, pixelStretch->x_ + bounds.GetWidth(),
924             pixelStretch->y_ + bounds.GetHeight()));
925         canvas->DetachBrush();
926     }
927 }
928 
CreateShadowPath(const std::shared_ptr<RSPath> rsPath,const std::shared_ptr<RSPath> & clipBounds,const RRect & rrect)929 Drawing::Path RSPropertyDrawableUtils::CreateShadowPath(const std::shared_ptr<RSPath> rsPath,
930     const std::shared_ptr<RSPath>& clipBounds, const RRect& rrect)
931 {
932     Drawing::Path path;
933     if (rsPath && rsPath->GetDrawingPath().IsValid()) {
934         path = rsPath->GetDrawingPath();
935     } else if (clipBounds) {
936         path = clipBounds->GetDrawingPath();
937     } else {
938         path.AddRoundRect(RRect2DrawingRRect(rrect));
939     }
940     return path;
941 }
942 
DrawShadow(Drawing::Canvas * canvas,Drawing::Path & path,const float & offsetX,const float & offsetY,const float & elevation,const bool & isFilled,Color spotColor)943 void RSPropertyDrawableUtils::DrawShadow(Drawing::Canvas* canvas, Drawing::Path& path, const float& offsetX,
944     const float& offsetY, const float& elevation, const bool& isFilled, Color spotColor)
945 {
946     RS_OPTIONAL_TRACE_NAME_FMT_LEVEL(TRACE_LEVEL_TWO,
947         "RSPropertyDrawableUtils::DrawShadow, ShadowElevation: %f, ShadowOffsetX: "
948         "%f, ShadowOffsetY: %f, bounds: %s",
949         elevation, offsetX, offsetY, path.GetBounds().ToString().c_str());
950     Drawing::AutoCanvasRestore acr(*canvas, true);
951     if (!isFilled) {
952         canvas->ClipPath(path, Drawing::ClipOp::DIFFERENCE, true);
953     }
954     path.Offset(offsetX, offsetY);
955     Drawing::Point3 planeParams = {0.0f, 0.0f, elevation};
956     std::vector<Drawing::Point> pt{{path.GetBounds().GetLeft() + path.GetBounds().GetWidth() / 2,
957         path.GetBounds().GetTop() + path.GetBounds().GetHeight() / 2}};
958     canvas->GetTotalMatrix().MapPoints(pt, pt, 1);
959     Drawing::Point3 lightPos = {pt[0].GetX(), pt[0].GetY(), DEFAULT_LIGHT_HEIGHT};
960     Color ambientColor = Color::FromArgbInt(DEFAULT_AMBIENT_COLOR);
961     ambientColor.MultiplyAlpha(canvas->GetAlpha());
962     spotColor.MultiplyAlpha(canvas->GetAlpha());
963     canvas->DrawShadowStyle(path, planeParams, lightPos, DEFAULT_LIGHT_RADIUS, Drawing::Color(ambientColor.AsArgbInt()),
964         Drawing::Color(spotColor.AsArgbInt()), Drawing::ShadowFlags::TRANSPARENT_OCCLUDER, true);
965 }
966 
DrawShadowMaskFilter(Drawing::Canvas * canvas,Drawing::Path & path,const float & offsetX,const float & offsetY,const float & radius,const bool & isFilled,Color spotColor)967 void RSPropertyDrawableUtils::DrawShadowMaskFilter(Drawing::Canvas* canvas, Drawing::Path& path, const float& offsetX,
968     const float& offsetY, const float& radius, const bool& isFilled, Color spotColor)
969 {
970     RS_OPTIONAL_TRACE_NAME_FMT_LEVEL(TRACE_LEVEL_TWO,
971         "RSPropertyDrawableUtils::DrawShadowMaskFilter, Radius: %f, ShadowOffsetX: "
972         "%f, ShadowOffsetY: %f, bounds: %s",
973         radius, offsetX, offsetY, path.GetBounds().ToString().c_str());
974     Drawing::AutoCanvasRestore acr(*canvas, true);
975     if (!isFilled) {
976         canvas->ClipPath(path, Drawing::ClipOp::DIFFERENCE, true);
977     }
978     path.Offset(offsetX, offsetY);
979     Drawing::Brush brush;
980     brush.SetColor(Drawing::Color::ColorQuadSetARGB(
981         spotColor.GetAlpha(), spotColor.GetRed(), spotColor.GetGreen(), spotColor.GetBlue()));
982     brush.SetAntiAlias(true);
983     Drawing::Filter filter;
984     filter.SetMaskFilter(
985         Drawing::MaskFilter::CreateBlurMaskFilter(Drawing::BlurType::NORMAL, radius));
986     brush.SetFilter(filter);
987     canvas->AttachBrush(brush);
988     canvas->DrawPath(path);
989     canvas->DetachBrush();
990 }
991 
DrawUseEffect(RSPaintFilterCanvas * canvas,UseEffectType useEffectType)992 void RSPropertyDrawableUtils::DrawUseEffect(RSPaintFilterCanvas* canvas, UseEffectType useEffectType)
993 {
994     const auto& effectData = useEffectType == UseEffectType::EFFECT_COMPONENT ?
995         canvas->GetEffectData() : canvas->GetBehindWindowData();
996     if (effectData == nullptr || effectData->cachedImage_ == nullptr || !RSSystemProperties::GetEffectMergeEnabled()) {
997         return;
998     }
999     RS_TRACE_FUNC();
1000     Drawing::AutoCanvasRestore acr(*canvas, true);
1001     // Align the current coordinate system with the one that the effect data was generated from. In most cases,
1002     // the two coordinate systems are the same, so the cachedMatrix_ should be set to identity.
1003     canvas->SetMatrix(effectData->cachedMatrix_);
1004     auto visibleRect = canvas->GetVisibleRect();
1005     visibleRect.Round();
1006     auto visibleIRect = Drawing::RectI(
1007         static_cast<int>(visibleRect.GetLeft()), static_cast<int>(visibleRect.GetTop()),
1008         static_cast<int>(visibleRect.GetRight()), static_cast<int>(visibleRect.GetBottom()));
1009     if (!visibleIRect.IsEmpty()) {
1010         canvas->ClipIRect(visibleIRect, Drawing::ClipOp::INTERSECT);
1011     }
1012     Drawing::Brush brush;
1013     canvas->AttachBrush(brush);
1014     // Draw the cached image in the coordinate system where the effect data is generated. The image content
1015     // outside the device clip bounds will be automatically clipped.
1016     canvas->DrawImage(*effectData->cachedImage_, static_cast<float>(effectData->cachedRect_.GetLeft()),
1017         static_cast<float>(effectData->cachedRect_.GetTop()), Drawing::SamplingOptions());
1018     RS_OPTIONAL_TRACE_NAME_FMT("RSPropertyDrawableUtils::DrawUseEffect cachedRect_:%s, DeviceClipBounds:%s, "
1019         "IdentityMatrix: %d", effectData->cachedRect_.ToString().c_str(),
1020         canvas->GetDeviceClipBounds().ToString().c_str(), effectData->cachedMatrix_.IsIdentity());
1021     canvas->DetachBrush();
1022 }
1023 
IsDangerousBlendMode(int blendMode,int blendApplyType)1024 bool RSPropertyDrawableUtils::IsDangerousBlendMode(int blendMode, int blendApplyType)
1025 {
1026     static const uint32_t fastDangerousBit =
1027         (1 << static_cast<int>(Drawing::BlendMode::CLEAR)) +
1028         (1 << static_cast<int>(Drawing::BlendMode::SRC_OUT)) +
1029         (1 << static_cast<int>(Drawing::BlendMode::DST_OUT)) +
1030         (1 << static_cast<int>(Drawing::BlendMode::XOR));
1031     static const uint32_t offscreenDangerousBit =
1032         (1 << static_cast<int>(Drawing::BlendMode::CLEAR)) +
1033         (1 << static_cast<int>(Drawing::BlendMode::SRC)) +
1034         (1 << static_cast<int>(Drawing::BlendMode::SRC_IN)) +
1035         (1 << static_cast<int>(Drawing::BlendMode::DST_IN)) +
1036         (1 << static_cast<int>(Drawing::BlendMode::SRC_OUT)) +
1037         (1 << static_cast<int>(Drawing::BlendMode::DST_OUT)) +
1038         (1 << static_cast<int>(Drawing::BlendMode::DST_ATOP)) +
1039         (1 << static_cast<int>(Drawing::BlendMode::XOR)) +
1040         (1 << static_cast<int>(Drawing::BlendMode::MODULATE));
1041     uint32_t tmp = 1 << blendMode;
1042     if (blendApplyType == static_cast<int>(RSColorBlendApplyType::FAST)) {
1043         return tmp & fastDangerousBit;
1044     }
1045     return tmp & offscreenDangerousBit;
1046 }
1047 
BeginBlender(RSPaintFilterCanvas & canvas,std::shared_ptr<Drawing::Blender> blender,int blendModeApplyType,bool isDangerous)1048 void RSPropertyDrawableUtils::BeginBlender(RSPaintFilterCanvas& canvas, std::shared_ptr<Drawing::Blender> blender,
1049     int blendModeApplyType, bool isDangerous)
1050 {
1051     if (isDangerous && !canvas.HasOffscreenLayer()) {
1052         Drawing::SaveLayerOps maskLayerRec(nullptr, nullptr, 0);
1053         canvas.SaveLayer(maskLayerRec);
1054         ROSEN_LOGD("Dangerous offscreen blendmode may produce transparent pixels, add extra offscreen here.");
1055     }
1056 
1057     // fast blender
1058     if (blendModeApplyType == static_cast<int>(RSColorBlendApplyType::FAST)) {
1059         canvas.SetBlender(blender);
1060         return;
1061     }
1062 
1063     // save layer mode
1064     Drawing::Brush blendBrush_;
1065     blendBrush_.SetAlphaF(canvas.GetAlpha());
1066     blendBrush_.SetBlender(blender);
1067     Drawing::SaveLayerOps maskLayerRec(nullptr, &blendBrush_, 0);
1068     canvas.SaveLayer(maskLayerRec);
1069     canvas.SetBlender(nullptr);
1070     canvas.SaveAlpha();
1071     canvas.SetAlpha(1.0f);
1072 }
1073 
DrawFilterWithDRM(Drawing::Canvas * canvas,bool isDark)1074 void RSPropertyDrawableUtils::DrawFilterWithDRM(Drawing::Canvas* canvas, bool isDark)
1075 {
1076     Drawing::Brush brush;
1077     int16_t rgb_light = 235;
1078     int16_t rgb_dark = 80;
1079     int16_t alpha = 245; // give a nearly opaque mask to replace blur effect
1080     RSColor demoColor = RSColor(rgb_light, rgb_light, rgb_light, alpha);
1081     if (isDark) {
1082         demoColor = RSColor(rgb_dark, rgb_dark, rgb_dark, alpha);
1083     }
1084 
1085     float sat = 1.0f;
1086     float brightness = 0.9f;
1087     float normalizedDegree = brightness - sat;
1088     const float brightnessMat[] = {
1089         1.0f,
1090         0.0f,
1091         0.0f,
1092         0.0f,
1093         normalizedDegree,
1094         0.0f,
1095         1.0f,
1096         0.0f,
1097         0.0f,
1098         normalizedDegree,
1099         0.0f,
1100         0.0f,
1101         1.0f,
1102         0.0f,
1103         normalizedDegree,
1104         0.0f,
1105         0.0f,
1106         0.0f,
1107         1.0f,
1108         0.0f,
1109     };
1110     Drawing::ColorMatrix cm;
1111     cm.SetSaturation(sat);
1112     float cmArray[Drawing::ColorMatrix::MATRIX_SIZE];
1113     cm.GetArray(cmArray);
1114     std::shared_ptr<Drawing::ColorFilter> filterCompose =
1115         Drawing::ColorFilter::CreateComposeColorFilter(cmArray, brightnessMat);
1116     auto colorImageFilter = Drawing::ImageFilter::CreateColorFilterImageFilter(*filterCompose, nullptr);
1117     Drawing::Filter filter;
1118     filter.SetImageFilter(colorImageFilter);
1119     brush.SetFilter(filter);
1120     brush.SetColor(demoColor.AsArgbInt());
1121     canvas->DrawBackground(brush);
1122 }
1123 
EndBlender(RSPaintFilterCanvas & canvas,int blendModeApplyType)1124 void RSPropertyDrawableUtils::EndBlender(RSPaintFilterCanvas& canvas, int blendModeApplyType)
1125 {
1126     // RSRenderNodeDrawable will do other necessary work (restore canvas & env), we only need to restore alpha
1127     if (blendModeApplyType != static_cast<int>(RSColorBlendApplyType::FAST)) {
1128         canvas.RestoreAlpha();
1129     }
1130 }
1131 
CalculateInvertColor(const Color & backgroundColor)1132 Color RSPropertyDrawableUtils::CalculateInvertColor(const Color& backgroundColor)
1133 {
1134     uint32_t a = backgroundColor.GetAlpha();
1135     uint32_t r = 255 - backgroundColor.GetRed(); // 255 max red channel value
1136     uint32_t g = 255 - backgroundColor.GetGreen(); // 255 max green channel value
1137     uint32_t b = 255 - backgroundColor.GetBlue(); // 255 max blue channel value
1138     return Color(r, g, b, a);
1139 }
1140 
GetInvertBackgroundColor(RSPaintFilterCanvas & canvas,bool needClipToBounds,const Vector4f & boundsRect,const Color & backgroundColor)1141 Color RSPropertyDrawableUtils::GetInvertBackgroundColor(RSPaintFilterCanvas& canvas, bool needClipToBounds,
1142     const Vector4f& boundsRect, const Color& backgroundColor)
1143 {
1144     Drawing::AutoCanvasRestore acr(canvas, true);
1145     if (!needClipToBounds) {
1146         RS_LOGI("RSPropertyDrawableUtils::GetInvertBackgroundColor not GetClipToBounds");
1147         Drawing::Rect rect = Drawing::Rect(0, 0, boundsRect.z_, boundsRect.w_);
1148         canvas.ClipRect(rect, Drawing::ClipOp::INTERSECT, false);
1149     }
1150     if (backgroundColor.GetAlpha() == 0xff) { // 0xff = 255, max alpha value
1151         RS_LOGI("RSPropertyDrawableUtils::GetInvertBackgroundColor not alpha");
1152         return RSPropertyDrawableUtils::CalculateInvertColor(backgroundColor);
1153     }
1154     auto imageSnapshot = canvas.GetSurface()->GetImageSnapshot(canvas.GetDeviceClipBounds());
1155     if (imageSnapshot == nullptr) {
1156         RS_LOGI("RSPropertyDrawableUtils::GetInvertBackgroundColor imageSnapshot null");
1157         return Color(0);
1158     }
1159     auto colorPicker = RSPropertiesPainter::CalcAverageColor(imageSnapshot);
1160     return RSPropertyDrawableUtils::CalculateInvertColor(Color(
1161         Drawing::Color::ColorQuadGetR(colorPicker), Drawing::Color::ColorQuadGetG(colorPicker),
1162         Drawing::Color::ColorQuadGetB(colorPicker), Drawing::Color::ColorQuadGetA(colorPicker)));
1163 }
1164 
GetGravityMatrix(const Gravity & gravity,const Drawing::Rect & rect,const float & w,const float & h,Drawing::Matrix & mat)1165 bool RSPropertyDrawableUtils::GetGravityMatrix(const Gravity& gravity, const Drawing::Rect& rect, const float& w,
1166     const float& h, Drawing::Matrix& mat)
1167 {
1168     if (w == rect.GetWidth() && h == rect.GetHeight()) {
1169         return false;
1170     }
1171     mat = Drawing::Matrix();
1172 
1173     switch (gravity) {
1174         case Gravity::CENTER: {
1175             mat.PreTranslate((rect.GetWidth() - w) / PARAM_DOUBLE, (rect.GetHeight() - h) / PARAM_DOUBLE);
1176             return true;
1177         }
1178         case Gravity::TOP: {
1179             mat.PreTranslate((rect.GetWidth() - w) / PARAM_DOUBLE, 0);
1180             return true;
1181         }
1182         case Gravity::BOTTOM: {
1183             mat.PreTranslate((rect.GetWidth() - w) / PARAM_DOUBLE, rect.GetHeight() - h);
1184             return true;
1185         }
1186         case Gravity::LEFT: {
1187             mat.PreTranslate(0, (rect.GetHeight() - h) / PARAM_DOUBLE);
1188             return true;
1189         }
1190         case Gravity::RIGHT: {
1191             mat.PreTranslate(rect.GetWidth() - w, (rect.GetHeight() - h) / PARAM_DOUBLE);
1192             return true;
1193         }
1194         case Gravity::TOP_LEFT: {
1195             return false;
1196         }
1197         case Gravity::TOP_RIGHT: {
1198             mat.PreTranslate(rect.GetWidth() - w, 0);
1199             return true;
1200         }
1201         case Gravity::BOTTOM_LEFT: {
1202             mat.PreTranslate(0, rect.GetHeight() - h);
1203             return true;
1204         }
1205         case Gravity::BOTTOM_RIGHT: {
1206             mat.PreTranslate(rect.GetWidth() - w, rect.GetHeight() - h);
1207             return true;
1208         }
1209         case Gravity::RESIZE: {
1210             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
1211                 return false;
1212             }
1213             mat.PreScale(rect.GetWidth() / w, rect.GetHeight() / h);
1214             return true;
1215         }
1216         case Gravity::RESIZE_ASPECT: {
1217             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
1218                 return false;
1219             }
1220             float scale = std::min(rect.GetWidth() / w, rect.GetHeight() / h);
1221             if (ROSEN_EQ(scale, 0.f)) {
1222                 return false;
1223             }
1224             mat.PreScale(scale, scale);
1225             mat.PreTranslate((rect.GetWidth() / scale - w) / PARAM_DOUBLE,
1226                 (rect.GetHeight() / scale - h) / PARAM_DOUBLE);
1227             return true;
1228         }
1229         case Gravity::RESIZE_ASPECT_TOP_LEFT: {
1230             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
1231                 return false;
1232             }
1233             float scale = std::min(rect.GetWidth() / w, rect.GetHeight() / h);
1234             mat.PreScale(scale, scale);
1235             return true;
1236         }
1237         case Gravity::RESIZE_ASPECT_BOTTOM_RIGHT: {
1238             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
1239                 return false;
1240             }
1241             float scale = std::min(rect.GetWidth() / w, rect.GetHeight() / h);
1242             if (ROSEN_EQ(scale, 0.f)) {
1243                 return false;
1244             }
1245             mat.PreScale(scale, scale);
1246             mat.PreTranslate(rect.GetWidth() / scale - w, rect.GetHeight() / scale - h);
1247             return true;
1248         }
1249         case Gravity::RESIZE_ASPECT_FILL: {
1250             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
1251                 return false;
1252             }
1253             float scale = std::max(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_FILL_TOP_LEFT: {
1263             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
1264                 return false;
1265             }
1266             float scale = std::max(rect.GetWidth() / w, rect.GetHeight() / h);
1267             mat.PreScale(scale, scale);
1268             return true;
1269         }
1270         case Gravity::RESIZE_ASPECT_FILL_BOTTOM_RIGHT: {
1271             if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
1272                 return false;
1273             }
1274             float scale = std::max(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         default: {
1283             ROSEN_LOGE("GetGravityMatrix unknow gravity=[%{public}d]", gravity);
1284             return false;
1285         }
1286     }
1287 }
1288 
RSFilterSetPixelStretch(const RSProperties & property,const std::shared_ptr<RSFilter> & filter)1289 bool RSPropertyDrawableUtils::RSFilterSetPixelStretch(const RSProperties& property,
1290     const std::shared_ptr<RSFilter>& filter)
1291 {
1292     if (!filter || !RSSystemProperties::GetMESABlurFuzedEnabled()) {
1293         return false;
1294     }
1295     auto drawingFilter = std::static_pointer_cast<RSDrawingFilter>(filter);
1296     std::shared_ptr<RSShaderFilter> mesaShaderFilter =
1297         drawingFilter->GetShaderFilterWithType(RSShaderFilter::MESA);
1298     if (!mesaShaderFilter) {
1299         return false;
1300     }
1301 
1302     auto& pixelStretch = property.GetPixelStretch();
1303     if (!pixelStretch.has_value()) {
1304         return false;
1305     }
1306 
1307     constexpr static float EPS = 1e-5f;
1308     // The pixel stretch is fuzed only when the stretch factors are negative
1309     if (pixelStretch->x_ > EPS || pixelStretch->y_ > EPS || pixelStretch->z_ > EPS || pixelStretch->w_ > EPS) {
1310         return false;
1311     }
1312 
1313     ROSEN_LOGD("RSPropertyDrawableUtils::DrawPixelStretch fuzed with MESABlur.");
1314     const auto& boundsRect = property.GetBoundsRect();
1315     auto tileMode = property.GetPixelStretchTileMode();
1316     auto pixelStretchParams = std::make_shared<RSPixelStretchParams>(std::abs(pixelStretch->x_),
1317                                                                      std::abs(pixelStretch->y_),
1318                                                                      std::abs(pixelStretch->z_),
1319                                                                      std::abs(pixelStretch->w_),
1320                                                                      tileMode,
1321                                                                      boundsRect.width_, boundsRect.height_);
1322     auto mesaBlurFilter = std::static_pointer_cast<RSMESABlurShaderFilter>(mesaShaderFilter);
1323     mesaBlurFilter->SetPixelStretchParams(pixelStretchParams);
1324     return true;
1325 }
1326 
RSFilterRemovePixelStretch(const std::shared_ptr<RSFilter> & filter)1327 void RSPropertyDrawableUtils::RSFilterRemovePixelStretch(const std::shared_ptr<RSFilter>& filter)
1328 {
1329     if (!filter) {
1330         return;
1331     }
1332     auto drawingFilter = std::static_pointer_cast<RSDrawingFilter>(filter);
1333     std::shared_ptr<RSShaderFilter> mesaShaderFilter =
1334         drawingFilter->GetShaderFilterWithType(RSShaderFilter::MESA);
1335     if (!mesaShaderFilter) {
1336         return;
1337     }
1338 
1339     ROSEN_LOGD("RSPropertyDrawableUtils::remove pixel stretch from the fuzed blur");
1340     auto mesaBlurFilter = std::static_pointer_cast<RSMESABlurShaderFilter>(mesaShaderFilter);
1341     std::shared_ptr<RSPixelStretchParams> pixelStretchParams = nullptr;
1342     mesaBlurFilter->SetPixelStretchParams(pixelStretchParams);
1343     return;
1344 }
1345 
GenerateBehindWindowFilter(float radius,float saturation,float brightness,RSColor maskColor)1346 std::shared_ptr<RSFilter> RSPropertyDrawableUtils::GenerateBehindWindowFilter(float radius,
1347     float saturation, float brightness, RSColor maskColor)
1348 {
1349     RS_OPTIONAL_TRACE_NAME_FMT_LEVEL(TRACE_LEVEL_TWO,
1350         "RSPropertyDrawableUtils::GenerateBehindWindowFilter, Radius: %f, Saturation: %f, "
1351         "Brightness: %f, MaskColor: %08X", radius, saturation, brightness, maskColor.AsArgbInt());
1352     uint32_t hash = SkOpts::hash(&radius, sizeof(radius), 0);
1353     std::shared_ptr<Drawing::ColorFilter> colorFilter = GenerateMaterialColorFilter(saturation, brightness);
1354     std::shared_ptr<Drawing::ImageFilter> blurColorFilter =
1355         Drawing::ImageFilter::CreateColorBlurImageFilter(*colorFilter, radius, radius);
1356     std::shared_ptr<RSDrawingFilter> filter = nullptr;
1357     if (RSSystemProperties::GetKawaseEnabled()) {
1358         std::shared_ptr<RSKawaseBlurShaderFilter> kawaseBlurFilter = std::make_shared<RSKawaseBlurShaderFilter>(radius);
1359         auto colorImageFilter = Drawing::ImageFilter::CreateColorFilterImageFilter(*colorFilter, nullptr);
1360         filter = filter?
1361             filter->Compose(colorImageFilter, hash) : std::make_shared<RSDrawingFilter>(colorImageFilter, hash);
1362         filter = filter->Compose(std::static_pointer_cast<RSShaderFilter>(kawaseBlurFilter));
1363     } else {
1364         hash = SkOpts::hash(&saturation, sizeof(saturation), hash);
1365         hash = SkOpts::hash(&brightness, sizeof(brightness), hash);
1366         filter = filter?
1367             filter->Compose(blurColorFilter, hash) : std::make_shared<RSDrawingFilter>(blurColorFilter, hash);
1368     }
1369     std::shared_ptr<RSMaskColorShaderFilter> maskColorShaderFilter = std::make_shared<RSMaskColorShaderFilter>(
1370         BLUR_COLOR_MODE::DEFAULT, maskColor);
1371     filter = filter->Compose(std::static_pointer_cast<RSShaderFilter>(maskColorShaderFilter));
1372     filter->SetSkipFrame(RSDrawingFilter::CanSkipFrame(radius));
1373     filter->SetSaturationForHPS(saturation);
1374     filter->SetBrightnessForHPS(brightness);
1375     filter->SetFilterType(RSFilter::MATERIAL);
1376     return filter;
1377 }
1378 
GenerateMaterialColorFilter(float sat,float brt)1379 std::shared_ptr<Drawing::ColorFilter> RSPropertyDrawableUtils::GenerateMaterialColorFilter(float sat, float brt)
1380 {
1381     float normalizedDegree = brt - 1.0;
1382     const float brightnessMat[] = {
1383         1.000000f, 0.000000f, 0.000000f, 0.000000f, normalizedDegree,
1384         0.000000f, 1.000000f, 0.000000f, 0.000000f, normalizedDegree,
1385         0.000000f, 0.000000f, 1.000000f, 0.000000f, normalizedDegree,
1386         0.000000f, 0.000000f, 0.000000f, 1.000000f, 0.000000f,
1387     };
1388     Drawing::ColorMatrix cm;
1389     cm.SetSaturation(sat);
1390     float cmArray[Drawing::ColorMatrix::MATRIX_SIZE];
1391     cm.GetArray(cmArray);
1392     return Drawing::ColorFilter::CreateComposeColorFilter(cmArray, brightnessMat, Drawing::Clamp::NO_CLAMP);
1393 }
1394 } // namespace Rosen
1395 } // namespace OHOS
1396