1 /*
2 * Copyright (c) 2021-2023 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 "property/rs_properties_painter.h"
17 #include "rs_trace.h"
18
19 #include "common/rs_obj_abs_geometry.h"
20 #include "common/rs_optional_trace.h"
21 #include "pipeline/rs_effect_render_node.h"
22 #include "pipeline/rs_paint_filter_canvas.h"
23 #include "pipeline/rs_root_render_node.h"
24 #include "platform/common/rs_log.h"
25 #include "property/rs_point_light_manager.h"
26 #include "property/rs_properties_def.h"
27 #include "render/rs_blur_filter.h"
28 #include "render/rs_skia_filter.h"
29 #include "render/rs_material_filter.h"
30 #include "platform/common/rs_system_properties.h"
31
32 #ifdef USE_ROSEN_DRAWING
33 #include <cstdint>
34 #include <algorithm>
35
36 #include "draw/canvas.h"
37 #include "draw/clip.h"
38 #include "drawing/draw/core_canvas.h"
39 #include "effect/runtime_blender_builder.h"
40 #include "effect/runtime_effect.h"
41 #include "effect/runtime_shader_builder.h"
42 #include "utils/rect.h"
43 #else
44 #include "include/core/SkCanvas.h"
45 #include "include/core/SkColorFilter.h"
46 #include "include/core/SkMaskFilter.h"
47 #include "include/core/SkPaint.h"
48 #include "include/core/SkPoint3.h"
49 #include "include/core/SkRRect.h"
50 #include "include/core/SkSurface.h"
51 #include "include/effects/Sk1DPathEffect.h"
52 #include "include/effects/SkDashPathEffect.h"
53 #include "include/effects/SkGradientShader.h"
54 #include "include/effects/SkLumaColorFilter.h"
55 #include "include/utils/SkShadowUtils.h"
56 #include "include/effects/SkImageFilters.h"
57 #include "include/effects/SkRuntimeEffect.h"
58 #endif
59 #include "src/image/SkImage_Base.h"
60
61 namespace OHOS {
62 namespace Rosen {
63 namespace {
64 bool g_forceBgAntiAlias = true;
65 constexpr int PARAM_DOUBLE = 2;
66 constexpr float MIN_TRANS_RATIO = 0.0f;
67 constexpr float MAX_TRANS_RATIO = 0.95f;
68 constexpr float MIN_SPOT_RATIO = 1.0f;
69 constexpr float MAX_SPOT_RATIO = 1.95f;
70 constexpr float MAX_AMBIENT_RADIUS = 150.0f;
71 // when the blur radius > SNAPSHOT_OUTSET_BLUR_RADIUS_THRESHOLD,
72 // the snapshot should call outset before blur to shrink by 1px.
73 constexpr static float SNAPSHOT_OUTSET_BLUR_RADIUS_THRESHOLD = 40.0f;
74 } // namespace
75
76 const bool RSPropertiesPainter::BLUR_ENABLED = RSSystemProperties::GetBlurEnabled();
77
78 #ifndef USE_ROSEN_DRAWING
79 #else
80 std::shared_ptr<Drawing::RuntimeEffect> RSPropertiesPainter::greyAdjustEffect_ = nullptr;
81 std::shared_ptr<Drawing::RuntimeEffect> RSPropertiesPainter::binarizationShaderEffect_ = nullptr;
82 std::shared_ptr<Drawing::RuntimeEffect> RSPropertiesPainter::lightUpEffectShaderEffect_ = nullptr;
83 std::shared_ptr<Drawing::RuntimeEffect> RSPropertiesPainter::dynamicLightUpBlenderEffect_ = nullptr;
84 #endif
85
86 #ifndef USE_ROSEN_DRAWING
Rect2SkRect(const RectF & r)87 SkRect RSPropertiesPainter::Rect2SkRect(const RectF& r)
88 {
89 return SkRect::MakeXYWH(r.left_, r.top_, r.width_, r.height_);
90 }
91 #else
Rect2DrawingRect(const RectF & r)92 Drawing::Rect RSPropertiesPainter::Rect2DrawingRect(const RectF& r)
93 {
94 return Drawing::Rect(r.left_, r.top_, r.left_ + r.width_, r.top_ + r.height_);
95 }
96 #endif
97
98 #ifndef USE_ROSEN_DRAWING
RRect2SkRRect(const RRect & rr)99 SkRRect RSPropertiesPainter::RRect2SkRRect(const RRect& rr)
100 {
101 SkRect rect = SkRect::MakeXYWH(rr.rect_.left_, rr.rect_.top_, rr.rect_.width_, rr.rect_.height_);
102 SkRRect rrect = SkRRect::MakeEmpty();
103
104 // set radius for all 4 corner of RRect
105 constexpr uint32_t NUM_OF_CORNERS_IN_RECT = 4;
106 SkVector vec[NUM_OF_CORNERS_IN_RECT];
107 for (uint32_t i = 0; i < NUM_OF_CORNERS_IN_RECT; i++) {
108 vec[i].set(rr.radius_[i].x_, rr.radius_[i].y_);
109 }
110
111 rrect.setRectRadii(rect, vec);
112 return rrect;
113 }
114 #else
RRect2DrawingRRect(const RRect & rr)115 Drawing::RoundRect RSPropertiesPainter::RRect2DrawingRRect(const RRect& rr)
116 {
117 Drawing::Rect rect = Drawing::Rect(
118 rr.rect_.left_, rr.rect_.top_, rr.rect_.left_ + rr.rect_.width_, rr.rect_.top_ + rr.rect_.height_);
119
120 // set radius for all 4 corner of RRect
121 constexpr uint32_t NUM_OF_CORNERS_IN_RECT = 4;
122 std::vector<Drawing::Point> radii(NUM_OF_CORNERS_IN_RECT);
123 for (uint32_t i = 0; i < NUM_OF_CORNERS_IN_RECT; i++) {
124 radii.at(i).SetX(rr.radius_[i].x_);
125 radii.at(i).SetY(rr.radius_[i].y_);
126 }
127 return Drawing::RoundRect(rect, radii);
128 }
129 #endif
130
131 #ifndef USE_ROSEN_DRAWING
GetGravityMatrix(Gravity gravity,RectF rect,float w,float h,SkMatrix & mat)132 bool RSPropertiesPainter::GetGravityMatrix(Gravity gravity, RectF rect, float w, float h, SkMatrix& mat)
133 #else
134 bool RSPropertiesPainter::GetGravityMatrix(Gravity gravity, RectF rect, float w, float h, Drawing::Matrix& mat)
135 #endif
136 {
137 if (w == rect.width_ && h == rect.height_) {
138 return false;
139 }
140 #ifndef USE_ROSEN_DRAWING
141 mat.reset();
142 #else
143 mat = Drawing::Matrix();
144 #endif
145
146 switch (gravity) {
147 case Gravity::CENTER: {
148 #ifndef USE_ROSEN_DRAWING
149 mat.preTranslate((rect.width_ - w) / PARAM_DOUBLE, (rect.height_ - h) / PARAM_DOUBLE);
150 #else
151 mat.PreTranslate((rect.width_ - w) / PARAM_DOUBLE, (rect.height_ - h) / PARAM_DOUBLE);
152 #endif
153 return true;
154 }
155 case Gravity::TOP: {
156 #ifndef USE_ROSEN_DRAWING
157 mat.preTranslate((rect.width_ - w) / PARAM_DOUBLE, 0);
158 #else
159 mat.PreTranslate((rect.width_ - w) / PARAM_DOUBLE, 0);
160 #endif
161 return true;
162 }
163 case Gravity::BOTTOM: {
164 #ifndef USE_ROSEN_DRAWING
165 mat.preTranslate((rect.width_ - w) / PARAM_DOUBLE, rect.height_ - h);
166 #else
167 mat.PreTranslate((rect.width_ - w) / PARAM_DOUBLE, rect.height_ - h);
168 #endif
169 return true;
170 }
171 case Gravity::LEFT: {
172 #ifndef USE_ROSEN_DRAWING
173 mat.preTranslate(0, (rect.height_ - h) / PARAM_DOUBLE);
174 #else
175 mat.PreTranslate(0, (rect.height_ - h) / PARAM_DOUBLE);
176 #endif
177 return true;
178 }
179 case Gravity::RIGHT: {
180 #ifndef USE_ROSEN_DRAWING
181 mat.preTranslate(rect.width_ - w, (rect.height_ - h) / PARAM_DOUBLE);
182 #else
183 mat.PreTranslate(rect.width_ - w, (rect.height_ - h) / PARAM_DOUBLE);
184 #endif
185 return true;
186 }
187 case Gravity::TOP_LEFT: {
188 return false;
189 }
190 case Gravity::TOP_RIGHT: {
191 #ifndef USE_ROSEN_DRAWING
192 mat.preTranslate(rect.width_ - w, 0);
193 #else
194 mat.PreTranslate(rect.width_ - w, 0);
195 #endif
196 return true;
197 }
198 case Gravity::BOTTOM_LEFT: {
199 #ifndef USE_ROSEN_DRAWING
200 mat.preTranslate(0, rect.height_ - h);
201 #else
202 mat.PreTranslate(0, rect.height_ - h);
203 #endif
204 return true;
205 }
206 case Gravity::BOTTOM_RIGHT: {
207 #ifndef USE_ROSEN_DRAWING
208 mat.preTranslate(rect.width_ - w, rect.height_ - h);
209 #else
210 mat.PreTranslate(rect.width_ - w, rect.height_ - h);
211 #endif
212 return true;
213 }
214 case Gravity::RESIZE: {
215 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
216 return false;
217 }
218 #ifndef USE_ROSEN_DRAWING
219 mat.preScale(rect.width_ / w, rect.height_ / h);
220 #else
221 mat.PreScale(rect.width_ / w, rect.height_ / h);
222 #endif
223 return true;
224 }
225 case Gravity::RESIZE_ASPECT: {
226 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
227 return false;
228 }
229 float scale = std::min(rect.width_ / w, rect.height_ / h);
230 if (ROSEN_EQ(scale, 0.f)) {
231 return false;
232 }
233 #ifndef USE_ROSEN_DRAWING
234 mat.preScale(scale, scale);
235 mat.preTranslate((rect.width_ / scale - w) / PARAM_DOUBLE, (rect.height_ / scale - h) / PARAM_DOUBLE);
236 #else
237 mat.PreScale(scale, scale);
238 mat.PreTranslate((rect.width_ / scale - w) / PARAM_DOUBLE, (rect.height_ / scale - h) / PARAM_DOUBLE);
239 #endif
240 return true;
241 }
242 case Gravity::RESIZE_ASPECT_TOP_LEFT: {
243 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
244 return false;
245 }
246 float scale = std::min(rect.width_ / w, rect.height_ / h);
247 #ifndef USE_ROSEN_DRAWING
248 mat.preScale(scale, scale);
249 #else
250 mat.PreScale(scale, scale);
251 #endif
252 return true;
253 }
254 case Gravity::RESIZE_ASPECT_BOTTOM_RIGHT: {
255 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
256 return false;
257 }
258 float scale = std::min(rect.width_ / w, rect.height_ / h);
259 if (ROSEN_EQ(scale, 0.f)) {
260 return false;
261 }
262 #ifndef USE_ROSEN_DRAWING
263 mat.preScale(scale, scale);
264 mat.preTranslate(rect.width_ / scale - w, rect.height_ / scale - h);
265 #else
266 mat.PreScale(scale, scale);
267 mat.PreTranslate(rect.width_ / scale - w, rect.height_ / scale - h);
268 #endif
269 return true;
270 }
271 case Gravity::RESIZE_ASPECT_FILL: {
272 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
273 return false;
274 }
275 float scale = std::max(rect.width_ / w, rect.height_ / h);
276 if (ROSEN_EQ(scale, 0.f)) {
277 return false;
278 }
279 #ifndef USE_ROSEN_DRAWING
280 mat.preScale(scale, scale);
281 mat.preTranslate((rect.width_ / scale - w) / PARAM_DOUBLE, (rect.height_ / scale - h) / PARAM_DOUBLE);
282 #else
283 mat.PreScale(scale, scale);
284 mat.PreTranslate((rect.width_ / scale - w) / PARAM_DOUBLE, (rect.height_ / scale - h) / PARAM_DOUBLE);
285 #endif
286 return true;
287 }
288 case Gravity::RESIZE_ASPECT_FILL_TOP_LEFT: {
289 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
290 return false;
291 }
292 float scale = std::max(rect.width_ / w, rect.height_ / h);
293 #ifndef USE_ROSEN_DRAWING
294 mat.preScale(scale, scale);
295 #else
296 mat.PreScale(scale, scale);
297 #endif
298 return true;
299 }
300 case Gravity::RESIZE_ASPECT_FILL_BOTTOM_RIGHT: {
301 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
302 return false;
303 }
304 float scale = std::max(rect.width_ / w, rect.height_ / h);
305 if (ROSEN_EQ(scale, 0.f)) {
306 return false;
307 }
308 #ifndef USE_ROSEN_DRAWING
309 mat.preScale(scale, scale);
310 mat.preTranslate(rect.width_ / scale - w, rect.height_ / scale - h);
311 #else
312 mat.PreScale(scale, scale);
313 mat.PreTranslate(rect.width_ / scale - w, rect.height_ / scale - h);
314 #endif
315 return true;
316 }
317 default: {
318 ROSEN_LOGE("GetGravityMatrix unknow gravity=[%{public}d]", gravity);
319 return false;
320 }
321 }
322 }
323
324 #ifndef USE_ROSEN_DRAWING
Clip(SkCanvas & canvas,RectF rect,bool isAntiAlias)325 void RSPropertiesPainter::Clip(SkCanvas& canvas, RectF rect, bool isAntiAlias)
326 {
327 // isAntiAlias is false only the method is called in ProcessAnimatePropertyBeforeChildren().
328 canvas.clipRect(Rect2SkRect(rect), isAntiAlias);
329 }
330 #else
Clip(Drawing::Canvas & canvas,RectF rect,bool isAntiAlias)331 void RSPropertiesPainter::Clip(Drawing::Canvas& canvas, RectF rect, bool isAntiAlias)
332 {
333 canvas.ClipRect(Rect2DrawingRect(rect), Drawing::ClipOp::INTERSECT, isAntiAlias);
334 }
335 #endif
336
337 #ifndef USE_ROSEN_DRAWING
GetShadowDirtyRect(RectI & dirtyShadow,const RSProperties & properties,const RRect * rrect,bool isAbsCoordinate,bool radiusInclude)338 void RSPropertiesPainter::GetShadowDirtyRect(RectI& dirtyShadow, const RSProperties& properties,
339 const RRect* rrect, bool isAbsCoordinate, bool radiusInclude)
340 {
341 // [Planning]: After Skia being updated, we should directly call SkShadowUtils::GetLocalBounds here.
342 if (!properties.IsShadowValid()) {
343 return;
344 }
345 SkPath skPath;
346 if (properties.GetShadowPath() && !properties.GetShadowPath()->GetSkiaPath().isEmpty()) {
347 skPath = properties.GetShadowPath()->GetSkiaPath();
348 } else if (properties.GetClipBounds()) {
349 skPath = properties.GetClipBounds()->GetSkiaPath();
350 } else {
351 if (rrect != nullptr) {
352 skPath.addRRect(RRect2SkRRect(*rrect));
353 } else {
354 skPath.addRRect(RRect2SkRRect(properties.GetRRect()));
355 }
356 }
357 skPath.offset(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
358
359 SkRect shadowRect = skPath.getBounds();
360 if (properties.GetShadowElevation() > 0.f) {
361 float elevation = properties.GetShadowElevation() + DEFAULT_TRANSLATION_Z;
362
363 float userTransRatio =
364 (elevation != DEFAULT_LIGHT_HEIGHT) ? elevation / (DEFAULT_LIGHT_HEIGHT - elevation) : MAX_TRANS_RATIO;
365 float transRatio = std::max(MIN_TRANS_RATIO, std::min(userTransRatio, MAX_TRANS_RATIO));
366
367 float userSpotRatio = (elevation != DEFAULT_LIGHT_HEIGHT)
368 ? DEFAULT_LIGHT_HEIGHT / (DEFAULT_LIGHT_HEIGHT - elevation)
369 : MAX_SPOT_RATIO;
370 float spotRatio = std::max(MIN_SPOT_RATIO, std::min(userSpotRatio, MAX_SPOT_RATIO));
371
372 SkRect ambientRect = skPath.getBounds();
373 SkRect spotRect = SkRect::MakeLTRB(ambientRect.left() * spotRatio, ambientRect.top() * spotRatio,
374 ambientRect.right() * spotRatio, ambientRect.bottom() * spotRatio);
375 spotRect.offset(-transRatio * DEFAULT_LIGHT_POSITION_X, -transRatio * DEFAULT_LIGHT_POSITION_Y);
376 spotRect.outset(transRatio * DEFAULT_LIGHT_RADIUS, transRatio * DEFAULT_LIGHT_RADIUS);
377
378 shadowRect = ambientRect;
379 float ambientBlur = std::min(elevation * 0.5f, MAX_AMBIENT_RADIUS);
380 shadowRect.outset(ambientBlur, ambientBlur);
381 shadowRect.join(spotRect);
382 shadowRect.outset(1, 1);
383 } else {
384 SkPaint paint;
385 paint.setAntiAlias(true);
386 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, properties.GetShadowRadius()));
387 if (paint.canComputeFastBounds() && radiusInclude) {
388 paint.computeFastBounds(shadowRect, &shadowRect);
389 }
390 }
391
392 auto geoPtr = (properties.GetBoundsGeometry());
393 SkMatrix matrix = (geoPtr && isAbsCoordinate) ? geoPtr->GetAbsMatrix() : SkMatrix::I();
394 matrix.mapRect(&shadowRect);
395
396 dirtyShadow.left_ = shadowRect.left();
397 dirtyShadow.top_ = shadowRect.top();
398 dirtyShadow.width_ = shadowRect.width();
399 dirtyShadow.height_ = shadowRect.height();
400 }
401 #else
GetShadowDirtyRect(RectI & dirtyShadow,const RSProperties & properties,const RRect * rrect,bool isAbsCoordinate,bool radiusInclude)402 void RSPropertiesPainter::GetShadowDirtyRect(RectI& dirtyShadow, const RSProperties& properties,
403 const RRect* rrect, bool isAbsCoordinate, bool radiusInclude)
404 {
405 // [Planning]: After Skia being updated, we should directly call SkShadowUtils::GetLocalBounds here.
406 if (!properties.IsShadowValid()) {
407 return;
408 }
409 Drawing::Path path;
410 if (properties.GetShadowPath() && properties.GetShadowPath()->GetDrawingPath().IsValid()) {
411 path = properties.GetShadowPath()->GetDrawingPath();
412 } else if (properties.GetClipBounds()) {
413 path = properties.GetClipBounds()->GetDrawingPath();
414 } else {
415 if (rrect != nullptr) {
416 path.AddRoundRect(RRect2DrawingRRect(*rrect));
417 } else {
418 path.AddRoundRect(RRect2DrawingRRect(properties.GetRRect()));
419 }
420 }
421 path.Offset(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
422
423 Drawing::Rect shadowRect = path.GetBounds();
424 if (properties.GetShadowElevation() > 0.f) {
425 float elevation = properties.GetShadowElevation() + DEFAULT_TRANSLATION_Z;
426
427 float userTransRatio =
428 (elevation != DEFAULT_LIGHT_HEIGHT) ? elevation / (DEFAULT_LIGHT_HEIGHT - elevation) : MAX_TRANS_RATIO;
429 float transRatio = std::max(MIN_TRANS_RATIO, std::min(userTransRatio, MAX_TRANS_RATIO));
430
431 float userSpotRatio = (elevation != DEFAULT_LIGHT_HEIGHT)
432 ? DEFAULT_LIGHT_HEIGHT / (DEFAULT_LIGHT_HEIGHT - elevation)
433 : MAX_SPOT_RATIO;
434 float spotRatio = std::max(MIN_SPOT_RATIO, std::min(userSpotRatio, MAX_SPOT_RATIO));
435
436 Drawing::Rect ambientRect = path.GetBounds();
437 Drawing::Rect spotRect = Drawing::Rect(ambientRect.GetLeft() * spotRatio, ambientRect.GetTop() * spotRatio,
438 ambientRect.GetRight() * spotRatio, ambientRect.GetBottom() * spotRatio);
439 spotRect.Offset(-transRatio * DEFAULT_LIGHT_POSITION_X, -transRatio * DEFAULT_LIGHT_POSITION_Y);
440 spotRect.MakeOutset(transRatio * DEFAULT_LIGHT_RADIUS, transRatio * DEFAULT_LIGHT_RADIUS);
441
442 shadowRect = ambientRect;
443 float ambientBlur = std::min(elevation * 0.5f, MAX_AMBIENT_RADIUS);
444 shadowRect.MakeOutset(ambientBlur, ambientBlur);
445
446 shadowRect.Join(spotRect);
447 shadowRect.MakeOutset(1, 1);
448 } else {
449 Drawing::Brush brush;
450 brush.SetAntiAlias(true);
451 Drawing::Filter filter;
452 filter.SetMaskFilter(
453 Drawing::MaskFilter::CreateBlurMaskFilter(Drawing::BlurType::NORMAL, properties.GetShadowRadius()));
454 brush.SetFilter(filter);
455 if (brush.CanComputeFastBounds() && radiusInclude) {
456 brush.ComputeFastBounds(shadowRect, &shadowRect);
457 }
458 }
459
460 auto geoPtr = (properties.GetBoundsGeometry());
461 Drawing::Matrix matrix = (geoPtr && isAbsCoordinate) ? geoPtr->GetAbsMatrix() : Drawing::Matrix();
462 matrix.MapRect(shadowRect, shadowRect);
463
464 dirtyShadow.left_ = shadowRect.GetLeft();
465 dirtyShadow.top_ = shadowRect.GetTop();
466 dirtyShadow.width_ = shadowRect.GetWidth();
467 dirtyShadow.height_ = shadowRect.GetHeight();
468 }
469 #endif
470
471 #ifndef USE_ROSEN_DRAWING
DrawShadow(const RSProperties & properties,RSPaintFilterCanvas & canvas,const RRect * rrect)472 void RSPropertiesPainter::DrawShadow(const RSProperties& properties, RSPaintFilterCanvas& canvas, const RRect* rrect)
473 {
474 // skip shadow if not valid or cache is enabled
475 if (properties.IsSpherizeValid() || !properties.IsShadowValid() || properties.GetNeedSkipShadow()
476 canvas.GetCacheType() == RSPaintFilterCanvas::CacheType::ENABLED) {
477 return;
478 }
479
480 RSAutoCanvasRestore acr(&canvas);
481 SkPath skPath;
482 if (properties.GetShadowPath() && !properties.GetShadowPath()->GetSkiaPath().isEmpty()) {
483 skPath = properties.GetShadowPath()->GetSkiaPath();
484 if (!properties.GetShadowIsFilled()) {
485 canvas.clipPath(skPath, SkClipOp::kDifference, true);
486 }
487 } else if (properties.GetClipBounds()) {
488 skPath = properties.GetClipBounds()->GetSkiaPath();
489 if (!properties.GetShadowIsFilled()) {
490 canvas.clipPath(skPath, SkClipOp::kDifference, true);
491 }
492 } else {
493 if (rrect != nullptr) {
494 skPath.addRRect(RRect2SkRRect(*rrect));
495 if (!properties.GetShadowIsFilled()) {
496 canvas.clipRRect(RRect2SkRRect(*rrect), SkClipOp::kDifference, true);
497 }
498 } else {
499 skPath.addRRect(RRect2SkRRect(properties.GetRRect()));
500 if (!properties.GetShadowIsFilled()) {
501 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), SkClipOp::kDifference, true);
502 }
503 }
504 }
505 if (properties.GetShadowMask()) {
506 DrawColorfulShadowInner(properties, canvas, skPath);
507 } else {
508 DrawShadowInner(properties, canvas, skPath);
509 }
510 }
511 #else
DrawShadow(const RSProperties & properties,RSPaintFilterCanvas & canvas,const RRect * rrect)512 void RSPropertiesPainter::DrawShadow(const RSProperties& properties, RSPaintFilterCanvas& canvas, const RRect* rrect)
513 {
514 // skip shadow if not valid or cache is enabled
515 if (properties.IsSpherizeValid() || !properties.IsShadowValid() ||
516 canvas.GetCacheType() == RSPaintFilterCanvas::CacheType::ENABLED) {
517 return;
518 }
519 Drawing::AutoCanvasRestore acr(canvas, true);
520 Drawing::Path path;
521 if (properties.GetShadowPath() && properties.GetShadowPath()->GetDrawingPath().IsValid()) {
522 path = properties.GetShadowPath()->GetDrawingPath();
523 if (!properties.GetShadowIsFilled()) {
524 canvas.ClipPath(path, Drawing::ClipOp::DIFFERENCE, true);
525 }
526 } else if (properties.GetClipBounds()) {
527 path = properties.GetClipBounds()->GetDrawingPath();
528 if (!properties.GetShadowIsFilled()) {
529 canvas.ClipPath(path, Drawing::ClipOp::DIFFERENCE, true);
530 }
531 } else {
532 if (rrect != nullptr) {
533 path.AddRoundRect(RRect2DrawingRRect(*rrect));
534 if (!properties.GetShadowIsFilled()) {
535 canvas.ClipRoundRect(RRect2DrawingRRect(*rrect), Drawing::ClipOp::DIFFERENCE, true);
536 }
537 } else {
538 path.AddRoundRect(RRect2DrawingRRect(properties.GetRRect()));
539 if (!properties.GetShadowIsFilled()) {
540 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::DIFFERENCE, true);
541 }
542 }
543 }
544 if (properties.GetShadowMask()) {
545 DrawColorfulShadowInner(properties, canvas, path);
546 } else {
547 DrawShadowInner(properties, canvas, path);
548 }
549 }
550 #endif
551
552 #ifndef USE_ROSEN_DRAWING
DrawColorfulShadowInner(const RSProperties & properties,RSPaintFilterCanvas & canvas,SkPath & skPath)553 void RSPropertiesPainter::DrawColorfulShadowInner(
554 const RSProperties& properties, RSPaintFilterCanvas& canvas, SkPath& skPath)
555 {
556 // blurRadius calculation is based on the formula in SkShadowUtils::DrawShadow, 0.25f and 128.0f are constants
557 const SkScalar blurRadius =
558 properties.GetShadowElevation() > 0.f
559 ? 0.25f * properties.GetShadowElevation() * (1 + properties.GetShadowElevation() / 128.0f)
560 : properties.GetShadowRadius();
561
562 // save layer, draw image with clipPath, blur and draw back
563 SkPaint blurPaint;
564 blurPaint.setImageFilter(SkImageFilters::Blur(blurRadius, blurRadius, SkTileMode::kDecal, nullptr));
565 canvas.saveLayer(nullptr, &blurPaint);
566
567 canvas.translate(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
568
569 canvas.clipPath(skPath);
570 // draw node content as shadow
571 // [PLANNING]: maybe we should also draw background color / image here, and we should cache the shadow image
572 if (auto node = RSBaseRenderNode::ReinterpretCast<RSCanvasRenderNode>(properties.backref_.lock())) {
573 node->InternalDrawContent(canvas);
574 }
575 }
576 #else
DrawColorfulShadowInner(const RSProperties & properties,RSPaintFilterCanvas & canvas,Drawing::Path & path)577 void RSPropertiesPainter::DrawColorfulShadowInner(
578 const RSProperties& properties, RSPaintFilterCanvas& canvas, Drawing::Path& path)
579 {
580 // blurRadius calculation is based on the formula in Canvas::DrawShadow, 0.25f and 128.0f are constants
581 const Drawing::scalar blurRadius =
582 properties.GetShadowElevation() > 0.f
583 ? 0.25f * properties.GetShadowElevation() * (1 + properties.GetShadowElevation() / 128.0f)
584 : properties.GetShadowRadius();
585
586 // save layer, draw image with clipPath, blur and draw back
587 Drawing::Brush blurBrush;
588 Drawing::Filter filter;
589 filter.SetImageFilter(Drawing::ImageFilter::CreateBlurImageFilter(
590 blurRadius, blurRadius, Drawing::TileMode::DECAL, nullptr));
591 blurBrush.SetFilter(filter);
592
593 canvas.SaveLayer({nullptr, &blurBrush});
594
595 canvas.Translate(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
596
597 canvas.ClipPath(path, Drawing::ClipOp::INTERSECT, false);
598 // draw node content as shadow
599 // [PLANNING]: maybe we should also draw background color / image here, and we should cache the shadow image
600 if (auto node = RSBaseRenderNode::ReinterpretCast<RSCanvasRenderNode>(properties.backref_.lock())) {
601 node->InternalDrawContent(canvas);
602 }
603 }
604 #endif
605
GetDarkColor(RSColor & color)606 void RSPropertiesPainter::GetDarkColor(RSColor& color)
607 {
608 // convert to lab
609 float minColorRange = 0;
610 float maxColorRange = 255;
611 float R = float(color.GetRed()) / maxColorRange;
612 float G = float(color.GetGreen()) / maxColorRange;
613 float B = float(color.GetBlue()) / maxColorRange;
614
615 float X = 0.4124 * R + 0.3576 * G + 0.1805 * B;
616 float Y = 0.2126 * R + 0.7152 * G + 0.0722 * B;
617 float Z = 0.0193 * R + 0.1192 * G + 0.9505 * B;
618
619 float Xn = 0.9505;
620 float Yn = 1.0000;
621 float Zn = 1.0889999;
622 float Fx = (X / Xn) > 0.008856 ? pow((X / Xn), 1.0 / 3) : (7.787 * (X / Xn) + 16.0 / 116);
623 float Fy = (Y / Yn) > 0.008856 ? pow((Y / Yn), 1.0 / 3) : (7.787 * (Y / Yn) + 16.0 / 116);
624 float Fz = (Z / Zn) > 0.008856 ? pow((Z / Zn), 1.0 / 3) : (7.787 * (Z / Zn) + 16.0 / 116);
625 float L = 116 * Fy - 16;
626 float a = 500 * (Fx - Fy);
627 float b = 200 * (Fy - Fz);
628
629 float standardLightness = 75.0;
630 if (L > standardLightness) {
631 float L1 = standardLightness;
632 float xw = 0.9505;
633 float yw = 1.0000;
634 float zw = 1.0889999;
635
636 float fy = (L1 + 16) / 116;
637 float fx = fy + (a / 500);
638 float fz = fy - (b / 200);
639
640 float X1 = xw * ((pow(fx, 3) > 0.008856) ? pow(fx, 3) : ((fx - 16.0 / 116) / 7.787));
641 float Y1 = yw * ((pow(fy, 3) > 0.008856) ? pow(fy, 3) : ((fy - 16.0 / 116) / 7.787));
642 float Z1 = zw * ((pow(fz, 3) > 0.008856) ? pow(fz, 3) : ((fz - 16.0 / 116) / 7.787));
643
644 float DarkR = 3.2406 * X1 - 1.5372 * Y1 - 0.4986 * Z1;
645 float DarkG = -0.9689 * X1 + 1.8758 * Y1 + 0.0415 * Z1;
646 float DarkB = 0.0557 * X1 - 0.2040 * Y1 + 1.0570 * Z1;
647
648 DarkR = std::clamp(maxColorRange * DarkR, minColorRange, maxColorRange);
649 DarkG = std::clamp(maxColorRange * DarkG, minColorRange, maxColorRange);
650 DarkB = std::clamp(maxColorRange * DarkB, minColorRange, maxColorRange);
651
652 color = RSColor(DarkR, DarkG, DarkB, color.GetAlpha());
653 }
654 }
655
656 #ifndef USE_ROSEN_DRAWING
PickColor(const RSProperties & properties,RSPaintFilterCanvas & canvas,SkPath & skPath,SkMatrix & matrix,SkIRect & deviceClipBounds,RSColor & colorPicked)657 bool RSPropertiesPainter::PickColor(const RSProperties& properties, RSPaintFilterCanvas& canvas, SkPath& skPath,
658 SkMatrix& matrix, SkIRect& deviceClipBounds, RSColor& colorPicked)
659 {
660 SkRect clipBounds = skPath.getBounds();
661 SkIRect clipIBounds = clipBounds.roundIn();
662 SkSurface* skSurface = canvas.GetSurface();
663 if (skSurface == nullptr) {
664 return false;
665 }
666
667 auto& colorPickerTask = properties.GetColorPickerCacheTaskShadow();
668 colorPickerTask->SetIsShadow(true);
669 int deviceWidth = 0;
670 int deviceHeight = 0;
671 int deviceClipBoundsW = skSurface->width();
672 int deviceClipBoundsH = skSurface->height();
673 if (!colorPickerTask->GetDeviceSize(deviceWidth, deviceHeight)) {
674 colorPickerTask->SetDeviceSize(deviceClipBoundsW, deviceClipBoundsH);
675 deviceWidth = deviceClipBoundsW;
676 deviceHeight = deviceClipBoundsH;
677 }
678 int32_t fLeft = std::clamp(int(matrix.getTranslateX()), 0, deviceWidth - 1);
679 int32_t fTop = std::clamp(int(matrix.getTranslateY()), 0, deviceHeight - 1);
680 int32_t fRight = std::clamp(int(fLeft + clipIBounds.width()), 0, deviceWidth - 1);
681 int32_t fBottom = std::clamp(int(fTop + clipIBounds.height()), 0, deviceHeight - 1);
682 if (fLeft == fRight || fTop == fBottom) {
683 return false;
684 }
685
686 SkIRect regionBounds = SkIRect::MakeLTRB(fLeft, fTop, fRight, fBottom);
687 sk_sp<SkImage> shadowRegionImage = skSurface->makeImageSnapshot(regionBounds);
688
689 if (shadowRegionImage == nullptr) {
690 return false;
691 }
692
693 // when color picker task resource is waitting for release, use color picked last frame
694 if (colorPickerTask->GetWaitRelease()) {
695 colorPickerTask->GetColorAverage(colorPicked);
696 return true;
697 }
698
699 if (RSColorPickerCacheTask::PostPartialColorPickerTask(colorPickerTask, shadowRegionImage)
700 && colorPickerTask->GetColor(colorPicked)) {
701 colorPickerTask->GetColorAverage(colorPicked);
702 colorPickerTask->SetStatus(CacheProcessStatus::WAITING);
703 return true;
704 }
705 colorPickerTask->GetColorAverage(colorPicked);
706 return true;
707 }
708 #else
PickColor(const RSProperties & properties,RSPaintFilterCanvas & canvas,Drawing::Path & drPath,Drawing::Matrix & matrix,Drawing::RectI & deviceClipBounds,RSColor & colorPicked)709 bool RSPropertiesPainter::PickColor(const RSProperties& properties, RSPaintFilterCanvas& canvas, Drawing::Path& drPath,
710 Drawing::Matrix& matrix, Drawing::RectI& deviceClipBounds, RSColor& colorPicked)
711 {
712 Drawing::Rect clipBounds = drPath.GetBounds();
713 Drawing::RectI clipIBounds = { static_cast<int>(clipBounds.GetLeft()), static_cast<int>(clipBounds.GetTop()),
714 static_cast<int>(clipBounds.GetRight()), static_cast<int>(clipBounds.GetBottom()) };
715 Drawing::Surface* drSurface = canvas.GetSurface();
716 if (drSurface == nullptr) {
717 return false;
718 }
719
720 auto& colorPickerTask = properties.GetColorPickerCacheTaskShadow();
721 if (!colorPickerTask) {
722 ROSEN_LOGE("RSPropertiesPainter::PickColor colorPickerTask is null");
723 return false;
724 }
725 colorPickerTask->SetIsShadow(true);
726 int deviceWidth = 0;
727 int deviceHeight = 0;
728 int deviceClipBoundsW = drSurface->Width();
729 int deviceClipBoundsH = drSurface->Height();
730 if (!colorPickerTask->GetDeviceSize(deviceWidth, deviceHeight)) {
731 colorPickerTask->SetDeviceSize(deviceClipBoundsW, deviceClipBoundsH);
732 deviceWidth = deviceClipBoundsW;
733 deviceHeight = deviceClipBoundsH;
734 }
735 int32_t fLeft = std::clamp(int(matrix.Get(Drawing::Matrix::Index::TRANS_X)), 0, deviceWidth - 1);
736 int32_t fTop = std::clamp(int(matrix.Get(Drawing::Matrix::Index::TRANS_Y)), 0, deviceHeight - 1);
737 int32_t fRight = std::clamp(int(fLeft + clipIBounds.GetWidth()), 0, deviceWidth - 1);
738 int32_t fBottom = std::clamp(int(fTop + clipIBounds.GetHeight()), 0, deviceHeight - 1);
739 if (fLeft == fRight || fTop == fBottom) {
740 return false;
741 }
742
743 Drawing::RectI regionBounds = { fLeft, fTop, fRight, fBottom };
744 std::shared_ptr<Drawing::Image> shadowRegionImage = drSurface->GetImageSnapshot(regionBounds);
745
746 if (shadowRegionImage == nullptr) {
747 return false;
748 }
749
750 // when color picker task resource is waitting for release, use color picked last frame
751 if (colorPickerTask->GetWaitRelease()) {
752 colorPickerTask->GetColorAverage(colorPicked);
753 return true;
754 }
755
756 if (RSColorPickerCacheTask::PostPartialColorPickerTask(colorPickerTask, shadowRegionImage)
757 && colorPickerTask->GetColor(colorPicked)) {
758 colorPickerTask->GetColorAverage(colorPicked);
759 colorPickerTask->SetStatus(CacheProcessStatus::WAITING);
760 return true;
761 }
762 colorPickerTask->GetColorAverage(colorPicked);
763 return true;
764 }
765 #endif
766
767 #ifndef USE_ROSEN_DRAWING
DrawShadowInner(const RSProperties & properties,RSPaintFilterCanvas & canvas,SkPath & skPath)768 void RSPropertiesPainter::DrawShadowInner(const RSProperties& properties, RSPaintFilterCanvas& canvas, SkPath& skPath)
769 {
770 skPath.offset(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
771 Color spotColor = properties.GetShadowColor();
772 // shadow alpha follow setting
773 auto shadowAlpha = spotColor.GetAlpha();
774 auto deviceClipBounds = canvas.getDeviceClipBounds();
775
776 // The translation of the matrix is rounded to improve the hit ratio of skia blurfilter cache,
777 // the function <compute_key_and_clip_bounds> in <skia/src/gpu/GrBlurUtil.cpp> for more details.
778 RSAutoCanvasRestore rst(&canvas);
779 auto matrix = canvas.getTotalMatrix();
780 matrix.setTranslateX(std::ceil(matrix.getTranslateX()));
781 matrix.setTranslateY(std::ceil(matrix.getTranslateY()));
782 canvas.setMatrix(matrix);
783
784 RSColor colorPicked;
785 auto& colorPickerTask = properties.GetColorPickerCacheTaskShadow();
786 if (colorPickerTask != nullptr &&
787 properties.GetShadowColorStrategy() != SHADOW_COLOR_STRATEGY::COLOR_STRATEGY_NONE) {
788 if (PickColor(properties, canvas, skPath, matrix, deviceClipBounds, colorPicked)) {
789 GetDarkColor(colorPicked);
790 } else {
791 shadowAlpha = 0;
792 }
793 if (!colorPickerTask->GetFirstGetColorFinished()) {
794 shadowAlpha = 0;
795 }
796 } else {
797 shadowAlpha = spotColor.GetAlpha();
798 colorPicked = spotColor;
799 }
800
801 if (properties.GetShadowElevation() > 0.f) {
802 SkPoint3 planeParams = { 0.0f, 0.0f, properties.GetShadowElevation() };
803 SkPoint pt = { skPath.getBounds().centerX(), skPath.getBounds().centerY() };
804 canvas.getTotalMatrix().mapPoints(&pt, 1);
805 SkPoint3 lightPos = {pt.fX, pt.fY, DEFAULT_LIGHT_HEIGHT};
806 Color ambientColor = Color::FromArgbInt(DEFAULT_AMBIENT_COLOR);
807 ambientColor.MultiplyAlpha(canvas.GetAlpha());
808 spotColor.MultiplyAlpha(canvas.GetAlpha());
809 SkShadowUtils::DrawShadow(&canvas, skPath, planeParams, lightPos, DEFAULT_LIGHT_RADIUS,
810 ambientColor.AsArgbInt(), spotColor.AsArgbInt(), SkShadowFlags::kTransparentOccluder_ShadowFlag);
811 } else {
812 SkPaint paint;
813 paint.setColor(SkColorSetARGB(shadowAlpha, colorPicked.GetRed(),
814 colorPicked.GetGreen(), colorPicked.GetBlue()));
815 paint.setAntiAlias(true);
816 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, properties.GetShadowRadius()));
817 canvas.drawPath(skPath, paint);
818 }
819 }
820 #else
DrawShadowInner(const RSProperties & properties,RSPaintFilterCanvas & canvas,Drawing::Path & path)821 void RSPropertiesPainter::DrawShadowInner(
822 const RSProperties& properties, RSPaintFilterCanvas& canvas, Drawing::Path& path)
823 {
824 path.Offset(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
825 Color spotColor = properties.GetShadowColor();
826 // shadow alpha follow setting
827 auto shadowAlpha = spotColor.GetAlpha();
828 auto deviceClipBounds = canvas.GetDeviceClipBounds();
829
830 // The translation of the matrix is rounded to improve the hit ratio of skia blurfilter cache,
831 // the function <compute_key_and_clip_bounds> in <skia/src/gpu/GrBlurUtil.cpp> for more details.
832 RSAutoCanvasRestore rst(&canvas);
833 auto matrix = canvas.GetTotalMatrix();
834 matrix.Set(Drawing::Matrix::TRANS_X, std::ceil(matrix.Get(Drawing::Matrix::TRANS_X)));
835 matrix.Set(Drawing::Matrix::TRANS_Y, std::ceil(matrix.Get(Drawing::Matrix::TRANS_Y)));
836 canvas.SetMatrix(matrix);
837
838 RSColor colorPicked;
839 auto& colorPickerTask = properties.GetColorPickerCacheTaskShadow();
840 if (colorPickerTask != nullptr &&
841 properties.GetShadowColorStrategy() != SHADOW_COLOR_STRATEGY::COLOR_STRATEGY_NONE) {
842 if (PickColor(properties, canvas, path, matrix, deviceClipBounds, colorPicked)) {
843 GetDarkColor(colorPicked);
844 } else {
845 shadowAlpha = 0;
846 }
847 if (!colorPickerTask->GetFirstGetColorFinished()) {
848 shadowAlpha = 0;
849 }
850 } else {
851 shadowAlpha = spotColor.GetAlpha();
852 colorPicked = spotColor;
853 }
854
855 if (properties.GetShadowElevation() > 0.f) {
856 Drawing::Point3 planeParams = { 0.0f, 0.0f, properties.GetShadowElevation() };
857 std::vector<Drawing::Point> pt{{path.GetBounds().GetLeft() + path.GetBounds().GetWidth() / 2,
858 path.GetBounds().GetTop() + path.GetBounds().GetHeight() / 2}};
859 canvas.GetTotalMatrix().MapPoints(pt, pt, 1);
860 Drawing::Point3 lightPos = {pt[0].GetX(), pt[0].GetY(), DEFAULT_LIGHT_HEIGHT};
861 Color ambientColor = Color::FromArgbInt(DEFAULT_AMBIENT_COLOR);
862 ambientColor.MultiplyAlpha(canvas.GetAlpha());
863 spotColor.MultiplyAlpha(canvas.GetAlpha());
864 canvas.DrawShadow(path, planeParams, lightPos, DEFAULT_LIGHT_RADIUS,
865 Drawing::Color(ambientColor.AsArgbInt()), Drawing::Color(spotColor.AsArgbInt()),
866 Drawing::ShadowFlags::TRANSPARENT_OCCLUDER);
867 } else {
868 Drawing::Brush brush;
869 brush.SetColor(Drawing::Color::ColorQuadSetARGB(
870 shadowAlpha, colorPicked.GetRed(), colorPicked.GetGreen(), colorPicked.GetBlue()));
871 brush.SetAntiAlias(true);
872 Drawing::Filter filter;
873 filter.SetMaskFilter(
874 Drawing::MaskFilter::CreateBlurMaskFilter(Drawing::BlurType::NORMAL, properties.GetShadowRadius()));
875 brush.SetFilter(filter);
876 canvas.AttachBrush(brush);
877 canvas.DrawPath(path);
878 canvas.DetachBrush();
879 }
880 }
881 #endif
882
883 #ifndef USE_ROSEN_DRAWING
MakeGreyAdjustmentEffect()884 sk_sp<SkRuntimeEffect> RSPropertiesPainter::MakeGreyAdjustmentEffect()
885 {
886 SkString GreyGradationString(R"(
887 uniform shader imageShader;
888 uniform float coefficient1;
889 uniform float coefficient2;
890
891 float poww(float x, float y) {
892 return (x < 0) ? -pow(-x, y) : pow(x, y);
893 }
894
895 float calculateT_y(float rgb) {
896 if (rgb > 127.5) { rgb = 255 - rgb; }
897 float b = 38.0;
898 float c = 45.0;
899 float d = 127.5;
900 float A = 106.5; // 3 * b - 3 * c + d;
901 float B = -93; // 3 * (c - 2 * b);
902 float C = 114; // 3 * b;
903 float p = 0.816240163988; // (3 * A * C - pow(B, 2)) / (3 * pow(A, 2));
904 float q = -rgb / 106.5 + 0.262253485943; // -rgb/A - B*C/(3*pow(A,2)) + 2*pow(B,3)/(27*pow(A,3))
905 float s1 = -(q / 2.0);
906 float s2 = sqrt(pow(s1, 2) + pow(p / 3, 3));
907 return poww((s1 + s2), 1.0 / 3) + poww((s1 - s2), 1.0 / 3) - (B / (3 * A));
908 }
909
910 float calculateGreyAdjustY(float rgb) {
911 float t_r = calculateT_y(rgb);
912 return (rgb < 127.5) ? (rgb + coefficient1 * pow((1 - t_r), 3)) : (rgb - coefficient2 * pow((1 - t_r), 3));
913 }
914
915 half4 main(float2 coord) {
916 vec3 color = vec3(imageShader.eval(coord).r, imageShader.eval(coord).g, imageShader.eval(coord).b);
917 float Y = (0.299 * color.r + 0.587 * color.g + 0.114 * color.b) * 255;
918 float U = (-0.147 * color.r - 0.289 * color.g + 0.436 * color.b) * 255;
919 float V = (0.615 * color.r - 0.515 * color.g - 0.100 * color.b) * 255;
920 Y = calculateGreyAdjustY(Y);
921 color.r = (Y + 1.14 * V) / 255.0;
922 color.g = (Y - 0.39 * U - 0.58 * V) / 255.0;
923 color.b = (Y + 2.03 * U) / 255.0;
924
925 return vec4(color, 1.0);
926 }
927 )");
928 if (!greyAdjustEffect_) {
929 auto [greyAdjustEffect, greyAdjustError] = SkRuntimeEffect::MakeForShader(GreyGradationString);
930 if (!greyAdjustEffect) {
931 return nullptr;
932 }
933 greyAdjustEffect_ = std::move(greyAdjustEffect);
934 }
935
936 return greyAdjustEffect_;
937 }
938 #else
MakeGreyAdjustmentEffect()939 std::shared_ptr<Drawing::RuntimeEffect> RSPropertiesPainter::MakeGreyAdjustmentEffect()
940 {
941 static const std::string GreyGradationString(R"(
942 uniform shader imageShader;
943 uniform float coefficient1;
944 uniform float coefficient2;
945
946 float poww(float x, float y) {
947 return (x < 0) ? -pow(-x, y) : pow(x, y);
948 }
949
950 float calculateT_y(float rgb) {
951 if (rgb > 127.5) { rgb = 255 - rgb; }
952 float b = 38.0;
953 float c = 45.0;
954 float d = 127.5;
955 float A = 106.5; // 3 * b - 3 * c + d;
956 float B = -93; // 3 * (c - 2 * b);
957 float C = 114; // 3 * b;
958 float p = 0.816240163988; // (3 * A * C - pow(B, 2)) / (3 * pow(A, 2));
959 float q = -rgb / 106.5 + 0.262253485943; // -rgb/A - B*C/(3*pow(A,2)) + 2*pow(B,3)/(27*pow(A,3))
960 float s1 = -(q / 2.0);
961 float s2 = sqrt(pow(s1, 2) + pow(p / 3, 3));
962 return poww((s1 + s2), 1.0 / 3) + poww((s1 - s2), 1.0 / 3) - (B / (3 * A));
963 }
964
965 float calculateGreyAdjustY(float rgb) {
966 float t_r = calculateT_y(rgb);
967 return (rgb < 127.5) ? (rgb + coefficient1 * pow((1 - t_r), 3)) : (rgb - coefficient2 * pow((1 - t_r), 3));
968 }
969
970 half4 main(float2 coord) {
971 vec3 color = vec3(imageShader.eval(coord).r, imageShader.eval(coord).g, imageShader.eval(coord).b);
972 float Y = (0.299 * color.r + 0.587 * color.g + 0.114 * color.b) * 255;
973 float U = (-0.147 * color.r - 0.289 * color.g + 0.436 * color.b) * 255;
974 float V = (0.615 * color.r - 0.515 * color.g - 0.100 * color.b) * 255;
975 Y = calculateGreyAdjustY(Y);
976 color.r = (Y + 1.14 * V) / 255.0;
977 color.g = (Y - 0.39 * U - 0.58 * V) / 255.0;
978 color.b = (Y + 2.03 * U) / 255.0;
979
980 return vec4(color, 1.0);
981 }
982 )");
983 if (!greyAdjustEffect_) {
984 std::shared_ptr<Drawing::RuntimeEffect> greyAdjustEffect =
985 Drawing::RuntimeEffect::CreateForShader(GreyGradationString);
986 if (!greyAdjustEffect) {
987 return nullptr;
988 }
989 greyAdjustEffect_ = std::move(greyAdjustEffect);
990 }
991
992 return greyAdjustEffect_;
993 }
994 #endif
995
996 #ifndef USE_ROSEN_DRAWING
DrawGreyAdjustment(SkCanvas & canvas,const sk_sp<SkImage> & image,const float greyCoef1,const float greyCoef2)997 sk_sp<SkImage> RSPropertiesPainter::DrawGreyAdjustment(SkCanvas& canvas, const sk_sp<SkImage>& image,
998 const float greyCoef1, const float greyCoef2)
999 {
1000 if (image == nullptr) {
1001 ROSEN_LOGE("RSPropertiesPainter::DrawGreyAdjustment image is null");
1002 return nullptr;
1003 }
1004 RS_TRACE_NAME_FMT("RSPropertiesPainter::DrawGreyAdjustment, greyCoef1 is: %f, greyCoef2 is: %f",
1005 greyCoef1, greyCoef2);
1006 auto greyAdjustEffect = MakeGreyAdjustmentEffect();
1007 if (!greyAdjustEffect) {
1008 ROSEN_LOGE("RSPropertiesPainter::DrawGreyAdjustment greyAdjustEffect is null");
1009 return nullptr;
1010 }
1011 SkRuntimeShaderBuilder builder(greyAdjustEffect);
1012 auto imageShader = image->makeShader(SkSamplingOptions(SkFilterMode::kLinear));
1013 builder.child("imageShader") = imageShader;
1014 builder.uniform("coefficient1") = greyCoef1;
1015 builder.uniform("coefficient2") = greyCoef2;
1016
1017 return builder.makeImage(canvas.recordingContext(), nullptr, image->imageInfo(), false);
1018 }
1019 #else
DrawGreyAdjustment(Drawing::Canvas & canvas,const std::shared_ptr<Drawing::Image> & image,const float greyCoef1,const float greyCoef2)1020 std::shared_ptr<Drawing::Image> RSPropertiesPainter::DrawGreyAdjustment(Drawing::Canvas& canvas,
1021 const std::shared_ptr<Drawing::Image>& image, const float greyCoef1, const float greyCoef2)
1022 {
1023 if (image == nullptr) {
1024 ROSEN_LOGE("RSPropertiesPainter::DrawGreyAdjustment image is null");
1025 return nullptr;
1026 }
1027 RS_TRACE_NAME_FMT("RSPropertiesPainter::DrawGreyAdjustment, greyCoef1 is: %f, greyCoef2 is: %f",
1028 greyCoef1, greyCoef2);
1029 auto greyAdjustEffect = MakeGreyAdjustmentEffect();
1030 if (!greyAdjustEffect) {
1031 ROSEN_LOGE("RSPropertiesPainter::DrawGreyAdjustment greyAdjustEffect is null");
1032 return nullptr;
1033 }
1034 std::shared_ptr<Drawing::RuntimeShaderBuilder> builder =
1035 std::make_shared<Drawing::RuntimeShaderBuilder>(greyAdjustEffect);
1036 Drawing::Matrix matrix;
1037 auto imageShader = Drawing::ShaderEffect::CreateImageShader(*image, Drawing::TileMode::CLAMP,
1038 Drawing::TileMode::CLAMP, Drawing::SamplingOptions(Drawing::FilterMode::LINEAR), matrix);
1039 builder->SetChild("imageShader", imageShader);
1040 builder->SetUniform("coefficient1", greyCoef1);
1041 builder->SetUniform("coefficient2", greyCoef2);
1042 return builder->MakeImage(canvas.GetGPUContext().get(), nullptr, image->GetImageInfo(), false);
1043 }
1044 #endif
1045
1046 #ifndef USE_ROSEN_DRAWING
DrawFilter(const RSProperties & properties,RSPaintFilterCanvas & canvas,FilterType filterType,const std::optional<SkRect> & rect,const std::shared_ptr<RSFilter> & externalFilter)1047 void RSPropertiesPainter::DrawFilter(const RSProperties& properties, RSPaintFilterCanvas& canvas,
1048 FilterType filterType, const std::optional<SkRect>& rect, const std::shared_ptr<RSFilter>& externalFilter)
1049 #else
1050 void RSPropertiesPainter::DrawFilter(const RSProperties& properties, RSPaintFilterCanvas& canvas,
1051 FilterType filterType, const std::optional<Drawing::Rect>& rect, const std::shared_ptr<RSFilter>& externalFilter)
1052 #endif
1053 {
1054 if (!BLUR_ENABLED) {
1055 ROSEN_LOGD("RSPropertiesPainter::DrawFilter close blur.");
1056 return;
1057 }
1058 // use provided filter if not null
1059 auto& RSFilter = externalFilter ? externalFilter
1060 : ((filterType == FilterType::BACKGROUND_FILTER) ? properties.GetBackgroundFilter() : properties.GetFilter());
1061 if (RSFilter == nullptr) {
1062 return;
1063 }
1064
1065 bool needSnapshotOutset = true;
1066 if (RSFilter->GetFilterType() == RSFilter::MATERIAL) {
1067 auto material = std::static_pointer_cast<RSMaterialFilter>(RSFilter);
1068 needSnapshotOutset = (material->GetRadius() >= SNAPSHOT_OUTSET_BLUR_RADIUS_THRESHOLD);
1069 }
1070 RS_OPTIONAL_TRACE_NAME("DrawFilter " + RSFilter->GetDescription());
1071 g_blurCnt++;
1072 #ifndef USE_ROSEN_DRAWING
1073 SkAutoCanvasRestore acr(&canvas, true);
1074 if (RSSystemProperties::GetPropertyDrawableEnable()) {
1075 // do nothing
1076 } else if (rect.has_value()) {
1077 canvas.clipRect((*rect), true);
1078 } else if (properties.GetClipBounds() != nullptr) {
1079 canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
1080 } else { // we always do clip for DrawFilter, even if ClipToBounds is false
1081 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
1082 }
1083
1084 auto filter = std::static_pointer_cast<RSSkiaFilter>(RSFilter);
1085 filter->SetGreyCoef(properties.GetGreyCoef1(), properties.GetGreyCoef2(), properties.IsGreyAdjustmentValid());
1086 auto skSurface = canvas.GetSurface();
1087 if (skSurface == nullptr) {
1088 ROSEN_LOGD("RSPropertiesPainter::DrawFilter skSurface null");
1089 auto paint = filter->GetPaint();
1090 SkCanvas::SaveLayerRec slr(nullptr, &paint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
1091 canvas.saveLayer(slr);
1092 filter->PostProcess(canvas);
1093 return;
1094 }
1095 #else
1096 Drawing::AutoCanvasRestore acr(canvas, true);
1097 if (RSSystemProperties::GetPropertyDrawableEnable()) {
1098 // do nothing
1099 } else if (rect.has_value()) {
1100 canvas.ClipRect((*rect), Drawing::ClipOp::INTERSECT, true);
1101 } else if (properties.GetClipBounds() != nullptr) {
1102 canvas.ClipPath(properties.GetClipBounds()->GetDrawingPath(), Drawing::ClipOp::INTERSECT, true);
1103 } else { // we always do clip for DrawFilter, even if ClipToBounds is false
1104 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, true);
1105 }
1106
1107 auto filter = std::static_pointer_cast<RSDrawingFilter>(RSFilter);
1108 filter->SetGreyCoef(properties.GetGreyCoef1(), properties.GetGreyCoef2(), properties.IsGreyAdjustmentValid());
1109 auto surface = canvas.GetSurface();
1110 if (surface == nullptr) {
1111 ROSEN_LOGD("RSPropertiesPainter::DrawFilter surface null");
1112 Drawing::Brush brush = filter->GetBrush();
1113 Drawing::SaveLayerOps slr(nullptr, &brush, Drawing::SaveLayerOps::Flags::INIT_WITH_PREVIOUS);
1114 canvas.SaveLayer(slr);
1115 filter->PostProcess(canvas);
1116 return;
1117 }
1118 #endif
1119
1120 // for foreground filter, when do online opacity, rendering result already applied opacity,
1121 // so drawImage should not apply opacity again
1122 RSAutoCanvasRestore autoCanvasRestore(&canvas,
1123 filterType == FilterType::FOREGROUND_FILTER ? RSPaintFilterCanvas::kAlpha : RSPaintFilterCanvas::kNone);
1124 if (filterType == FilterType::FOREGROUND_FILTER) {
1125 canvas.SetAlpha(1.0);
1126 }
1127
1128 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
1129 // Optional use cacheManager to draw filter
1130 if (auto& cacheManager = properties.GetFilterCacheManager(filterType == FilterType::FOREGROUND_FILTER);
1131 cacheManager != nullptr && !canvas.GetDisableFilterCache()) {
1132 if (filter->GetFilterType() == RSFilter::LINEAR_GRADIENT_BLUR) {
1133 filter->SetBoundsGeometry(properties.GetFrameWidth(), properties.GetFrameHeight());
1134 }
1135 cacheManager->DrawFilter(canvas, filter, needSnapshotOutset);
1136 return;
1137 }
1138 #endif
1139
1140 #ifndef USE_ROSEN_DRAWING
1141 auto clipIBounds = canvas.getDeviceClipBounds();
1142 auto imageSnapshot = skSurface->makeImageSnapshot(
1143 needSnapshotOutset ? clipIBounds.makeOutset(-1, -1) : clipIBounds);
1144 #else
1145 auto clipIBounds = canvas.GetDeviceClipBounds();
1146 auto imageClipIBounds = clipIBounds;
1147 if (needSnapshotOutset) {
1148 imageClipIBounds.MakeOutset(-1, -1);
1149 }
1150 auto imageSnapshot = surface->GetImageSnapshot(imageClipIBounds);
1151 #endif
1152 if (imageSnapshot == nullptr) {
1153 ROSEN_LOGE("RSPropertiesPainter::DrawFilter image null");
1154 return;
1155 }
1156 #ifndef USE_ROSEN_DRAWING
1157 if (RSSystemProperties::GetImageGpuResourceCacheEnable(imageSnapshot->width(), imageSnapshot->height())) {
1158 ROSEN_LOGD("DrawFilter cache image resource(width:%{public}d, height:%{public}d).",
1159 imageSnapshot->width(), imageSnapshot->height());
1160 as_IB(imageSnapshot)->hintCacheGpuResource();
1161 #else
1162 if (RSSystemProperties::GetImageGpuResourceCacheEnable(imageSnapshot->GetWidth(), imageSnapshot->GetHeight())) {
1163 ROSEN_LOGD("DrawFilter cache image resource(width:%{public}d, height:%{public}d).",
1164 imageSnapshot->GetWidth(), imageSnapshot->GetHeight());
1165 as_IB(imageSnapshot->ExportSkImage().get())->hintCacheGpuResource();
1166 #endif
1167 }
1168
1169 filter->PreProcess(imageSnapshot);
1170 #ifndef USE_ROSEN_DRAWING
1171 if (filter->GetFilterType() == RSFilter::LINEAR_GRADIENT_BLUR) {
1172 SkMatrix mat = canvas.getTotalMatrix();
1173 filter->SetCanvasChange(mat, skSurface->width(), skSurface->height());
1174 filter->SetBoundsGeometry(properties.GetFrameWidth(), properties.GetFrameHeight());
1175 }
1176
1177 canvas.resetMatrix();
1178 auto visibleIRect = canvas.GetVisibleRect().round();
1179 if (!visibleIRect.isEmpty()) {
1180 canvas.clipIRect(visibleIRect);
1181 }
1182 filter->DrawImageRect(
1183 canvas, imageSnapshot, SkRect::Make(imageSnapshot->bounds()), SkRect::Make(clipIBounds));
1184 #else
1185 if (filter->GetFilterType() == RSFilter::LINEAR_GRADIENT_BLUR) {
1186 Drawing::Matrix mat = canvas.GetTotalMatrix();
1187 filter->SetCanvasChange(mat, surface->Width(), surface->Height());
1188 filter->SetBoundsGeometry(properties.GetFrameWidth(), properties.GetFrameHeight());
1189 }
1190
1191 canvas.ResetMatrix();
1192 auto visibleRect = canvas.GetVisibleRect();
1193 visibleRect.Round();
1194 auto visibleIRect = Drawing::RectI(
1195 static_cast<int>(visibleRect.GetLeft()), static_cast<int>(visibleRect.GetTop()),
1196 static_cast<int>(visibleRect.GetRight()), static_cast<int>(visibleRect.GetBottom()));
1197 if (!visibleIRect.IsEmpty()) {
1198 canvas.ClipIRect(visibleIRect, Drawing::ClipOp::INTERSECT);
1199 }
1200 Drawing::Rect srcRect = Drawing::Rect(0, 0, imageSnapshot->GetWidth(), imageSnapshot->GetHeight());
1201 Drawing::Rect dstRect = clipIBounds;
1202 filter->DrawImageRect(canvas, imageSnapshot, srcRect, dstRect);
1203 #endif
1204 filter->PostProcess(canvas);
1205 }
1206
1207 void RSPropertiesPainter::DrawBackgroundImageAsEffect(const RSProperties& properties, RSPaintFilterCanvas& canvas)
1208 {
1209 RS_TRACE_FUNC();
1210 auto boundsRect = properties.GetBoundsRect();
1211
1212 // Optional use cacheManager to draw filter, cache is valid, skip drawing background image
1213 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
1214 if (auto& cacheManager = properties.GetFilterCacheManager(false);
1215 cacheManager != nullptr && !canvas.GetDisableFilterCache() && cacheManager->IsCacheValid()) {
1216 // no need to validate parameters, the caller already do it
1217 #ifndef USE_ROSEN_DRAWING
1218 canvas.clipRect(RSPropertiesPainter::Rect2SkRect(boundsRect));
1219 auto filter = std::static_pointer_cast<RSSkiaFilter>(properties.GetBackgroundFilter());
1220 #else
1221 canvas.ClipRect(RSPropertiesPainter::Rect2DrawingRect(boundsRect));
1222 auto filter = std::static_pointer_cast<RSDrawingFilter>(properties.GetBackgroundFilter());
1223 #endif
1224 // extract cache data from cacheManager
1225 auto&& data = cacheManager->GeneratedCachedEffectData(canvas, filter);
1226 canvas.SetEffectData(data);
1227 return;
1228 }
1229 #endif
1230
1231 auto surface = canvas.GetSurface();
1232 if (!surface) {
1233 ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundImageAsEffect surface null");
1234 return;
1235 }
1236 // create offscreen surface with same size as current surface (PLANNING: use bounds size instead)
1237 #ifndef USE_ROSEN_DRAWING
1238 auto offscreenSurface = surface->makeSurface(surface->width(), surface->height());
1239 #else
1240 auto offscreenSurface = surface->MakeSurface(canvas.GetWidth(), canvas.GetHeight());
1241 #endif
1242 auto offscreenCanvas = std::make_shared<RSPaintFilterCanvas>(offscreenSurface.get());
1243 // copy matrix and other properties to offscreen canvas
1244 #ifndef USE_ROSEN_DRAWING
1245 offscreenCanvas->setMatrix(canvas.getTotalMatrix());
1246 #else
1247 offscreenCanvas->SetMatrix(canvas.GetTotalMatrix());
1248 #endif
1249 offscreenCanvas->CopyConfiguration(canvas);
1250 // draw background onto offscreen canvas
1251 RSPropertiesPainter::DrawBackground(properties, *offscreenCanvas);
1252 // generate effect data
1253 RSPropertiesPainter::DrawBackgroundEffect(properties, *offscreenCanvas);
1254 // extract effect data from offscreen canvas and set to canvas
1255 canvas.SetEffectData(offscreenCanvas->GetEffectData());
1256 }
1257
1258 void RSPropertiesPainter::DrawBackgroundEffect(
1259 const RSProperties& properties, RSPaintFilterCanvas& canvas)
1260 {
1261 auto& RSFilter = properties.GetBackgroundFilter();
1262 if (RSFilter == nullptr) {
1263 return;
1264 }
1265 g_blurCnt++;
1266 RS_TRACE_NAME("DrawBackgroundEffect " + RSFilter->GetDescription());
1267 auto surface = canvas.GetSurface();
1268 if (surface == nullptr) {
1269 ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundEffect surface null");
1270 return;
1271 }
1272
1273 #ifndef USE_ROSEN_DRAWING
1274 canvas.save();
1275 canvas.clipRect(Rect2SkRect(properties.GetBoundsRect()));
1276 auto bounds = canvas.getDeviceClipBounds();
1277 canvas.restore();
1278 auto filter = std::static_pointer_cast<RSSkiaFilter>(RSFilter);
1279 #else
1280 canvas.Save();
1281 canvas.ClipRect(Rect2DrawingRect(properties.GetBoundsRect()));
1282 auto bounds = canvas.GetDeviceClipBounds();
1283 canvas.Restore();
1284 auto filter = std::static_pointer_cast<RSDrawingFilter>(RSFilter);
1285 #endif
1286
1287 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
1288 // Optional use cacheManager to draw filter
1289 if (auto& cacheManager = properties.GetFilterCacheManager(false);
1290 cacheManager != nullptr && !canvas.GetDisableFilterCache()) {
1291 auto node = properties.backref_.lock();
1292 if (node == nullptr) {
1293 ROSEN_LOGE("DrawBackgroundEffect::node is null");
1294 return;
1295 }
1296 auto effectNode = node->ReinterpretCastTo<RSEffectRenderNode>();
1297 if (effectNode == nullptr) {
1298 ROSEN_LOGE("DrawBackgroundEffect::node reinterpret cast failed.");
1299 return;
1300 }
1301 // node is freeze or screen rotating, force cache filterred snapshot.
1302 auto forceCacheFlags = std::make_tuple(false, effectNode->GetRotationChanged());
1303 auto&& data = cacheManager->GeneratedCachedEffectData(canvas, filter, bounds, bounds, forceCacheFlags);
1304 canvas.SetEffectData(data);
1305 return;
1306 }
1307 #endif
1308
1309 auto imageRect = bounds;
1310 #ifndef USE_ROSEN_DRAWING
1311 auto imageSnapshot = surface->makeImageSnapshot(imageRect);
1312 #else
1313 auto imageSnapshot = surface->GetImageSnapshot(imageRect);
1314 #endif
1315 if (imageSnapshot == nullptr) {
1316 ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundEffect image snapshot null");
1317 return;
1318 }
1319
1320 filter->PreProcess(imageSnapshot);
1321 // create a offscreen skSurface
1322 #ifndef USE_ROSEN_DRAWING
1323 sk_sp<SkSurface> offscreenSurface = surface->makeSurface(imageSnapshot->imageInfo());
1324 if (offscreenSurface == nullptr) {
1325 ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundEffect offscreenSurface null");
1326 return;
1327 }
1328 RSPaintFilterCanvas offscreenCanvas(offscreenSurface.get());
1329 auto clipBounds = SkRect::MakeIWH(imageRect.width(), imageRect.height());
1330 filter->DrawImageRect(offscreenCanvas, imageSnapshot, SkRect::Make(imageSnapshot->bounds()), clipBounds);
1331 filter->PostProcess(offscreenCanvas);
1332
1333 auto imageCache = offscreenSurface->makeImageSnapshot();
1334 #else
1335 std::shared_ptr<Drawing::Surface> offscreenSurface =
1336 surface->MakeSurface(imageSnapshot->GetWidth(), imageSnapshot->GetHeight());
1337 if (offscreenSurface == nullptr) {
1338 ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundEffect offscreenSurface null");
1339 return;
1340 }
1341 RSPaintFilterCanvas offscreenCanvas(offscreenSurface.get());
1342 auto clipBounds = Drawing::Rect(0, 0, imageRect.GetWidth(), imageRect.GetHeight());
1343 auto imageSnapshotBounds = Drawing::Rect(0, 0, imageSnapshot->GetWidth(), imageSnapshot->GetHeight());
1344 filter->DrawImageRect(offscreenCanvas, imageSnapshot, imageSnapshotBounds, clipBounds);
1345 filter->PostProcess(offscreenCanvas);
1346
1347 auto imageCache = offscreenSurface->GetImageSnapshot();
1348 #endif
1349 if (imageCache == nullptr) {
1350 ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundEffect imageCache snapshot null");
1351 return;
1352 }
1353 auto data = std::make_shared<RSPaintFilterCanvas::CachedEffectData>(std::move(imageCache), std::move(imageRect));
1354 canvas.SetEffectData(std::move(data));
1355 }
1356
1357 void RSPropertiesPainter::ApplyBackgroundEffectFallback(const RSProperties& properties, RSPaintFilterCanvas& canvas)
1358 {
1359 RS_TRACE_FUNC();
1360 auto parentNode = properties.backref_.lock();
1361 while (parentNode && !parentNode->IsInstanceOf<RSEffectRenderNode>()) {
1362 parentNode = parentNode->GetParent().lock();
1363 }
1364 if (!parentNode) {
1365 ROSEN_LOGD("RSPropertiesPainter::ApplyBackgroundEffectFallback: parentNode null, draw filter failed.");
1366 return;
1367 }
1368 auto& filter = parentNode->GetRenderProperties().GetBackgroundFilter();
1369 if (filter == nullptr || !filter->IsValid()) {
1370 ROSEN_LOGD("RSPropertiesPainter::ApplyBackgroundEffectFallback: parent EffectRenderNode has no filter, "
1371 "draw filter failed.");
1372 return;
1373 }
1374 DrawFilter(properties, canvas, FilterType::BACKGROUND_FILTER, std::nullopt, filter);
1375 }
1376
1377 void RSPropertiesPainter::ClipVisibleCanvas(const RSProperties& properties, RSPaintFilterCanvas& canvas)
1378 {
1379 #ifndef USE_ROSEN_DRAWING
1380 if (RSSystemProperties::GetPropertyDrawableEnable()) {
1381 // do nothing
1382 } else if (properties.GetClipBounds() != nullptr) {
1383 canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
1384 } else { // we always do clip for ApplyBackgroundEffect, even if ClipToBounds is false
1385 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
1386 }
1387 canvas.resetMatrix();
1388 auto visibleIRect = canvas.GetVisibleRect().round();
1389 if (!visibleIRect.isEmpty()) {
1390 canvas.clipIRect(visibleIRect);
1391 }
1392 #else
1393 if (RSSystemProperties::GetPropertyDrawableEnable()) {
1394 // do nothing
1395 } else if (properties.GetClipBounds() != nullptr) {
1396 canvas.ClipPath(properties.GetClipBounds()->GetDrawingPath(), Drawing::ClipOp::INTERSECT, true);
1397 } else { // we always do clip for ApplyBackgroundEffect, even if ClipToBounds is false
1398 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, true);
1399 }
1400 canvas.ResetMatrix();
1401 auto visibleRect = canvas.GetVisibleRect();
1402 visibleRect.Round();
1403 auto visibleIRect = Drawing::RectI(
1404 static_cast<int>(visibleRect.GetLeft()), static_cast<int>(visibleRect.GetTop()),
1405 static_cast<int>(visibleRect.GetRight()), static_cast<int>(visibleRect.GetBottom()));
1406 if (!visibleIRect.IsEmpty()) {
1407 canvas.ClipIRect(visibleIRect, Drawing::ClipOp::INTERSECT);
1408 }
1409 #endif
1410 }
1411
1412 void RSPropertiesPainter::ApplyBackgroundEffect(const RSProperties& properties, RSPaintFilterCanvas& canvas)
1413 {
1414 const auto& effectData = canvas.GetEffectData();
1415 if (effectData == nullptr || effectData->cachedImage_ == nullptr
1416 || !RSSystemProperties::GetEffectMergeEnabled()) {
1417 // no effectData available, draw background filter in fallback method
1418 ROSEN_LOGD("RSPropertiesPainter::ApplyBackgroundEffect: effectData null, try fallback method.");
1419 ApplyBackgroundEffectFallback(properties, canvas);
1420 return;
1421 }
1422 RS_TRACE_FUNC();
1423 #ifndef USE_ROSEN_DRAWING
1424 SkAutoCanvasRestore acr(&canvas, true);
1425 ClipVisibleCanvas(properties, canvas);
1426 SkPaint defaultPaint;
1427 // dstRect: canvas clip region
1428 auto dstRect = SkRect::Make(canvas.getDeviceClipBounds());
1429 // srcRect: map dstRect onto cache coordinate
1430 auto srcRect = dstRect.makeOffset(-effectData->cachedRect_.left(), -effectData->cachedRect_.top());
1431 canvas.drawImageRect(effectData->cachedImage_, srcRect, dstRect, SkSamplingOptions(), &defaultPaint,
1432 SkCanvas::kFast_SrcRectConstraint);
1433 #else
1434 Drawing::AutoCanvasRestore acr(canvas, true);
1435 ClipVisibleCanvas(properties, canvas);
1436 Drawing::Brush brush;
1437 canvas.AttachBrush(brush);
1438 // dstRect: canvas clip region
1439 Drawing::Rect dstRect = canvas.GetDeviceClipBounds();
1440 // srcRect: map dstRect onto cache coordinate
1441 Drawing::Rect srcRect = dstRect;
1442 srcRect.Offset(-effectData->cachedRect_.GetLeft(), -effectData->cachedRect_.GetTop());
1443 canvas.DrawImageRect(*effectData->cachedImage_, srcRect, dstRect,
1444 Drawing::SamplingOptions(), Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
1445 canvas.DetachBrush();
1446 #endif
1447 }
1448
1449 void RSPropertiesPainter::DrawPixelStretch(const RSProperties& properties, RSPaintFilterCanvas& canvas)
1450 {
1451 auto& pixelStretch = properties.GetPixelStretch();
1452 if (!pixelStretch.has_value()) {
1453 return;
1454 }
1455 #ifndef USE_ROSEN_DRAWING
1456 auto skSurface = canvas.GetSurface();
1457 if (skSurface == nullptr) {
1458 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch skSurface null");
1459 return;
1460 }
1461
1462 canvas.save();
1463 auto bounds = RSPropertiesPainter::Rect2SkRect(properties.GetBoundsRect());
1464 canvas.clipRect(bounds);
1465 auto clipBounds = canvas.getDeviceClipBounds();
1466 clipBounds.setXYWH(clipBounds.left(), clipBounds.top(), clipBounds.width() - 1, clipBounds.height() - 1);
1467 canvas.restore();
1468
1469 /* Calculates the relative coordinates of the clipbounds
1470 with respect to the origin of the current canvas coordinates */
1471 SkMatrix worldToLocalMat;
1472 if (!canvas.getTotalMatrix().invert(&worldToLocalMat)) {
1473 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch get invert matrix failed.");
1474 }
1475 SkRect localClipBounds;
1476 SkRect fClipBounds = SkRect::MakeXYWH(clipBounds.x(), clipBounds.y(), clipBounds.width(), clipBounds.height());
1477 if (!worldToLocalMat.mapRect(&localClipBounds, fClipBounds)) {
1478 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch map rect failed.");
1479 }
1480
1481 if (!bounds.intersect(localClipBounds)) {
1482 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch intersect clipbounds failed");
1483 }
1484
1485 auto scaledBounds = SkRect::MakeLTRB(bounds.left() - pixelStretch->x_, bounds.top() - pixelStretch->y_,
1486 bounds.right() + pixelStretch->z_, bounds.bottom() + pixelStretch->w_);
1487 if (scaledBounds.isEmpty() || bounds.isEmpty() || clipBounds.isEmpty()) {
1488 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch invalid scaled bounds");
1489 return;
1490 }
1491
1492 auto image = skSurface->makeImageSnapshot(clipBounds);
1493 if (image == nullptr) {
1494 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch image null");
1495 return;
1496 }
1497
1498 SkPaint paint;
1499 SkMatrix inverseMat, rotateMat;
1500 auto boundsGeo = (properties.GetBoundsGeometry());
1501 if (boundsGeo && !boundsGeo->IsEmpty()) {
1502 auto transMat = canvas.getTotalMatrix();
1503 /* transMat.getSkewY() is the sin of the rotation angle(sin0 = 0,sin90 =1 sin180 = 0,sin270 = -1),
1504 if transMat.getSkewY() is not 0 or -1 or 1,the rotation angle is not a multiple of 90,not Stretch*/
1505 if (ROSEN_EQ(transMat.getSkewY(), 0.f) || ROSEN_EQ(transMat.getSkewY(), 1.f) ||
1506 ROSEN_EQ(transMat.getSkewY(), -1.f)) {
1507 } else {
1508 ROSEN_LOGD("rotate degree is not 0 or 90 or 180 or 270,return.");
1509 return;
1510 }
1511 rotateMat.setScale(transMat.getScaleX(), transMat.getScaleY());
1512 rotateMat.setSkewX(transMat.getSkewX());
1513 rotateMat.setSkewY(transMat.getSkewY());
1514 rotateMat.preTranslate(-bounds.x(), -bounds.y());
1515 rotateMat.postTranslate(bounds.x(), bounds.y());
1516
1517 SkRect transBounds = rotateMat.mapRect(bounds);
1518
1519 rotateMat.setTranslateX(bounds.x() - transBounds.x());
1520 rotateMat.setTranslateY(bounds.y() - transBounds.y());
1521 if (!rotateMat.invert(&inverseMat)) {
1522 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch get invert matrix failed.");
1523 }
1524 }
1525
1526 canvas.save();
1527 canvas.translate(bounds.x(), bounds.y());
1528
1529 // NOTE: Ensure that EPS is consistent with rs_properties.cpp
1530 constexpr static float EPS = 1e-5f;
1531 if (pixelStretch->x_ > EPS || pixelStretch->y_ > EPS || pixelStretch->z_ > EPS || pixelStretch->w_ > EPS) {
1532 paint.setShader(image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions(), &inverseMat));
1533 canvas.drawRect(
1534 SkRect::MakeXYWH(-pixelStretch->x_, -pixelStretch->y_, scaledBounds.width(), scaledBounds.height()), paint);
1535 } else {
1536 inverseMat.postScale(scaledBounds.width() / bounds.width(), scaledBounds.height() / bounds.height());
1537 paint.setShader(image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions(), &inverseMat));
1538 canvas.translate(-pixelStretch->x_, -pixelStretch->y_);
1539 canvas.drawRect(SkRect::MakeXYWH(pixelStretch->x_, pixelStretch->y_, bounds.width(), bounds.height()), paint);
1540 }
1541 canvas.restore();
1542 }
1543 #else
1544 auto surface = canvas.GetSurface();
1545 if (surface == nullptr) {
1546 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch surface null");
1547 return;
1548 }
1549
1550 canvas.Save();
1551 auto bounds = RSPropertiesPainter::Rect2DrawingRect(properties.GetBoundsRect());
1552 canvas.ClipRect(bounds, Drawing::ClipOp::INTERSECT, false);
1553 auto tmpBounds = canvas.GetDeviceClipBounds();
1554 Drawing::Rect clipBounds(
1555 tmpBounds.GetLeft(), tmpBounds.GetTop(), tmpBounds.GetRight() - 1, tmpBounds.GetBottom() - 1);
1556 canvas.Restore();
1557
1558 /* Calculates the relative coordinates of the clipbounds
1559 with respect to the origin of the current canvas coordinates */
1560 Drawing::Matrix worldToLocalMat;
1561 if (!canvas.GetTotalMatrix().Invert(worldToLocalMat)) {
1562 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch get invert matrix failed.");
1563 }
1564 Drawing::Rect localClipBounds;
1565 Drawing::Rect fClipBounds(clipBounds.GetLeft(), clipBounds.GetTop(), clipBounds.GetRight(),
1566 clipBounds.GetBottom());
1567 if (!worldToLocalMat.MapRect(localClipBounds, fClipBounds)) {
1568 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch map rect failed.");
1569 }
1570
1571 if (!bounds.Intersect(localClipBounds)) {
1572 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch intersect clipbounds failed");
1573 }
1574
1575 auto scaledBounds = Drawing::Rect(bounds.GetLeft() - pixelStretch->x_, bounds.GetTop() - pixelStretch->y_,
1576 bounds.GetRight() + pixelStretch->z_, bounds.GetBottom() + pixelStretch->w_);
1577 if (!scaledBounds.IsValid() || !bounds.IsValid() || !clipBounds.IsValid()) {
1578 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch invalid scaled bounds");
1579 return;
1580 }
1581
1582 Drawing::RectI rectI(static_cast<int>(fClipBounds.GetLeft()), static_cast<int>(fClipBounds.GetTop()),
1583 static_cast<int>(fClipBounds.GetRight()), static_cast<int>(fClipBounds.GetBottom()));
1584 auto image = surface->GetImageSnapshot(rectI);
1585 if (image == nullptr) {
1586 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch image null");
1587 return;
1588 }
1589
1590 Drawing::Brush brush;
1591 Drawing::Matrix inverseMat, rotateMat;
1592 auto boundsGeo = (properties.GetBoundsGeometry());
1593 if (boundsGeo && !boundsGeo->IsEmpty()) {
1594 auto transMat = canvas.GetTotalMatrix();
1595 /* transMat.getSkewY() is the sin of the rotation angle(sin0 = 0,sin90 =1 sin180 = 0,sin270 = -1),
1596 if transMat.getSkewY() is not 0 or -1 or 1,the rotation angle is not a multiple of 90,not Stretch*/
1597 auto skewY = transMat.Get(Drawing::Matrix::SKEW_Y);
1598 if (ROSEN_EQ(skewY, 0.f) || ROSEN_EQ(skewY, 1.f) ||
1599 ROSEN_EQ(skewY, -1.f)) {
1600 } else {
1601 ROSEN_LOGD("rotate degree is not 0 or 90 or 180 or 270,return.");
1602 return;
1603 }
1604 rotateMat.SetScale(transMat.Get(Drawing::Matrix::SCALE_X), transMat.Get(Drawing::Matrix::SCALE_Y));
1605 rotateMat.Set(Drawing::Matrix::SKEW_X, transMat.Get(Drawing::Matrix::SKEW_X));
1606 rotateMat.Set(Drawing::Matrix::SKEW_Y, transMat.Get(Drawing::Matrix::SKEW_Y));
1607 rotateMat.PreTranslate(-bounds.GetLeft(), -bounds.GetTop());
1608 rotateMat.PostTranslate(bounds.GetLeft(), bounds.GetTop());
1609
1610 Drawing::Rect transBounds;
1611 rotateMat.MapRect(transBounds, bounds);
1612 rotateMat.Set(Drawing::Matrix::TRANS_X, bounds.GetLeft() - transBounds.GetLeft());
1613 rotateMat.Set(Drawing::Matrix::TRANS_Y, bounds.GetTop() - transBounds.GetTop());
1614 if (!rotateMat.Invert(inverseMat)) {
1615 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch get invert matrix failed.");
1616 }
1617 }
1618
1619 canvas.Save();
1620 canvas.Translate(bounds.GetLeft(), bounds.GetTop());
1621 Drawing::SamplingOptions samplingOptions;
1622 constexpr static float EPS = 1e-5f;
1623 if (pixelStretch->x_ > EPS || pixelStretch->y_ > EPS || pixelStretch->z_ > EPS || pixelStretch->w_ > EPS) {
1624 brush.SetShaderEffect(Drawing::ShaderEffect::CreateImageShader(
1625 *image, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, samplingOptions, inverseMat));
1626 canvas.AttachBrush(brush);
1627 canvas.DrawRect(Drawing::Rect(-pixelStretch->x_, -pixelStretch->y_,
1628 -pixelStretch->x_ + scaledBounds.GetWidth(), -pixelStretch->y_ + scaledBounds.GetHeight()));
1629 canvas.DetachBrush();
1630 } else {
1631 inverseMat.PostScale(scaledBounds.GetWidth() / bounds.GetWidth(), scaledBounds.GetHeight() / bounds.GetHeight());
1632 brush.SetShaderEffect(Drawing::ShaderEffect::CreateImageShader(
1633 *image, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, samplingOptions, inverseMat));
1634
1635 canvas.Translate(-pixelStretch->x_, -pixelStretch->y_);
1636 canvas.AttachBrush(brush);
1637 canvas.DrawRect(Drawing::Rect(pixelStretch->x_, pixelStretch->y_,
1638 pixelStretch->x_ + bounds.GetWidth(), pixelStretch->y_ + bounds.GetHeight()));
1639 canvas.DetachBrush();
1640 }
1641 canvas.Restore();
1642 }
1643 #endif
1644
1645 #ifndef USE_ROSEN_DRAWING
CalcAverageColor(sk_sp<SkImage> imageSnapshot)1646 SkColor RSPropertiesPainter::CalcAverageColor(sk_sp<SkImage> imageSnapshot)
1647 {
1648 // create a 1x1 SkPixmap
1649 uint32_t pixel[1] = { 0 };
1650 auto single_pixel_info = SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
1651 SkPixmap single_pixel(single_pixel_info, pixel, single_pixel_info.bytesPerPixel());
1652
1653 // resize snapshot to 1x1 to calculate average color
1654 // kMedium_SkFilterQuality will do bilerp + mipmaps for down-scaling, we can easily get average color
1655 imageSnapshot->scalePixels(single_pixel, SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear));
1656 // convert color format and return average color
1657 return SkColor4f::FromBytes_RGBA(pixel[0]).toSkColor();
1658 }
1659 #else
CalcAverageColor(std::shared_ptr<Drawing::Image> imageSnapshot)1660 Drawing::ColorQuad RSPropertiesPainter::CalcAverageColor(std::shared_ptr<Drawing::Image> imageSnapshot)
1661 {
1662 // create a 1x1 SkPixmap
1663 uint32_t pixel[1] = { 0 };
1664 auto single_pixel_info = SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
1665 SkPixmap single_pixel(single_pixel_info, pixel, single_pixel_info.bytesPerPixel());
1666
1667 // resize snapshot to 1x1 to calculate average color
1668 // kMedium_SkFilterQuality will do bilerp + mipmaps for down-scaling, we can easily get average color
1669 imageSnapshot->ExportSkImage()->scalePixels(
1670 single_pixel, SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear));
1671 // convert color format and return average color
1672 return SkColor4f::FromBytes_RGBA(pixel[0]).toSkColor();
1673 }
1674 #endif
1675
GetAndResetBlurCnt()1676 int RSPropertiesPainter::GetAndResetBlurCnt()
1677 {
1678 auto blurCnt = g_blurCnt;
1679 g_blurCnt = 0;
1680 return blurCnt;
1681 }
1682
DrawBackground(const RSProperties & properties,RSPaintFilterCanvas & canvas,bool isAntiAlias,bool isSurfaceView)1683 void RSPropertiesPainter::DrawBackground(const RSProperties& properties, RSPaintFilterCanvas& canvas,
1684 bool isAntiAlias, bool isSurfaceView)
1685 {
1686 // only disable antialias when background is rect and g_forceBgAntiAlias is false
1687 bool antiAlias = g_forceBgAntiAlias || !properties.GetCornerRadius().IsZero();
1688 // clip
1689 #ifndef USE_ROSEN_DRAWING
1690 if (properties.GetClipBounds() != nullptr) {
1691 canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), antiAlias);
1692 } else if (properties.GetClipToBounds()) {
1693 // In NEW_SKIA version, L476 code will cause crash if the second parameter is true.
1694 // so isAntiAlias is false only the method is called in ProcessAnimatePropertyBeforeChildren().
1695 if (properties.GetCornerRadius().IsZero()) {
1696 canvas.clipRect(Rect2SkRect(properties.GetBoundsRect()), isAntiAlias);
1697 } else {
1698 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), antiAlias);
1699 }
1700 } else if (properties.GetClipToRRect()) {
1701 canvas.clipRRect(RRect2SkRRect(properties.GetClipRRect()), antiAlias);
1702 }
1703 // paint backgroundColor
1704 SkPaint paint;
1705 paint.setAntiAlias(antiAlias);
1706 auto bgColor = properties.GetBackgroundColor();
1707 if (bgColor != RgbPalette::Transparent() && !isSurfaceView) {
1708 paint.setColor(bgColor.AsArgbInt());
1709 canvas.drawRRect(RRect2SkRRect(properties.GetInnerRRect()), paint);
1710 }
1711 if (const auto& bgShader = properties.GetBackgroundShader()) {
1712 SkAutoCanvasRestore acr(&canvas, true);
1713 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), antiAlias);
1714 paint.setShader(bgShader->GetSkShader());
1715 canvas.drawPaint(paint);
1716 }
1717 if (const auto& bgImage = properties.GetBgImage()) {
1718 SkAutoCanvasRestore acr(&canvas, true);
1719 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), antiAlias);
1720 auto boundsRect = Rect2SkRect(properties.GetBoundsRect());
1721 bgImage->SetDstRect(properties.GetBgImageRect());
1722 bgImage->CanvasDrawImage(canvas, boundsRect, SkSamplingOptions(), paint, true);
1723 }
1724 #else
1725 if (properties.GetClipBounds() != nullptr) {
1726 auto& path = properties.GetClipBounds()->GetDrawingPath();
1727 canvas.ClipPath(path, Drawing::ClipOp::INTERSECT, antiAlias);
1728 } else if (properties.GetClipToBounds()) {
1729 if (properties.GetCornerRadius().IsZero()) {
1730 canvas.ClipRect(Rect2DrawingRect(properties.GetBoundsRect()), Drawing::ClipOp::INTERSECT, isAntiAlias);
1731 } else {
1732 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, antiAlias);
1733 }
1734 } else if (properties.GetClipToRRect()) {
1735 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetClipRRect()), Drawing::ClipOp::INTERSECT, antiAlias);
1736 }
1737 // paint backgroundColor
1738 Drawing::Brush brush;
1739 brush.SetAntiAlias(antiAlias);
1740 auto bgColor = properties.GetBackgroundColor();
1741 if (bgColor != RgbPalette::Transparent() && !isSurfaceView) {
1742 brush.SetColor(Drawing::Color(bgColor.AsArgbInt()));
1743 canvas.AttachBrush(brush);
1744 canvas.DrawRoundRect(RRect2DrawingRRect(properties.GetRRect()));
1745 canvas.DetachBrush();
1746 }
1747 if (const auto& bgShader = properties.GetBackgroundShader()) {
1748 Drawing::AutoCanvasRestore acr(canvas, true);
1749 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, antiAlias);
1750 auto shaderEffect = bgShader->GetDrawingShader();
1751 brush.SetShaderEffect(shaderEffect);
1752 canvas.DrawBackground(brush);
1753 }
1754 if (const auto& bgImage = properties.GetBgImage()) {
1755 Drawing::AutoCanvasRestore acr(canvas, true);
1756 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, antiAlias);
1757 auto boundsRect = Rect2DrawingRect(properties.GetBoundsRect());
1758 bgImage->SetDstRect(properties.GetBgImageRect());
1759 canvas.AttachBrush(brush);
1760 bgImage->CanvasDrawImage(canvas, boundsRect, Drawing::SamplingOptions(), true);
1761 canvas.DetachBrush();
1762 }
1763 #endif
1764 }
1765
SetBgAntiAlias(bool forceBgAntiAlias)1766 void RSPropertiesPainter::SetBgAntiAlias(bool forceBgAntiAlias)
1767 {
1768 g_forceBgAntiAlias = forceBgAntiAlias;
1769 }
1770
GetBgAntiAlias()1771 bool RSPropertiesPainter::GetBgAntiAlias()
1772 {
1773 return g_forceBgAntiAlias;
1774 }
1775
1776 #ifndef USE_ROSEN_DRAWING
DrawFrame(const RSProperties & properties,RSPaintFilterCanvas & canvas,DrawCmdListPtr & cmds)1777 void RSPropertiesPainter::DrawFrame(const RSProperties& properties, RSPaintFilterCanvas& canvas, DrawCmdListPtr& cmds)
1778 {
1779 if (cmds == nullptr) {
1780 return;
1781 }
1782 SkMatrix mat;
1783 if (GetGravityMatrix(
1784 properties.GetFrameGravity(), properties.GetFrameRect(), cmds->GetWidth(), cmds->GetHeight(), mat)) {
1785 canvas.concat(mat);
1786 }
1787 auto frameRect = Rect2SkRect(properties.GetFrameRect());
1788 cmds->Playback(canvas, &frameRect);
1789 }
1790 #else
DrawFrame(const RSProperties & properties,RSPaintFilterCanvas & canvas,Drawing::DrawCmdListPtr & cmds)1791 void RSPropertiesPainter::DrawFrame(
1792 const RSProperties& properties, RSPaintFilterCanvas& canvas, Drawing::DrawCmdListPtr& cmds)
1793 {
1794 if (cmds == nullptr) {
1795 return;
1796 }
1797 Drawing::Matrix mat;
1798 if (GetGravityMatrix(
1799 properties.GetFrameGravity(), properties.GetFrameRect(), cmds->GetWidth(), cmds->GetHeight(), mat)) {
1800 canvas.ConcatMatrix(mat);
1801 }
1802 auto frameRect = Rect2DrawingRect(properties.GetFrameRect());
1803 cmds->Playback(canvas, &frameRect);
1804 }
1805 #endif
1806
GetRRectForDrawingBorder(const RSProperties & properties,const std::shared_ptr<RSBorder> & border,const bool & isOutline)1807 RRect RSPropertiesPainter::GetRRectForDrawingBorder(const RSProperties& properties,
1808 const std::shared_ptr<RSBorder>& border, const bool& isOutline)
1809 {
1810 if (!border) {
1811 return RRect();
1812 }
1813
1814 return isOutline ?
1815 RRect(properties.GetRRect().rect_.MakeOutset(border->GetWidthFour()), border->GetRadiusFour()) :
1816 properties.GetRRect();
1817 }
1818
GetInnerRRectForDrawingBorder(const RSProperties & properties,const std::shared_ptr<RSBorder> & border,const bool & isOutline)1819 RRect RSPropertiesPainter::GetInnerRRectForDrawingBorder(const RSProperties& properties,
1820 const std::shared_ptr<RSBorder>& border, const bool& isOutline)
1821 {
1822 if (!border) {
1823 return RRect();
1824 }
1825 return isOutline ? properties.GetRRect() : properties.GetInnerRRect();
1826 }
1827
1828 #ifndef USE_ROSEN_DRAWING
1829 static std::shared_ptr<SkRuntimeShaderBuilder> phongShaderBuilder;
1830
GetPhongShaderBuilder()1831 const std::shared_ptr<SkRuntimeShaderBuilder>& RSPropertiesPainter::GetPhongShaderBuilder()
1832 {
1833 if (phongShaderBuilder) {
1834 return phongShaderBuilder;
1835 }
1836 sk_sp<SkRuntimeEffect> lightEffect_;
1837 SkString lightString(R"(
1838 uniform mat4 lightPos;
1839 uniform mat4 viewPos;
1840 uniform vec4 specularStrength;
1841
1842 half4 main(float2 fragCoord) {
1843 vec3 lightColor = vec3(1.0, 1.0, 1.0);
1844 float ambientStrength = 0.0;
1845 vec3 diffuseColor = vec3(1.0, 1.0, 1.0);
1846 float diffuseStrength = 0.0;
1847 vec3 specularColor = vec3(1.0, 1.0, 1.0);
1848 float shininess = 8.0;
1849 half4 fragColor;
1850 vec4 NormalMap = vec4(0.0, 0.0, 1.0, 0.0);
1851 // ambient
1852 vec4 ambient = lightColor.rgb1 * ambientStrength;
1853 vec3 norm = normalize(NormalMap.rgb);
1854
1855 for (int i = 0; i < 4; i++) {
1856 if (abs(specularStrength[i]) > 0.01) {
1857 vec3 lightDir = normalize(vec3(lightPos[i].xy - fragCoord, lightPos[i].z));
1858 float diff = max(dot(norm, lightDir), 0.0);
1859 vec4 diffuse = diff * lightColor.rgb1;
1860 vec3 viewDir = normalize(vec3(viewPos[i].xy - fragCoord, viewPos[i].z)); // view vector
1861 vec3 halfwayDir = normalize(lightDir + viewDir); // half vector
1862 float spec = pow(max(dot(norm, halfwayDir), 0.0), shininess); // exponential relationship of angle
1863 vec4 specular = lightColor.rgb1 * spec; // multiply color of incident light
1864 vec4 o = ambient + diffuse * diffuseStrength * diffuseColor.rgb1; // diffuse reflection
1865 fragColor = fragColor + o + specular * specularStrength[i] * specularColor.rgb1;
1866 }
1867 }
1868 return half4(fragColor);
1869 }
1870 )");
1871 auto [lightEffect, error] = SkRuntimeEffect::MakeForShader(lightString);
1872 if (!lightEffect) {
1873 ROSEN_LOGE("light effect errro: %{public}s", error.c_str());
1874 return phongShaderBuilder;
1875 }
1876 lightEffect_ = std::move(lightEffect);
1877 phongShaderBuilder = std::make_shared<SkRuntimeShaderBuilder>(lightEffect_);
1878 return phongShaderBuilder;
1879 }
1880 #else
1881 static std::shared_ptr<Drawing::RuntimeShaderBuilder> phongShaderBuilder = nullptr;
1882
GetPhongShaderBuilder()1883 const std::shared_ptr<Drawing::RuntimeShaderBuilder>& RSPropertiesPainter::GetPhongShaderBuilder()
1884 {
1885 if (phongShaderBuilder) {
1886 return phongShaderBuilder;
1887 }
1888 std::shared_ptr<Drawing::RuntimeEffect> lightEffect_;
1889 std::string lightString(R"(
1890 uniform mat4 lightPos;
1891 uniform mat4 viewPos;
1892 uniform vec4 specularStrength;
1893
1894 half4 main(float2 fragCoord) {
1895 vec3 lightColor = vec3(1.0, 1.0, 1.0);
1896 float ambientStrength = 0.0;
1897 vec3 diffuseColor = vec3(1.0, 1.0, 1.0);
1898 float diffuseStrength = 0.0;
1899 vec3 specularColor = vec3(1.0, 1.0, 1.0);
1900 float shininess = 8.0;
1901 half4 fragColor;
1902 vec4 NormalMap = vec4(0.0, 0.0, 1.0, 0.0);
1903 // ambient
1904 vec4 ambient = lightColor.rgb1 * ambientStrength;
1905 vec3 norm = normalize(NormalMap.rgb);
1906
1907 for (int i = 0; i < 4; i++) {
1908 if (abs(specularStrength[i]) > 0.01) {
1909 vec3 lightDir = normalize(vec3(lightPos[i].xy - fragCoord, lightPos[i].z));
1910 float diff = max(dot(norm, lightDir), 0.0);
1911 vec4 diffuse = diff * lightColor.rgb1;
1912 vec3 viewDir = normalize(vec3(viewPos[i].xy - fragCoord, viewPos[i].z)); // view vector
1913 vec3 halfwayDir = normalize(lightDir + viewDir); // half vector
1914 float spec = pow(max(dot(norm, halfwayDir), 0.0), shininess); // exponential relationship of angle
1915 vec4 specular = lightColor.rgb1 * spec; // multiply color of incident light
1916 vec4 o = ambient + diffuse * diffuseStrength * diffuseColor.rgb1; // diffuse reflection
1917 fragColor = fragColor + o + specular * specularStrength[i] * specularColor.rgb1;
1918 }
1919 }
1920 return half4(fragColor);
1921 }
1922 )");
1923 std::shared_ptr<Drawing::RuntimeEffect> lightEffect = Drawing::RuntimeEffect::CreateForShader(lightString);
1924 if (!lightEffect) {
1925 ROSEN_LOGE("light effect error");
1926 return phongShaderBuilder;
1927 }
1928 lightEffect_ = std::move(lightEffect);
1929 phongShaderBuilder = std::make_shared<Drawing::RuntimeShaderBuilder>(lightEffect_);
1930 return phongShaderBuilder;
1931 }
1932 #endif
1933
1934 #ifndef USE_ROSEN_DRAWING
DrawLight(const RSProperties & properties,SkCanvas & canvas)1935 void RSPropertiesPainter::DrawLight(const RSProperties& properties, SkCanvas& canvas)
1936 #else
1937 void RSPropertiesPainter::DrawLight(const RSProperties& properties, Drawing::Canvas& canvas)
1938 #endif
1939 {
1940 auto lightBuilder = GetPhongShaderBuilder();
1941 if (!lightBuilder) {
1942 return;
1943 }
1944 const auto& lightSources = properties.GetIlluminated()->GetLightSources();
1945 if (lightSources.empty()) {
1946 ROSEN_LOGD("RSPropertiesPainter::DrawLight lightSourceList is empty!");
1947 return;
1948 }
1949 const auto& geoPtr = (properties.GetBoundsGeometry());
1950 if (!geoPtr || geoPtr->IsEmpty()) {
1951 return;
1952 }
1953 DrawLightInner(properties, canvas, lightBuilder, lightSources, geoPtr);
1954 }
1955
1956 #ifndef USE_ROSEN_DRAWING
DrawLightInner(const RSProperties & properties,SkCanvas & canvas,std::shared_ptr<SkRuntimeShaderBuilder> & lightBuilder,const std::unordered_set<std::shared_ptr<RSLightSource>> & lightSources,const std::shared_ptr<RSObjAbsGeometry> & geoPtr)1957 void RSPropertiesPainter::DrawLightInner(const RSProperties& properties, SkCanvas& canvas,
1958 std::shared_ptr<SkRuntimeShaderBuilder>& lightBuilder,
1959 const std::unordered_set<std::shared_ptr<RSLightSource>>& lightSources,
1960 const std::shared_ptr<RSObjAbsGeometry>& geoPtr)
1961 {
1962 auto iter = lightSources.begin();
1963 auto cnt = 0;
1964 SkM44 lightPositionMatrix;
1965 SkM44 viewPosMatrix;
1966 SkV4 lightIntensityV4;
1967 constexpr int MAX_LIGHT_SOUCES = 4;
1968 while (iter != lightSources.end() && cnt < MAX_LIGHT_SOUCES) {
1969 auto lightPos = RSPointLightManager::Instance()->CalculateLightPosForIlluminated((*iter), geoPtr);
1970 auto lightIntensity = (*iter)->GetLightIntensity();
1971 auto lightPositionV4 = SkV4 { lightPos.x_, lightPos.y_, lightPos.z_, lightPos.w_ };
1972 auto viewPosV4 = SkV4 { lightPos.x_, lightPos.y_, lightPos.z_, lightPos.w_ };
1973 lightIntensityV4[cnt] = lightIntensity;
1974 lightPositionMatrix.setCol(cnt, lightPositionV4);
1975 viewPosMatrix.setCol(cnt, viewPosV4);
1976 iter++;
1977 cnt++;
1978 }
1979 lightBuilder->uniform("lightPos") = lightPositionMatrix;
1980 lightBuilder->uniform("viewPos") = viewPosMatrix;
1981 SkPaint paint;
1982 paint.setAntiAlias(true);
1983 auto illuminatedType = properties.GetIlluminated()->GetIlluminatedType();
1984 ROSEN_LOGD("RSPropertiesPainter::DrawLight illuminatedType:%{public}d", illuminatedType);
1985 if (illuminatedType == IlluminatedType::CONTENT) {
1986 DrawContentLight(properties, canvas, lightBuilder, paint, lightIntensityV4);
1987 } else if (illuminatedType == IlluminatedType::BORDER) {
1988 DrawBorderLight(properties, canvas, lightBuilder, paint, lightIntensityV4);
1989 } else if (illuminatedType == IlluminatedType::BORDER_CONTENT) {
1990 DrawContentLight(properties, canvas, lightBuilder, paint, lightIntensityV4);
1991 DrawBorderLight(properties, canvas, lightBuilder, paint, lightIntensityV4);
1992 }
1993 }
1994 #else
DrawLightInner(const RSProperties & properties,Drawing::Canvas & canvas,std::shared_ptr<Drawing::RuntimeShaderBuilder> & lightBuilder,const std::unordered_set<std::shared_ptr<RSLightSource>> & lightSources,const std::shared_ptr<RSObjAbsGeometry> & geoPtr)1995 void RSPropertiesPainter::DrawLightInner(const RSProperties& properties, Drawing::Canvas& canvas,
1996 std::shared_ptr<Drawing::RuntimeShaderBuilder>& lightBuilder,
1997 const std::unordered_set<std::shared_ptr<RSLightSource>>& lightSources,
1998 const std::shared_ptr<RSObjAbsGeometry>& geoPtr)
1999 {
2000 auto iter = lightSources.begin();
2001 auto cnt = 0;
2002 Drawing::Matrix44 lightPositionMatrix;
2003 Drawing::Matrix44 viewPosMatrix;
2004 Vector4f lightIntensityV4;
2005 constexpr int MAX_LIGHT_SOUCES = 4;
2006 while (iter != lightSources.end() && cnt < MAX_LIGHT_SOUCES) {
2007 auto lightPos = RSPointLightManager::Instance()->CalculateLightPosForIlluminated((*iter), geoPtr);
2008 auto lightIntensity = (*iter)->GetLightIntensity();
2009 lightIntensityV4[cnt] = lightIntensity;
2010 lightPositionMatrix.SetCol(cnt, lightPos.x_, lightPos.y_, lightPos.z_, lightPos.w_);
2011 viewPosMatrix.SetCol(cnt, lightPos.x_, lightPos.y_, lightPos.z_, lightPos.w_);
2012 iter++;
2013 cnt++;
2014 }
2015 lightBuilder->SetUniform("lightPos", lightPositionMatrix);
2016 lightBuilder->SetUniform("viewPos", viewPosMatrix);
2017 Drawing::Pen pen;
2018 Drawing::Brush brush;
2019 pen.SetAntiAlias(true);
2020 brush.SetAntiAlias(true);
2021 auto illuminatedType = properties.GetIlluminated()->GetIlluminatedType();
2022 ROSEN_LOGD("RSPropertiesPainter::DrawLight illuminatedType:%{public}d", illuminatedType);
2023 if (illuminatedType == IlluminatedType::CONTENT) {
2024 DrawContentLight(properties, canvas, lightBuilder, brush, lightIntensityV4);
2025 } else if (illuminatedType == IlluminatedType::BORDER) {
2026 DrawBorderLight(properties, canvas, lightBuilder, pen, lightIntensityV4);
2027 } else if (illuminatedType == IlluminatedType::BORDER_CONTENT) {
2028 DrawContentLight(properties, canvas, lightBuilder, brush, lightIntensityV4);
2029 DrawBorderLight(properties, canvas, lightBuilder, pen, lightIntensityV4);
2030 }
2031 }
2032 #endif
2033
2034 #ifndef USE_ROSEN_DRAWING
DrawContentLight(const RSProperties & properties,SkCanvas & canvas,std::shared_ptr<SkRuntimeShaderBuilder> & lightBuilder,SkPaint & paint,SkV4 & lightIntensity)2035 void RSPropertiesPainter::DrawContentLight(const RSProperties& properties, SkCanvas& canvas,
2036 std::shared_ptr<SkRuntimeShaderBuilder>& lightBuilder, SkPaint& paint, SkV4& lightIntensity)
2037 #else
2038 void RSPropertiesPainter::DrawContentLight(const RSProperties& properties, Drawing::Canvas& canvas,
2039 std::shared_ptr<Drawing::RuntimeShaderBuilder>& lightBuilder, Drawing::Brush& brush, Vector4f& lightIntensity)
2040 #endif
2041 {
2042 // content light
2043 #ifndef USE_ROSEN_DRAWING
2044 sk_sp<SkShader> shader;
2045 #else
2046 std::shared_ptr<Drawing::ShaderEffect> shader;
2047 #endif
2048 auto contentStrength = lightIntensity * 0.3f;
2049 #ifndef USE_ROSEN_DRAWING
2050 lightBuilder->uniform("specularStrength") = contentStrength;
2051 shader = lightBuilder->makeShader(nullptr, false);
2052 paint.setShader(shader);
2053 canvas.drawRRect(RRect2SkRRect(properties.GetRRect()), paint);
2054 #else
2055 lightBuilder->SetUniformVec4("specularStrength", contentStrength.x_,
2056 contentStrength.y_, contentStrength.z_, contentStrength.w_);
2057 shader = lightBuilder->MakeShader(nullptr, false);
2058 brush.SetShaderEffect(shader);
2059 canvas.AttachBrush(brush);
2060 canvas.DrawRoundRect(RRect2DrawingRRect(properties.GetRRect()));
2061 canvas.DetachBrush();
2062 #endif
2063 }
2064
2065 #ifndef USE_ROSEN_DRAWING
DrawBorderLight(const RSProperties & properties,SkCanvas & canvas,std::shared_ptr<SkRuntimeShaderBuilder> & lightBuilder,SkPaint & paint,SkV4 & lightIntensity)2066 void RSPropertiesPainter::DrawBorderLight(const RSProperties& properties, SkCanvas& canvas,
2067 std::shared_ptr<SkRuntimeShaderBuilder>& lightBuilder, SkPaint& paint, SkV4& lightIntensity)
2068 #else
2069 void RSPropertiesPainter::DrawBorderLight(const RSProperties& properties, Drawing::Canvas& canvas,
2070 std::shared_ptr<Drawing::RuntimeShaderBuilder>& lightBuilder, Drawing::Pen& pen, Vector4f& lightIntensity)
2071 #endif
2072 {
2073 // border light
2074 #ifndef USE_ROSEN_DRAWING
2075 sk_sp<SkShader> shader;
2076 #else
2077 std::shared_ptr<Drawing::ShaderEffect> shader;
2078 #endif
2079 #ifndef USE_ROSEN_DRAWING
2080 lightBuilder->uniform("specularStrength") = lightIntensity;
2081 shader = lightBuilder->makeShader(nullptr, false);
2082 paint.setShader(shader);
2083 float borderWidth = std::ceil(properties.GetIlluminatedBorderWidth());
2084 paint.setStrokeWidth(borderWidth);
2085 paint.setStyle(SkPaint::Style::kStroke_Style);
2086 #else
2087 lightBuilder->SetUniformVec4("specularStrength", lightIntensity.x_,
2088 lightIntensity.y_, lightIntensity.z_, lightIntensity.w_);
2089 shader = lightBuilder->MakeShader(nullptr, false);
2090 pen.SetShaderEffect(shader);
2091 float borderWidth = std::ceil(properties.GetIlluminatedBorderWidth());
2092 pen.SetWidth(borderWidth);
2093 #endif
2094 auto borderRect = properties.GetRRect().rect_;
2095 float borderRadius = properties.GetRRect().radius_[0].x_;
2096 auto borderRRect = RRect(RectF(borderRect.left_ + borderWidth / 2.0f, borderRect.top_ + borderWidth / 2.0f,
2097 borderRect.width_ - borderWidth, borderRect.height_ - borderWidth),
2098 borderRadius - borderWidth / 2.0f, borderRadius - borderWidth / 2.0f);
2099 #ifndef USE_ROSEN_DRAWING
2100 canvas.drawRRect(RRect2SkRRect(borderRRect), paint);
2101 #else
2102 canvas.AttachPen(pen);
2103 canvas.DrawRoundRect(RRect2DrawingRRect(borderRRect));
2104 canvas.DetachPen();
2105 #endif
2106 }
2107
2108 #ifndef USE_ROSEN_DRAWING
DrawBorderBase(const RSProperties & properties,SkCanvas & canvas,const std::shared_ptr<RSBorder> & border,const bool & isOutline)2109 void RSPropertiesPainter::DrawBorderBase(const RSProperties& properties, SkCanvas& canvas,
2110 const std::shared_ptr<RSBorder>& border, const bool& isOutline)
2111 {
2112 if (!border || !border->HasBorder()) {
2113 return;
2114 }
2115
2116 SkPaint paint;
2117 paint.setAntiAlias(true);
2118 if (border->ApplyFillStyle(paint)) {
2119 auto skRRect = RRect2SkRRect(GetRRectForDrawingBorder(
2120 properties, border, isOutline));
2121 auto innerSkRRect = RRect2SkRRect(GetInnerRRectForDrawingBorder(
2122 properties, border, isOutline));
2123 canvas.drawDRRect(skRRect, innerSkRRect, paint);
2124 } else {
2125 bool isZero = isOutline ? border->GetRadiusFour().IsZero() : properties.GetCornerRadius().IsZero();
2126 if (isZero && border->ApplyFourLine(paint)) {
2127 RectF rectf = isOutline ?
2128 properties.GetBoundsRect().MakeOutset(border->GetWidthFour()) : properties.GetBoundsRect();
2129 border->PaintFourLine(canvas, paint, rectf);
2130 } else if (border->ApplyPathStyle(paint)) {
2131 auto borderWidth = border->GetWidth();
2132 RRect rrect = GetRRectForDrawingBorder(properties, border, isOutline);
2133 rrect.rect_.width_ -= borderWidth;
2134 rrect.rect_.height_ -= borderWidth;
2135 rrect.rect_.Move(borderWidth / PARAM_DOUBLE, borderWidth / PARAM_DOUBLE);
2136 SkPath borderPath;
2137 borderPath.addRRect(RRect2SkRRect(rrect));
2138 canvas.drawPath(borderPath, paint);
2139 } else {
2140 SkAutoCanvasRestore acr(&canvas, true);
2141 auto rrect = RRect2SkRRect(GetRRectForDrawingBorder(
2142 properties, border, isOutline));
2143 canvas.clipRRect(rrect, true);
2144 auto innerSkRRect = RRect2SkRRect(GetInnerRRectForDrawingBorder(
2145 properties, border, isOutline));
2146 canvas.clipRRect(innerSkRRect, SkClipOp::kDifference, true);
2147 paint.setStyle(SkPaint::Style::kStroke_Style);
2148 SkPoint center = { innerSkRRect.rect().centerX(), innerSkRRect.rect().centerY() };
2149 border->PaintTopPath(canvas, paint, rrect, center);
2150 border->PaintRightPath(canvas, paint, rrect, center);
2151 border->PaintBottomPath(canvas, paint, rrect, center);
2152 border->PaintLeftPath(canvas, paint, rrect, center);
2153 }
2154 }
2155 }
2156 #else
DrawBorderBase(const RSProperties & properties,Drawing::Canvas & canvas,const std::shared_ptr<RSBorder> & border,const bool & isOutline)2157 void RSPropertiesPainter::DrawBorderBase(const RSProperties& properties, Drawing::Canvas& canvas,
2158 const std::shared_ptr<RSBorder>& border, const bool& isOutline)
2159 {
2160 if (!border || !border->HasBorder()) {
2161 return;
2162 }
2163
2164 Drawing::Brush brush;
2165 Drawing::Pen pen;
2166 brush.SetAntiAlias(true);
2167 pen.SetAntiAlias(true);
2168 if (border->ApplyFillStyle(brush)) {
2169 auto roundRect = RRect2DrawingRRect(GetRRectForDrawingBorder(properties, border, isOutline));
2170 auto innerRoundRect = RRect2DrawingRRect(GetInnerRRectForDrawingBorder(
2171 properties, border, isOutline));
2172 canvas.AttachBrush(brush);
2173 canvas.DrawNestedRoundRect(roundRect, innerRoundRect);
2174 canvas.DetachBrush();
2175 } else {
2176 bool isZero = isOutline ? border->GetRadiusFour().IsZero() : properties.GetCornerRadius().IsZero();
2177 if (isZero && border->ApplyFourLine(pen)) {
2178 RectF rectf = isOutline ?
2179 properties.GetBoundsRect().MakeOutset(border->GetWidthFour()) : properties.GetBoundsRect();
2180 border->PaintFourLine(canvas, pen, rectf);
2181 } else if (border->ApplyPathStyle(pen)) {
2182 auto borderWidth = border->GetWidth();
2183 RRect rrect = GetRRectForDrawingBorder(properties, border, isOutline);
2184 rrect.rect_.width_ -= borderWidth;
2185 rrect.rect_.height_ -= borderWidth;
2186 rrect.rect_.Move(borderWidth / PARAM_DOUBLE, borderWidth / PARAM_DOUBLE);
2187 Drawing::Path borderPath;
2188 borderPath.AddRoundRect(RRect2DrawingRRect(rrect));
2189 canvas.AttachPen(pen);
2190 canvas.DrawPath(borderPath);
2191 canvas.DetachPen();
2192 } else {
2193 Drawing::AutoCanvasRestore acr(canvas, true);
2194 auto rrect = RRect2DrawingRRect(GetRRectForDrawingBorder(properties, border, isOutline));
2195 canvas.ClipRoundRect(rrect, Drawing::ClipOp::INTERSECT, true);
2196 auto innerRoundRect = RRect2DrawingRRect(GetInnerRRectForDrawingBorder(
2197 properties, border, isOutline));
2198 canvas.ClipRoundRect(innerRoundRect, Drawing::ClipOp::DIFFERENCE, true);
2199 Drawing::scalar centerX = innerRoundRect.GetRect().GetLeft() + innerRoundRect.GetRect().GetWidth() / 2;
2200 Drawing::scalar centerY = innerRoundRect.GetRect().GetTop() + innerRoundRect.GetRect().GetHeight() / 2;
2201 Drawing::Point center = { centerX, centerY };
2202 auto rect = rrect.GetRect();
2203 Drawing::SaveLayerOps slr(&rect, nullptr);
2204 canvas.SaveLayer(slr);
2205 border->PaintTopPath(canvas, pen, rrect, center);
2206 border->PaintRightPath(canvas, pen, rrect, center);
2207 border->PaintBottomPath(canvas, pen, rrect, center);
2208 border->PaintLeftPath(canvas, pen, rrect, center);
2209 }
2210 }
2211 }
2212 #endif
2213
2214 #ifndef USE_ROSEN_DRAWING
DrawBorder(const RSProperties & properties,SkCanvas & canvas)2215 void RSPropertiesPainter::DrawBorder(const RSProperties& properties, SkCanvas& canvas)
2216 #else
2217 void RSPropertiesPainter::DrawBorder(const RSProperties& properties, Drawing::Canvas& canvas)
2218 #endif
2219 {
2220 auto border = properties.GetBorder();
2221 if (border && border->HasBorder()) {
2222 DrawBorderBase(properties, canvas, border, false);
2223 }
2224 }
2225
GetOutlineDirtyRect(RectI & dirtyOutline,const RSProperties & properties,const bool & isAbsCoordinate)2226 void RSPropertiesPainter::GetOutlineDirtyRect(RectI& dirtyOutline,
2227 const RSProperties& properties, const bool& isAbsCoordinate)
2228 {
2229 auto outline = properties.GetOutline();
2230 if (!outline || !outline->HasBorder()) {
2231 return;
2232 }
2233
2234 auto geoPtr = properties.GetBoundsGeometry();
2235 #ifndef USE_ROSEN_DRAWING
2236 SkMatrix matrix = (geoPtr && isAbsCoordinate) ? geoPtr->GetAbsMatrix() : SkMatrix::I();
2237 auto skRect = Rect2SkRect(GetRRectForDrawingBorder(properties, outline, true).rect_);
2238 matrix.MapRect(&skRect);
2239 dirtyOutline.left_ = std::floor(skRect.left());
2240 dirtyOutline.top_ = std::floor(skRect.top());
2241 dirtyOutline.width_ = std::ceil(skRect.width()) + PARAM_DOUBLE;
2242 dirtyOutline.height_ = std::ceil(skRect.height()) + PARAM_DOUBLE;
2243 #else
2244 Drawing::Matrix matrix = (geoPtr && isAbsCoordinate) ? geoPtr->GetAbsMatrix() : Drawing::Matrix();
2245 auto drawingRect = Rect2DrawingRect(GetRRectForDrawingBorder(properties, outline, true).rect_);
2246 matrix.MapRect(drawingRect, drawingRect);
2247 dirtyOutline.left_ = std::floor(drawingRect.GetLeft());
2248 dirtyOutline.top_ = std::floor(drawingRect.GetTop());
2249 dirtyOutline.width_ = std::ceil(drawingRect.GetWidth()) + PARAM_DOUBLE;
2250 dirtyOutline.height_ = std::ceil(drawingRect.GetHeight()) + PARAM_DOUBLE;
2251 #endif
2252 }
2253
2254 #ifndef USE_ROSEN_DRAWING
DrawOutline(const RSProperties & properties,SkCanvas & canvas)2255 void RSPropertiesPainter::DrawOutline(const RSProperties& properties, SkCanvas& canvas)
2256 #else
2257 void RSPropertiesPainter::DrawOutline(const RSProperties& properties, Drawing::Canvas& canvas)
2258 #endif
2259 {
2260 auto outline = properties.GetOutline();
2261 if (outline && outline->HasBorder()) {
2262 DrawBorderBase(properties, canvas, outline, true);
2263 }
2264 }
2265
2266 #ifndef USE_ROSEN_DRAWING
DrawForegroundColor(const RSProperties & properties,SkCanvas & canvas)2267 void RSPropertiesPainter::DrawForegroundColor(const RSProperties& properties, SkCanvas& canvas)
2268 {
2269 auto bgColor = properties.GetForegroundColor();
2270 if (bgColor == RgbPalette::Transparent()) {
2271 return;
2272 }
2273 // clip
2274 if (properties.GetClipBounds() != nullptr) {
2275 canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
2276 } else if (properties.GetClipToBounds()) {
2277 canvas.clipRect(Rect2SkRect(properties.GetBoundsRect()), true);
2278 } else if (properties.GetClipToRRect()) {
2279 canvas.clipRRect(RRect2SkRRect(properties.GetClipRRect()), true);
2280 }
2281
2282 SkPaint paint;
2283 paint.setColor(bgColor.AsArgbInt());
2284 paint.setAntiAlias(true);
2285 canvas.drawRRect(RRect2SkRRect(properties.GetRRect()), paint);
2286 }
2287 #else
DrawForegroundColor(const RSProperties & properties,Drawing::Canvas & canvas)2288 void RSPropertiesPainter::DrawForegroundColor(const RSProperties& properties, Drawing::Canvas& canvas)
2289 {
2290 auto bgColor = properties.GetForegroundColor();
2291 if (bgColor == RgbPalette::Transparent()) {
2292 return;
2293 }
2294 // clip
2295 if (properties.GetClipBounds() != nullptr) {
2296 canvas.ClipPath(properties.GetClipBounds()->GetDrawingPath(), Drawing::ClipOp::INTERSECT, true);
2297 } else if (properties.GetClipToBounds()) {
2298 canvas.ClipRect(Rect2DrawingRect(properties.GetBoundsRect()), Drawing::ClipOp::INTERSECT, true);
2299 } else if (properties.GetClipToRRect()) {
2300 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetClipRRect()), Drawing::ClipOp::INTERSECT, true);
2301 }
2302
2303 Drawing::Brush brush;
2304 brush.SetColor(Drawing::Color(bgColor.AsArgbInt()));
2305 brush.SetAntiAlias(true);
2306 canvas.AttachBrush(brush);
2307 canvas.DrawRoundRect(RRect2DrawingRRect(properties.GetRRect()));
2308 canvas.DetachBrush();
2309 }
2310 #endif
2311
2312 #ifndef USE_ROSEN_DRAWING
DrawMask(const RSProperties & properties,SkCanvas & canvas,SkRect maskBounds)2313 void RSPropertiesPainter::DrawMask(const RSProperties& properties, SkCanvas& canvas, SkRect maskBounds)
2314 {
2315 std::shared_ptr<RSMask> mask = properties.GetMask();
2316 if (mask == nullptr) {
2317 return;
2318 }
2319 if (mask->IsSvgMask() && !mask->GetSvgDom() && !mask->GetSvgPicture()) {
2320 ROSEN_LOGD("RSPropertiesPainter::DrawMask not has Svg Mask property");
2321 return;
2322 }
2323
2324 canvas.save();
2325 canvas.saveLayer(maskBounds, nullptr);
2326 int tmpLayer = canvas.getSaveCount();
2327
2328 SkPaint maskfilter;
2329 auto filter = SkColorFilters::Compose(SkLumaColorFilter::Make(), SkColorFilters::SRGBToLinearGamma());
2330 maskfilter.setColorFilter(filter);
2331 canvas.saveLayer(maskBounds, &maskfilter);
2332 if (mask->IsSvgMask()) {
2333 SkAutoCanvasRestore maskSave(&canvas, true);
2334 canvas.translate(maskBounds.fLeft + mask->GetSvgX(), maskBounds.fTop + mask->GetSvgY());
2335 canvas.scale(mask->GetScaleX(), mask->GetScaleY());
2336 if (mask->GetSvgDom()) {
2337 mask->GetSvgDom()->render(&canvas);
2338 } else if (mask->GetSvgPicture()) {
2339 canvas.drawPicture(mask->GetSvgPicture());
2340 }
2341 } else if (mask->IsGradientMask()) {
2342 SkAutoCanvasRestore maskSave(&canvas, true);
2343 canvas.translate(maskBounds.fLeft, maskBounds.fTop);
2344 SkRect skRect = SkRect::MakeIWH(maskBounds.fRight - maskBounds.fLeft, maskBounds.fBottom - maskBounds.fTop);
2345 canvas.drawRect(skRect, mask->GetMaskPaint());
2346 } else if (mask->IsPathMask()) {
2347 SkAutoCanvasRestore maskSave(&canvas, true);
2348 canvas.translate(maskBounds.fLeft, maskBounds.fTop);
2349 canvas.drawPath(mask->GetMaskPath(), mask->GetMaskPaint());
2350 }
2351
2352 // back to mask layer
2353 canvas.restoreToCount(tmpLayer);
2354 // create content layer
2355 SkPaint maskPaint;
2356 maskPaint.setBlendMode(SkBlendMode::kSrcIn);
2357 canvas.saveLayer(maskBounds, &maskPaint);
2358 canvas.clipRect(maskBounds, true);
2359 }
2360 #else
DrawMask(const RSProperties & properties,Drawing::Canvas & canvas,Drawing::Rect maskBounds)2361 void RSPropertiesPainter::DrawMask(const RSProperties& properties, Drawing::Canvas& canvas, Drawing::Rect maskBounds)
2362 {
2363 std::shared_ptr<RSMask> mask = properties.GetMask();
2364 if (mask == nullptr) {
2365 return;
2366 }
2367 if (mask->IsSvgMask() && !mask->GetSvgDom() && !mask->GetSvgPicture()) {
2368 ROSEN_LOGD("RSPropertiesPainter::DrawMask not has Svg Mask property");
2369 return;
2370 }
2371
2372 canvas.Save();
2373 Drawing::SaveLayerOps slr(&maskBounds, nullptr);
2374 canvas.SaveLayer(slr);
2375 int tmpLayer = canvas.GetSaveCount();
2376
2377 Drawing::Brush maskfilter;
2378 Drawing::Filter filter;
2379 filter.SetColorFilter(Drawing::ColorFilter::CreateComposeColorFilter(
2380 *(Drawing::ColorFilter::CreateLumaColorFilter()), *(Drawing::ColorFilter::CreateSrgbGammaToLinear())));
2381 maskfilter.SetFilter(filter);
2382 Drawing::SaveLayerOps slrMask(&maskBounds, &maskfilter);
2383 canvas.SaveLayer(slrMask);
2384 if (mask->IsSvgMask()) {
2385 Drawing::AutoCanvasRestore maskSave(canvas, true);
2386 canvas.Translate(maskBounds.GetLeft() + mask->GetSvgX(), maskBounds.GetTop() + mask->GetSvgY());
2387 canvas.Scale(mask->GetScaleX(), mask->GetScaleY());
2388 if (mask->GetSvgDom()) {
2389 canvas.DrawSVGDOM(mask->GetSvgDom());
2390 } else if (mask->GetSvgPicture()) {
2391 canvas.DrawPicture(*mask->GetSvgPicture());
2392 }
2393 } else if (mask->IsGradientMask()) {
2394 Drawing::AutoCanvasRestore maskSave(canvas, true);
2395 canvas.Translate(maskBounds.GetLeft(), maskBounds.GetTop());
2396 Drawing::Rect rect = Drawing::Rect(
2397 0, 0, maskBounds.GetWidth(), maskBounds.GetHeight());
2398 canvas.AttachBrush(mask->GetMaskBrush());
2399 canvas.DrawRect(rect);
2400 canvas.DetachBrush();
2401 } else if (mask->IsPathMask()) {
2402 Drawing::AutoCanvasRestore maskSave(canvas, true);
2403 canvas.Translate(maskBounds.GetLeft(), maskBounds.GetTop());
2404 canvas.AttachBrush(mask->GetMaskBrush());
2405 canvas.AttachPen(mask->GetMaskPen());
2406 canvas.DrawPath(*mask->GetMaskPath());
2407 canvas.DetachBrush();
2408 canvas.DetachPen();
2409 }
2410
2411 // back to mask layer
2412 canvas.RestoreToCount(tmpLayer);
2413 // create content layer
2414 Drawing::Brush maskPaint;
2415 maskPaint.SetBlendMode(Drawing::BlendMode::SRC_IN);
2416 Drawing::SaveLayerOps slrContent(&maskBounds, &maskPaint);
2417 canvas.SaveLayer(slrContent);
2418 canvas.ClipRect(maskBounds, Drawing::ClipOp::INTERSECT, true);
2419 }
2420 #endif
2421
2422 #ifndef USE_ROSEN_DRAWING
DrawMask(const RSProperties & properties,SkCanvas & canvas)2423 void RSPropertiesPainter::DrawMask(const RSProperties& properties, SkCanvas& canvas)
2424 {
2425 SkRect maskBounds = Rect2SkRect(properties.GetBoundsRect());
2426 DrawMask(properties, canvas, maskBounds);
2427 }
2428 #else
DrawMask(const RSProperties & properties,Drawing::Canvas & canvas)2429 void RSPropertiesPainter::DrawMask(const RSProperties& properties, Drawing::Canvas& canvas)
2430 {
2431 Drawing::Rect maskBounds = Rect2DrawingRect(properties.GetBoundsRect());
2432 DrawMask(properties, canvas, maskBounds);
2433 }
2434 #endif
2435
2436 #ifndef USE_ROSEN_DRAWING
GetCmdsClipRect(DrawCmdListPtr & cmds)2437 RectF RSPropertiesPainter::GetCmdsClipRect(DrawCmdListPtr& cmds)
2438 {
2439 #if defined(RS_ENABLE_DRIVEN_RENDER)
2440 RectF clipRect;
2441 if (cmds == nullptr) {
2442 return clipRect;
2443 }
2444 SkRect rect;
2445 cmds->CheckClipRect(rect);
2446 clipRect = { rect.left(), rect.top(), rect.width(), rect.height() };
2447 return clipRect;
2448 #else
2449 return RectF { 0.0f, 0.0f, 0.0f, 0.0f };
2450 #endif
2451 }
2452 #else
GetCmdsClipRect(Drawing::DrawCmdListPtr & cmds)2453 RectF RSPropertiesPainter::GetCmdsClipRect(Drawing::DrawCmdListPtr& cmds)
2454 {
2455 ROSEN_LOGE("Drawing Unsupport RSPropertiesPainter::GetCmdsClipRect");
2456 return RectF { 0.0f, 0.0f, 0.0f, 0.0f };
2457 }
2458 #endif
2459
2460 #ifndef USE_ROSEN_DRAWING
DrawFrameForDriven(const RSProperties & properties,RSPaintFilterCanvas & canvas,DrawCmdListPtr & cmds)2461 void RSPropertiesPainter::DrawFrameForDriven(const RSProperties& properties, RSPaintFilterCanvas& canvas,
2462 DrawCmdListPtr& cmds)
2463 #else
2464 void RSPropertiesPainter::DrawFrameForDriven(const RSProperties& properties, RSPaintFilterCanvas& canvas,
2465 Drawing::DrawCmdListPtr& cmds)
2466 #endif
2467 {
2468 #if defined(RS_ENABLE_DRIVEN_RENDER)
2469 if (cmds == nullptr) {
2470 return;
2471 }
2472 #ifndef USE_ROSEN_DRAWING
2473 SkMatrix mat;
2474 if (GetGravityMatrix(
2475 properties.GetFrameGravity(), properties.GetFrameRect(), cmds->GetWidth(), cmds->GetHeight(), mat)) {
2476 canvas.concat(mat);
2477 }
2478 auto frameRect = Rect2SkRect(properties.GetFrameRect());
2479 #else
2480 Rosen::Drawing::Matrix mat;
2481 if (GetGravityMatrix(
2482 properties.GetFrameGravity(), properties.GetFrameRect(), cmds->GetWidth(), cmds->GetHeight(), mat)) {
2483 canvas.ConcatMatrix(mat);
2484 }
2485 auto frameRect = Rect2DrawingRect(properties.GetFrameRect());
2486 #endif
2487 // temporary solution for driven content clip
2488 #ifndef USE_ROSEN_DRAWING
2489 cmds->ReplaceDrivenCmds();
2490 cmds->Playback(canvas, &frameRect);
2491 cmds->RestoreOriginCmdsForDriven();
2492 #else
2493 cmds->Playback(canvas, &frameRect);
2494 #endif
2495 #endif
2496 }
2497
2498 #ifndef USE_ROSEN_DRAWING
DrawSpherize(const RSProperties & properties,RSPaintFilterCanvas & canvas,const sk_sp<SkSurface> & spherizeSurface)2499 void RSPropertiesPainter::DrawSpherize(const RSProperties& properties, RSPaintFilterCanvas& canvas,
2500 const sk_sp<SkSurface>& spherizeSurface)
2501 {
2502 if (spherizeSurface == nullptr) {
2503 return;
2504 }
2505 SkAutoCanvasRestore acr(&canvas, true);
2506 float canvasWidth = properties.GetBoundsRect().GetWidth();
2507 float canvasHeight = properties.GetBoundsRect().GetHeight();
2508 if (spherizeSurface->width() == 0 || spherizeSurface->height() == 0) {
2509 return;
2510 }
2511 canvas.scale(canvasWidth / spherizeSurface->width(), canvasHeight / spherizeSurface->height());
2512
2513 auto imageSnapshot = spherizeSurface->makeImageSnapshot();
2514 if (imageSnapshot == nullptr) {
2515 ROSEN_LOGE("RSPropertiesPainter::DrawCachedSpherizeSurface image is null");
2516 return;
2517 }
2518
2519 SkPaint paint;
2520 paint.setBlendMode(SkBlendMode::kSrcOver);
2521 paint.setShader(imageSnapshot->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions()));
2522
2523 float width = imageSnapshot->width();
2524 float height = imageSnapshot->height();
2525 float degree = properties.GetSpherize();
2526 bool isWidthGreater = width > height;
2527 ROSEN_LOGI("RSPropertiesPainter::DrawCachedSpherizeSurface spherize degree [%{public}f]", degree);
2528
2529 const SkPoint texCoords[4] = {
2530 {0.0f, 0.0f}, {width, 0.0f}, {width, height}, {0.0f, height}
2531 };
2532 float offsetSquare = 0.f;
2533 if (isWidthGreater) {
2534 offsetSquare = (width - height) * degree / 2.0; // half of the change distance
2535 width = width - (width - height) * degree;
2536 } else {
2537 offsetSquare = (height - width) * degree / 2.0; // half of the change distance
2538 height = height - (height - width) * degree;
2539 }
2540
2541 float segmentWidthOne = width / 3.0;
2542 float segmentWidthTwo = width / 3.0 * 2.0;
2543 float segmentHeightOne = height / 3.0;
2544 float segmentHeightTwo = height / 3.0 * 2.0;
2545 float offsetSphereWidth = width / 6 * degree;
2546 float offsetSphereHeight = height / 6 * degree;
2547
2548 SkPoint ctrlPoints[12] = {
2549 // top edge control points
2550 {0.0f, 0.0f}, {segmentWidthOne, 0.0f}, {segmentWidthTwo, 0.0f}, {width, 0.0f},
2551 // right edge control points
2552 {width, segmentHeightOne}, {width, segmentHeightTwo},
2553 // bottom edge control points
2554 {width, height}, {segmentWidthTwo, height}, {segmentWidthOne, height}, {0.0f, height},
2555 // left edge control points
2556 {0.0f, segmentHeightTwo}, {0.0f, segmentHeightOne}
2557 };
2558 ctrlPoints[0].offset(offsetSphereWidth, offsetSphereHeight); // top left control point
2559 ctrlPoints[3].offset(-offsetSphereWidth, offsetSphereHeight); // top right control point
2560 ctrlPoints[6].offset(-offsetSphereWidth, -offsetSphereHeight); // bottom right control point
2561 ctrlPoints[9].offset(offsetSphereWidth, -offsetSphereHeight); // bottom left control point
2562 if (isWidthGreater) {
2563 SkPoint::Offset(ctrlPoints, SK_ARRAY_COUNT(ctrlPoints), offsetSquare, 0);
2564 } else {
2565 SkPoint::Offset(ctrlPoints, SK_ARRAY_COUNT(ctrlPoints), 0, offsetSquare);
2566 }
2567 SkPath path;
2568 path.moveTo(ctrlPoints[0]);
2569 path.cubicTo(ctrlPoints[1], ctrlPoints[2], ctrlPoints[3]); // upper edge
2570 path.cubicTo(ctrlPoints[4], ctrlPoints[5], ctrlPoints[6]); // right edge
2571 path.cubicTo(ctrlPoints[7], ctrlPoints[8], ctrlPoints[9]); // bottom edge
2572 path.cubicTo(ctrlPoints[10], ctrlPoints[11], ctrlPoints[0]); // left edge
2573 canvas.clipPath(path, true);
2574 canvas.drawPatch(ctrlPoints, nullptr, texCoords, SkBlendMode::kSrcOver, paint);
2575 }
2576 #else
DrawSpherize(const RSProperties & properties,RSPaintFilterCanvas & canvas,const std::shared_ptr<Drawing::Surface> & spherizeSurface)2577 void RSPropertiesPainter::DrawSpherize(const RSProperties& properties, RSPaintFilterCanvas& canvas,
2578 const std::shared_ptr<Drawing::Surface>& spherizeSurface)
2579 {
2580 if (spherizeSurface == nullptr) {
2581 return;
2582 }
2583 if (spherizeSurface->Width() == 0 || spherizeSurface->Height() == 0) {
2584 return;
2585 }
2586 Drawing::AutoCanvasRestore acr(canvas, true);
2587 float canvasWidth = properties.GetBoundsRect().GetWidth();
2588 float canvasHeight = properties.GetBoundsRect().GetHeight();
2589
2590 auto imageSnapshot = spherizeSurface->GetImageSnapshot();
2591 if (imageSnapshot == nullptr) {
2592 ROSEN_LOGE("RSPropertiesPainter::DrawCachedSpherizeSurface image is null");
2593 return;
2594 }
2595 int imageWidth = imageSnapshot->GetWidth();
2596 int imageHeight = imageSnapshot->GetHeight();
2597 if (imageWidth == 0 || imageHeight == 0) {
2598 return;
2599 }
2600 canvas.Scale(canvasWidth / imageWidth, canvasHeight / imageHeight);
2601
2602 float width = imageWidth;
2603 float height = imageHeight;
2604 float degree = properties.GetSpherize();
2605 bool isWidthGreater = width > height;
2606 ROSEN_LOGI("RSPropertiesPainter::DrawCachedSpherizeSurface spherize degree [%{public}f]", degree);
2607
2608 Drawing::Brush brush;
2609 brush.SetBlendMode(Drawing::BlendMode::SRC_OVER);
2610 Drawing::SamplingOptions samplingOptions;
2611 Drawing::Matrix scaleMat;
2612 brush.SetShaderEffect(Drawing::ShaderEffect::CreateImageShader(
2613 *imageSnapshot, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, samplingOptions, scaleMat));
2614 canvas.AttachBrush(brush);
2615
2616 const Drawing::Point texCoords[4] = {
2617 {0.0f, 0.0f}, {width, 0.0f}, {width, height}, {0.0f, height}
2618 };
2619 float offsetSquare = 0.f;
2620 if (isWidthGreater) {
2621 offsetSquare = (width - height) * degree / 2.0; // half of the change distance
2622 width = width - (width - height) * degree;
2623 } else {
2624 offsetSquare = (height - width) * degree / 2.0; // half of the change distance
2625 height = height - (height - width) * degree;
2626 }
2627
2628 float segmentWidthOne = width / 3.0;
2629 float segmentWidthTwo = width / 3.0 * 2.0;
2630 float segmentHeightOne = height / 3.0;
2631 float segmentHeightTwo = height / 3.0 * 2.0;
2632 float offsetSphereWidth = width / 6 * degree;
2633 float offsetSphereHeight = height / 6 * degree;
2634
2635 const int PointNum = 12;
2636 Drawing::Point ctrlPoints[PointNum] = {
2637 // top edge control points
2638 {0.0f, 0.0f}, {segmentWidthOne, 0.0f}, {segmentWidthTwo, 0.0f}, {width, 0.0f},
2639 // right edge control points
2640 {width, segmentHeightOne}, {width, segmentHeightTwo},
2641 // bottom edge control points
2642 {width, height}, {segmentWidthTwo, height}, {segmentWidthOne, height}, {0.0f, height},
2643 // left edge control points
2644 {0.0f, segmentHeightTwo}, {0.0f, segmentHeightOne}
2645 };
2646 ctrlPoints[0].Offset(offsetSphereWidth, offsetSphereHeight); // top left control point
2647 ctrlPoints[3].Offset(-offsetSphereWidth, offsetSphereHeight); // top right control point
2648 ctrlPoints[6].Offset(-offsetSphereWidth, -offsetSphereHeight); // bottom right control point
2649 ctrlPoints[9].Offset(offsetSphereWidth, -offsetSphereHeight); // bottom left control point
2650 if (isWidthGreater) {
2651 for (int i = 0; i < PointNum; ++i) {
2652 ctrlPoints[i].Offset(offsetSquare, 0);
2653 }
2654 } else {
2655 for (int i = 0; i < PointNum; ++i) {
2656 ctrlPoints[i].Offset(0, offsetSquare);
2657 }
2658 }
2659 Drawing::Path path;
2660 path.MoveTo(ctrlPoints[0].GetX(), ctrlPoints[0].GetY());
2661 path.CubicTo(ctrlPoints[1], ctrlPoints[2], ctrlPoints[3]); // upper edge
2662 path.CubicTo(ctrlPoints[4], ctrlPoints[5], ctrlPoints[6]); // right edge
2663 path.CubicTo(ctrlPoints[7], ctrlPoints[8], ctrlPoints[9]); // bottom edge
2664 path.CubicTo(ctrlPoints[10], ctrlPoints[11], ctrlPoints[0]); // left edge
2665 canvas.ClipPath(path, Drawing::ClipOp::INTERSECT, true);
2666 canvas.DrawPatch(ctrlPoints, nullptr, texCoords, Drawing::BlendMode::SRC_OVER);
2667 canvas.DetachBrush();
2668 }
2669 #endif
2670
DrawColorFilter(const RSProperties & properties,RSPaintFilterCanvas & canvas)2671 void RSPropertiesPainter::DrawColorFilter(const RSProperties& properties, RSPaintFilterCanvas& canvas)
2672 {
2673 // if useEffect defined, use color filter from parent EffectView.
2674 auto& colorFilter = properties.GetColorFilter();
2675 if (colorFilter == nullptr) {
2676 return;
2677 }
2678 #ifndef USE_ROSEN_DRAWING
2679 SkAutoCanvasRestore acr(&canvas, true);
2680 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
2681 SkPaint paint;
2682 paint.setAntiAlias(true);
2683 paint.setColorFilter(colorFilter);
2684 auto skSurface = canvas.GetSurface();
2685 if (skSurface == nullptr) {
2686 ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter skSurface is null");
2687 return;
2688 }
2689 auto clipBounds = canvas.getDeviceClipBounds();
2690 auto imageSnapshot = skSurface->makeImageSnapshot(clipBounds);
2691 if (imageSnapshot == nullptr) {
2692 ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter image is null");
2693 return;
2694 }
2695 as_IB(imageSnapshot)->hintCacheGpuResource();
2696 canvas.resetMatrix();
2697 SkSamplingOptions options(SkFilterMode::kNearest, SkMipmapMode::kNone);
2698 canvas.drawImageRect(imageSnapshot, SkRect::Make(clipBounds), options, &paint);
2699 #else
2700 Drawing::AutoCanvasRestore acr(canvas, true);
2701 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, true);
2702 Drawing::Brush brush;
2703 brush.SetAntiAlias(true);
2704 Drawing::Filter filter;
2705 filter.SetColorFilter(colorFilter);
2706 brush.SetFilter(filter);
2707 auto surface = canvas.GetSurface();
2708 if (surface == nullptr) {
2709 ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter surface is null");
2710 return;
2711 }
2712 auto clipBounds = canvas.GetDeviceClipBounds();
2713 auto imageSnapshot = surface->GetImageSnapshot(clipBounds);
2714 if (imageSnapshot == nullptr) {
2715 ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter image is null");
2716 return;
2717 }
2718 as_IB(imageSnapshot->ExportSkImage().get())->hintCacheGpuResource();
2719 canvas.ResetMatrix();
2720 Drawing::SamplingOptions options(Drawing::FilterMode::NEAREST, Drawing::MipmapMode::NONE);
2721 canvas.AttachBrush(brush);
2722 canvas.DrawImageRect(*imageSnapshot, clipBounds, options);
2723 canvas.DetachBrush();
2724 #endif
2725 }
2726
2727 #ifndef USE_ROSEN_DRAWING
DrawBinarizationShader(const RSProperties & properties,RSPaintFilterCanvas & canvas)2728 void RSPropertiesPainter::DrawBinarizationShader(const RSProperties& properties, RSPaintFilterCanvas& canvas)
2729 {
2730 SkAutoCanvasRestore acr(&canvas, true);
2731 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
2732 auto skSurface = canvas.GetSurface();
2733 if (skSurface == nullptr) {
2734 ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter skSurface is null");
2735 return;
2736 }
2737 auto clipBounds = canvas.getDeviceClipBounds();
2738 auto imageSnapshot = skSurface->makeImageSnapshot(clipBounds);
2739 if (imageSnapshot == nullptr) {
2740 ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter image is null");
2741 return;
2742 }
2743 auto& aiInvert = properties.GetAiInvert();
2744 auto imageShader = imageSnapshot->makeShader(SkSamplingOptions(SkFilterMode::kLinear));
2745 float thresholdLow = aiInvert->z_ - aiInvert->w_;
2746 float thresholdHigh = aiInvert->z_ + aiInvert->w_;
2747 auto shader = MakeBinarizationShader(
2748 aiInvert->x_, aiInvert->y_, thresholdLow, thresholdHigh, imageShader);
2749 SkPaint paint;
2750 paint.setShader(shader);
2751 paint.setAntiAlias(true);
2752 canvas.resetMatrix();
2753 canvas.translate(clipBounds.left(), clipBounds.top());
2754 canvas.drawPaint(paint);
2755 }
2756 #else
DrawBinarizationShader(const RSProperties & properties,RSPaintFilterCanvas & canvas)2757 void RSPropertiesPainter::DrawBinarizationShader(const RSProperties& properties, RSPaintFilterCanvas& canvas)
2758 {
2759 Drawing::AutoCanvasRestore acr(canvas, true);
2760 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, true);
2761 auto drSurface = canvas.GetSurface();
2762 if (drSurface == nullptr) {
2763 ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter drSurface is null");
2764 return;
2765 }
2766 auto clipBounds = canvas.GetDeviceClipBounds();
2767 auto imageSnapshot = drSurface->GetImageSnapshot(clipBounds);
2768 if (imageSnapshot == nullptr) {
2769 ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter image is null");
2770 return;
2771 }
2772 auto& aiInvert = properties.GetAiInvert();
2773 Drawing::Matrix matrix;
2774 auto imageShader = Drawing::ShaderEffect::CreateImageShader(*imageSnapshot, Drawing::TileMode::CLAMP,
2775 Drawing::TileMode::CLAMP, Drawing::SamplingOptions(Drawing::FilterMode::LINEAR), matrix);
2776 float thresholdLow = aiInvert->z_ - aiInvert->w_;
2777 float thresholdHigh = aiInvert->z_ + aiInvert->w_;
2778 auto shader = MakeBinarizationShader(
2779 aiInvert->x_, aiInvert->y_, thresholdLow, thresholdHigh, imageShader);
2780 Drawing::Brush brush;
2781 brush.SetShaderEffect(shader);
2782 brush.SetAntiAlias(true);
2783 canvas.ResetMatrix();
2784 canvas.Translate(clipBounds.GetLeft(), clipBounds.GetTop());
2785 canvas.DrawBackground(brush);
2786 }
2787 #endif
2788
2789 #ifndef USE_ROSEN_DRAWING
MakeBinarizationShader(float low,float high,float thresholdLow,float thresholdHigh,sk_sp<SkShader> imageShader)2790 sk_sp<SkShader> RSPropertiesPainter::MakeBinarizationShader(float low, float high, float thresholdLow,
2791 float thresholdHigh, sk_sp<SkShader> imageShader)
2792 {
2793 static constexpr char prog[] = R"(
2794 uniform half low;
2795 uniform half high;
2796 uniform half thresholdLow;
2797 uniform half thresholdHigh;
2798 uniform shader imageShader;
2799
2800 half4 main(float2 coord) {
2801 half3 c = imageShader.eval(float2(coord.x, coord.y)).rgb;
2802 float gray = 0.299 * c.r + 0.587 * c.g + 0.114 * c.b;
2803 float lowRes = mix(high, -1.0, step(thresholdLow, gray));
2804 float highRes = mix(-1.0, low, step(thresholdHigh, gray));
2805 float midRes = (thresholdHigh - gray) * (high - low) / (thresholdHigh - thresholdLow) + low;
2806 float invertedGray = mix(midRes, max(lowRes, highRes), step(-0.5, max(lowRes, highRes)));
2807 half3 invert = half3(invertedGray);
2808 return half4(invert, 1.0);
2809 }
2810 )";
2811 auto [effect, err] = SkRuntimeEffect::MakeForShader(SkString(prog));
2812 if (!effect) {
2813 ROSEN_LOGE("MakeBinarizationShader::RuntimeShader effect error: %{public}s\n", err.c_str());
2814 return nullptr;
2815 }
2816 SkRuntimeShaderBuilder builder(effect);
2817 // aviod zero-divide in shader
2818 thresholdHigh = thresholdHigh <= thresholdLow ? thresholdHigh + 1e-6 : thresholdHigh;
2819 builder.child("imageShader") = imageShader;
2820 builder.uniform("low") = low;
2821 builder.uniform("high") = high;
2822 builder.uniform("thresholdLow") = thresholdLow;
2823 builder.uniform("thresholdHigh") = thresholdHigh;
2824 return builder.makeShader(nullptr, false);
2825 }
2826 #else
MakeBinarizationShader(float low,float high,float thresholdLow,float thresholdHigh,std::shared_ptr<Drawing::ShaderEffect> imageShader)2827 std::shared_ptr<Drawing::ShaderEffect> RSPropertiesPainter::MakeBinarizationShader(float low, float high,
2828 float thresholdLow, float thresholdHigh,
2829 std::shared_ptr<Drawing::ShaderEffect> imageShader)
2830 {
2831 static constexpr char prog[] = R"(
2832 uniform half low;
2833 uniform half high;
2834 uniform half thresholdLow;
2835 uniform half thresholdHigh;
2836 uniform shader imageShader;
2837
2838 half4 main(float2 coord) {
2839 half3 c = imageShader.eval(float2(coord.x, coord.y)).rgb;
2840 float gray = 0.299 * c.r + 0.587 * c.g + 0.114 * c.b;
2841 float lowRes = mix(high, -1.0, step(thresholdLow, gray));
2842 float highRes = mix(-1.0, low, step(thresholdHigh, gray));
2843 float midRes = (thresholdHigh - gray) * (high - low) / (thresholdHigh - thresholdLow) + low;
2844 float invertedGray = mix(midRes, max(lowRes, highRes), step(-0.5, max(lowRes, highRes)));
2845 half3 invert = half3(invertedGray);
2846 return half4(invert, 1.0);
2847 }
2848 )";
2849 if (binarizationShaderEffect_ == nullptr) {
2850 binarizationShaderEffect_ = Drawing::RuntimeEffect::CreateForShader(prog);
2851 if (binarizationShaderEffect_ == nullptr) {
2852 ROSEN_LOGE("MakeBinarizationShader::RuntimeShader effect error\n");
2853 return nullptr;
2854 }
2855 }
2856 std::shared_ptr<Drawing::RuntimeShaderBuilder> builder =
2857 std::make_shared<Drawing::RuntimeShaderBuilder>(binarizationShaderEffect_);
2858 // aviod zero-divide in shader
2859 thresholdHigh = thresholdHigh <= thresholdLow ? thresholdHigh + 1e-6 : thresholdHigh;
2860 builder->SetChild("imageShader", imageShader);
2861 builder->SetUniform("low", low);
2862 builder->SetUniform("high", high);
2863 builder->SetUniform("thresholdLow", thresholdLow);
2864 builder->SetUniform("thresholdHigh", thresholdHigh);
2865 return builder->MakeShader(nullptr, false);
2866 }
2867 #endif
2868
DrawLightUpEffect(const RSProperties & properties,RSPaintFilterCanvas & canvas)2869 void RSPropertiesPainter::DrawLightUpEffect(const RSProperties& properties, RSPaintFilterCanvas& canvas)
2870 {
2871 #ifndef USE_ROSEN_DRAWING
2872 SkSurface* skSurface = canvas.GetSurface();
2873 if (skSurface == nullptr) {
2874 ROSEN_LOGD("RSPropertiesPainter::DrawLightUpEffect skSurface is null");
2875 return;
2876 }
2877 SkAutoCanvasRestore acr(&canvas, true);
2878 if (properties.GetClipBounds() != nullptr) {
2879 canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
2880 } else {
2881 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
2882 }
2883
2884 auto clipBounds = canvas.getDeviceClipBounds();
2885 auto image = skSurface->makeImageSnapshot(clipBounds);
2886 if (image == nullptr) {
2887 ROSEN_LOGE("RSPropertiesPainter::DrawLightUpEffect image is null");
2888 return;
2889 }
2890 auto imageShader = image->makeShader(SkSamplingOptions(SkFilterMode::kLinear));
2891 auto shader = MakeLightUpEffectShader(properties.GetLightUpEffect(), imageShader);
2892 SkPaint paint;
2893 paint.setShader(shader);
2894 canvas.resetMatrix();
2895 canvas.translate(clipBounds.left(), clipBounds.top());
2896 canvas.drawPaint(paint);
2897 #else
2898 Drawing::Surface* surface = canvas.GetSurface();
2899 if (surface == nullptr) {
2900 ROSEN_LOGD("RSPropertiesPainter::DrawLightUpEffect surface is null");
2901 return;
2902 }
2903 Drawing::AutoCanvasRestore acr(canvas, true);
2904 if (properties.GetClipBounds() != nullptr) {
2905 canvas.ClipPath(properties.GetClipBounds()->GetDrawingPath(), Drawing::ClipOp::INTERSECT, true);
2906 } else {
2907 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, true);
2908 }
2909
2910 auto clipBounds = canvas.GetDeviceClipBounds();
2911 auto image = surface->GetImageSnapshot(clipBounds);
2912 if (image == nullptr) {
2913 ROSEN_LOGE("RSPropertiesPainter::DrawLightUpEffect image is null");
2914 return;
2915 }
2916 Drawing::Matrix scaleMat;
2917 auto imageShader = Drawing::ShaderEffect::CreateImageShader(
2918 *image, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP,
2919 Drawing::SamplingOptions(Drawing::FilterMode::LINEAR), scaleMat);
2920 auto shader = MakeLightUpEffectShader(properties.GetLightUpEffect(), imageShader);
2921 Drawing::Brush brush;
2922 brush.SetShaderEffect(shader);
2923 canvas.ResetMatrix();
2924 canvas.Translate(clipBounds.GetLeft(), clipBounds.GetTop());
2925 canvas.DrawBackground(brush);
2926 #endif
2927 }
2928
2929 #ifndef USE_ROSEN_DRAWING
MakeLightUpEffectShader(float lightUpDeg,sk_sp<SkShader> imageShader)2930 sk_sp<SkShader> RSPropertiesPainter::MakeLightUpEffectShader(float lightUpDeg, sk_sp<SkShader> imageShader)
2931 #else
2932 std::shared_ptr<Drawing::ShaderEffect> RSPropertiesPainter::MakeLightUpEffectShader(
2933 float lightUpDeg, std::shared_ptr<Drawing::ShaderEffect> imageShader)
2934 #endif
2935 {
2936 static constexpr char prog[] = R"(
2937 uniform half lightUpDeg;
2938 uniform shader imageShader;
2939 vec3 rgb2hsv(in vec3 c)
2940 {
2941 vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
2942 vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
2943 vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
2944 float d = q.x - min(q.w, q.y);
2945 float e = 1.0e-10;
2946 return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
2947 }
2948 vec3 hsv2rgb(in vec3 c)
2949 {
2950 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);
2951 return c.z * mix(vec3(1.0), rgb, c.y);
2952 }
2953 half4 main(float2 coord)
2954 {
2955 vec3 hsv = rgb2hsv(imageShader.eval(coord).rgb);
2956 float satUpper = clamp(hsv.y * 1.2, 0.0, 1.0);
2957 hsv.y = mix(satUpper, hsv.y, lightUpDeg);
2958 hsv.z += lightUpDeg - 1.0;
2959 return vec4(hsv2rgb(hsv), 1.0);
2960 }
2961 )";
2962 #ifndef USE_ROSEN_DRAWING
2963 auto [effect, err] = SkRuntimeEffect::MakeForShader(SkString(prog));
2964 sk_sp<SkShader> children[] = {imageShader};
2965 size_t childCount = 1;
2966 return effect->makeShader(SkData::MakeWithCopy(
2967 &lightUpDeg, sizeof(lightUpDeg)), children, childCount, nullptr, false);
2968 #else
2969 if (lightUpEffectShaderEffect_ == nullptr) {
2970 lightUpEffectShaderEffect_ = Drawing::RuntimeEffect::CreateForShader(prog);
2971 if (lightUpEffectShaderEffect_ == nullptr) {
2972 return nullptr;
2973 }
2974 }
2975 std::shared_ptr<Drawing::ShaderEffect> children[] = {imageShader};
2976 size_t childCount = 1;
2977 auto data = std::make_shared<Drawing::Data>();
2978 data->BuildWithCopy(&lightUpDeg, sizeof(lightUpDeg));
2979 return lightUpEffectShaderEffect_->MakeShader(data, children, childCount, nullptr, false);
2980 #endif
2981 }
2982
DrawDynamicLightUp(const RSProperties & properties,RSPaintFilterCanvas & canvas)2983 void RSPropertiesPainter::DrawDynamicLightUp(const RSProperties& properties, RSPaintFilterCanvas& canvas)
2984 {
2985 #ifndef USE_ROSEN_DRAWING
2986 SkAutoCanvasRestore acr(&canvas, true);
2987 if (RSSystemProperties::GetPropertyDrawableEnable()) {
2988 // do nothing
2989 } else if (properties.GetClipBounds() != nullptr) {
2990 canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
2991 } else {
2992 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
2993 }
2994
2995 auto blender = MakeDynamicLightUpBlender(properties.GetDynamicLightUpRate().value() * canvas.GetAlpha(),
2996 properties.GetDynamicLightUpDegree().value() * canvas.GetAlpha());
2997 SkPaint paint;
2998 paint.setBlender(blender);
2999 canvas.drawPaint(paint);
3000 #else
3001 Drawing::Surface* surface = canvas.GetSurface();
3002 if (surface == nullptr) {
3003 ROSEN_LOGD("RSPropertiesPainter::DrawDynamicLightUp surface is null");
3004 return;
3005 }
3006 Drawing::AutoCanvasRestore acr(canvas, true);
3007 if (RSSystemProperties::GetPropertyDrawableEnable()) {
3008 // do nothing
3009 } else if (properties.GetClipBounds() != nullptr) {
3010 canvas.ClipPath(properties.GetClipBounds()->GetDrawingPath(), Drawing::ClipOp::INTERSECT, true);
3011 } else {
3012 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, true);
3013 }
3014
3015 auto blender = MakeDynamicLightUpBlender(properties.GetDynamicLightUpRate().value() * canvas.GetAlpha(),
3016 properties.GetDynamicLightUpDegree().value() * canvas.GetAlpha());
3017 Drawing::Brush brush;
3018 brush.SetBlender(blender);
3019 canvas.DrawBackground(brush);
3020 #endif
3021 }
3022
3023 #ifndef USE_ROSEN_DRAWING
MakeDynamicLightUpBlender(float dynamicLightUpRate,float dynamicLightUpDeg)3024 sk_sp<SkBlender> RSPropertiesPainter::MakeDynamicLightUpBlender(
3025 float dynamicLightUpRate, float dynamicLightUpDeg)
3026 #else
3027 std::shared_ptr<Drawing::Blender> RSPropertiesPainter::MakeDynamicLightUpBlender(
3028 float dynamicLightUpRate, float dynamicLightUpDeg)
3029 #endif
3030 {
3031 #ifndef USE_ROSEN_DRAWING
3032 static constexpr char prog[] = R"(
3033 uniform half dynamicLightUpRate;
3034 uniform half dynamicLightUpDeg;
3035
3036 vec4 main(vec4 src, vec4 dst) {
3037 float x = 0.299 * dst.r + 0.587 * dst.g + 0.114 * dst.b;
3038 float y = (0 - dynamicLightUpRate) * x + dynamicLightUpDeg;
3039 float R = clamp((dst.r + y), 0.0, 1.0);
3040 float G = clamp((dst.g + y), 0.0, 1.0);
3041 float B = clamp((dst.b + y), 0.0, 1.0);
3042 return vec4(R, G, B, 1.0);
3043 }
3044 )";
3045
3046 auto [effect, err] = SkRuntimeEffect::MakeForBlender(SkString(prog));
3047 if (!effect) {
3048 ROSEN_LOGE("MakeDynamicLightUpBlender::RuntimeBlender effect error: %{public}s\n", err.c_str());
3049 return nullptr;
3050 }
3051 SkRuntimeBlendBuilder builder(effect);
3052 builder.uniform("dynamicLightUpRate") = dynamicLightUpRate;
3053 builder.uniform("dynamicLightUpDeg") = dynamicLightUpDeg;
3054 return builder.makeBlender();
3055 #else
3056 static constexpr char prog[] = R"(
3057 uniform half dynamicLightUpRate;
3058 uniform half dynamicLightUpDeg;
3059 uniform shader imageShader;
3060
3061 vec4 main(vec4 src, vec4 dst) {
3062 float x = 0.299 * dst.r + 0.587 * dst.g + 0.114 * dst.b;
3063 float y = (0 - dynamicLightUpRate) * x + dynamicLightUpDeg;
3064 float R = clamp((dst.r + y), 0.0, 1.0);
3065 float G = clamp((dst.g + y), 0.0, 1.0);
3066 float B = clamp((dst.b + y), 0.0, 1.0);
3067 return vec4(R, G, B, 1.0);
3068 }
3069 )";
3070 if (dynamicLightUpBlenderEffect_ == nullptr) {
3071 dynamicLightUpBlenderEffect_ = Drawing::RuntimeEffect::CreateForBlender(prog);
3072 if (dynamicLightUpBlenderEffect_ == nullptr) {
3073 ROSEN_LOGE("MakeDynamicLightUpBlender::MakeDynamicLightUpBlender effect error!\n");
3074 return nullptr;
3075 }
3076 }
3077 std::shared_ptr<Drawing::RuntimeBlenderBuilder> builder =
3078 std::make_shared<Drawing::RuntimeBlenderBuilder>(dynamicLightUpBlenderEffect_);
3079 builder->SetUniform("dynamicLightUpRate", dynamicLightUpRate);
3080 builder->SetUniform("dynamicLightUpDeg", dynamicLightUpDeg);
3081 return builder->MakeBlender();
3082 #endif
3083 }
3084
DrawParticle(const RSProperties & properties,RSPaintFilterCanvas & canvas)3085 void RSPropertiesPainter::DrawParticle(const RSProperties& properties, RSPaintFilterCanvas& canvas)
3086 {
3087 const auto& particleVector = properties.GetParticles();
3088 if (particleVector.GetParticleSize() == 0) {
3089 return;
3090 }
3091 const auto& particles = particleVector.GetParticleVector();
3092 auto bounds = properties.GetDrawRegion();
3093 for (const auto& particle : particles) {
3094 if (particle != nullptr && particle->IsAlive()) {
3095 // Get particle properties
3096 auto position = particle->GetPosition();
3097 float opacity = particle->GetOpacity();
3098 float scale = particle->GetScale();
3099 if (!(bounds->Intersect(position.x_, position.y_)) || opacity <= 0.f || scale <= 0.f) {
3100 continue;
3101 }
3102 auto particleType = particle->GetParticleType();
3103 #ifndef USE_ROSEN_DRAWING
3104 SkPaint paint;
3105 paint.setAntiAlias(true);
3106 paint.setAlphaf(opacity);
3107 auto clipBounds = SkRect::MakeXYWH(bounds->left_, bounds->top_, bounds->width_, bounds->height_);
3108 canvas.clipRect(clipBounds, true);
3109 #else
3110 Drawing::Brush brush;
3111 brush.SetAntiAlias(true);
3112 brush.SetAlphaF(opacity);
3113 auto clipBounds = Drawing::Rect(
3114 bounds->left_, bounds->top_, bounds->left_ + bounds->width_, bounds->top_ + bounds->height_);
3115 canvas.ClipRect(clipBounds, Drawing::ClipOp::INTERSECT, true);
3116 #endif
3117
3118 if (particleType == ParticleType::POINTS) {
3119 auto radius = particle->GetRadius();
3120 Color color = particle->GetColor();
3121 auto alpha = color.GetAlpha();
3122 color.SetAlpha(alpha * opacity);
3123 #ifndef USE_ROSEN_DRAWING
3124 paint.setColor(color.AsArgbInt());
3125 canvas.drawCircle(position.x_, position.y_, radius * scale, paint);
3126 #else
3127 brush.SetColor(color.AsArgbInt());
3128 canvas.AttachBrush(brush);
3129 canvas.DrawCircle(Drawing::Point(position.x_, position.y_), radius * scale);
3130 canvas.DetachBrush();
3131 #endif
3132 } else {
3133 auto imageSize = particle->GetImageSize();
3134 auto image = particle->GetImage();
3135 float left = position.x_;
3136 float top = position.y_;
3137 float right = position.x_ + imageSize.x_ * scale;
3138 float bottom = position.y_ + imageSize.y_ * scale;
3139 #ifndef USE_ROSEN_DRAWING
3140 canvas.save();
3141 canvas.translate(position.x_, position.y_);
3142 canvas.rotate(particle->GetSpin(), imageSize.x_ * scale / 2.f, imageSize.y_ * scale / 2.f);
3143 #else
3144 canvas.Save();
3145 canvas.Translate(position.x_, position.y_);
3146 canvas.Rotate(particle->GetSpin(), imageSize.x_ * scale / 2.f, imageSize.y_ * scale / 2.f);
3147 #endif
3148 RectF destRect(left, top, right, bottom);
3149 image->SetDstRect(destRect);
3150 image->SetScale(scale);
3151 image->SetImageRepeat(0);
3152 #ifndef USE_ROSEN_DRAWING
3153 SkRect rect { left, top, right, bottom };
3154 image->CanvasDrawImage(canvas, rect, SkSamplingOptions(), paint, false);
3155 canvas.restore();
3156 #else
3157 Drawing::Rect rect { left, top, right, bottom };
3158 canvas.AttachBrush(brush);
3159 image->CanvasDrawImage(canvas, rect, Drawing::SamplingOptions(), false);
3160 canvas.DetachBrush();
3161 canvas.Restore();
3162 #endif
3163 }
3164 }
3165 }
3166 }
3167
BeginBlendMode(RSPaintFilterCanvas & canvas,const RSProperties & properties)3168 void RSPropertiesPainter::BeginBlendMode(RSPaintFilterCanvas& canvas, const RSProperties& properties)
3169 {
3170 auto blendMode = properties.GetColorBlendMode();
3171 int blendModeApplyType = properties.GetColorBlendApplyType();
3172
3173 if (blendMode == 0) {
3174 // no blend
3175 return;
3176 }
3177
3178 #ifndef USE_ROSEN_DRAWING
3179 canvas.save();
3180 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
3181 #else
3182 canvas.Save();
3183 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, true);
3184 #endif
3185
3186 // fast blend mode
3187 if (blendModeApplyType == static_cast<int>(RSColorBlendApplyType::FAST)) {
3188 canvas.SaveBlendMode();
3189 canvas.SetBlendMode({ blendMode - 1 }); // map blendMode to SkBlendMode
3190 return;
3191 }
3192
3193 // save layer mode
3194 #ifndef USE_ROSEN_DRAWING
3195 auto matrix = canvas.getTotalMatrix();
3196 matrix.setTranslateX(std::ceil(matrix.getTranslateX()));
3197 matrix.setTranslateY(std::ceil(matrix.getTranslateY()));
3198 canvas.setMatrix(matrix);
3199 SkPaint blendPaint_;
3200 blendPaint_.setAlphaf(canvas.GetAlpha());
3201 blendPaint_.setBlendMode(static_cast<SkBlendMode>(blendMode - 1)); // map blendMode to SkBlendMode
3202 canvas.saveLayer(nullptr, &blendPaint_);
3203 #else
3204 auto matrix = canvas.GetTotalMatrix();
3205 matrix.Set(Drawing::Matrix::TRANS_X, std::ceil(matrix.Get(Drawing::Matrix::TRANS_X)));
3206 matrix.Set(Drawing::Matrix::TRANS_Y, std::ceil(matrix.Get(Drawing::Matrix::TRANS_Y)));
3207 canvas.SetMatrix(matrix);
3208 Drawing::Brush blendBrush_;
3209 blendBrush_.SetAlphaF(canvas.GetAlpha());
3210 blendBrush_.SetBlendMode(static_cast<Drawing::BlendMode>(blendMode - 1)); // map blendMode to Drawing::BlendMode
3211 Drawing::SaveLayerOps maskLayerRec(nullptr, &blendBrush_, 0);
3212 canvas.SaveLayer(maskLayerRec);
3213 #endif
3214 canvas.SaveBlendMode();
3215 canvas.SetBlendMode(std::nullopt);
3216 canvas.SaveAlpha();
3217 canvas.SetAlpha(1.0f);
3218 }
3219
EndBlendMode(RSPaintFilterCanvas & canvas,const RSProperties & properties)3220 void RSPropertiesPainter::EndBlendMode(RSPaintFilterCanvas& canvas, const RSProperties& properties)
3221 {
3222 auto blendMode = properties.GetColorBlendMode();
3223 int blendModeApplyType = properties.GetColorBlendApplyType();
3224
3225 if (blendMode == 0) {
3226 // no blend
3227 return;
3228 }
3229
3230 if (blendModeApplyType == static_cast<int>(RSColorBlendApplyType::FAST)) {
3231 canvas.RestoreBlendMode();
3232 } else {
3233 canvas.RestoreBlendMode();
3234 canvas.RestoreAlpha();
3235 #ifndef USE_ROSEN_DRAWING
3236 canvas.restore();
3237 #else
3238 canvas.Restore();
3239 #endif
3240 }
3241 #ifndef USE_ROSEN_DRAWING
3242 canvas.restore();
3243 #else
3244 canvas.Restore();
3245 #endif
3246 }
3247 } // namespace Rosen
3248 } // namespace OHOS
3249