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