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