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