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