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
18 #include "common/rs_optional_trace.h"
19 #include "common/rs_obj_abs_geometry.h"
20 #include "common/rs_vector2.h"
21 #include "pipeline/rs_draw_cmd_list.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 "render/rs_blur_filter.h"
26 #include "render/rs_image.h"
27 #include "render/rs_mask.h"
28 #include "render/rs_path.h"
29 #include "render/rs_shader.h"
30 #include "render/rs_skia_filter.h"
31 #include "animation/rs_render_particle.h"
32
33 #ifdef USE_ROSEN_DRAWING
34 #include <cstdint>
35
36 #include "draw/canvas.h"
37 #include "draw/clip.h"
38 #include "drawing/draw/core_canvas.h"
39 #include "recording/recording_path.h"
40 #include "recording/recording_shader_effect.h"
41 #include "utils/rect.h"
42 #else
43 #include "include/core/SkCanvas.h"
44 #include "include/core/SkColorFilter.h"
45 #include "include/core/SkMaskFilter.h"
46 #include "include/core/SkPaint.h"
47 #include "include/core/SkPoint3.h"
48 #include "include/core/SkRRect.h"
49 #include "include/core/SkSurface.h"
50 #include "include/effects/Sk1DPathEffect.h"
51 #include "include/effects/SkDashPathEffect.h"
52 #include "include/effects/SkGradientShader.h"
53 #include "include/effects/SkLumaColorFilter.h"
54 #include "include/utils/SkShadowUtils.h"
55 #include "src/image/SkImage_Base.h"
56 #ifdef NEW_SKIA
57 #include "include/effects/SkImageFilters.h"
58 #include "include/effects/SkRuntimeEffect.h"
59 #else
60 #include "include/effects/SkBlurImageFilter.h"
61 #endif
62 #endif
63
64 namespace OHOS {
65 namespace Rosen {
66 namespace {
67 bool g_forceBgAntiAlias = true;
68 constexpr int PARAM_DOUBLE = 2;
69 constexpr float MIN_TRANS_RATIO = 0.0f;
70 constexpr float MAX_TRANS_RATIO = 0.95f;
71 constexpr float MIN_SPOT_RATIO = 1.0f;
72 constexpr float MAX_SPOT_RATIO = 1.95f;
73 constexpr float MAX_AMBIENT_RADIUS = 150.0f;
74 const bool BLUR_ENABLED = RSSystemProperties::GetBlurEnabled();
75 #ifndef USE_ROSEN_DRAWING
76 constexpr static float FLOAT_ZERO_THRESHOLD = 0.001f;
77 constexpr static uint8_t DIRECTION_NUM = 4;
78 #endif
79 } // namespace
80
81 #ifndef USE_ROSEN_DRAWING
Rect2SkRect(const RectF & r)82 SkRect RSPropertiesPainter::Rect2SkRect(const RectF& r)
83 {
84 return SkRect::MakeXYWH(r.left_, r.top_, r.width_, r.height_);
85 }
86 #else
Rect2DrawingRect(const RectF & r)87 Drawing::Rect RSPropertiesPainter::Rect2DrawingRect(const RectF& r)
88 {
89 return Drawing::Rect(r.left_, r.top_, r.left_ + r.width_, r.top_ + r.height_);
90 }
91 #endif
92
93 #ifndef USE_ROSEN_DRAWING
RRect2SkRRect(const RRect & rr)94 SkRRect RSPropertiesPainter::RRect2SkRRect(const RRect& rr)
95 {
96 SkRect rect = SkRect::MakeXYWH(rr.rect_.left_, rr.rect_.top_, rr.rect_.width_, rr.rect_.height_);
97 SkRRect rrect = SkRRect::MakeEmpty();
98
99 // set radius for all 4 corner of RRect
100 constexpr uint32_t NUM_OF_CORNERS_IN_RECT = 4;
101 SkVector vec[NUM_OF_CORNERS_IN_RECT];
102 for (uint32_t i = 0; i < NUM_OF_CORNERS_IN_RECT; i++) {
103 vec[i].set(rr.radius_[i].x_, rr.radius_[i].y_);
104 }
105
106 rrect.setRectRadii(rect, vec);
107 return rrect;
108 }
109 #else
RRect2DrawingRRect(const RRect & rr)110 Drawing::RoundRect RSPropertiesPainter::RRect2DrawingRRect(const RRect& rr)
111 {
112 Drawing::Rect rect = Drawing::Rect(
113 rr.rect_.left_, rr.rect_.top_, rr.rect_.left_ + rr.rect_.width_, rr.rect_.top_ + rr.rect_.height_);
114
115 // set radius for all 4 corner of RRect
116 constexpr uint32_t NUM_OF_CORNERS_IN_RECT = 4;
117 std::vector<Drawing::Point> radii(NUM_OF_CORNERS_IN_RECT);
118 for (uint32_t i = 0; i < NUM_OF_CORNERS_IN_RECT; i++) {
119 radii.at(i).SetX(rr.radius_[i].x_);
120 radii.at(i).SetY(rr.radius_[i].y_);
121 }
122 return Drawing::RoundRect(rect, radii);
123 }
124 #endif
125
126 #ifndef USE_ROSEN_DRAWING
GetGravityMatrix(Gravity gravity,RectF rect,float w,float h,SkMatrix & mat)127 bool RSPropertiesPainter::GetGravityMatrix(Gravity gravity, RectF rect, float w, float h, SkMatrix& mat)
128 {
129 if (w == rect.width_ && h == rect.height_) {
130 return false;
131 }
132 mat.reset();
133 switch (gravity) {
134 case Gravity::CENTER: {
135 mat.preTranslate((rect.width_ - w) / PARAM_DOUBLE, (rect.height_ - h) / PARAM_DOUBLE);
136 return true;
137 }
138 case Gravity::TOP: {
139 mat.preTranslate((rect.width_ - w) / PARAM_DOUBLE, 0);
140 return true;
141 }
142 case Gravity::BOTTOM: {
143 mat.preTranslate((rect.width_ - w) / PARAM_DOUBLE, rect.height_ - h);
144 return true;
145 }
146 case Gravity::LEFT: {
147 mat.preTranslate(0, (rect.height_ - h) / PARAM_DOUBLE);
148 return true;
149 }
150 case Gravity::RIGHT: {
151 mat.preTranslate(rect.width_ - w, (rect.height_ - h) / PARAM_DOUBLE);
152 return true;
153 }
154 case Gravity::TOP_LEFT: {
155 return false;
156 }
157 case Gravity::TOP_RIGHT: {
158 mat.preTranslate(rect.width_ - w, 0);
159 return true;
160 }
161 case Gravity::BOTTOM_LEFT: {
162 mat.preTranslate(0, rect.height_ - h);
163 return true;
164 }
165 case Gravity::BOTTOM_RIGHT: {
166 mat.preTranslate(rect.width_ - w, rect.height_ - h);
167 return true;
168 }
169 case Gravity::RESIZE: {
170 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
171 return false;
172 }
173 mat.preScale(rect.width_ / w, rect.height_ / h);
174 return true;
175 }
176 case Gravity::RESIZE_ASPECT: {
177 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
178 return false;
179 }
180 float scale = std::min(rect.width_ / w, rect.height_ / h);
181 if (ROSEN_EQ(scale, 0.f)) {
182 return false;
183 }
184 mat.preScale(scale, scale);
185 mat.preTranslate((rect.width_ / scale - w) / PARAM_DOUBLE, (rect.height_ / scale - h) / PARAM_DOUBLE);
186 return true;
187 }
188 case Gravity::RESIZE_ASPECT_TOP_LEFT: {
189 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
190 return false;
191 }
192 float scale = std::min(rect.width_ / w, rect.height_ / h);
193 mat.preScale(scale, scale);
194 return true;
195 }
196 case Gravity::RESIZE_ASPECT_BOTTOM_RIGHT: {
197 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
198 return false;
199 }
200 float scale = std::min(rect.width_ / w, rect.height_ / h);
201 if (ROSEN_EQ(scale, 0.f)) {
202 return false;
203 }
204 mat.preScale(scale, scale);
205 mat.preTranslate(rect.width_ / scale - w, rect.height_ / scale - h);
206 return true;
207 }
208 case Gravity::RESIZE_ASPECT_FILL: {
209 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
210 return false;
211 }
212 float scale = std::max(rect.width_ / w, rect.height_ / h);
213 if (ROSEN_EQ(scale, 0.f)) {
214 return false;
215 }
216 mat.preScale(scale, scale);
217 mat.preTranslate((rect.width_ / scale - w) / PARAM_DOUBLE, (rect.height_ / scale - h) / PARAM_DOUBLE);
218 return true;
219 }
220 case Gravity::RESIZE_ASPECT_FILL_TOP_LEFT: {
221 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
222 return false;
223 }
224 float scale = std::max(rect.width_ / w, rect.height_ / h);
225 mat.preScale(scale, scale);
226 return true;
227 }
228 case Gravity::RESIZE_ASPECT_FILL_BOTTOM_RIGHT: {
229 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
230 return false;
231 }
232 float scale = std::max(rect.width_ / w, rect.height_ / h);
233 if (ROSEN_EQ(scale, 0.f)) {
234 return false;
235 }
236 mat.preScale(scale, scale);
237 mat.preTranslate(rect.width_ / scale - w, rect.height_ / scale - h);
238 return true;
239 }
240 default: {
241 ROSEN_LOGE("GetGravityMatrix unknow gravity=[%d]", gravity);
242 return false;
243 }
244 }
245 }
246 #else
GetGravityMatrix(Gravity gravity,RectF rect,float w,float h,Drawing::Matrix & mat)247 bool RSPropertiesPainter::GetGravityMatrix(Gravity gravity, RectF rect, float w, float h, Drawing::Matrix& mat)
248 {
249 if (w == rect.width_ && h == rect.height_) {
250 return false;
251 }
252 mat = Drawing::Matrix();
253 switch (gravity) {
254 case Gravity::CENTER: {
255 mat.PreTranslate((rect.width_ - w) / PARAM_DOUBLE, (rect.height_ - h) / PARAM_DOUBLE);
256 return true;
257 }
258 case Gravity::TOP: {
259 mat.PreTranslate((rect.width_ - w) / PARAM_DOUBLE, 0);
260 return true;
261 }
262 case Gravity::BOTTOM: {
263 mat.PreTranslate((rect.width_ - w) / PARAM_DOUBLE, rect.height_ - h);
264 return true;
265 }
266 case Gravity::LEFT: {
267 mat.PreTranslate(0, (rect.height_ - h) / PARAM_DOUBLE);
268 return true;
269 }
270 case Gravity::RIGHT: {
271 mat.PreTranslate(rect.width_ - w, (rect.height_ - h) / PARAM_DOUBLE);
272 return true;
273 }
274 case Gravity::TOP_LEFT: {
275 return false;
276 }
277 case Gravity::TOP_RIGHT: {
278 mat.PreTranslate(rect.width_ - w, 0);
279 return true;
280 }
281 case Gravity::BOTTOM_LEFT: {
282 mat.PreTranslate(0, rect.height_ - h);
283 return true;
284 }
285 case Gravity::BOTTOM_RIGHT: {
286 mat.PreTranslate(rect.width_ - w, rect.height_ - h);
287 return true;
288 }
289 case Gravity::RESIZE: {
290 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
291 return false;
292 }
293 mat.PreScale(rect.width_ / w, rect.height_ / h);
294 return true;
295 }
296 case Gravity::RESIZE_ASPECT: {
297 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
298 return false;
299 }
300 float scale = std::min(rect.width_ / w, rect.height_ / h);
301 if (ROSEN_EQ(scale, 0.f)) {
302 return false;
303 }
304 mat.PreScale(scale, scale);
305 mat.PreTranslate((rect.width_ / scale - w) / PARAM_DOUBLE, (rect.height_ / scale - h) / PARAM_DOUBLE);
306 return true;
307 }
308 case Gravity::RESIZE_ASPECT_TOP_LEFT: {
309 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
310 return false;
311 }
312 float scale = std::min(rect.width_ / w, rect.height_ / h);
313 mat.PreScale(scale, scale);
314 return true;
315 }
316 case Gravity::RESIZE_ASPECT_BOTTOM_RIGHT: {
317 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
318 return false;
319 }
320 float scale = std::min(rect.width_ / w, rect.height_ / h);
321 if (ROSEN_EQ(scale, 0.f)) {
322 return false;
323 }
324 mat.PreScale(scale, scale);
325 mat.PreTranslate(rect.width_ / scale - w, rect.height_ / scale - h);
326 return true;
327 }
328 case Gravity::RESIZE_ASPECT_FILL: {
329 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
330 return false;
331 }
332 float scale = std::max(rect.width_ / w, rect.height_ / h);
333 if (ROSEN_EQ(scale, 0.f)) {
334 return false;
335 }
336 mat.PreScale(scale, scale);
337 mat.PreTranslate((rect.width_ / scale - w) / PARAM_DOUBLE, (rect.height_ / scale - h) / PARAM_DOUBLE);
338 return true;
339 }
340 case Gravity::RESIZE_ASPECT_FILL_TOP_LEFT: {
341 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
342 return false;
343 }
344 float scale = std::max(rect.width_ / w, rect.height_ / h);
345 mat.PreScale(scale, scale);
346 return true;
347 }
348 case Gravity::RESIZE_ASPECT_FILL_BOTTOM_RIGHT: {
349 if (ROSEN_EQ(w, 0.f) || ROSEN_EQ(h, 0.f)) {
350 return false;
351 }
352 float scale = std::max(rect.width_ / w, rect.height_ / h);
353 if (ROSEN_EQ(scale, 0.f)) {
354 return false;
355 }
356 mat.PreScale(scale, scale);
357 mat.PreTranslate(rect.width_ / scale - w, rect.height_ / scale - h);
358 return true;
359 }
360 default: {
361 ROSEN_LOGE("GetGravityMatrix unknow gravity=[%d]", gravity);
362 return false;
363 }
364 }
365 }
366 #endif
367
368 #ifndef USE_ROSEN_DRAWING
Clip(SkCanvas & canvas,RectF rect,bool isAntiAlias)369 void RSPropertiesPainter::Clip(SkCanvas& canvas, RectF rect, bool isAntiAlias)
370 {
371 // isAntiAlias is false only the method is called in ProcessAnimatePropertyBeforeChildren().
372 canvas.clipRect(Rect2SkRect(rect), isAntiAlias);
373 }
374 #else
Clip(Drawing::Canvas & canvas,RectF rect,bool isAntiAlias)375 void RSPropertiesPainter::Clip(Drawing::Canvas& canvas, RectF rect, bool isAntiAlias)
376 {
377 canvas.ClipRect(Rect2DrawingRect(rect), Drawing::ClipOp::INTERSECT, isAntiAlias);
378 }
379 #endif
380
381 #ifndef USE_ROSEN_DRAWING
GetShadowDirtyRect(RectI & dirtyShadow,const RSProperties & properties,const RRect * rrect,bool isAbsCoordinate)382 void RSPropertiesPainter::GetShadowDirtyRect(RectI& dirtyShadow, const RSProperties& properties,
383 const RRect* rrect, bool isAbsCoordinate)
384 {
385 // [Planning]: After Skia being updated, we should directly call SkShadowUtils::GetLocalBounds here.
386 if (!properties.IsShadowValid()) {
387 return;
388 }
389 SkPath skPath;
390 if (properties.GetShadowPath() && !properties.GetShadowPath()->GetSkiaPath().isEmpty()) {
391 skPath = properties.GetShadowPath()->GetSkiaPath();
392 } else if (properties.GetClipBounds()) {
393 skPath = properties.GetClipBounds()->GetSkiaPath();
394 } else {
395 if (rrect != nullptr) {
396 skPath.addRRect(RRect2SkRRect(*rrect));
397 } else {
398 skPath.addRRect(RRect2SkRRect(properties.GetRRect()));
399 }
400 }
401 skPath.offset(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
402
403 SkRect shadowRect = skPath.getBounds();
404 if (properties.shadow_->GetHardwareAcceleration()) {
405 if (properties.GetShadowElevation() <= 0.f) {
406 return;
407 }
408 float elevation = properties.GetShadowElevation() + DEFAULT_TRANSLATION_Z;
409
410 float userTransRatio =
411 (elevation != DEFAULT_LIGHT_HEIGHT) ? elevation / (DEFAULT_LIGHT_HEIGHT - elevation) : MAX_TRANS_RATIO;
412 float transRatio = std::max(MIN_TRANS_RATIO, std::min(userTransRatio, MAX_TRANS_RATIO));
413
414 float userSpotRatio = (elevation != DEFAULT_LIGHT_HEIGHT)
415 ? DEFAULT_LIGHT_HEIGHT / (DEFAULT_LIGHT_HEIGHT - elevation)
416 : MAX_SPOT_RATIO;
417 float spotRatio = std::max(MIN_SPOT_RATIO, std::min(userSpotRatio, MAX_SPOT_RATIO));
418
419 SkRect ambientRect = skPath.getBounds();
420 SkRect spotRect = SkRect::MakeLTRB(ambientRect.left() * spotRatio, ambientRect.top() * spotRatio,
421 ambientRect.right() * spotRatio, ambientRect.bottom() * spotRatio);
422 spotRect.offset(-transRatio * DEFAULT_LIGHT_POSITION_X, -transRatio * DEFAULT_LIGHT_POSITION_Y);
423 spotRect.outset(transRatio * DEFAULT_LIGHT_RADIUS, transRatio * DEFAULT_LIGHT_RADIUS);
424
425 shadowRect = ambientRect;
426 float ambientBlur = std::min(elevation * 0.5f, MAX_AMBIENT_RADIUS);
427 shadowRect.outset(ambientBlur, ambientBlur);
428 shadowRect.join(spotRect);
429 shadowRect.outset(1, 1);
430 } else {
431 SkPaint paint;
432 paint.setAntiAlias(true);
433 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, properties.GetShadowRadius()));
434 if (paint.canComputeFastBounds()) {
435 paint.computeFastBounds(shadowRect, &shadowRect);
436 }
437 }
438
439 auto geoPtr = (properties.GetBoundsGeometry());
440 SkMatrix matrix = (geoPtr && isAbsCoordinate) ? geoPtr->GetAbsMatrix() : SkMatrix::I();
441 matrix.mapRect(&shadowRect);
442
443 dirtyShadow.left_ = shadowRect.left();
444 dirtyShadow.top_ = shadowRect.top();
445 dirtyShadow.width_ = shadowRect.width();
446 dirtyShadow.height_ = shadowRect.height();
447 }
448 #else
GetShadowDirtyRect(RectI & dirtyShadow,const RSProperties & properties,const RRect * rrect,bool isAbsCoordinate)449 void RSPropertiesPainter::GetShadowDirtyRect(RectI& dirtyShadow, const RSProperties& properties,
450 const RRect* rrect, bool isAbsCoordinate)
451 {
452 // [Planning]: After Skia being updated, we should directly call SkShadowUtils::GetLocalBounds here.
453 if (!properties.IsShadowValid()) {
454 return;
455 }
456 Drawing::Path path;
457 if (properties.GetShadowPath() && !properties.GetShadowPath()->GetDrawingPath().IsValid()) {
458 path = properties.GetShadowPath()->GetDrawingPath();
459 } else if (properties.GetClipBounds()) {
460 path = properties.GetClipBounds()->GetDrawingPath();
461 } else {
462 if (rrect != nullptr) {
463 path.AddRoundRect(RRect2DrawingRRect(*rrect));
464 } else {
465 path.AddRoundRect(RRect2DrawingRRect(properties.GetRRect()));
466 }
467 }
468 path.Offset(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
469
470 Drawing::Rect shadowRect = path.GetBounds();
471 if (properties.shadow_->GetHardwareAcceleration()) {
472 if (properties.GetShadowElevation() <= 0.f) {
473 return;
474 }
475 float elevation = properties.GetShadowElevation() + DEFAULT_TRANSLATION_Z;
476
477 float userTransRatio =
478 (elevation != DEFAULT_LIGHT_HEIGHT) ? elevation / (DEFAULT_LIGHT_HEIGHT - elevation) : MAX_TRANS_RATIO;
479 float transRatio = std::max(MIN_TRANS_RATIO, std::min(userTransRatio, MAX_TRANS_RATIO));
480
481 float userSpotRatio = (elevation != DEFAULT_LIGHT_HEIGHT)
482 ? DEFAULT_LIGHT_HEIGHT / (DEFAULT_LIGHT_HEIGHT - elevation)
483 : MAX_SPOT_RATIO;
484 float spotRatio = std::max(MIN_SPOT_RATIO, std::min(userSpotRatio, MAX_SPOT_RATIO));
485
486 Drawing::Rect ambientRect = path.GetBounds();
487 Drawing::Rect spotRect = Drawing::Rect(ambientRect.GetLeft() * spotRatio, ambientRect.GetTop() * spotRatio,
488 ambientRect.GetRight() * spotRatio, ambientRect.GetBottom() * spotRatio);
489 spotRect.Offset(-transRatio * DEFAULT_LIGHT_POSITION_X, -transRatio * DEFAULT_LIGHT_POSITION_Y);
490 // spotRect outset (transRatio * DEFAULT_LIGHT_RADIUS, transRatio * DEFAULT_LIGHT_RADIUS)
491 spotRect.SetLeft(spotRect.GetLeft() - transRatio * DEFAULT_LIGHT_RADIUS);
492 spotRect.SetTop(spotRect.GetTop() - transRatio * DEFAULT_LIGHT_RADIUS);
493 spotRect.SetRight(spotRect.GetRight() + transRatio * DEFAULT_LIGHT_RADIUS);
494 spotRect.SetBottom(spotRect.GetBottom() + transRatio * DEFAULT_LIGHT_RADIUS);
495
496 shadowRect = ambientRect;
497 std::min(elevation * 0.5f, MAX_AMBIENT_RADIUS);
498 float ambientBlur = std::min(elevation * 0.5f, MAX_AMBIENT_RADIUS);
499 // shadowRect outset (ambientBlur, ambientBlur)
500 shadowRect.SetLeft(shadowRect.GetLeft() - ambientBlur);
501 shadowRect.SetTop(shadowRect.GetTop() - ambientBlur);
502 shadowRect.SetRight(shadowRect.GetRight() + ambientBlur);
503 shadowRect.SetBottom(shadowRect.GetBottom() + ambientBlur);
504
505 shadowRect.Join(spotRect);
506 // shadowRect outset (1, 1)
507 shadowRect.SetLeft(shadowRect.GetLeft() - 1);
508 shadowRect.SetTop(shadowRect.GetTop() - 1);
509 shadowRect.SetRight(shadowRect.GetRight() + 1);
510 shadowRect.SetBottom(shadowRect.GetBottom() + 1);
511 } else {
512 Drawing::Brush brush;
513 brush.SetAntiAlias(true);
514 Drawing::Filter filter;
515 filter.SetMaskFilter(
516 Drawing::MaskFilter::CreateBlurMaskFilter(Drawing::BlurType::NORMAL, properties.GetShadowRadius()));
517 brush.SetFilter(filter);
518 }
519
520 auto geoPtr = (properties.GetBoundsGeometry());
521 Drawing::Matrix matrix = geoPtr ? geoPtr->GetAbsMatrix() : Drawing::Matrix();
522 matrix.MapRect(shadowRect, shadowRect);
523
524 dirtyShadow.left_ = shadowRect.GetLeft();
525 dirtyShadow.top_ = shadowRect.GetTop();
526 dirtyShadow.width_ = shadowRect.GetWidth();
527 dirtyShadow.height_ = shadowRect.GetHeight();
528 }
529 #endif
530
531 #ifndef USE_ROSEN_DRAWING
DrawShadow(const RSProperties & properties,RSPaintFilterCanvas & canvas,const RRect * rrect,bool isLeashWindow)532 void RSPropertiesPainter::DrawShadow(const RSProperties& properties,
533 RSPaintFilterCanvas& canvas, const RRect* rrect, bool isLeashWindow)
534 {
535 // skip shadow if not valid or cache is enabled
536 if (properties.IsSpherizeValid() || !properties.IsShadowValid() ||
537 canvas.GetCacheType() == RSPaintFilterCanvas::CacheType::ENABLED) {
538 return;
539 }
540 RSAutoCanvasRestore acr(&canvas);
541 SkPath skPath;
542 if (properties.GetShadowPath() && !properties.GetShadowPath()->GetSkiaPath().isEmpty()) {
543 skPath = properties.GetShadowPath()->GetSkiaPath();
544 if (!isLeashWindow) {
545 canvas.clipPath(skPath, SkClipOp::kDifference, true);
546 }
547 } else if (properties.GetClipBounds()) {
548 skPath = properties.GetClipBounds()->GetSkiaPath();
549 if (!isLeashWindow) {
550 canvas.clipPath(skPath, SkClipOp::kDifference, true);
551 }
552 } else {
553 if (rrect != nullptr) {
554 skPath.addRRect(RRect2SkRRect(*rrect));
555 if (!isLeashWindow) {
556 canvas.clipRRect(RRect2SkRRect(*rrect), SkClipOp::kDifference, true);
557 }
558 } else {
559 skPath.addRRect(RRect2SkRRect(properties.GetRRect()));
560 if (!isLeashWindow) {
561 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), SkClipOp::kDifference, true);
562 }
563 }
564 }
565 if (properties.GetShadowMask()) {
566 DrawColorfulShadowInner(properties, canvas, skPath);
567 } else {
568 DrawShadowInner(properties, canvas, skPath);
569 }
570 }
571 #else
DrawShadow(const RSProperties & properties,RSPaintFilterCanvas & canvas,const RRect * rrect,bool isLeashWindow)572 void RSPropertiesPainter::DrawShadow(const RSProperties& properties,
573 RSPaintFilterCanvas& canvas, const RRect* rrect, bool isLeashWindow)
574 {
575 // skip shadow if not valid or cache is enabled
576 //Todo isCacheEnabled
577 if (properties.IsSpherizeValid() || !properties.IsShadowValid()) {
578 return;
579 }
580 Drawing::AutoCanvasRestore acr(canvas, true);
581 Drawing::Path path;
582 if (properties.GetShadowPath() && !properties.GetShadowPath()->GetDrawingPath().IsValid()) {
583 path = properties.GetShadowPath()->GetDrawingPath();
584 if (!isLeashWindow) {
585 canvas.ClipPath(path, Drawing::ClipOp::DIFFERENCE, true);
586 }
587 } else if (properties.GetClipBounds()) {
588 path = properties.GetClipBounds()->GetDrawingPath();
589 if (!isLeashWindow) {
590 canvas.ClipPath(path, Drawing::ClipOp::DIFFERENCE, true);
591 }
592 } else {
593 if (rrect != nullptr) {
594 path.AddRoundRect(RRect2DrawingRRect(*rrect));
595 if (!isLeashWindow) {
596 canvas.ClipRoundRect(RRect2DrawingRRect(*rrect), Drawing::ClipOp::DIFFERENCE, true);
597 }
598 } else {
599 path.AddRoundRect(RRect2DrawingRRect(properties.GetRRect()));
600 if (!isLeashWindow) {
601 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::DIFFERENCE, true);
602 }
603 }
604 }
605 if (properties.GetShadowMask()) {
606 DrawColorfulShadowInner(properties, canvas, path);
607 } else {
608 DrawShadowInner(properties, canvas, path);
609 }
610 }
611 #endif
612
613 #ifndef USE_ROSEN_DRAWING
DrawColorfulShadowInner(const RSProperties & properties,RSPaintFilterCanvas & canvas,SkPath & skPath)614 void RSPropertiesPainter::DrawColorfulShadowInner(
615 const RSProperties& properties, RSPaintFilterCanvas& canvas, SkPath& skPath)
616 {
617 // blurRadius calculation is based on the formula in SkShadowUtils::DrawShadow, 0.25f and 128.0f are constants
618 const SkScalar blurRadius =
619 properties.shadow_->GetHardwareAcceleration()
620 ? 0.25f * properties.GetShadowElevation() * (1 + properties.GetShadowElevation() / 128.0f)
621 : properties.GetShadowRadius();
622
623 // save layer, draw image with clipPath, blur and draw back
624 SkPaint blurPaint;
625 #ifdef NEW_SKIA
626 blurPaint.setImageFilter(SkImageFilters::Blur(blurRadius, blurRadius, SkTileMode::kDecal, nullptr));
627 #else
628 blurPaint.setImageFilter(SkBlurImageFilter::Make(blurRadius, blurRadius, SkTileMode::kDecal, nullptr));
629 #endif
630 canvas.saveLayer(nullptr, &blurPaint);
631
632 canvas.translate(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
633
634 canvas.clipPath(skPath);
635 // draw node content as shadow
636 // [PLANNING]: maybe we should also draw background color / image here, and we should cache the shadow image
637 if (auto node = RSBaseRenderNode::ReinterpretCast<RSCanvasRenderNode>(properties.backref_.lock())) {
638 node->InternalDrawContent(canvas);
639 }
640 }
641 #else
DrawColorfulShadowInner(const RSProperties & properties,RSPaintFilterCanvas & canvas,Drawing::Path & path)642 void RSPropertiesPainter::DrawColorfulShadowInner(
643 const RSProperties& properties, RSPaintFilterCanvas& canvas, Drawing::Path& path)
644 {
645 // blurRadius calculation is based on the formula in Canvas::DrawShadow, 0.25f and 128.0f are constants
646 const Drawing::scalar blurRadius =
647 properties.shadow_->GetHardwareAcceleration()
648 ? 0.25f * properties.GetShadowElevation() * (1 + properties.GetShadowElevation() / 128.0f)
649 : properties.GetShadowRadius();
650
651 // save layer, draw image with clipPath, blur and draw back
652 Drawing::Brush blurBrush;
653 Drawing::Filter filter;
654 filter.SetImageFilter(Drawing::ImageFilter::CreateBlurImageFilter(
655 blurRadius, blurRadius, Drawing::TileMode::DECAL, nullptr));
656 blurBrush.SetFilter(filter);
657
658 canvas.SaveLayer({nullptr, &blurBrush});
659
660 canvas.Translate(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
661
662 canvas.ClipPath(path, Drawing::ClipOp::INTERSECT, false);
663 // draw node content as shadow
664 // [PLANNING]: maybe we should also draw background color / image here, and we should cache the shadow image
665 if (auto node = RSBaseRenderNode::ReinterpretCast<RSCanvasRenderNode>(properties.backref_.lock())) {
666 node->InternalDrawContent(canvas);
667 }
668 }
669 #endif
670
671 #ifndef USE_ROSEN_DRAWING
DrawShadowInner(const RSProperties & properties,RSPaintFilterCanvas & canvas,SkPath & skPath)672 void RSPropertiesPainter::DrawShadowInner(const RSProperties& properties, RSPaintFilterCanvas& canvas, SkPath& skPath)
673 {
674 skPath.offset(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
675 Color spotColor = properties.GetShadowColor();
676
677 // The translation of the matrix is rounded to improve the hit ratio of skia blurfilter cache,
678 // the function <compute_key_and_clip_bounds> in <skia/src/gpu/GrBlurUtil.cpp> for more details.
679 RSAutoCanvasRestore rst(&canvas);
680 auto matrix = canvas.getTotalMatrix();
681 matrix.setTranslateX(std::ceil(matrix.getTranslateX()));
682 matrix.setTranslateY(std::ceil(matrix.getTranslateY()));
683 // Round the scaleX/scaleY to 2 decimal places.
684 matrix.setScaleX(std::round(matrix.getScaleX() * 100) / 100);
685 matrix.setScaleY(std::round(matrix.getScaleY() * 100) / 100);
686 canvas.setMatrix(matrix);
687
688 if (properties.shadow_->GetHardwareAcceleration()) {
689 if (properties.GetShadowElevation() <= 0.f) {
690 return;
691 }
692 SkPoint3 planeParams = { 0.0f, 0.0f, properties.GetShadowElevation() };
693 SkPoint3 lightPos = { canvas.getTotalMatrix().getTranslateX() + skPath.getBounds().centerX(),
694 canvas.getTotalMatrix().getTranslateY() + skPath.getBounds().centerY(), DEFAULT_LIGHT_HEIGHT };
695 Color ambientColor = Color::FromArgbInt(DEFAULT_AMBIENT_COLOR);
696 ambientColor.MultiplyAlpha(canvas.GetAlpha());
697 spotColor.MultiplyAlpha(canvas.GetAlpha());
698 SkShadowUtils::DrawShadow(&canvas, skPath, planeParams, lightPos, DEFAULT_LIGHT_RADIUS,
699 ambientColor.AsArgbInt(), spotColor.AsArgbInt(), SkShadowFlags::kTransparentOccluder_ShadowFlag);
700 } else {
701 SkPaint paint;
702 paint.setColor(spotColor.AsArgbInt());
703 paint.setAntiAlias(true);
704 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, properties.GetShadowRadius()));
705 canvas.drawPath(skPath, paint);
706 }
707 }
708 #else
DrawShadowInner(const RSProperties & properties,RSPaintFilterCanvas & canvas,Drawing::Path & path)709 void RSPropertiesPainter::DrawShadowInner(
710 const RSProperties& properties, RSPaintFilterCanvas& canvas, Drawing::Path& path)
711 {
712 path.Offset(properties.GetShadowOffsetX(), properties.GetShadowOffsetY());
713 Color spotColor = properties.GetShadowColor();
714 if (properties.shadow_->GetHardwareAcceleration()) {
715 if (properties.GetShadowElevation() <= 0.f) {
716 return;
717 }
718 Drawing::Point3 planeParams = { 0.0f, 0.0f, properties.GetShadowElevation() };
719 Drawing::scalar centerX = path.GetBounds().GetLeft() + path.GetBounds().GetWidth() / 2;
720 Drawing::scalar centerY = path.GetBounds().GetTop() + path.GetBounds().GetHeight() / 2;
721 Drawing::Point3 lightPos = {
722 canvas.GetTotalMatrix().Get(Drawing::Matrix::TRANS_X) + centerX,
723 canvas.GetTotalMatrix().Get(Drawing::Matrix::TRANS_X) + centerY, DEFAULT_LIGHT_HEIGHT };
724 Color ambientColor = Color::FromArgbInt(DEFAULT_AMBIENT_COLOR);
725 ambientColor.MultiplyAlpha(canvas.GetAlpha());
726 spotColor.MultiplyAlpha(canvas.GetAlpha());
727 canvas.DrawShadow(path, planeParams, lightPos, DEFAULT_LIGHT_RADIUS,
728 Drawing::Color(ambientColor.AsArgbInt()), Drawing::Color(spotColor.AsArgbInt()),
729 Drawing::ShadowFlags::TRANSPARENT_OCCLUDER);
730 } else {
731 Drawing::Brush brush;
732 brush.SetColor(Drawing::Color(spotColor.AsArgbInt()));
733 brush.SetAntiAlias(true);
734 Drawing::Filter filter;
735 filter.SetMaskFilter(
736 Drawing::MaskFilter::CreateBlurMaskFilter(Drawing::BlurType::NORMAL, properties.GetShadowRadius()));
737 brush.SetFilter(filter);
738 canvas.AttachBrush(brush);
739 canvas.DrawPath(path);
740 canvas.DetachBrush();
741 }
742 }
743 #endif
744
745 #ifndef USE_ROSEN_DRAWING
746 #ifdef NEW_SKIA
GetGradientDirectionPoints(SkPoint (& pts)[2],const SkRect & clipBounds,GradientDirection direction)747 bool RSPropertiesPainter::GetGradientDirectionPoints(
748 SkPoint (&pts)[2], const SkRect& clipBounds, GradientDirection direction)
749 {
750 switch (direction) {
751 case GradientDirection::BOTTOM: {
752 pts[0].set(clipBounds.width() / 2, 0); // 2 represents middle of width;
753 pts[1].set(clipBounds.width() / 2, clipBounds.height()); // 2 represents middle of width;
754 break;
755 }
756 case GradientDirection::TOP: {
757 pts[0].set(clipBounds.width() / 2, clipBounds.height()); // 2 represents middle of width;
758 pts[1].set(clipBounds.width() / 2, 0); // 2 represents middle of width;
759 break;
760 }
761 case GradientDirection::RIGHT: {
762 pts[0].set(0, clipBounds.height() / 2); // 2 represents middle of height;
763 pts[1].set(clipBounds.width(), clipBounds.height() / 2); // 2 represents middle of height;
764 break;
765 }
766 case GradientDirection::LEFT: {
767 pts[0].set(clipBounds.width(), clipBounds.height() / 2); // 2 represents middle of height;
768 pts[1].set(0, clipBounds.height() / 2); // 2 represents middle of height;
769 break;
770 }
771 case GradientDirection::RIGHT_BOTTOM: {
772 pts[0].set(0, 0);
773 pts[1].set(clipBounds.width(), clipBounds.height());
774 break;
775 }
776 case GradientDirection::LEFT_TOP: {
777 pts[0].set(clipBounds.width(), clipBounds.height());
778 pts[1].set(0, 0);
779 break;
780 }
781 case GradientDirection::LEFT_BOTTOM: {
782 pts[0].set(clipBounds.width(), 0);
783 pts[1].set(0, clipBounds.height());
784 break;
785 }
786 case GradientDirection::RIGHT_TOP: {
787 pts[0].set(0, clipBounds.height());
788 pts[1].set(clipBounds.width(), 0);
789 break;
790 }
791 default: {
792 return false;
793 }
794 }
795 return true;
796 }
TransformGradientBlurDirection(uint8_t & direction,const uint8_t directionBias)797 void RSPropertiesPainter::TransformGradientBlurDirection(uint8_t& direction, const uint8_t directionBias)
798 {
799 if (direction == static_cast<uint8_t>(GradientDirection::LEFT_BOTTOM)) {
800 direction += 2; // 2 is used to transtorm diagnal direction.
801 } else if (direction == static_cast<uint8_t>(GradientDirection::RIGHT_TOP) ||
802 direction == static_cast<uint8_t>(GradientDirection::RIGHT_BOTTOM)) {
803 direction -= 1; // 1 is used to transtorm diagnal direction.
804 }
805 if (direction <= static_cast<uint8_t>(GradientDirection::BOTTOM)) {
806 if (direction < directionBias) {
807 direction += DIRECTION_NUM;
808 }
809 direction -= directionBias;
810 } else {
811 direction -= DIRECTION_NUM;
812 if (direction < directionBias) {
813 direction += DIRECTION_NUM;
814 }
815 direction -= directionBias;
816 direction += DIRECTION_NUM;
817 }
818 if (direction == static_cast<uint8_t>(GradientDirection::RIGHT_BOTTOM)) {
819 direction -= 2; // 2 is used to restore diagnal direction.
820 } else if (direction == static_cast<uint8_t>(GradientDirection::LEFT_BOTTOM) ||
821 direction == static_cast<uint8_t>(GradientDirection::RIGHT_TOP)) {
822 direction += 1; // 1 is used to restore diagnal direction.
823 }
824 }
825
MakeAlphaGradientShader(const SkRect & clipBounds,const std::shared_ptr<RSLinearGradientBlurPara> & para,uint8_t directionBias)826 sk_sp<SkShader> RSPropertiesPainter::MakeAlphaGradientShader(
827 const SkRect& clipBounds, const std::shared_ptr<RSLinearGradientBlurPara>& para, uint8_t directionBias)
828 {
829 std::vector<SkColor> c;
830 std::vector<SkScalar> p;
831 SkPoint pts[2];
832 uint8_t direction = static_cast<uint8_t>(para->direction_);
833 if (directionBias != 0) {
834 TransformGradientBlurDirection(direction, directionBias);
835 }
836 bool result = GetGradientDirectionPoints(
837 pts, clipBounds, static_cast<GradientDirection>(direction));
838 if (!result) {
839 return nullptr;
840 }
841 uint8_t ColorMax = 255;
842 uint8_t ColorMin = 0;
843 if (para->fractionStops_[0].second > 0.01) { // 0.01 represents the fraction bias
844 c.emplace_back(SkColorSetARGB(ColorMin, ColorMax, ColorMax, ColorMax));
845 p.emplace_back(para->fractionStops_[0].second - 0.01); // 0.01 represents the fraction bias
846 }
847 for (size_t i = 0; i < para->fractionStops_.size(); i++) {
848 c.emplace_back(SkColorSetARGB(
849 static_cast<uint8_t>(para->fractionStops_[i].first * ColorMax), ColorMax, ColorMax, ColorMax));
850 p.emplace_back(para->fractionStops_[i].second);
851 }
852 // 0.01 represents the fraction bias
853 if (para->fractionStops_[para->fractionStops_.size() - 1].second < (1 - 0.01)) {
854 c.emplace_back(SkColorSetARGB(ColorMin, ColorMax, ColorMax, ColorMax));
855 // 0.01 represents the fraction bias
856 p.emplace_back(para->fractionStops_[para->fractionStops_.size() - 1].second + 0.01);
857 }
858 auto shader = SkGradientShader::MakeLinear(pts, &c[0], &p[0], p.size(), SkTileMode::kClamp);
859 return shader;
860 }
861
MakeHorizontalMeanBlurShader(float radiusIn,sk_sp<SkShader> shader,sk_sp<SkShader> gradientShader)862 sk_sp<SkShader> RSPropertiesPainter::MakeHorizontalMeanBlurShader(
863 float radiusIn, sk_sp<SkShader> shader, sk_sp<SkShader> gradientShader)
864 {
865 const char* prog = R"(
866 uniform half r;
867 uniform shader imageShader;
868 uniform shader gradientShader;
869 half4 meanFilter(float2 coord, half radius)
870 {
871 half4 sum = vec4(0.0);
872 half div = 0;
873 for (half x = -30.0; x < 30.0; x += 1.0) {
874 if (x > radius) {
875 break;
876 }
877 if (abs(x) < radius) {
878 div += 1;
879 sum += imageShader.eval(coord + float2(x, 0));
880 }
881 }
882 return half4(sum.xyz / div, 1.0);
883 }
884 half4 main(float2 coord)
885 {
886 if (abs(gradientShader.eval(coord).a - 0) < 0.001) {
887 return imageShader.eval(coord);
888 }
889 float val = clamp(r * gradientShader.eval(coord).a, 1.0, r);
890 return meanFilter(coord, val);
891 }
892 )";
893 auto [effect, err] = SkRuntimeEffect::MakeForShader(SkString(prog));
894 sk_sp<SkShader> children[] = {shader, gradientShader};
895 size_t childCount = 2;
896 return effect->makeShader(SkData::MakeWithCopy(
897 &radiusIn, sizeof(radiusIn)), children, childCount, nullptr, false);
898 }
899
MakeVerticalMeanBlurShader(float radiusIn,sk_sp<SkShader> shader,sk_sp<SkShader> gradientShader)900 sk_sp<SkShader> RSPropertiesPainter::MakeVerticalMeanBlurShader(
901 float radiusIn, sk_sp<SkShader> shader, sk_sp<SkShader> gradientShader)
902 {
903 const char* prog = R"(
904 uniform half r;
905 uniform shader imageShader;
906 uniform shader gradientShader;
907 half4 meanFilter(float2 coord, half radius)
908 {
909 half4 sum = vec4(0.0);
910 half div = 0;
911 for (half y = -30.0; y < 30.0; y += 1.0) {
912 if (y > radius) {
913 break;
914 }
915 if (abs(y) < radius) {
916 div += 1;
917 sum += imageShader.eval(coord + float2(0, y));
918 }
919 }
920 return half4(sum.xyz / div, 1.0);
921 }
922 half4 main(float2 coord)
923 {
924 if (abs(gradientShader.eval(coord).a - 0) < 0.001) {
925 return imageShader.eval(coord);
926 }
927 float val = clamp(r * gradientShader.eval(coord).a, 1.0, r);
928 return meanFilter(coord, val);
929 }
930 )";
931 auto [effect, err] = SkRuntimeEffect::MakeForShader(SkString(prog));
932 sk_sp<SkShader> children[] = {shader, gradientShader};
933 size_t childCount = 2;
934 return effect->makeShader(SkData::MakeWithCopy(
935 &radiusIn, sizeof(radiusIn)), children, childCount, nullptr, false);
936 }
937
DrawHorizontalLinearGradientBlur(SkSurface * skSurface,RSPaintFilterCanvas & canvas,float radius,sk_sp<SkShader> alphaGradientShader,const SkIRect & clipIPadding)938 void RSPropertiesPainter::DrawHorizontalLinearGradientBlur(SkSurface* skSurface, RSPaintFilterCanvas& canvas,
939 float radius, sk_sp<SkShader> alphaGradientShader, const SkIRect& clipIPadding)
940 {
941 auto image = skSurface->makeImageSnapshot(clipIPadding);
942 if (image == nullptr) {
943 return;
944 }
945 auto imageShader = image->makeShader(SkSamplingOptions(SkFilterMode::kLinear));
946 auto shader = MakeHorizontalMeanBlurShader(radius, imageShader, alphaGradientShader);
947 SkPaint paint;
948 paint.setShader(shader);
949 canvas.drawRect(SkRect::Make(clipIPadding.makeOffset(-clipIPadding.left(), -clipIPadding.top())), paint);
950 }
951
DrawVerticalLinearGradientBlur(SkSurface * skSurface,RSPaintFilterCanvas & canvas,float radius,sk_sp<SkShader> alphaGradientShader,const SkIRect & clipIPadding)952 void RSPropertiesPainter::DrawVerticalLinearGradientBlur(SkSurface* skSurface, RSPaintFilterCanvas& canvas,
953 float radius, sk_sp<SkShader> alphaGradientShader, const SkIRect& clipIPadding)
954 {
955 auto image = skSurface->makeImageSnapshot(clipIPadding);
956 if (image == nullptr) {
957 return;
958 }
959 auto imageShader = image->makeShader(SkSamplingOptions(SkFilterMode::kLinear));
960 auto shader = MakeVerticalMeanBlurShader(radius, imageShader, alphaGradientShader);
961 SkPaint paint;
962 paint.setShader(shader);
963 canvas.drawRect(SkRect::Make(clipIPadding.makeOffset(-clipIPadding.left(), -clipIPadding.top())), paint);
964 }
965
CalcDirectionBias(const SkMatrix & mat)966 uint8_t RSPropertiesPainter::CalcDirectionBias(const SkMatrix& mat)
967 {
968 uint8_t directionBias = 0;
969 // 1 and 3 represents rotate matrix's index
970 if ((mat.get(1) > FLOAT_ZERO_THRESHOLD) && (mat.get(3) < (0 - FLOAT_ZERO_THRESHOLD))) {
971 directionBias = 1; // 1 represents rotate 90 degree
972 // 0 and 4 represents rotate matrix's index
973 } else if ((mat.get(0) < (0 - FLOAT_ZERO_THRESHOLD)) && (mat.get(4) < (0 - FLOAT_ZERO_THRESHOLD))) {
974 directionBias = 2; // 2 represents rotate 180 degree
975 // 1 and 3 represents rotate matrix's index
976 } else if ((mat.get(1) < (0 - FLOAT_ZERO_THRESHOLD)) && (mat.get(3) > FLOAT_ZERO_THRESHOLD)) {
977 directionBias = 3; // 3 represents rotate 270 degree
978 }
979 return directionBias;
980 }
981 #endif
982 #endif
983
984 #ifndef USE_ROSEN_DRAWING
DrawLinearGradientBlurFilter(const RSProperties & properties,RSPaintFilterCanvas & canvas,const std::optional<SkRect> & rect)985 void RSPropertiesPainter::DrawLinearGradientBlurFilter(
986 const RSProperties& properties, RSPaintFilterCanvas& canvas, const std::optional<SkRect>& rect)
987 {
988 const auto& para = properties.GetLinearGradientBlurPara();
989 if (para == nullptr || para->blurRadius_ <= 0) {
990 return;
991 }
992 #ifdef NEW_SKIA
993 SkSurface* skSurface = canvas.GetSurface();
994 if (skSurface == nullptr) {
995 return;
996 }
997 SkAutoCanvasRestore acr(&canvas, true);
998 if (rect.has_value()) {
999 canvas.clipRect((*rect), true);
1000 } else if (properties.GetClipBounds() != nullptr) {
1001 canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
1002 } else { // we always do clip for DrawLinearGradientBlurFilter, even if ClipToBounds is false
1003 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
1004 }
1005
1006 auto clipBounds = canvas.getDeviceClipBounds();
1007 auto clipIPadding = clipBounds.makeOutset(-1, -1);
1008 SkMatrix mat = canvas.getTotalMatrix();
1009 uint8_t directionBias = CalcDirectionBias(mat);
1010
1011 auto alphaGradientShader = MakeAlphaGradientShader(SkRect::Make(clipIPadding), para, directionBias);
1012 if (alphaGradientShader == nullptr) {
1013 ROSEN_LOGE("RSPropertiesPainter::DrawLinearGradientBlurFilter alphaGradientShader null");
1014 return;
1015 }
1016 float radius = para->blurRadius_ / 2;
1017 canvas.resetMatrix();
1018 canvas.translate(clipIPadding.left(), clipIPadding.top());
1019
1020 DrawHorizontalLinearGradientBlur(skSurface, canvas, radius, alphaGradientShader, clipIPadding);
1021 DrawVerticalLinearGradientBlur(skSurface, canvas, radius, alphaGradientShader, clipIPadding);
1022 DrawHorizontalLinearGradientBlur(skSurface, canvas, radius, alphaGradientShader, clipIPadding);
1023 DrawVerticalLinearGradientBlur(skSurface, canvas, radius, alphaGradientShader, clipIPadding);
1024 #endif
1025 }
1026 #else
DrawLinearGradientBlurFilter(const RSProperties & properties,RSPaintFilterCanvas & canvas,const std::optional<Drawing::Rect> & rect)1027 void RSPropertiesPainter::DrawLinearGradientBlurFilter(
1028 const RSProperties& properties, RSPaintFilterCanvas& canvas, const std::optional<Drawing::Rect>& rect)
1029 {
1030 }
1031 #endif
1032
1033
1034 #ifndef USE_ROSEN_DRAWING
DrawFilter(const RSProperties & properties,RSPaintFilterCanvas & canvas,FilterType filterType,const std::optional<SkRect> & rect)1035 void RSPropertiesPainter::DrawFilter(const RSProperties& properties, RSPaintFilterCanvas& canvas,
1036 FilterType filterType, const std::optional<SkRect>& rect)
1037 {
1038 if (!BLUR_ENABLED) {
1039 ROSEN_LOGD("RSPropertiesPainter::DrawFilter close blur.");
1040 return;
1041 }
1042 auto& RSFilter =
1043 (filterType == FilterType::BACKGROUND_FILTER) ? properties.GetBackgroundFilter() : properties.GetFilter();
1044 if (RSFilter == nullptr || !RSFilter->IsValid()) {
1045 return;
1046 }
1047 #ifdef NEW_SKIA
1048 RS_OPTIONAL_TRACE_BEGIN("DrawFilter " + RSFilter->GetDescription());
1049 g_blurCnt++;
1050 SkAutoCanvasRestore acr(&canvas, true);
1051 if (rect.has_value()) {
1052 canvas.clipRect((*rect), true);
1053 } else if (properties.GetClipBounds() != nullptr) {
1054 canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
1055 } else { // we always do clip for DrawFilter, even if ClipToBounds is false
1056 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
1057 }
1058
1059 auto filter = std::static_pointer_cast<RSSkiaFilter>(RSFilter);
1060 auto skSurface = canvas.GetSurface();
1061 if (skSurface == nullptr) {
1062 ROSEN_LOGD("RSPropertiesPainter::DrawFilter skSurface null");
1063 auto paint = filter->GetPaint();
1064 SkCanvas::SaveLayerRec slr(nullptr, &paint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
1065 canvas.saveLayer(slr);
1066 filter->PostProcess(canvas);
1067 RS_OPTIONAL_TRACE_END();
1068 return;
1069 }
1070
1071 // for foreground filter, when do online opacity, rendering result already applied opacity,
1072 // so drawImage should not apply opacity again
1073 RSAutoCanvasRestore autoCanvasRestore(&canvas,
1074 filterType == FilterType::FOREGROUND_FILTER ? RSAutoCanvasRestore::kAlpha : RSAutoCanvasRestore::kNone);
1075 if (filterType == FilterType::FOREGROUND_FILTER) {
1076 canvas.SetAlpha(1.0);
1077 }
1078
1079 // Optional use cacheManager to draw filter
1080 if (auto& cacheManager = properties.GetFilterCacheManager(filterType == FilterType::FOREGROUND_FILTER)) {
1081 cacheManager->DrawFilter(canvas, filter);
1082 RS_OPTIONAL_TRACE_END();
1083 return;
1084 }
1085
1086 auto clipIBounds = canvas.getDeviceClipBounds();
1087 auto imageSnapshot = skSurface->makeImageSnapshot(clipIBounds);
1088 if (imageSnapshot == nullptr) {
1089 ROSEN_LOGE("RSPropertiesPainter::DrawFilter image null");
1090 RS_OPTIONAL_TRACE_END();
1091 return;
1092 }
1093 if (RSSystemProperties::GetImageGpuResourceCacheEnable(imageSnapshot->width(), imageSnapshot->height())) {
1094 ROSEN_LOGD("DrawFilter cache image resource(width:%d, height:%d).",
1095 imageSnapshot->width(), imageSnapshot->height());
1096 as_IB(imageSnapshot)->hintCacheGpuResource();
1097 }
1098
1099 filter->PreProcess(imageSnapshot);
1100 canvas.resetMatrix();
1101 auto visibleIRect = canvas.GetVisibleRect().round();
1102 if (!visibleIRect.isEmpty()) {
1103 canvas.clipIRect(visibleIRect);
1104 }
1105 filter->DrawImageRect(
1106 canvas, imageSnapshot, SkRect::Make(imageSnapshot->bounds().makeOutset(-1, -1)), SkRect::Make(clipIBounds));
1107 filter->PostProcess(canvas);
1108 RS_OPTIONAL_TRACE_END();
1109 #endif
1110 }
1111 #else
DrawFilter(const RSProperties & properties,RSPaintFilterCanvas & canvas,FilterType filterType,const std::optional<Drawing::Rect> & rect)1112 void RSPropertiesPainter::DrawFilter(const RSProperties& properties, RSPaintFilterCanvas& canvas,
1113 FilterType filterType, const std::optional<Drawing::Rect>& rect)
1114 {
1115 auto& RSFilter =
1116 (filterType == FilterType::BACKGROUND_FILTER) ? properties.GetBackgroundFilter() : properties.GetFilter();
1117 if (RSFilter == nullptr || !RSFilter->IsValid()) {
1118 return;
1119 }
1120 RS_TRACE_NAME("DrawFilter " + RSFilter->GetDescription());
1121 g_blurCnt++;
1122 Drawing::AutoCanvasRestore acr(canvas, true);
1123 if (rect.has_value()) {
1124 canvas.ClipRect((*rect), Drawing::ClipOp::INTERSECT, true);
1125 } else if (properties.GetClipBounds() != nullptr) {
1126 canvas.ClipPath(properties.GetClipBounds()->GetDrawingPath(), Drawing::ClipOp::INTERSECT, true);
1127 } else {
1128 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, true);
1129 }
1130 auto filter = std::static_pointer_cast<RSDrawingFilter>(RSFilter);
1131 auto surface = canvas.GetSurface();
1132 if (surface == nullptr) {
1133 ROSEN_LOGD("RSPropertiesPainter::DrawFilter surface null");
1134 auto brush = filter->GetBrush();
1135 Drawing::SaveLayerOps slr(nullptr, &brush, Drawing::SaveLayerOps::Flags::INIT_WITH_PREVIOUS);
1136 canvas.SaveLayer(slr);
1137 filter->PostProcess(canvas);
1138 return;
1139 }
1140
1141 // for foreground filter, when do online opacity, rendering result already applied opacity,
1142 // so drawImage should not apply opacity again
1143 RSAutoCanvasRestore autoCanvasRestore(&canvas,
1144 filterType == FilterType::FOREGROUND_FILTER ? RSAutoCanvasRestore::kAlpha : RSAutoCanvasRestore::kNone);
1145 if (filterType == FilterType::FOREGROUND_FILTER) {
1146 canvas.SetAlpha(1.0);
1147 }
1148
1149 auto clipIBounds = canvas.GetDeviceClipBounds();
1150 auto clipIPadding = Drawing::RectI(clipIBounds.GetLeft() + 1, clipIBounds.GetTop() + 1,
1151 clipIBounds.GetRight() - 1, clipIBounds.GetBottom() - 1);
1152 auto imageSnapshot = surface->GetImageSnapshot(clipIPadding);
1153 if (imageSnapshot == nullptr) {
1154 ROSEN_LOGE("RSPropertiesPainter::DrawFilter image null");
1155 return;
1156 }
1157 filter->PreProcess(imageSnapshot);
1158 canvas.ResetMatrix();
1159 auto visibleRect = canvas.GetVisibleRect();
1160 auto visibleIRect = Drawing::RectI(visibleRect.GetLeft(), visibleRect.GetTop(),
1161 visibleRect.GetRight(), visibleRect.GetBottom());
1162 if (visibleIRect.Intersect(clipIBounds)) {
1163 auto clipRect = Drawing::Rect(visibleIRect.GetLeft(), visibleIRect.GetTop(),
1164 visibleIRect.GetRight(), visibleIRect.GetBottom());
1165 canvas.ClipRect(clipRect, Drawing::ClipOp::INTERSECT, false);
1166 auto srcRect = Drawing::Rect(visibleIRect.GetLeft() + 1, visibleIRect.GetTop() + 1,
1167 visibleIRect.GetRight() - 1, visibleIRect.GetBottom() - 1);
1168 srcRect.Offset(-clipIPadding.GetLeft(), -clipIPadding.GetTop());
1169 filter->DrawImageRect(canvas, imageSnapshot, srcRect, clipRect);
1170 } else {
1171 auto srcRect = Drawing::Rect(0, 0, clipIPadding.GetWidth(), clipIPadding.GetHeight());
1172 auto dstRect = Drawing::Rect(clipIBounds.GetLeft(), clipIBounds.GetTop(),
1173 clipIBounds.GetRight(), clipIBounds.GetBottom());
1174 filter->DrawImageRect(canvas, imageSnapshot, srcRect, dstRect);
1175 }
1176 filter->PostProcess(canvas);
1177 }
1178 #endif
1179
1180 #ifndef USE_ROSEN_DRAWING
DrawBackgroundEffect(const RSProperties & properties,RSPaintFilterCanvas & canvas,const SkIRect & rect)1181 void RSPropertiesPainter::DrawBackgroundEffect(
1182 const RSProperties& properties, RSPaintFilterCanvas& canvas, const SkIRect& rect)
1183 {
1184 auto& RSFilter = properties.GetBackgroundFilter();
1185 if (RSFilter == nullptr || !RSFilter->IsValid()) {
1186 return;
1187 }
1188 auto filter = std::static_pointer_cast<RSSkiaFilter>(RSFilter);
1189 RS_TRACE_NAME("DrawBackgroundEffect " + filter->GetDescription());
1190 auto skSurface = canvas.GetSurface();
1191 if (skSurface == nullptr) {
1192 ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundEffect skSurface null");
1193 return;
1194 }
1195 g_blurCnt++;
1196
1197 // Optional use cacheManager to draw filter
1198 if (auto& cacheManager = properties.GetFilterCacheManager(false)) {
1199 // the input rect is in global coordinate, so we need to save/reset matrix before clip
1200 SkAutoCanvasRestore acr(&canvas, true);
1201 canvas.resetMatrix();
1202 #ifdef NEW_SKIA
1203 canvas.clipIRect(rect);
1204 #endif
1205 auto data = cacheManager->GeneratedCachedEffectData(canvas, filter);
1206 canvas.SetEffectData(data);
1207 return;
1208 }
1209
1210 SkIRect imageRect = SkIRect::MakeWH(skSurface->width(), skSurface->height());
1211 imageRect.intersect(rect);
1212 auto imageSnapshot = skSurface->makeImageSnapshot(imageRect);
1213 if (imageSnapshot == nullptr) {
1214 ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundEffect image snapshot null");
1215 return;
1216 }
1217
1218 filter->PreProcess(imageSnapshot);
1219 // create a offscreen skSurface
1220 sk_sp<SkSurface> offscreenSurface = skSurface->makeSurface(imageSnapshot->imageInfo());
1221 if (offscreenSurface == nullptr) {
1222 ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundEffect offscreenSurface null");
1223 return;
1224 }
1225 RSPaintFilterCanvas offscreenCanvas(offscreenSurface.get());
1226 auto clipBounds = SkRect::MakeIWH(imageRect.width(), imageRect.height());
1227 filter->DrawImageRect(offscreenCanvas, imageSnapshot, SkRect::Make(imageSnapshot->bounds()), clipBounds);
1228 filter->PostProcess(offscreenCanvas);
1229
1230 auto imageCache = offscreenSurface->makeImageSnapshot();
1231 if (imageCache == nullptr) {
1232 ROSEN_LOGE("RSPropertiesPainter::DrawBackgroundEffect imageCache snapshot null");
1233 return;
1234 }
1235 CachedEffectData data = { imageCache, imageRect };
1236 canvas.SetEffectData(data);
1237 }
1238 #else
DrawBackgroundEffect(const RSProperties & properties,RSPaintFilterCanvas & canvas,const Drawing::RectI & rect)1239 void RSPropertiesPainter::DrawBackgroundEffect(
1240 const RSProperties& properties, RSPaintFilterCanvas& canvas, const Drawing::RectI& rect)
1241 {
1242 }
1243 #endif
1244
ApplyBackgroundEffect(const RSProperties & properties,RSPaintFilterCanvas & canvas)1245 void RSPropertiesPainter::ApplyBackgroundEffect(const RSProperties& properties, RSPaintFilterCanvas& canvas)
1246 {
1247 #ifndef USE_ROSEN_DRAWING
1248 RS_TRACE_NAME("ApplyBackgroundEffect");
1249 SkAutoCanvasRestore acr(&canvas, true);
1250 if (properties.GetClipBounds() != nullptr) {
1251 canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
1252 } else { // we always do clip for ApplyBackgroundEffect, even if ClipToBounds is false
1253 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
1254 }
1255 canvas.resetMatrix();
1256 auto visibleIRect = canvas.GetVisibleRect().round();
1257 #ifdef NEW_SKIA
1258 if (!visibleIRect.isEmpty()) {
1259 canvas.clipIRect(visibleIRect);
1260 }
1261 #endif
1262
1263 const auto& [bgImage, imageIRect, unused] = canvas.GetEffectData();
1264 if (bgImage == nullptr) {
1265 ROSEN_LOGE("RSPropertiesPainter::ApplyBackgroundEffect bgImage null");
1266 return;
1267 }
1268 SkPaint defaultPaint;
1269 // dstRect: canvas clip region
1270 auto dstRect = SkRect::Make(canvas.getDeviceClipBounds());
1271 // srcRect: map dstRect onto cache coordinate
1272 auto srcRect = dstRect.makeOffset(-imageIRect.left(), -imageIRect.top());
1273 #ifdef NEW_SKIA
1274 canvas.drawImageRect(
1275 bgImage, srcRect, dstRect, SkSamplingOptions(), &defaultPaint, SkCanvas::kStrict_SrcRectConstraint);
1276 #else
1277 auto clipIBounds = canvas.getDeviceClipBounds();
1278 auto clipIPadding = clipIBounds.makeOutset(-1, -1);
1279 canvas.drawImageRect(bgImage, SkRect::Make(clipIPadding.makeOffset(-imageIRect.left(), -imageIRect.top())),
1280 SkRect::Make(clipIPadding), &defaultPaint);
1281 #endif
1282 #endif
1283 }
1284
DrawForegroundEffect(const RSProperties & properties,RSPaintFilterCanvas & canvas)1285 void RSPropertiesPainter::DrawForegroundEffect(const RSProperties& properties, RSPaintFilterCanvas& canvas)
1286 {
1287 #ifndef USE_ROSEN_DRAWING
1288 const auto& data = canvas.GetEffectData();
1289 if (data.childrenPath_.isEmpty()) {
1290 return;
1291 }
1292 auto& colorFilter = properties.GetColorFilter();
1293 if (colorFilter == nullptr) {
1294 return;
1295 }
1296 RS_TRACE_NAME("DrawForegroundEffect");
1297 SkAutoCanvasRestore acr(&canvas, true);
1298 canvas.resetMatrix();
1299 canvas.clipPath(data.childrenPath_, true);
1300 SkPaint paint;
1301 paint.setAntiAlias(true);
1302 paint.setColorFilter(colorFilter);
1303 auto pathBounds = data.childrenPath_.getBounds();
1304 SkCanvas::SaveLayerRec slr(&pathBounds, &paint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
1305 canvas.saveLayer(slr);
1306 #endif
1307 }
1308
1309 #ifndef USE_ROSEN_DRAWING
DrawPixelStretch(const RSProperties & properties,RSPaintFilterCanvas & canvas)1310 void RSPropertiesPainter::DrawPixelStretch(const RSProperties& properties, RSPaintFilterCanvas& canvas)
1311 {
1312 auto& pixelStretch = properties.GetPixelStretch();
1313 if (!pixelStretch.has_value()) {
1314 return;
1315 }
1316
1317 auto skSurface = canvas.GetSurface();
1318 if (skSurface == nullptr) {
1319 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch skSurface null");
1320 return;
1321 }
1322
1323 canvas.save();
1324 auto bounds = RSPropertiesPainter::Rect2SkRect(properties.GetBoundsRect());
1325 canvas.clipRect(bounds);
1326 auto clipBounds = canvas.getDeviceClipBounds();
1327 clipBounds.setXYWH(clipBounds.left(), clipBounds.top(), clipBounds.width() - 1, clipBounds.height() - 1);
1328 canvas.restore();
1329
1330 /* Calculates the relative coordinates of the clipbounds
1331 with respect to the origin of the current canvas coordinates */
1332 SkMatrix worldToLocalMat;
1333 if (!canvas.getTotalMatrix().invert(&worldToLocalMat)) {
1334 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch get invert matrix failed.");
1335 }
1336 SkRect localClipBounds;
1337 SkRect fClipBounds = SkRect::MakeXYWH(clipBounds.x(), clipBounds.y(), clipBounds.width(), clipBounds.height());
1338 if (!worldToLocalMat.mapRect(&localClipBounds, fClipBounds)) {
1339 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch map rect failed.");
1340 }
1341
1342 if (!bounds.intersect(localClipBounds)) {
1343 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch intersect clipbounds failed");
1344 }
1345
1346 auto scaledBounds = SkRect::MakeLTRB(bounds.left() - pixelStretch->x_, bounds.top() - pixelStretch->y_,
1347 bounds.right() + pixelStretch->z_, bounds.bottom() + pixelStretch->w_);
1348 if (scaledBounds.isEmpty() || bounds.isEmpty() || clipBounds.isEmpty()) {
1349 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch invalid scaled bounds");
1350 return;
1351 }
1352
1353 auto image = skSurface->makeImageSnapshot(clipBounds);
1354 if (image == nullptr) {
1355 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch image null");
1356 return;
1357 }
1358
1359 SkPaint paint;
1360 SkMatrix inverseMat, scaleMat;
1361 auto boundsGeo = (properties.GetBoundsGeometry());
1362 if (boundsGeo && !boundsGeo->IsEmpty()) {
1363 if (!canvas.getTotalMatrix().invert(&inverseMat)) {
1364 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch get inverse matrix failed.");
1365 }
1366 scaleMat.setScale(inverseMat.getScaleX(), inverseMat.getScaleY());
1367 }
1368
1369 canvas.save();
1370 canvas.translate(bounds.x(), bounds.y());
1371 if (pixelStretch->x_ < 0) {
1372 #ifdef NEW_SKIA
1373 paint.setShader(image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions(), &scaleMat));
1374 #else
1375 paint.setShader(image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, &scaleMat));
1376 #endif
1377 canvas.drawRect(
1378 SkRect::MakeXYWH(-pixelStretch->x_, -pixelStretch->y_, scaledBounds.width(), scaledBounds.height()), paint);
1379 } else {
1380 scaleMat.setScale(scaledBounds.width() / bounds.width() * scaleMat.getScaleX(),
1381 scaledBounds.height() / bounds.height() * scaleMat.getScaleY());
1382 #ifdef NEW_SKIA
1383 paint.setShader(image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions(), &scaleMat));
1384 #else
1385 paint.setShader(image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, &scaleMat));
1386 #endif
1387 canvas.translate(-pixelStretch->x_, -pixelStretch->y_);
1388 canvas.drawRect(SkRect::MakeXYWH(pixelStretch->x_, pixelStretch->y_, bounds.width(), bounds.height()), paint);
1389 }
1390 canvas.restore();
1391 }
1392 #else
DrawPixelStretch(const RSProperties & properties,RSPaintFilterCanvas & canvas)1393 void RSPropertiesPainter::DrawPixelStretch(const RSProperties& properties, RSPaintFilterCanvas& canvas)
1394 {
1395 if (!properties.IsPixelStretchValid() && !properties.IsPixelStretchPercentValid()) {
1396 return;
1397 }
1398
1399 auto surface = canvas.GetSurface();
1400 if (surface == nullptr) {
1401 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch surface null");
1402 return;
1403 }
1404
1405 canvas.Save();
1406 auto bounds = RSPropertiesPainter::Rect2DrawingRect(properties.GetBoundsRect());
1407 canvas.ClipRect(bounds, Drawing::ClipOp::INTERSECT, false);
1408 auto tmpBounds = canvas.GetDeviceClipBounds();
1409 Drawing::Rect clipBounds(
1410 tmpBounds.GetLeft(), tmpBounds.GetTop(), tmpBounds.GetWidth() - 1, tmpBounds.GetHeight() - 1);
1411 canvas.Restore();
1412
1413 /* Calculates the relative coordinates of the clipbounds
1414 with respect to the origin of the current canvas coordinates */
1415 Drawing::Matrix worldToLocalMat;
1416 if (!canvas.GetTotalMatrix().Invert(worldToLocalMat)) {
1417 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch get invert matrix failed.");
1418 }
1419 Drawing::Rect localClipBounds;
1420 Drawing::Rect fClipBounds(clipBounds.GetLeft(), clipBounds.GetTop(), clipBounds.GetWidth(),
1421 clipBounds.GetBottom());
1422 if (!worldToLocalMat.MapRect(localClipBounds, fClipBounds)) {
1423 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch map rect failed.");
1424 }
1425
1426 if (!bounds.Intersect(localClipBounds)) {
1427 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch intersect clipbounds failed");
1428 }
1429
1430 auto scaledBounds = Drawing::Rect(bounds.GetLeft() - stretchSize.x_, bounds.GetTop() - stretchSize.y_,
1431 bounds.GetRight() + stretchSize.z_, bounds.GetBottom() + stretchSize.w_);
1432 if (!scaledBounds.IsValid() || !bounds.IsValid() || !clipBounds.IsValid()) {
1433 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch invalid scaled bounds");
1434 return;
1435 }
1436
1437 Drawing::RectI rectI(static_cast<int>(fClipBounds.GetLeft()), static_cast<int>(fClipBounds.GetTop()),
1438 static_cast<int>(fClipBounds.GetRight()), static_cast<int>(fClipBounds.GetBottom()));
1439 auto image = surface->GetImageSnapshot(rectI);
1440 if (image == nullptr) {
1441 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch image null");
1442 return;
1443 }
1444
1445 Drawing::Brush brush;
1446 Drawing::Matrix inverseMat, scaleMat;
1447 auto boundsGeo = (properties.GetBoundsGeometry());
1448 if (boundsGeo && !boundsGeo->IsEmpty()) {
1449 if (!canvas.GetTotalMatrix().Invert(inverseMat)) {
1450 ROSEN_LOGE("RSPropertiesPainter::DrawPixelStretch get inverse matrix failed.");
1451 }
1452 scaleMat.Set(Drawing::Matrix::SCALE_X, inverseMat.Get(Drawing::Matrix::SCALE_X));
1453 scaleMat.Set(Drawing::Matrix::SCALE_Y, inverseMat.Get(Drawing::Matrix::SCALE_Y));
1454 }
1455
1456 canvas.Save();
1457 canvas.Translate(bounds.GetLeft(), bounds.GetTop());
1458 Drawing::SamplingOptions samplingOptions;
1459 if (properties.IsPixelStretchExpanded()) {
1460 brush.SetShaderEffect(Drawing::ShaderEffect::CreateImageShader(
1461 *image, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, samplingOptions, scaleMat));
1462 canvas.AttachBrush(brush);
1463 canvas.DrawRect(Drawing::Rect(-stretchSize.x_, -stretchSize.y_,
1464 -stretchSize.x_ + scaledBounds.GetWidth(), -stretchSize.y_ + scaledBounds.GetHeight()));
1465 canvas.DetachBrush();
1466 } else {
1467 scaleMat.Scale(
1468 scaledBounds.GetWidth() / bounds.GetWidth(), scaledBounds.GetHeight() / bounds.GetHeight(), 0, 0);
1469 brush.SetShaderEffect(Drawing::ShaderEffect::CreateImageShader(
1470 *image, Drawing::TileMode::CLAMP, Drawing::TileMode::CLAMP, samplingOptions, scaleMat));
1471
1472 canvas.Translate(-stretchSize.x_, -stretchSize.y_);
1473 canvas.AttachBrush(brush);
1474 canvas.DrawRect(Drawing::Rect(
1475 stretchSize.x_, stretchSize.y_, stretchSize.x_ + bounds.GetWidth(), stretchSize.y_ + bounds.GetHeight()));
1476 canvas.DetachBrush();
1477 }
1478 canvas.Restore();
1479 }
1480 #endif
1481
1482 #ifndef USE_ROSEN_DRAWING
CalcAverageColor(sk_sp<SkImage> imageSnapshot)1483 SkColor RSPropertiesPainter::CalcAverageColor(sk_sp<SkImage> imageSnapshot)
1484 {
1485 // create a 1x1 SkPixmap
1486 uint32_t pixel[1] = { 0 };
1487 auto single_pixel_info = SkImageInfo::MakeN32Premul(1, 1);
1488 SkPixmap single_pixel(single_pixel_info, pixel, single_pixel_info.bytesPerPixel());
1489
1490 // resize snapshot to 1x1 to calculate average color
1491 // kMedium_SkFilterQuality will do bilerp + mipmaps for down-scaling, we can easily get average color
1492 #ifdef NEW_SKIA
1493 imageSnapshot->scalePixels(single_pixel, SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear));
1494 #else
1495 imageSnapshot->scalePixels(single_pixel, SkFilterQuality::kMedium_SkFilterQuality);
1496 #endif
1497 // convert color format and return average color
1498 return SkColor4f::FromBytes_RGBA(pixel[0]).toSkColor();
1499 }
1500 #else
CalcAverageColor(std::shared_ptr<Drawing::Image> imageSnapshot)1501 Drawing::ColorQuad RSPropertiesPainter::CalcAverageColor(std::shared_ptr<Drawing::Image> imageSnapshot)
1502 {
1503 // create a 1x1 SkPixmap
1504 return Drawing::ColorQuad();
1505 }
1506 #endif
1507
GetAndResetBlurCnt()1508 int RSPropertiesPainter::GetAndResetBlurCnt()
1509 {
1510 auto blurCnt = g_blurCnt;
1511 g_blurCnt = 0;
1512 return blurCnt;
1513 }
1514
DrawBackground(const RSProperties & properties,RSPaintFilterCanvas & canvas,bool isAntiAlias)1515 void RSPropertiesPainter::DrawBackground(const RSProperties& properties, RSPaintFilterCanvas& canvas, bool isAntiAlias)
1516 {
1517 // only disable antialias when background is rect and g_forceBgAntiAlias is false
1518 bool antiAlias = g_forceBgAntiAlias || !properties.GetCornerRadius().IsZero();
1519 // clip
1520 #ifndef USE_ROSEN_DRAWING
1521 if (properties.GetClipBounds() != nullptr) {
1522 canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), antiAlias);
1523 } else if (properties.GetClipToBounds()) {
1524 // In NEW_SKIA version, L476 code will cause crash if the second parameter is true.
1525 // so isAntiAlias is false only the method is called in ProcessAnimatePropertyBeforeChildren().
1526 #ifdef NEW_SKIA
1527 if (properties.GetCornerRadius().IsZero()) {
1528 canvas.clipRect(Rect2SkRect(properties.GetBoundsRect()), isAntiAlias);
1529 } else {
1530 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), antiAlias);
1531 }
1532 #else
1533 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), antiAlias);
1534 #endif
1535 } else if (properties.GetClipToRRect()) {
1536 canvas.clipRRect(RRect2SkRRect(properties.GetClipRRect()), antiAlias);
1537 }
1538 // paint backgroundColor
1539 SkPaint paint;
1540 paint.setAntiAlias(antiAlias);
1541 auto bgColor = properties.GetBackgroundColor();
1542 if (bgColor != RgbPalette::Transparent()) {
1543 paint.setColor(bgColor.AsArgbInt());
1544 canvas.drawRRect(RRect2SkRRect(properties.GetInnerRRect()), paint);
1545 }
1546 if (const auto& bgShader = properties.GetBackgroundShader()) {
1547 SkAutoCanvasRestore acr(&canvas, true);
1548 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), antiAlias);
1549 paint.setShader(bgShader->GetSkShader());
1550 canvas.drawPaint(paint);
1551 }
1552 if (const auto& bgImage = properties.GetBgImage()) {
1553 SkAutoCanvasRestore acr(&canvas, true);
1554 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), antiAlias);
1555 auto boundsRect = Rect2SkRect(properties.GetBoundsRect());
1556 bgImage->SetDstRect(properties.GetBgImageRect());
1557 #ifdef NEW_SKIA
1558 bgImage->CanvasDrawImage(canvas, boundsRect, SkSamplingOptions(), paint, true);
1559 #else
1560 bgImage->CanvasDrawImage(canvas, boundsRect, paint, true);
1561 #endif
1562 }
1563 #else
1564 if (properties.GetClipBounds() != nullptr) {
1565 auto& path = properties.GetClipBounds()->GetDrawingPath();
1566 if (path.GetDrawingType() == Drawing::DrawingType::RECORDING) {
1567 auto clipPath = static_cast<const Drawing::RecordingPath&>(path).GetCmdList()->Playback();
1568 canvas.ClipPath(*clipPath, Drawing::ClipOp::INTERSECT, antiAlias);
1569 } else {
1570 canvas.ClipPath(path, Drawing::ClipOp::INTERSECT, antiAlias);
1571 }
1572 } else if (properties.GetClipToBounds()) {
1573 if (properties.GetCornerRadius().IsZero()) {
1574 canvas.ClipRect(Rect2DrawingRect(properties.GetBoundsRect()), Drawing::ClipOp::INTERSECT, isAntiAlias);
1575 } else {
1576 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, antiAlias);
1577 }
1578 } else if (properties.GetClipToRRect()) {
1579 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetClipRRect()), Drawing::ClipOp::INTERSECT, antiAlias);
1580 }
1581 // paint backgroundColor
1582 Drawing::Brush brush;
1583 brush.SetAntiAlias(antiAlias);
1584 auto bgColor = properties.GetBackgroundColor();
1585 if (bgColor != RgbPalette::Transparent()) {
1586 brush.SetColor(Drawing::Color(bgColor.AsArgbInt()));
1587 canvas.AttachBrush(brush);
1588 canvas.DrawRoundRect(RRect2DrawingRRect(properties.GetRRect()));
1589 canvas.DetachBrush();
1590 }
1591 if (const auto& bgShader = properties.GetBackgroundShader()) {
1592 canvas.Save();
1593 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, antiAlias);
1594 auto shaderEffect = bgShader->GetDrawingShader();
1595 if (shaderEffect && shaderEffect->GetDrawingType() == Drawing::DrawingType::RECORDING) {
1596 auto shader =
1597 std::static_pointer_cast<Drawing::RecordingShaderEffect>(shaderEffect)->GetCmdList()->Playback();
1598 brush.SetShaderEffect(shader);
1599 } else {
1600 brush.SetShaderEffect(shaderEffect);
1601 }
1602 canvas.DrawBackground(brush);
1603 canvas.Restore();
1604 }
1605 if (const auto& bgImage = properties.GetBgImage()) {
1606 canvas.Save();
1607 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, antiAlias);
1608 auto boundsRect = Rect2DrawingRect(properties.GetBoundsRect());
1609 bgImage->SetDstRect(properties.GetBgImageRect());
1610 canvas.AttachBrush(brush);
1611 bgImage->CanvasDrawImage(canvas, boundsRect, true);
1612 canvas.DetachBrush();
1613 canvas.Restore();
1614 }
1615 #endif
1616 }
1617
SetBgAntiAlias(bool forceBgAntiAlias)1618 void RSPropertiesPainter::SetBgAntiAlias(bool forceBgAntiAlias)
1619 {
1620 g_forceBgAntiAlias = forceBgAntiAlias;
1621 }
1622
GetBgAntiAlias()1623 bool RSPropertiesPainter::GetBgAntiAlias()
1624 {
1625 return g_forceBgAntiAlias;
1626 }
1627
1628 #ifndef USE_ROSEN_DRAWING
DrawFrame(const RSProperties & properties,RSPaintFilterCanvas & canvas,DrawCmdListPtr & cmds)1629 void RSPropertiesPainter::DrawFrame(const RSProperties& properties, RSPaintFilterCanvas& canvas, DrawCmdListPtr& cmds)
1630 {
1631 if (cmds == nullptr) {
1632 return;
1633 }
1634 SkMatrix mat;
1635 if (GetGravityMatrix(
1636 properties.GetFrameGravity(), properties.GetFrameRect(), cmds->GetWidth(), cmds->GetHeight(), mat)) {
1637 canvas.concat(mat);
1638 }
1639 auto frameRect = Rect2SkRect(properties.GetFrameRect());
1640 cmds->Playback(canvas, &frameRect);
1641 }
1642 #else
DrawFrame(const RSProperties & properties,RSPaintFilterCanvas & canvas,Drawing::DrawCmdListPtr & cmds)1643 void RSPropertiesPainter::DrawFrame(
1644 const RSProperties& properties, RSPaintFilterCanvas& canvas, Drawing::DrawCmdListPtr& cmds)
1645 {
1646 if (cmds == nullptr) {
1647 return;
1648 }
1649 Drawing::Matrix mat;
1650 if (GetGravityMatrix(
1651 properties.GetFrameGravity(), properties.GetFrameRect(), cmds->GetWidth(), cmds->GetHeight(), mat)) {
1652 canvas.ConcatMatrix(mat);
1653 }
1654 auto frameRect = Rect2DrawingRect(properties.GetFrameRect());
1655 cmds->Playback(canvas, &frameRect);
1656 }
1657 #endif
1658
1659 #ifndef USE_ROSEN_DRAWING
DrawBorder(const RSProperties & properties,SkCanvas & canvas)1660 void RSPropertiesPainter::DrawBorder(const RSProperties& properties, SkCanvas& canvas)
1661 {
1662 auto border = properties.GetBorder();
1663 if (!border || !border->HasBorder()) {
1664 return;
1665 }
1666 SkPaint paint;
1667 paint.setAntiAlias(true);
1668 if (border->ApplyFillStyle(paint)) {
1669 canvas.drawDRRect(RRect2SkRRect(properties.GetRRect()), RRect2SkRRect(properties.GetInnerRRect()), paint);
1670 } else if (properties.GetCornerRadius().IsZero() && border->ApplyFourLine(paint)) {
1671 RectF rect = properties.GetBoundsRect();
1672 border->PaintFourLine(canvas, paint, rect);
1673 } else if (border->ApplyPathStyle(paint)) {
1674 auto borderWidth = border->GetWidth();
1675 RRect rrect = properties.GetRRect();
1676 rrect.rect_.width_ -= borderWidth;
1677 rrect.rect_.height_ -= borderWidth;
1678 rrect.rect_.Move(borderWidth / PARAM_DOUBLE, borderWidth / PARAM_DOUBLE);
1679 SkPath borderPath;
1680 borderPath.addRRect(RRect2SkRRect(rrect));
1681 canvas.drawPath(borderPath, paint);
1682 } else {
1683 SkAutoCanvasRestore acr(&canvas, true);
1684 canvas.clipRRect(RRect2SkRRect(properties.GetInnerRRect()), SkClipOp::kDifference, true);
1685 SkRRect rrect = RRect2SkRRect(properties.GetRRect());
1686 paint.setStyle(SkPaint::Style::kStroke_Style);
1687 border->PaintTopPath(canvas, paint, rrect);
1688 border->PaintRightPath(canvas, paint, rrect);
1689 border->PaintBottomPath(canvas, paint, rrect);
1690 border->PaintLeftPath(canvas, paint, rrect);
1691 }
1692 }
1693 #else
DrawBorder(const RSProperties & properties,Drawing::Canvas & canvas)1694 void RSPropertiesPainter::DrawBorder(const RSProperties& properties, Drawing::Canvas& canvas)
1695 {
1696 auto border = properties.GetBorder();
1697 if (!border || !border->HasBorder()) {
1698 return;
1699 }
1700 Drawing::Pen pen;
1701 Drawing::Brush brush;
1702 pen.SetAntiAlias(true);
1703 brush.SetAntiAlias(true);
1704 if (properties.GetCornerRadius().IsZero() && border->ApplyFourLine(pen)) {
1705 RectF rect = properties.GetBoundsRect();
1706 border->PaintFourLine(canvas, pen, rect);
1707 } else if (border->ApplyFillStyle(brush)) {
1708 canvas.AttachBrush(brush);
1709 canvas.DrawNestedRoundRect(
1710 RRect2DrawingRRect(properties.GetRRect()), RRect2DrawingRRect(properties.GetInnerRRect()));
1711 canvas.DetachBrush();
1712 } else if (border->ApplyPathStyle(pen)) {
1713 auto borderWidth = border->GetWidth();
1714 RRect rrect = properties.GetRRect();
1715 rrect.rect_.width_ -= borderWidth;
1716 rrect.rect_.height_ -= borderWidth;
1717 rrect.rect_.Move(borderWidth / PARAM_DOUBLE, borderWidth / PARAM_DOUBLE);
1718 Drawing::Path borderPath;
1719 borderPath.AddRoundRect(RRect2DrawingRRect(rrect));
1720 canvas.AttachPen(pen);
1721 canvas.DrawPath(borderPath);
1722 canvas.DetachPen();
1723 } else {
1724 Drawing::AutoCanvasRestore acr(canvas, true);
1725 canvas.ClipRoundRect(RRect2DrawingRRect(properties.GetInnerRRect()), Drawing::ClipOp::DIFFERENCE, true);
1726 Drawing::RoundRect rrect = RRect2DrawingRRect(properties.GetRRect());
1727 border->PaintTopPath(canvas, pen, rrect);
1728 border->PaintRightPath(canvas, pen, rrect);
1729 border->PaintBottomPath(canvas, pen, rrect);
1730 border->PaintLeftPath(canvas, pen, rrect);
1731 }
1732 }
1733 #endif
1734
1735 #ifndef USE_ROSEN_DRAWING
DrawForegroundColor(const RSProperties & properties,SkCanvas & canvas)1736 void RSPropertiesPainter::DrawForegroundColor(const RSProperties& properties, SkCanvas& canvas)
1737 {
1738 auto bgColor = properties.GetForegroundColor();
1739 if (bgColor == RgbPalette::Transparent()) {
1740 return;
1741 }
1742 // clip
1743 if (properties.GetClipBounds() != nullptr) {
1744 canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
1745 } else if (properties.GetClipToBounds()) {
1746 canvas.clipRect(Rect2SkRect(properties.GetBoundsRect()), true);
1747 } else if (properties.GetClipToRRect()) {
1748 canvas.clipRRect(RRect2SkRRect(properties.GetClipRRect()), true);
1749 }
1750
1751 SkPaint paint;
1752 paint.setColor(bgColor.AsArgbInt());
1753 paint.setAntiAlias(true);
1754 canvas.drawRRect(RRect2SkRRect(properties.GetRRect()), paint);
1755 }
1756 #else
DrawForegroundColor(const RSProperties & properties,Drawing::Canvas & canvas)1757 void RSPropertiesPainter::DrawForegroundColor(const RSProperties& properties, Drawing::Canvas& canvas)
1758 {
1759 auto bgColor = properties.GetForegroundColor();
1760 if (bgColor == RgbPalette::Transparent()) {
1761 return;
1762 }
1763 // clip
1764 if (properties.GetClipBounds() != nullptr) {
1765 canvas.ClipPath(properties.GetClipBounds()->GetDrawingPath(), Drawing::ClipOp::INTERSECT, true);
1766 } else if (properties.GetClipToBounds()) {
1767 canvas.ClipRect(Rect2DrawingRect(properties.GetBoundsRect()), Drawing::ClipOp::INTERSECT, true);
1768 }
1769
1770 Drawing::Brush brush;
1771 brush.SetColor(Drawing::Color(bgColor.AsArgbInt()));
1772 brush.SetAntiAlias(true);
1773 canvas.AttachBrush(brush);
1774 canvas.DrawRoundRect(RRect2DrawingRRect(properties.GetRRect()));
1775 canvas.DetachBrush();
1776 }
1777 #endif
1778
1779 #ifndef USE_ROSEN_DRAWING
DrawMask(const RSProperties & properties,SkCanvas & canvas,SkRect maskBounds)1780 void RSPropertiesPainter::DrawMask(const RSProperties& properties, SkCanvas& canvas, SkRect maskBounds)
1781 {
1782 std::shared_ptr<RSMask> mask = properties.GetMask();
1783 if (mask == nullptr) {
1784 return;
1785 }
1786 if (mask->IsSvgMask() && !mask->GetSvgDom() && !mask->GetSvgPicture()) {
1787 ROSEN_LOGD("RSPropertiesPainter::DrawMask not has Svg Mask property");
1788 return;
1789 }
1790
1791 canvas.save();
1792 canvas.saveLayer(maskBounds, nullptr);
1793 int tmpLayer = canvas.getSaveCount();
1794
1795 SkPaint maskfilter;
1796 auto filter = SkColorFilters::Compose(SkLumaColorFilter::Make(), SkColorFilters::SRGBToLinearGamma());
1797 maskfilter.setColorFilter(filter);
1798 canvas.saveLayer(maskBounds, &maskfilter);
1799 if (mask->IsSvgMask()) {
1800 SkAutoCanvasRestore maskSave(&canvas, true);
1801 canvas.translate(maskBounds.fLeft + mask->GetSvgX(), maskBounds.fTop + mask->GetSvgY());
1802 canvas.scale(mask->GetScaleX(), mask->GetScaleY());
1803 if (mask->GetSvgDom()) {
1804 mask->GetSvgDom()->render(&canvas);
1805 } else if (mask->GetSvgPicture()) {
1806 canvas.drawPicture(mask->GetSvgPicture());
1807 }
1808 } else if (mask->IsGradientMask()) {
1809 SkAutoCanvasRestore maskSave(&canvas, true);
1810 canvas.translate(maskBounds.fLeft, maskBounds.fTop);
1811 SkRect skRect = SkRect::MakeIWH(maskBounds.fRight - maskBounds.fLeft, maskBounds.fBottom - maskBounds.fTop);
1812 canvas.drawRect(skRect, mask->GetMaskPaint());
1813 } else if (mask->IsPathMask()) {
1814 SkAutoCanvasRestore maskSave(&canvas, true);
1815 canvas.translate(maskBounds.fLeft, maskBounds.fTop);
1816 canvas.drawPath(mask->GetMaskPath(), mask->GetMaskPaint());
1817 }
1818
1819 // back to mask layer
1820 canvas.restoreToCount(tmpLayer);
1821 // create content layer
1822 SkPaint maskPaint;
1823 maskPaint.setBlendMode(SkBlendMode::kSrcIn);
1824 canvas.saveLayer(maskBounds, &maskPaint);
1825 canvas.clipRect(maskBounds, true);
1826 }
1827 #else
DrawMask(const RSProperties & properties,Drawing::Canvas & canvas,Drawing::Rect maskBounds)1828 void RSPropertiesPainter::DrawMask(const RSProperties& properties, Drawing::Canvas& canvas, Drawing::Rect maskBounds)
1829 {
1830 std::shared_ptr<RSMask> mask = properties.GetMask();
1831 if (mask == nullptr) {
1832 return;
1833 }
1834 if (mask->IsSvgMask() && !mask->GetSvgDom() && !mask->GetSvgPicture()) {
1835 ROSEN_LOGD("RSPropertiesPainter::DrawMask not has Svg Mask property");
1836 return;
1837 }
1838
1839 canvas.Save();
1840 Drawing::SaveLayerOps slr(&maskBounds, nullptr);
1841 canvas.SaveLayer(slr);
1842 int tmpLayer = canvas.GetSaveCount();
1843
1844 Drawing::Brush maskfilter;
1845 Drawing::Filter filter;
1846 filter.SetColorFilter(Drawing::ColorFilter::CreateComposeColorFilter(
1847 *(Drawing::ColorFilter::CreateLumaColorFilter()), *(Drawing::ColorFilter::CreateSrgbGammaToLinear())));
1848 maskfilter.SetFilter(filter);
1849 Drawing::SaveLayerOps slrMask(&maskBounds, &maskfilter);
1850 canvas.SaveLayer(slrMask);
1851 if (mask->IsSvgMask()) {
1852 Drawing::AutoCanvasRestore maskSave(canvas, true);
1853 canvas.Translate(maskBounds.GetLeft() + mask->GetSvgX(), maskBounds.GetTop() + mask->GetSvgY());
1854 canvas.Scale(mask->GetScaleX(), mask->GetScaleY());
1855 if (mask->GetSvgDom()) {
1856 canvas.DrawSVGDOM(mask->GetSvgDom());
1857 } else if (mask->GetSvgPicture()) {
1858 canvas.DrawPicture(*mask->GetSvgPicture());
1859 }
1860 } else if (mask->IsGradientMask()) {
1861 Drawing::AutoCanvasRestore maskSave(canvas, true);
1862 canvas.Translate(maskBounds.GetLeft(), maskBounds.GetTop());
1863 Drawing::Rect rect = Drawing::Rect(
1864 0, 0, maskBounds.GetRight() - maskBounds.GetLeft(), maskBounds.GetBottom() - maskBounds.GetTop());
1865 canvas.AttachBrush(mask->GetMaskBrush());
1866 canvas.DrawRect(rect);
1867 canvas.DetachBrush();
1868 } else if (mask->IsPathMask()) {
1869 Drawing::AutoCanvasRestore maskSave(canvas, true);
1870 canvas.Translate(maskBounds.GetLeft(), maskBounds.GetTop());
1871 canvas.AttachBrush(mask->GetMaskBrush());
1872 canvas.DrawPath(mask->GetMaskPath());
1873 canvas.DetachBrush();
1874 }
1875
1876 // back to mask layer
1877 canvas.RestoreToCount(tmpLayer);
1878 // create content layer
1879 Drawing::Brush maskPaint;
1880 maskPaint.SetBlendMode(Drawing::BlendMode::SRC_IN);
1881 Drawing::SaveLayerOps slrContent(&maskBounds, &maskPaint);
1882 canvas.SaveLayer(slrContent);
1883 canvas.ClipRect(maskBounds, Drawing::ClipOp::INTERSECT, true);
1884 }
1885 #endif
1886
1887 #ifndef USE_ROSEN_DRAWING
DrawMask(const RSProperties & properties,SkCanvas & canvas)1888 void RSPropertiesPainter::DrawMask(const RSProperties& properties, SkCanvas& canvas)
1889 {
1890 SkRect maskBounds = Rect2SkRect(properties.GetBoundsRect());
1891 DrawMask(properties, canvas, maskBounds);
1892 }
1893 #else
DrawMask(const RSProperties & properties,Drawing::Canvas & canvas)1894 void RSPropertiesPainter::DrawMask(const RSProperties& properties, Drawing::Canvas& canvas)
1895 {
1896 Drawing::Rect maskBounds = Rect2DrawingRect(properties.GetBoundsRect());
1897 DrawMask(properties, canvas, maskBounds);
1898 }
1899 #endif
1900
1901 #ifndef USE_ROSEN_DRAWING
GetCmdsClipRect(DrawCmdListPtr & cmds)1902 RectF RSPropertiesPainter::GetCmdsClipRect(DrawCmdListPtr& cmds)
1903 #else
1904 RectF RSPropertiesPainter::GetCmdsClipRect(Drawing::DrawCmdListPtr& cmds)
1905 #endif
1906 {
1907 #if defined(RS_ENABLE_DRIVEN_RENDER) && defined(RS_ENABLE_GL)
1908 RectF clipRect;
1909 if (cmds == nullptr) {
1910 return clipRect;
1911 }
1912 #ifndef USE_ROSEN_DRAWING
1913 SkRect rect;
1914 cmds->CheckClipRect(rect);
1915 clipRect = { rect.left(), rect.top(), rect.width(), rect.height() };
1916 #else
1917 Drawing::Rect rect;
1918 cmds->CheckClipRect(rect);
1919 clipRect = { rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight() };
1920 #endif
1921 return clipRect;
1922 #else
1923 return RectF { 0.0f, 0.0f, 0.0f, 0.0f };
1924 #endif
1925 }
1926
1927 #ifndef USE_ROSEN_DRAWING
DrawFrameForDriven(const RSProperties & properties,RSPaintFilterCanvas & canvas,DrawCmdListPtr & cmds)1928 void RSPropertiesPainter::DrawFrameForDriven(const RSProperties& properties, RSPaintFilterCanvas& canvas,
1929 DrawCmdListPtr& cmds)
1930 #else
1931 void RSPropertiesPainter::DrawFrameForDriven(const RSProperties& properties, RSPaintFilterCanvas& canvas,
1932 Drawing::DrawCmdListPtr& cmds)
1933 #endif
1934 {
1935 #if defined(RS_ENABLE_DRIVEN_RENDER) && defined(RS_ENABLE_GL)
1936 if (cmds == nullptr) {
1937 return;
1938 }
1939 #ifndef USE_ROSEN_DRAWING
1940 SkMatrix mat;
1941 if (GetGravityMatrix(
1942 properties.GetFrameGravity(), properties.GetFrameRect(), cmds->GetWidth(), cmds->GetHeight(), mat)) {
1943 canvas.concat(mat);
1944 }
1945 auto frameRect = Rect2SkRect(properties.GetFrameRect());
1946 #else
1947 Rosen::Drawing::Matrix mat;
1948 if (GetGravityMatrix(
1949 properties.GetFrameGravity(), properties.GetFrameRect(), cmds->GetWidth(), cmds->GetHeight(), mat)) {
1950 canvas.ConcatMatrix(mat);
1951 }
1952 auto frameRect = Rect2DrawingRect(properties.GetFrameRect());
1953 #endif
1954 // temporary solution for driven content clip
1955 cmds->ReplaceDrivenCmds();
1956 cmds->Playback(canvas, &frameRect);
1957 cmds->RestoreOriginCmdsForDriven();
1958 #endif
1959 }
1960
1961 #ifndef USE_ROSEN_DRAWING
DrawSpherize(const RSProperties & properties,RSPaintFilterCanvas & canvas,const sk_sp<SkSurface> & spherizeSurface)1962 void RSPropertiesPainter::DrawSpherize(const RSProperties& properties, RSPaintFilterCanvas& canvas,
1963 const sk_sp<SkSurface>& spherizeSurface)
1964 {
1965 if (spherizeSurface == nullptr) {
1966 return;
1967 }
1968 SkAutoCanvasRestore acr(&canvas, true);
1969 float canvasWidth = properties.GetBoundsRect().GetWidth();
1970 float canvasHeight = properties.GetBoundsRect().GetHeight();
1971 if (spherizeSurface->width() == 0 || spherizeSurface->height() == 0) {
1972 return;
1973 }
1974 canvas.scale(canvasWidth / spherizeSurface->width(), canvasHeight / spherizeSurface->height());
1975
1976 auto imageSnapshot = spherizeSurface->makeImageSnapshot();
1977 if (imageSnapshot == nullptr) {
1978 ROSEN_LOGE("RSPropertiesPainter::DrawCachedSpherizeSurface image is null");
1979 return;
1980 }
1981
1982 SkPaint paint;
1983 paint.setBlendMode(SkBlendMode::kSrcOver);
1984 #ifdef NEW_SKIA
1985 paint.setShader(imageSnapshot->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions()));
1986 #else
1987 paint.setShader(imageSnapshot->makeShader(SkTileMode::kClamp, SkTileMode::kClamp));
1988 #endif
1989
1990 float width = imageSnapshot->width();
1991 float height = imageSnapshot->height();
1992 float degree = properties.GetSpherize();
1993 bool isWidthGreater = width > height;
1994 ROSEN_LOGI("RSPropertiesPainter::DrawCachedSpherizeSurface spherize degree [%f]", degree);
1995
1996 const SkPoint texCoords[4] = {
1997 {0.0f, 0.0f}, {width, 0.0f}, {width, height}, {0.0f, height}
1998 };
1999 float offsetSquare = 0.f;
2000 if (isWidthGreater) {
2001 offsetSquare = (width - height) * degree / 2.0; // half of the change distance
2002 width = width - (width - height) * degree;
2003 } else {
2004 offsetSquare = (height - width) * degree / 2.0; // half of the change distance
2005 height = height - (height - width) * degree;
2006 }
2007
2008 float segmentWidthOne = width / 3.0;
2009 float segmentWidthTwo = width / 3.0 * 2.0;
2010 float segmentHeightOne = height / 3.0;
2011 float segmentHeightTwo = height / 3.0 * 2.0;
2012 float offsetSphereWidth = width / 6 * degree;
2013 float offsetSphereHeight = height / 6 * degree;
2014
2015 SkPoint ctrlPoints[12] = {
2016 // top edge control points
2017 {0.0f, 0.0f}, {segmentWidthOne, 0.0f}, {segmentWidthTwo, 0.0f}, {width, 0.0f},
2018 // right edge control points
2019 {width, segmentHeightOne}, {width, segmentHeightTwo},
2020 // bottom edge control points
2021 {width, height}, {segmentWidthTwo, height}, {segmentWidthOne, height}, {0.0f, height},
2022 // left edge control points
2023 {0.0f, segmentHeightTwo}, {0.0f, segmentHeightOne}
2024 };
2025 ctrlPoints[0].offset(offsetSphereWidth, offsetSphereHeight); // top left control point
2026 ctrlPoints[3].offset(-offsetSphereWidth, offsetSphereHeight); // top right control point
2027 ctrlPoints[6].offset(-offsetSphereWidth, -offsetSphereHeight); // bottom right control point
2028 ctrlPoints[9].offset(offsetSphereWidth, -offsetSphereHeight); // bottom left control point
2029 if (isWidthGreater) {
2030 SkPoint::Offset(ctrlPoints, SK_ARRAY_COUNT(ctrlPoints), offsetSquare, 0);
2031 } else {
2032 SkPoint::Offset(ctrlPoints, SK_ARRAY_COUNT(ctrlPoints), 0, offsetSquare);
2033 }
2034 SkPath path;
2035 path.moveTo(ctrlPoints[0]);
2036 path.cubicTo(ctrlPoints[1], ctrlPoints[2], ctrlPoints[3]); // upper edge
2037 path.cubicTo(ctrlPoints[4], ctrlPoints[5], ctrlPoints[6]); // right edge
2038 path.cubicTo(ctrlPoints[7], ctrlPoints[8], ctrlPoints[9]); // bottom edge
2039 path.cubicTo(ctrlPoints[10], ctrlPoints[11], ctrlPoints[0]); // left edge
2040 canvas.clipPath(path, true);
2041 canvas.drawPatch(ctrlPoints, nullptr, texCoords, SkBlendMode::kSrcOver, paint);
2042 }
2043 #else
DrawSpherize(const RSProperties & properties,RSPaintFilterCanvas & canvas,const std::shared_ptr<Drawing::Surface> & spherizeSurface)2044 void RSPropertiesPainter::DrawSpherize(const RSProperties& properties, RSPaintFilterCanvas& canvas,
2045 const std::shared_ptr<Drawing::Surface>& spherizeSurface)
2046 {
2047 }
2048 #endif
2049
DrawColorFilter(const RSProperties & properties,RSPaintFilterCanvas & canvas)2050 void RSPropertiesPainter::DrawColorFilter(const RSProperties& properties, RSPaintFilterCanvas& canvas)
2051 {
2052 // if useEffect defined, use color filter from parent EffectView.
2053 auto& colorFilter = properties.GetColorFilter();
2054 if (colorFilter == nullptr) {
2055 return;
2056 }
2057 #ifndef USE_ROSEN_DRAWING
2058 SkAutoCanvasRestore acr(&canvas, true);
2059 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
2060 SkPaint paint;
2061 paint.setAntiAlias(true);
2062 paint.setColorFilter(colorFilter);
2063 auto skSurface = canvas.GetSurface();
2064 if (skSurface == nullptr) {
2065 ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter skSurface is null");
2066 return;
2067 }
2068 auto clipBounds = canvas.getDeviceClipBounds();
2069 auto imageSnapshot = skSurface->makeImageSnapshot(clipBounds);
2070 if (imageSnapshot == nullptr) {
2071 ROSEN_LOGE("RSPropertiesPainter::DrawColorFilter image is null");
2072 return;
2073 }
2074 SkSamplingOptions options;
2075 canvas.drawImageRect(imageSnapshot, Rect2SkRect(properties.GetBoundsRect()), options, &paint);
2076 #endif
2077 }
2078
DrawLightUpEffect(const RSProperties & properties,RSPaintFilterCanvas & canvas)2079 void RSPropertiesPainter::DrawLightUpEffect(const RSProperties& properties, RSPaintFilterCanvas& canvas)
2080 {
2081 #ifndef USE_ROSEN_DRAWING
2082 #ifdef NEW_SKIA
2083 SkSurface* skSurface = canvas.GetSurface();
2084 if (skSurface == nullptr) {
2085 ROSEN_LOGD("RSPropertiesPainter::DrawLightUpEffect skSurface is null");
2086 return;
2087 }
2088 SkAutoCanvasRestore acr(&canvas, true);
2089 if (properties.GetClipBounds() != nullptr) {
2090 canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
2091 } else {
2092 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
2093 }
2094
2095 auto clipBounds = canvas.getDeviceClipBounds();
2096 auto image = skSurface->makeImageSnapshot(clipBounds);
2097 if (image == nullptr) {
2098 ROSEN_LOGE("RSPropertiesPainter::DrawLightUpEffect image is null");
2099 return;
2100 }
2101 auto imageShader = image->makeShader(SkSamplingOptions(SkFilterMode::kLinear));
2102 auto shader = MakeLightUpEffectShader(properties.GetLightUpEffect(), imageShader);
2103 SkPaint paint;
2104 paint.setShader(shader);
2105 canvas.resetMatrix();
2106 canvas.translate(clipBounds.left(), clipBounds.top());
2107 canvas.drawPaint(paint);
2108 #endif
2109 #endif
2110 }
2111
2112 #ifndef USE_ROSEN_DRAWING
2113 #ifdef NEW_SKIA
MakeLightUpEffectShader(float lightUpDeg,sk_sp<SkShader> imageShader)2114 sk_sp<SkShader> RSPropertiesPainter::MakeLightUpEffectShader(float lightUpDeg, sk_sp<SkShader> imageShader)
2115 {
2116 static constexpr char prog[] = R"(
2117 uniform half lightUpDeg;
2118 uniform shader imageShader;
2119 vec3 rgb2hsv(in vec3 c)
2120 {
2121 vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
2122 vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
2123 vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
2124 float d = q.x - min(q.w, q.y);
2125 float e = 1.0e-10;
2126 return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
2127 }
2128 vec3 hsv2rgb(in vec3 c)
2129 {
2130 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);
2131 return c.z * mix(vec3(1.0), rgb, c.y);
2132 }
2133 half4 main(float2 coord)
2134 {
2135 vec3 hsv = rgb2hsv(imageShader.eval(coord).rgb);
2136 float satUpper = clamp(hsv.y * 1.2, 0.0, 1.0);
2137 hsv.y = mix(satUpper, hsv.y, lightUpDeg);
2138 hsv.z += lightUpDeg - 1.0;
2139 return vec4(hsv2rgb(hsv), 1.0);
2140 }
2141 )";
2142 auto [effect, err] = SkRuntimeEffect::MakeForShader(SkString(prog));
2143 sk_sp<SkShader> children[] = {imageShader};
2144 size_t childCount = 1;
2145 return effect->makeShader(SkData::MakeWithCopy(
2146 &lightUpDeg, sizeof(lightUpDeg)), children, childCount, nullptr, false);
2147 }
2148 #endif
2149 #endif
2150
DrawDynamicLightUp(const RSProperties & properties,RSPaintFilterCanvas & canvas)2151 void RSPropertiesPainter::DrawDynamicLightUp(const RSProperties& properties, RSPaintFilterCanvas& canvas)
2152 {
2153 #ifndef USE_ROSEN_DRAWING
2154 #ifdef NEW_SKIA
2155 SkSurface* skSurface = canvas.GetSurface();
2156 if (skSurface == nullptr) {
2157 ROSEN_LOGD("RSPropertiesPainter::DrawDynamicLightUp skSurface is null");
2158 return;
2159 }
2160 SkAutoCanvasRestore acr(&canvas, true);
2161 if (properties.GetClipBounds() != nullptr) {
2162 canvas.clipPath(properties.GetClipBounds()->GetSkiaPath(), true);
2163 } else {
2164 canvas.clipRRect(RRect2SkRRect(properties.GetRRect()), true);
2165 }
2166
2167 auto clipBounds = canvas.getDeviceClipBounds();
2168 auto image = skSurface->makeImageSnapshot(clipBounds);
2169 if (image == nullptr) {
2170 ROSEN_LOGE("RSPropertiesPainter::DrawDynamicLightUp image is null");
2171 return;
2172 }
2173 auto imageShader = image->makeShader(SkSamplingOptions(SkFilterMode::kLinear));
2174 auto shader = MakeDynamicLightUpShader(
2175 properties.GetDynamicLightUpRate().value(), properties.GetDynamicLightUpDegree().value(), imageShader);
2176 SkPaint paint;
2177 paint.setShader(shader);
2178 canvas.resetMatrix();
2179 canvas.translate(clipBounds.left(), clipBounds.top());
2180 canvas.drawPaint(paint);
2181 #endif
2182 #endif
2183 }
2184
2185 #ifndef USE_ROSEN_DRAWING
2186 #ifdef NEW_SKIA
MakeDynamicLightUpShader(float dynamicLightUpRate,float dynamicLightUpDeg,sk_sp<SkShader> imageShader)2187 sk_sp<SkShader> RSPropertiesPainter::MakeDynamicLightUpShader(
2188 float dynamicLightUpRate, float dynamicLightUpDeg, sk_sp<SkShader> imageShader)
2189 {
2190 static constexpr char prog[] = R"(
2191 uniform half dynamicLightUpRate;
2192 uniform half dynamicLightUpDeg;
2193 uniform shader imageShader;
2194
2195 half4 main(float2 coord) {
2196 vec3 c = vec3(imageShader.eval(coord).r * 255,
2197 imageShader.eval(coord).g * 255, imageShader.eval(coord).b * 255);
2198 float x = 0.299 * c.r + 0.587 * c.g + 0.114 * c.b;
2199 float y = (0 - dynamicLightUpRate) * x + dynamicLightUpDeg * 255;
2200 float R = clamp((c.r + y) / 255, 0.0, 1.0);
2201 float G = clamp((c.g + y) / 255, 0.0, 1.0);
2202 float B = clamp((c.b + y) / 255, 0.0, 1.0);
2203 return vec4(R, G, B, 1.0);
2204 }
2205 )";
2206 auto [effect, err] = SkRuntimeEffect::MakeForShader(SkString(prog));
2207 if (!effect) {
2208 ROSEN_LOGE("MakeDynamicLightUpShader::RuntimeShader effect error: %s\n", err.c_str());
2209 return nullptr;
2210 }
2211 SkRuntimeShaderBuilder builder(effect);
2212 builder.child("imageShader") = imageShader;
2213 builder.uniform("dynamicLightUpRate") = dynamicLightUpRate;
2214 builder.uniform("dynamicLightUpDeg") = dynamicLightUpDeg;
2215 return builder.makeShader(nullptr, false);
2216 }
2217 #endif
2218 #endif
2219
DrawParticle(const RSProperties & properties,RSPaintFilterCanvas & canvas)2220 void RSPropertiesPainter::DrawParticle(const RSProperties& properties, RSPaintFilterCanvas& canvas)
2221 {
2222 auto particleVector = properties.GetParticles();
2223 if (particleVector.GetParticleSize() == 0) {
2224 return;
2225 }
2226 auto particles = particleVector.GetParticleVector();
2227 auto bounds = properties.GetDrawRegion();
2228 for (size_t i = 0; i < particles.size(); i++) {
2229 if (particles[i] != nullptr && particles[i]->IsAlive()) {
2230 // Get particle properties
2231 auto position = particles[i]->GetPosition();
2232 float opacity = particles[i]->GetOpacity();
2233 float scale = particles[i]->GetScale();
2234 if (!(bounds->Intersect(position.x_, position.y_)) || opacity <= 0.f || scale <= 0.f) {
2235 continue;
2236 }
2237 auto particleType = particles[i]->GetParticleType();
2238 #ifndef USE_ROSEN_DRAWING
2239 SkPaint paint;
2240 paint.setAntiAlias(true);
2241 paint.setAlphaf(opacity);
2242 auto clipBounds = SkRect::MakeXYWH(bounds->left_, bounds->top_, bounds->width_, bounds->height_);
2243 canvas.clipRect(clipBounds, true);
2244 #else
2245 Drawing::Brush brush;
2246 brush.SetAntiAlias(true);
2247 brush.SetAlphaF(opacity);
2248 auto clipBounds = Drawing::Rect(
2249 bounds->left_, bounds->top_, bounds->left_ + bounds->width_, bounds->top_ + bounds->height_);
2250 canvas.ClipRect(clipBounds, Drawing::ClipOp::INTERSECT, true);
2251 #endif
2252
2253 if (particleType == ParticleType::POINTS) {
2254 auto radius = particles[i]->GetRadius();
2255 Color color = particles[i]->GetColor();
2256 auto alpha = color.GetAlpha();
2257 color.SetAlpha(alpha * opacity);
2258 #ifndef USE_ROSEN_DRAWING
2259 paint.setColor(color.AsArgbInt());
2260 canvas.drawCircle(position.x_, position.y_, radius * scale, paint);
2261 #else
2262 brush.SetColor(color.AsArgbInt());
2263 canvas.AttachBrush(brush);
2264 canvas.DrawCircle(Drawing::Point(position.x_, position.y_), radius);
2265 canvas.DetachBrush();
2266 #endif
2267 } else {
2268 auto imageSize = particles[i]->GetImageSize();
2269 auto image = particles[i]->GetImage();
2270 float left = position.x_;
2271 float top = position.y_;
2272 float right = position.x_ + imageSize.x_ * scale;
2273 float bottom = position.y_ + imageSize.y_ * scale;
2274 canvas.save();
2275 canvas.translate(position.x_, position.y_);
2276 #ifndef USE_ROSEN_DRAWING
2277 canvas.rotate(particles[i]->GetSpin(), imageSize.x_ * scale / 2.f, imageSize.y_ * scale / 2.f);
2278 #else
2279 canvas.Save();
2280 canvas.Translate(position.x_, position.y_);
2281 canvas.Rotate(particles[i]->GetSpin(), imageSize.x_ * scale / 2.f, imageSize.y_ * scale / 2.f);
2282 #endif
2283 RectF destRect(left, top, right, bottom);
2284 image->SetDstRect(destRect);
2285 image->SetScale(scale);
2286 image->SetImageRepeat(0);
2287 #ifndef USE_ROSEN_DRAWING
2288 SkRect rect { left, top, right, bottom };
2289 #ifdef NEW_SKIA
2290 image->CanvasDrawImage(canvas, rect, SkSamplingOptions(), paint, false);
2291 canvas.restore();
2292 #else
2293 image->CanvasDrawImage(canvas, rect, paint, false);
2294 canvas.restore();
2295 #endif
2296 #else
2297 Drawing::Rect rect { fLeft, ftop, fRight, fBottom };
2298 canvas.AttachBrush(brush);
2299 image->CanvasDrawImage(canvas, rect, false);
2300 canvas.DetachBrush();
2301 canvas.Restore();
2302 #endif
2303 }
2304 }
2305 }
2306 }
2307
2308 } // namespace Rosen
2309 } // namespace OHOS
2310