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