1 /*
2 * Copyright (c) 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_property_drawable_bounds_geometry.h"
17
18 #include <utility>
19
20 #include "common/rs_obj_abs_geometry.h"
21 #include "common/rs_optional_trace.h"
22 #include "common/rs_vector4.h"
23 #include "pipeline/rs_canvas_render_node.h"
24 #include "pipeline/rs_effect_render_node.h"
25 #include "pipeline/rs_paint_filter_canvas.h"
26 #include "platform/common/rs_log.h"
27 #include "platform/common/rs_system_properties.h"
28 #include "property/rs_properties.h"
29 #include "property/rs_properties_def.h"
30 #include "property/rs_properties_painter.h"
31 #include "render/rs_drawing_filter.h"
32
33 namespace {
34 constexpr int PARAM_DOUBLE = 2;
35 constexpr int TRACE_LEVEL_TWO = 2;
36 } // namespace
37 namespace OHOS::Rosen {
38 // ============================================================================
39 // Bounds geometry
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const40 void RSBoundsGeometryDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
41 {
42 canvas.ConcatMatrix(content.GetRenderProperties().GetBoundsGeometry()->GetMatrix());
43 }
Generate(const RSRenderContent & content)44 RSPropertyDrawable::DrawablePtr RSBoundsGeometryDrawable::Generate(const RSRenderContent& content)
45 {
46 return std::make_unique<RSBoundsGeometryDrawable>();
47 }
48
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const49 void RSClipBoundsDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
50 {
51 // Planning: Generate() should calculate the draw op and cache it
52 auto& properties = content.GetRenderProperties();
53 if (properties.GetClipBounds() != nullptr) {
54 canvas.ClipPath(properties.GetClipBounds()->GetDrawingPath(), Drawing::ClipOp::INTERSECT, true);
55 } else if (properties.GetClipToRRect()) {
56 canvas.ClipRoundRect(
57 RSPropertiesPainter::RRect2DrawingRRect(properties.GetClipRRect()), Drawing::ClipOp::INTERSECT, false);
58 } else if (!properties.GetCornerRadius().IsZero()) {
59 canvas.ClipRoundRect(
60 RSPropertiesPainter::RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::INTERSECT, true);
61 } else {
62 canvas.ClipRect(
63 RSPropertiesPainter::Rect2DrawingRect(properties.GetBoundsRect()), Drawing::ClipOp::INTERSECT, true);
64 }
65 }
66
Generate(const RSRenderContent & content)67 RSPropertyDrawable::DrawablePtr RSClipBoundsDrawable::Generate(const RSRenderContent& content)
68 {
69 return std::make_unique<RSClipBoundsDrawable>();
70 }
71
72 // ============================================================================
73 // PointLight
Generate(const RSRenderContent & content)74 RSPropertyDrawable::DrawablePtr RSPointLightDrawable::Generate(const RSRenderContent& content)
75 {
76 const auto& properties = content.GetRenderProperties();
77 const auto& illuminatedPtr = properties.GetIlluminated();
78 if (illuminatedPtr && illuminatedPtr->IsIlluminatedValid()) {
79 return std::make_unique<RSPointLightDrawable>();
80 }
81 return nullptr;
82 }
83
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const84 void RSPointLightDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
85 {
86 auto& properties = content.GetRenderProperties();
87 const auto& illuminatedPtr = properties.GetIlluminated();
88 if (illuminatedPtr && illuminatedPtr->IsIlluminated()) {
89 RSPropertiesPainter::DrawLight(properties, canvas);
90 }
91 }
92
93 // ============================================================================
94 // Border
Generate(const RSRenderContent & content)95 RSPropertyDrawable::DrawablePtr RSBorderDrawable::Generate(const RSRenderContent& content)
96 {
97 auto& properties = content.GetRenderProperties();
98 auto border = properties.GetBorder();
99 if (!border || !border->HasBorder()) {
100 return nullptr;
101 }
102 Drawing::Pen pen;
103 Drawing::Brush brush;
104 pen.SetAntiAlias(true);
105 brush.SetAntiAlias(true);
106 if (border->ApplyFillStyle(brush)) {
107 return std::make_unique<RSBorderDRRectDrawable>(
108 std::move(brush), std::move(pen), properties, true);
109 } else if (properties.GetCornerRadius().IsZero() && border->ApplyFourLine(pen)) {
110 return std::make_unique<RSBorderFourLineDrawable>(
111 std::move(brush), std::move(pen), properties, true);
112 } else if (border->ApplyPathStyle(pen) && border->ApplySimpleBorder(properties.GetRRect())) {
113 return std::make_unique<RSBorderPathDrawable>(
114 std::move(brush), std::move(pen), properties, true);
115 } else {
116 return std::make_unique<RSBorderFourLineRoundCornerDrawable>(
117 std::move(brush), std::move(pen), properties, true);
118 }
119 }
RSBorderDRRectDrawable(Drawing::Brush && brush,Drawing::Pen && pen,const RSProperties & properties,const bool & drawBorder)120 RSBorderDRRectDrawable::RSBorderDRRectDrawable(Drawing::Brush&& brush, Drawing::Pen&& pen,
121 const RSProperties& properties, const bool& drawBorder)
122 : RSBorderDrawable(std::move(brush), std::move(pen))
123 {
124 drawBorder_ = drawBorder;
125 OnBoundsChange(properties);
126 }
127
OnBoundsChange(const RSProperties & properties)128 void RSBorderDRRectDrawable::OnBoundsChange(const RSProperties& properties)
129 {
130 if (drawBorder_) {
131 inner_ = RSPropertiesPainter::RRect2DrawingRRect(properties.GetInnerRRect());
132 outer_ = RSPropertiesPainter::RRect2DrawingRRect(properties.GetRRect());
133 } else {
134 inner_ = RSPropertiesPainter::RRect2DrawingRRect(properties.GetRRect());
135 RectF rect = properties.GetBoundsRect().MakeOutset(properties.GetOutline()->GetWidthFour());
136 outer_ = RSPropertiesPainter::RRect2DrawingRRect(RRect(rect, properties.GetOutline()->GetRadiusFour()));
137 }
138 }
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const139 void RSBorderDRRectDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
140 {
141 canvas.AttachBrush(brush_);
142 canvas.DrawNestedRoundRect(outer_, inner_);
143 canvas.DetachBrush();
144 }
145
RSBorderFourLineDrawable(Drawing::Brush && brush,Drawing::Pen && pen,const RSProperties & properties,const bool & drawBorder)146 RSBorderFourLineDrawable::RSBorderFourLineDrawable(Drawing::Brush&& brush, Drawing::Pen&& pen,
147 const RSProperties& properties, const bool& drawBorder)
148 : RSBorderDrawable(std::move(brush), std::move(pen))
149 {
150 drawBorder_ = drawBorder;
151 OnBoundsChange(properties);
152 }
153
OnBoundsChange(const RSProperties & properties)154 void RSBorderFourLineDrawable::OnBoundsChange(const RSProperties& properties)
155 {
156 if (drawBorder_) {
157 rect_ = properties.GetBoundsRect();
158 } else {
159 rect_ = properties.GetBoundsRect().MakeOutset(properties.GetOutline()->GetWidthFour());
160 }
161 }
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const162 void RSBorderFourLineDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
163 {
164 auto pen = pen_;
165 if (drawBorder_) {
166 content.GetRenderProperties().GetBorder()->PaintFourLine(canvas, pen, rect_);
167 } else {
168 content.GetRenderProperties().GetOutline()->PaintFourLine(canvas, pen, rect_);
169 }
170 }
171
RSBorderPathDrawable(Drawing::Brush && brush,Drawing::Pen && pen,const RSProperties & properties,const bool & drawBorder)172 RSBorderPathDrawable::RSBorderPathDrawable(Drawing::Brush&& brush, Drawing::Pen&& pen,
173 const RSProperties& properties, const bool& drawBorder)
174 : RSBorderDrawable(std::move(brush), std::move(pen))
175 {
176 drawBorder_ = drawBorder;
177 OnBoundsChange(properties);
178 }
179
OnBoundsChange(const RSProperties & properties)180 void RSBorderPathDrawable::OnBoundsChange(const RSProperties& properties)
181 {
182 float borderWidth;
183 RRect rrect;
184 if (drawBorder_) {
185 borderWidth = properties.GetBorder()->GetWidth();
186 rrect = properties.GetRRect();
187 } else {
188 borderWidth = properties.GetOutline()->GetWidth();
189 RectF rect = properties.GetBoundsRect().MakeOutset(properties.GetOutline()->GetWidthFour());
190 rrect = RRect(rect, properties.GetOutline()->GetRadiusFour());
191 }
192 rrect.rect_.width_ -= borderWidth;
193 rrect.rect_.height_ -= borderWidth;
194 rrect.rect_.Move(borderWidth / PARAM_DOUBLE, borderWidth / PARAM_DOUBLE);
195 borderPath_.Reset();
196 borderPath_.AddRoundRect(RSPropertiesPainter::RRect2DrawingRRect(rrect));
197 }
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const198 void RSBorderPathDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
199 {
200 canvas.AttachPen(pen_);
201 canvas.DrawPath(borderPath_);
202 canvas.DetachPen();
203 }
204
RSBorderFourLineRoundCornerDrawable(Drawing::Brush && brush,Drawing::Pen && pen,const RSProperties & properties,const bool & drawBorder)205 RSBorderFourLineRoundCornerDrawable::RSBorderFourLineRoundCornerDrawable(
206 Drawing::Brush&& brush, Drawing::Pen&& pen, const RSProperties& properties, const bool& drawBorder)
207 : RSBorderDrawable(std::move(brush), std::move(pen)), drawBorder_(drawBorder)
208 {
209 OnBoundsChange(properties);
210 }
211
OnBoundsChange(const RSProperties & properties)212 void RSBorderFourLineRoundCornerDrawable::OnBoundsChange(const RSProperties& properties)
213 {
214 if (drawBorder_) {
215 innerRrect_ = RSPropertiesPainter::RRect2DrawingRRect(properties.GetInnerRRect());
216 rrect_ = RSPropertiesPainter::RRect2DrawingRRect(properties.GetRRect());
217 } else {
218 innerRrect_ = RSPropertiesPainter::RRect2DrawingRRect(properties.GetRRect());
219 RectF rect = properties.GetBoundsRect().MakeOutset(properties.GetOutline()->GetWidthFour());
220 rrect_ = RSPropertiesPainter::RRect2DrawingRRect(RRect(rect, properties.GetOutline()->GetRadiusFour()));
221 }
222 }
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const223 void RSBorderFourLineRoundCornerDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
224 {
225 auto pen = pen_;
226 auto& properties = content.GetRenderProperties();
227 auto rect = rrect_.GetRect();
228 RSBorderGeo borderGeo;
229 borderGeo.rrect = rrect_;
230 borderGeo.innerRRect = innerRrect_;
231 auto centerX = innerRrect_.GetRect().GetLeft() + innerRrect_.GetRect().GetWidth() / 2;
232 auto centerY = innerRrect_.GetRect().GetTop() + innerRrect_.GetRect().GetHeight() / 2;
233 borderGeo.center = { centerX, centerY };
234 Drawing::AutoCanvasRestore acr(canvas, false);
235 Drawing::SaveLayerOps slr(&rect, nullptr);
236 canvas.SaveLayer(slr);
237 if (drawBorder_) {
238 properties.GetBorder()->DrawBorders(canvas, pen, borderGeo);
239 } else {
240 properties.GetOutline()->DrawBorders(canvas, pen, borderGeo);
241 }
242 }
243
244 // ============================================================================
245 // Outline
Generate(const RSRenderContent & content)246 RSPropertyDrawable::DrawablePtr RSOutlineDrawable::Generate(const RSRenderContent& content)
247 {
248 auto& properties = content.GetRenderProperties();
249 auto& outline = properties.GetOutline();
250 if (!outline || !outline->HasBorder()) {
251 return nullptr;
252 }
253 Drawing::Pen pen;
254 Drawing::Brush brush;
255 pen.SetAntiAlias(true);
256 brush.SetAntiAlias(true);
257 if (outline->ApplyFillStyle(brush)) {
258 return std::make_unique<RSBorderDRRectDrawable>(std::move(brush), std::move(pen), properties, false);
259 } else if (outline->GetRadiusFour().IsZero() && outline->ApplyFourLine(pen)) {
260 return std::make_unique<RSBorderFourLineDrawable>(std::move(brush), std::move(pen), properties, false);
261 } else if (outline->ApplyPathStyle(pen)) {
262 return std::make_unique<RSBorderPathDrawable>(std::move(brush), std::move(pen), properties, false);
263 } else {
264 return std::make_unique<RSBorderFourLineRoundCornerDrawable>(
265 std::move(brush), std::move(pen), properties, false);
266 }
267 }
268
269 // ============================================================================
270 // Mask
Generate(const RSRenderContent & content)271 RSPropertyDrawable::DrawablePtr RSMaskDrawable::Generate(const RSRenderContent& content)
272 {
273 auto& properties = content.GetRenderProperties();
274 std::shared_ptr<RSMask> mask = properties.GetMask();
275 if (mask == nullptr) {
276 return nullptr;
277 }
278 if (mask->IsSvgMask() && !mask->GetSvgDom() && !mask->GetSvgPicture()) {
279 return nullptr;
280 }
281 if (mask->IsSvgMask()) {
282 if (mask->GetSvgDom()) {
283 return std::make_unique<RSSvgDomMaskDrawable>(mask);
284 } else if (mask->GetSvgPicture()) {
285 return std::make_unique<RSSvgPictureMaskDrawable>(mask);
286 }
287 } else if (mask->IsGradientMask()) {
288 return std::make_unique<RSGradientMaskDrawable>(mask);
289 } else if (mask->IsPathMask()) {
290 return std::make_unique<RSPathMaskDrawable>(mask);
291 } else if (mask->IsPixelMapMask()) {
292 return std::make_unique<RSPixelMapMaskDrawable>(mask);
293 }
294 return nullptr;
295 }
296
RSMaskDrawable(std::shared_ptr<RSMask> mask)297 RSMaskDrawable::RSMaskDrawable(std::shared_ptr<RSMask> mask) : mask_(std::move(mask))
298 {
299 maskBrush_.SetBlendMode(Drawing::BlendMode::SRC_IN);
300 Drawing::Filter filter;
301 filter.SetColorFilter(Drawing::ColorFilter::CreateComposeColorFilter(
302 *(Drawing::ColorFilter::CreateLumaColorFilter()), *(Drawing::ColorFilter::CreateSrgbGammaToLinear())));
303 maskFilterBrush_.SetFilter(filter);
304 }
305
RSSvgDomMaskDrawable(std::shared_ptr<RSMask> mask)306 RSSvgDomMaskDrawable::RSSvgDomMaskDrawable(std::shared_ptr<RSMask> mask) : RSMaskDrawable(mask) {}
307
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const308 void RSSvgDomMaskDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
309 {
310 auto& properties = content.GetRenderProperties();
311 auto bounds = RSPropertiesPainter::Rect2DrawingRect(properties.GetBoundsRect());
312 canvas.Save();
313 Drawing::SaveLayerOps slr(&bounds, nullptr);
314 canvas.SaveLayer(slr);
315 uint32_t tmpLayer = canvas.GetSaveCount();
316 Drawing::SaveLayerOps slrMask(&bounds, &maskFilterBrush_);
317 canvas.SaveLayer(slrMask);
318 {
319 Drawing::AutoCanvasRestore acr(canvas, true);
320 canvas.Translate(bounds.GetLeft() + mask_->GetSvgX(), bounds.GetTop() + mask_->GetSvgY());
321 canvas.Scale(mask_->GetScaleX(), mask_->GetScaleY());
322 canvas.DrawSVGDOM(mask_->GetSvgDom());
323 }
324 canvas.RestoreToCount(tmpLayer);
325 Drawing::SaveLayerOps slrContent(&bounds, &maskBrush_);
326 canvas.SaveLayer(slrContent);
327 canvas.ClipRect(bounds, Drawing::ClipOp::INTERSECT, true);
328 }
329
RSSvgPictureMaskDrawable(std::shared_ptr<RSMask> mask)330 RSSvgPictureMaskDrawable::RSSvgPictureMaskDrawable(std::shared_ptr<RSMask> mask) : RSMaskDrawable(mask) {}
331
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const332 void RSSvgPictureMaskDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
333 {
334 auto& properties = content.GetRenderProperties();
335 auto bounds = RSPropertiesPainter::Rect2DrawingRect(properties.GetBoundsRect());
336 canvas.Save();
337 Drawing::SaveLayerOps slr(&bounds, nullptr);
338 canvas.SaveLayer(slr);
339 uint32_t tmpLayer = canvas.GetSaveCount();
340 Drawing::SaveLayerOps slrMask(&bounds, &maskFilterBrush_);
341 canvas.SaveLayer(slrMask);
342 {
343 Drawing::AutoCanvasRestore acr(canvas, true);
344 canvas.Translate(bounds.GetLeft() + mask_->GetSvgX(), bounds.GetTop() + mask_->GetSvgY());
345 canvas.Scale(mask_->GetScaleX(), mask_->GetScaleY());
346 canvas.DrawPicture(*mask_->GetSvgPicture());
347 }
348 canvas.RestoreToCount(tmpLayer);
349 Drawing::SaveLayerOps slrContent(&bounds, &maskBrush_);
350 canvas.SaveLayer(slrContent);
351 canvas.ClipRect(bounds, Drawing::ClipOp::INTERSECT, true);
352 }
353
RSGradientMaskDrawable(std::shared_ptr<RSMask> mask)354 RSGradientMaskDrawable::RSGradientMaskDrawable(std::shared_ptr<RSMask> mask) : RSMaskDrawable(mask) {}
355
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const356 void RSGradientMaskDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
357 {
358 auto& properties = content.GetRenderProperties();
359 auto bounds = RSPropertiesPainter::Rect2DrawingRect(properties.GetBoundsRect());
360 canvas.Save();
361 Drawing::SaveLayerOps slr(&bounds, nullptr);
362 canvas.SaveLayer(slr);
363 uint32_t tmpLayer = canvas.GetSaveCount();
364 Drawing::SaveLayerOps slrMask(&bounds, &maskFilterBrush_);
365 canvas.SaveLayer(slrMask);
366 {
367 Drawing::AutoCanvasRestore acr(canvas, true);
368 canvas.Translate(bounds.GetLeft(), bounds.GetTop());
369 Drawing::Rect rect =
370 Drawing::Rect(0, 0, bounds.GetRight() - bounds.GetLeft(), bounds.GetBottom() - bounds.GetTop());
371 canvas.AttachBrush(mask_->GetMaskBrush());
372 canvas.DrawRect(rect);
373 canvas.DetachBrush();
374 }
375 canvas.RestoreToCount(tmpLayer);
376 Drawing::SaveLayerOps slrContent(&bounds, &maskBrush_);
377 canvas.SaveLayer(slrContent);
378 canvas.ClipRect(bounds, Drawing::ClipOp::INTERSECT, true);
379 }
380
RSPathMaskDrawable(std::shared_ptr<RSMask> mask)381 RSPathMaskDrawable::RSPathMaskDrawable(std::shared_ptr<RSMask> mask) : RSMaskDrawable(mask) {}
382
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const383 void RSPathMaskDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
384 {
385 auto& properties = content.GetRenderProperties();
386 auto bounds = RSPropertiesPainter::Rect2DrawingRect(properties.GetBoundsRect());
387 canvas.Save();
388 Drawing::SaveLayerOps slr(&bounds, nullptr);
389 canvas.SaveLayer(slr);
390 uint32_t tmpLayer = canvas.GetSaveCount();
391 Drawing::SaveLayerOps slrMask(&bounds, &maskFilterBrush_);
392 canvas.SaveLayer(slrMask);
393 {
394 Drawing::AutoCanvasRestore acr(canvas, true);
395 canvas.Translate(bounds.GetLeft(), bounds.GetTop());
396 canvas.AttachBrush(mask_->GetMaskBrush());
397 canvas.AttachPen(mask_->GetMaskPen());
398 canvas.DrawPath(*mask_->GetMaskPath());
399 canvas.DetachBrush();
400 canvas.DetachPen();
401 }
402 canvas.RestoreToCount(tmpLayer);
403 Drawing::SaveLayerOps slrContent(&bounds, &maskBrush_);
404 canvas.SaveLayer(slrContent);
405 canvas.ClipRect(bounds, Drawing::ClipOp::INTERSECT, true);
406 }
407
RSPixelMapMaskDrawable(std::shared_ptr<RSMask> mask)408 RSPixelMapMaskDrawable::RSPixelMapMaskDrawable(std::shared_ptr<RSMask> mask) : RSMaskDrawable(mask) {}
409
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const410 void RSPixelMapMaskDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
411 {
412 auto& properties = content.GetRenderProperties();
413 auto bounds = RSPropertiesPainter::Rect2DrawingRect(properties.GetBoundsRect());
414 canvas.Save();
415 Drawing::SaveLayerOps slr(&bounds, nullptr);
416 canvas.SaveLayer(slr);
417 uint32_t tmpLayer = canvas.GetSaveCount();
418 Drawing::SaveLayerOps slrMask(&bounds, &maskFilterBrush_);
419 canvas.SaveLayer(slrMask);
420 {
421 Drawing::AutoCanvasRestore acr(canvas, true);
422 if (mask_ && mask_->GetImage()) {
423 canvas.DrawImage(*mask_->GetImage(), 0.f, 0.f, Drawing::SamplingOptions());
424 }
425 }
426 canvas.RestoreToCount(tmpLayer);
427 Drawing::SaveLayerOps slrContent(&bounds, &maskBrush_);
428 canvas.SaveLayer(slrContent);
429 canvas.ClipRect(bounds, Drawing::ClipOp::INTERSECT, true);
430 }
431
432 // ============================================================================
433 // Shadow
Generate(const RSRenderContent & content)434 RSPropertyDrawable::DrawablePtr RSShadowBaseDrawable::Generate(const RSRenderContent& content)
435 {
436 auto& properties = content.GetRenderProperties();
437 if (properties.IsSpherizeValid() || properties.IsAttractionValid() || !properties.IsShadowValid() ||
438 properties.GetNeedSkipShadow()) {
439 return nullptr;
440 }
441 if (properties.GetShadowMask()) {
442 return std::make_unique<RSColorfulShadowDrawable>(properties);
443 } else {
444 if (properties.GetShadowElevation() > 0.f) {
445 return std::make_unique<RSHardwareAccelerationShadowDrawable>(properties);
446 } else {
447 return std::make_unique<RSShadowDrawable>(properties);
448 }
449 return nullptr;
450 }
451 }
452
RSShadowBaseDrawable(const RSProperties & properties)453 RSShadowBaseDrawable::RSShadowBaseDrawable(const RSProperties& properties)
454 : offsetX_(properties.GetShadowOffsetX()), offsetY_(properties.GetShadowOffsetY()),
455 color_(properties.GetShadowColor())
456 {}
457
RSShadowDrawable(const RSProperties & properties)458 RSShadowDrawable::RSShadowDrawable(const RSProperties& properties)
459 : RSShadowBaseDrawable(properties), radius_(properties.GetShadowRadius())
460 {}
461
ClipShadowPath(const RSRenderContent & content,RSPaintFilterCanvas & canvas,Drawing::Path & path) const462 void RSShadowBaseDrawable::ClipShadowPath(
463 const RSRenderContent& content, RSPaintFilterCanvas& canvas, Drawing::Path& path) const
464 {
465 const auto& properties = content.GetRenderProperties();
466 if (properties.GetShadowPath() && properties.GetShadowPath()->GetDrawingPath().IsValid()) {
467 path = properties.GetShadowPath()->GetDrawingPath();
468 if (!properties.GetShadowIsFilled()) {
469 canvas.ClipPath(path, Drawing::ClipOp::DIFFERENCE, true);
470 }
471 } else if (properties.GetClipBounds()) {
472 path = properties.GetClipBounds()->GetDrawingPath();
473 if (!properties.GetShadowIsFilled()) {
474 canvas.ClipPath(path, Drawing::ClipOp::DIFFERENCE, true);
475 }
476 } else {
477 path.AddRoundRect(RSPropertiesPainter::RRect2DrawingRRect(properties.GetRRect()));
478 if (!properties.GetShadowIsFilled()) {
479 canvas.ClipRoundRect(
480 RSPropertiesPainter::RRect2DrawingRRect(properties.GetRRect()), Drawing::ClipOp::DIFFERENCE, true);
481 }
482 }
483 }
484
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const485 void RSShadowDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
486 {
487 if (content.GetRenderProperties().GetNeedSkipShadow()) {
488 return;
489 }
490 if (canvas.GetCacheType() == RSPaintFilterCanvas::CacheType::ENABLED) {
491 return;
492 }
493 RS_OPTIONAL_TRACE_NAME_FMT_LEVEL(TRACE_LEVEL_TWO,
494 "RSShadowDrawable::DrawShadow, Radius: %f, ShadowOffsetX: %f, ShadowOffsetY: %f, bounds: %s", radius_, offsetX_,
495 offsetY_, content.GetRenderProperties().GetBoundsGeometry()->GetAbsRect().ToString().c_str());
496 auto deviceClipBounds = canvas.GetDeviceClipBounds();
497 Drawing::AutoCanvasRestore acr(canvas, true);
498 Drawing::Path path;
499 ClipShadowPath(content, canvas, path);
500 path.Offset(offsetX_, offsetY_);
501 auto matrix = canvas.GetTotalMatrix();
502 matrix.Set(Drawing::Matrix::TRANS_X, std::ceil(matrix.Get(Drawing::Matrix::TRANS_X)));
503 matrix.Set(Drawing::Matrix::TRANS_Y, std::ceil(matrix.Get(Drawing::Matrix::TRANS_Y)));
504 canvas.SetMatrix(matrix);
505 Drawing::Brush brush;
506 brush.SetColor(Drawing::Color::ColorQuadSetARGB(
507 color_.GetAlpha(), color_.GetRed(), color_.GetGreen(), color_.GetBlue()));
508 brush.SetAntiAlias(true);
509 Drawing::Filter filter;
510 filter.SetMaskFilter(Drawing::MaskFilter::CreateBlurMaskFilter(Drawing::BlurType::NORMAL, radius_));
511 brush.SetFilter(filter);
512 canvas.AttachBrush(brush);
513 canvas.DrawPath(path);
514 canvas.DetachBrush();
515 }
516
RSHardwareAccelerationShadowDrawable(const RSProperties & properties)517 RSHardwareAccelerationShadowDrawable::RSHardwareAccelerationShadowDrawable(const RSProperties& properties)
518 : RSShadowBaseDrawable(properties), shadowElevation_(properties.GetShadowElevation())
519 {}
520
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const521 void RSHardwareAccelerationShadowDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
522 {
523 if (canvas.GetCacheType() == RSPaintFilterCanvas::CacheType::ENABLED) {
524 return;
525 }
526 RS_OPTIONAL_TRACE_NAME_FMT_LEVEL(TRACE_LEVEL_TWO,
527 "RSHardwareAccelerationShadowDrawable::DrawShadow, Elevation: %f, ShadowOffsetX: %f, "
528 "ShadowOffsetY: %f, bounds: %s",
529 shadowElevation_, offsetX_, offsetY_,
530 content.GetRenderProperties().GetBoundsGeometry()->GetAbsRect().ToString().c_str());
531 Drawing::AutoCanvasRestore acr(canvas, true);
532 Drawing::Path path;
533 ClipShadowPath(content, canvas, path);
534 path.Offset(offsetX_, offsetY_);
535 RSAutoCanvasRestore rst(&canvas);
536 auto matrix = canvas.GetTotalMatrix();
537 matrix.Set(Drawing::Matrix::TRANS_X, std::ceil(matrix.Get(Drawing::Matrix::TRANS_X)));
538 matrix.Set(Drawing::Matrix::TRANS_Y, std::ceil(matrix.Get(Drawing::Matrix::TRANS_Y)));
539 canvas.SetMatrix(matrix);
540 Drawing::Point3 planeParams = { 0.0f, 0.0f, shadowElevation_ };
541 std::vector<Drawing::Point> pt{{path.GetBounds().GetLeft() + path.GetBounds().GetWidth() / 2,
542 path.GetBounds().GetTop() + path.GetBounds().GetHeight() / 2}};
543 canvas.GetTotalMatrix().MapPoints(pt, pt, 1);
544 Drawing::Point3 lightPos = {pt[0].GetX(), pt[0].GetY(), DEFAULT_LIGHT_HEIGHT};
545 Color ambientColor = Color::FromArgbInt(DEFAULT_AMBIENT_COLOR);
546 ambientColor.MultiplyAlpha(canvas.GetAlpha());
547 Color spotColor = color_;
548 spotColor.MultiplyAlpha(canvas.GetAlpha());
549 canvas.DrawShadowStyle(path, planeParams, lightPos, DEFAULT_LIGHT_RADIUS, Drawing::Color(ambientColor.AsArgbInt()),
550 Drawing::Color(spotColor.AsArgbInt()), Drawing::ShadowFlags::TRANSPARENT_OCCLUDER, true);
551 }
552
RSColorfulShadowDrawable(const RSProperties & properties)553 RSColorfulShadowDrawable::RSColorfulShadowDrawable(const RSProperties& properties) : RSShadowBaseDrawable(properties)
554 {
555 const Drawing::scalar blurRadius =
556 properties.GetShadowElevation() > 0.f
557 ? 0.25f * properties.GetShadowElevation() * (1 + properties.GetShadowElevation() / 128.0f)
558 : properties.GetShadowRadius();
559 Drawing::Filter filter;
560 filter.SetImageFilter(
561 Drawing::ImageFilter::CreateBlurImageFilter(blurRadius, blurRadius, Drawing::TileMode::DECAL, nullptr));
562 blurBrush_.SetFilter(filter);
563 node_ = properties.backref_;
564 }
565
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const566 void RSColorfulShadowDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
567 {
568 if (canvas.GetCacheType() == RSPaintFilterCanvas::CacheType::ENABLED) {
569 return;
570 }
571 Drawing::AutoCanvasRestore acr(canvas, true);
572 Drawing::Path path;
573 ClipShadowPath(content, canvas, path);
574 // save layer, draw image with clipPath, blur and draw back
575 Drawing::SaveLayerOps slr(nullptr, &blurBrush_);
576 canvas.SaveLayer(slr);
577 canvas.Translate(offsetX_, offsetY_);
578 canvas.ClipPath(path, Drawing::ClipOp::INTERSECT, false);
579 // draw node content as shadow
580 // [PLANNING]: maybe we should also draw background color / image here, and we should cache the shadow image
581 if (auto node = RSBaseRenderNode::ReinterpretCast<RSCanvasRenderNode>(node_.lock())) {
582 node->InternalDrawContent(canvas, false);
583 }
584 }
585
586 // ============================================================================
587 // DynamicLightUp
Generate(const RSRenderContent & content)588 RSPropertyDrawable::DrawablePtr RSDynamicLightUpDrawable::Generate(const RSRenderContent& content)
589 {
590 auto& properties = content.GetRenderProperties();
591 if (!properties.IsDynamicLightUpValid()) {
592 return nullptr;
593 }
594 return std::make_unique<RSDynamicLightUpDrawable>();
595 }
596
Update(const RSRenderContent & content)597 bool RSDynamicLightUpDrawable::Update(const RSRenderContent& content)
598 {
599 return content.GetRenderProperties().IsDynamicLightUpValid();
600 }
601
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const602 void RSDynamicLightUpDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
603 {
604 RSPropertiesPainter::DrawDynamicLightUp(content.GetRenderProperties(), canvas);
605 }
606
607 // ============================================================================
608 // LightUpEffect
Generate(const RSRenderContent & content)609 RSPropertyDrawable::DrawablePtr RSLightUpEffectDrawable::Generate(const RSRenderContent& content)
610 {
611 if (!content.GetRenderProperties().IsLightUpEffectValid()) {
612 return nullptr;
613 }
614 return std::make_unique<RSLightUpEffectDrawable>();
615 }
616
Update(const RSRenderContent & content)617 bool RSLightUpEffectDrawable::Update(const RSRenderContent& content)
618 {
619 return content.GetRenderProperties().IsLightUpEffectValid();
620 }
621
622 // ============================================================================
623 //DynamicDim
Generate(const RSRenderContent & context)624 RSPropertyDrawable::DrawablePtr RSDynamicDimDrawable::Generate(const RSRenderContent& context)
625 {
626 if (!context.GetRenderProperties().IsDynamicDimValid()) {
627 return nullptr;
628 }
629 return std::make_unique<RSDynamicDimDrawable>();
630 }
631
Update(const RSRenderContent & context)632 bool RSDynamicDimDrawable::Update(const RSRenderContent& context)
633 {
634 return context.GetRenderProperties().IsDynamicDimValid();
635 }
636
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const637 void RSDynamicDimDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
638 {
639 RSPropertiesPainter::DrawDynamicDim(content.GetRenderProperties(), canvas);
640 }
641
642 // ============================================================================
643 // Binarization
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const644 void RSBinarizationDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
645 {
646 RSPropertiesPainter::DrawBinarizationShader(content.GetRenderProperties(), canvas);
647 }
648
Generate(const RSRenderContent & content)649 RSPropertyDrawable::DrawablePtr RSBinarizationDrawable::Generate(const RSRenderContent& content)
650 {
651 auto& aiInvert = content.GetRenderProperties().GetAiInvert();
652 if (!aiInvert.has_value()) {
653 return nullptr;
654 }
655 return std::make_unique<RSBinarizationDrawable>();
656 }
657
658 // ============================================================================
659 // LightUpEffect
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const660 void RSLightUpEffectDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
661 {
662 RSPropertiesPainter::DrawLightUpEffect(content.GetRenderProperties(), canvas);
663 }
664
665 // ============================================================================
666 // background filter
Generate(const RSRenderContent & content)667 RSPropertyDrawable::DrawablePtr RSBackgroundFilterDrawable::Generate(const RSRenderContent& content)
668 {
669 if (!RSPropertiesPainter::BLUR_ENABLED) {
670 ROSEN_LOGD("RSBackgroundFilterDrawable::Generate close blur.");
671 return nullptr;
672 }
673 auto& filter = content.GetRenderProperties().GetBackgroundFilter();
674 if (filter == nullptr) {
675 return nullptr;
676 }
677 if (content.GetType() == RSRenderNodeType::EFFECT_NODE) {
678 // for RSEffectRenderNode, we just use generates effect data, instead of draw filter
679 return std::make_unique<RSEffectDataGenerateDrawable>();
680 }
681 return std::make_unique<RSBackgroundFilterDrawable>();
682 }
683
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const684 void RSBackgroundFilterDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
685 {
686 // fix compatibility with Node Group, copied from RSCanvasRenderNode::ProcessAnimatePropertyBeforeChildren
687 if (canvas.GetCacheType() == RSPaintFilterCanvas::CacheType::OFFSCREEN) {
688 return;
689 }
690 RSPropertiesPainter::DrawFilter(content.GetRenderProperties(), canvas, FilterType::BACKGROUND_FILTER);
691 }
692
693 // compositing filter
Generate(const RSRenderContent & content)694 RSPropertyDrawable::DrawablePtr RSCompositingFilterDrawable::Generate(const RSRenderContent& content)
695 {
696 if (!RSPropertiesPainter::BLUR_ENABLED) {
697 ROSEN_LOGD("RSCompositingFilterDrawable::Generate close blur.");
698 return nullptr;
699 }
700 auto& filter = content.GetRenderProperties().GetFilter();
701 if (filter == nullptr) {
702 return nullptr;
703 }
704 return std::make_unique<RSCompositingFilterDrawable>();
705 }
706
Update(const RSRenderContent & content)707 bool RSCompositingFilterDrawable::Update(const RSRenderContent& content)
708 {
709 return content.GetRenderProperties().GetFilter() != nullptr;
710 }
711
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const712 void RSCompositingFilterDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
713 {
714 RSPropertiesPainter::DrawFilter(content.GetRenderProperties(), canvas, FilterType::FOREGROUND_FILTER);
715 }
716
IsForegroundFilterValid(const RSRenderContent & content)717 bool IsForegroundFilterValid(const RSRenderContent& content)
718 {
719 auto& rsFilter = content.GetRenderProperties().GetForegroundFilter();
720 if (rsFilter == nullptr) {
721 return false;
722 }
723 return true;
724 }
725
726 // foreground filter
Generate(const RSRenderContent & content)727 RSPropertyDrawable::DrawablePtr RSForegroundFilterDrawable::Generate(const RSRenderContent& content)
728 {
729 if (!RSPropertiesPainter::FOREGROUND_FILTER_ENABLED) {
730 ROSEN_LOGD("RSForegroundFilterDrawable::Generate close blur.");
731 return nullptr;
732 }
733
734 if (!IsForegroundFilterValid(content)) {
735 return nullptr;
736 }
737 return std::make_unique<RSForegroundFilterDrawable>();
738 }
739
Update(const RSRenderContent & content)740 bool RSForegroundFilterDrawable::Update(const RSRenderContent& content)
741 {
742 return content.GetRenderProperties().GetForegroundFilter() != nullptr;
743 }
744
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const745 void RSForegroundFilterDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
746 {
747 RS_OPTIONAL_TRACE_NAME("RSForegroundFilterDrawable::Draw");
748 auto surface = canvas.GetSurface();
749 if (!surface) {
750 ROSEN_LOGD("RSForegroundFilterDrawable::Draw main screen canvas no surface.");
751 return;
752 }
753 auto bounds = content.GetRenderProperties().GetBoundsRect();
754 std::shared_ptr<Drawing::Surface> offscreenSurface = surface->MakeSurface(bounds.width_, bounds.height_);
755 if (!offscreenSurface) {
756 ROSEN_LOGD("RSForegroundFilterDrawable::Draw create offscreenSurface fail.");
757 return;
758 }
759 auto offscreenCanvas = std::make_shared<RSPaintFilterCanvas>(offscreenSurface.get());
760 if (!offscreenCanvas) {
761 ROSEN_LOGD("RSForegroundFilterDrawable::Draw create offscreenCanvas fail.");
762 return;
763 }
764 canvas.StoreCanvas();
765 canvas.ReplaceMainScreenData(offscreenSurface, offscreenCanvas);
766 offscreenCanvas->Clear(Drawing::Color::COLOR_TRANSPARENT);
767 canvas.SavePCanvasList();
768 canvas.RemoveAll();
769 canvas.AddCanvas(offscreenCanvas.get());
770 }
771
772 // foreground filter restore
Generate(const RSRenderContent & content)773 RSPropertyDrawable::DrawablePtr RSForegroundFilterRestoreDrawable::Generate(const RSRenderContent& content)
774 {
775 if (!RSPropertiesPainter::FOREGROUND_FILTER_ENABLED) {
776 ROSEN_LOGD("RSForegroundFilterDrawable::Generate close blur.");
777 return nullptr;
778 }
779
780 if (!IsForegroundFilterValid(content)) {
781 return nullptr;
782 }
783
784 return std::make_unique<RSForegroundFilterRestoreDrawable>();
785 }
786
Update(const RSRenderContent & content)787 bool RSForegroundFilterRestoreDrawable::Update(const RSRenderContent& content)
788 {
789 return content.GetRenderProperties().GetForegroundFilter() != nullptr;
790 }
791
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const792 void RSForegroundFilterRestoreDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
793 {
794 RSPropertiesPainter::DrawForegroundFilter(content.GetRenderProperties(), canvas);
795 }
796
797 // effect data
Update(const RSRenderContent & content)798 bool RSEffectDataGenerateDrawable::Update(const RSRenderContent& content)
799 {
800 return content.GetRenderProperties().GetBackgroundFilter() != nullptr;
801 }
802
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const803 void RSEffectDataGenerateDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
804 {
805 const auto& properties = content.GetRenderProperties();
806 if (properties.GetHaveEffectRegion() && properties.GetBackgroundFilter() &&
807 RSSystemProperties::GetEffectMergeEnabled()) {
808 RSPropertiesPainter::DrawBackgroundEffect(content.GetRenderProperties(), canvas);
809 }
810 }
811
812 // effect data apply
Generate(const RSRenderContent & content)813 RSPropertyDrawable::DrawablePtr RSEffectDataApplyDrawable::Generate(const RSRenderContent& content)
814 {
815 if (content.GetRenderProperties().GetUseEffect() == false) {
816 return nullptr;
817 }
818 return std::make_unique<RSEffectDataApplyDrawable>();
819 }
820
Update(const RSRenderContent & content)821 bool RSEffectDataApplyDrawable::Update(const RSRenderContent& content)
822 {
823 return content.GetRenderProperties().GetUseEffect();
824 }
825
Update(const RSRenderContent & content)826 bool RSBackgroundFilterDrawable::Update(const RSRenderContent& content)
827 {
828 return content.GetRenderProperties().GetBackgroundFilter() != nullptr;
829 }
830
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const831 void RSEffectDataApplyDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
832 {
833 // fix compatibility with Node Group, copied from RSCanvasRenderNode::ProcessAnimatePropertyBeforeChildren
834 if (canvas.GetCacheType() == RSPaintFilterCanvas::CacheType::OFFSCREEN) {
835 return;
836 }
837 RSPropertiesPainter::ApplyBackgroundEffect(content.GetRenderProperties(), canvas);
838 }
839
840 // ============================================================================
841 // ForegroundColor
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const842 void RSForegroundColorDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
843 {
844 auto& properties = content.GetRenderProperties();
845 canvas.AttachBrush(brush_);
846 canvas.DrawRoundRect(RSPropertiesPainter::RRect2DrawingRRect(properties.GetRRect()));
847 canvas.DetachBrush();
848 }
849
Update(const RSRenderContent & content)850 bool RSForegroundColorDrawable::Update(const RSRenderContent& content)
851 {
852 auto fgColor = content.GetRenderProperties().GetForegroundColor();
853 brush_.SetColor(fgColor.AsArgbInt());
854 return fgColor != RgbPalette::Transparent();
855 }
856
Generate(const RSRenderContent & content)857 RSPropertyDrawable::DrawablePtr RSForegroundColorDrawable::Generate(const RSRenderContent& content)
858 {
859 auto fgColor = content.GetRenderProperties().GetForegroundColor();
860 if (fgColor == RgbPalette::Transparent()) {
861 return nullptr;
862 }
863 Drawing::Brush brush;
864 brush.SetColor(fgColor.AsArgbInt());
865 brush.SetAntiAlias(true);
866 return std::make_unique<RSForegroundColorDrawable>(std::move(brush));
867 }
868
869 // ============================================================================
870 // Particle
Generate(const RSRenderContent & content)871 RSPropertyDrawable::DrawablePtr RSParticleDrawable::Generate(const RSRenderContent& content)
872 {
873 auto& properties = content.GetRenderProperties();
874 const auto& particleVector = properties.GetParticles();
875 if (particleVector.GetParticleSize() == 0) {
876 return nullptr;
877 }
878 return std::make_unique<RSParticleDrawable>();
879 }
880
Update(const RSRenderContent & content)881 bool RSParticleDrawable::Update(const RSRenderContent& content)
882 {
883 auto& properties = content.GetRenderProperties();
884 return properties.GetPixelStretch().has_value();
885 }
886
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const887 void RSParticleDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
888 {
889 RSPropertiesPainter::DrawParticle(content.GetRenderProperties(), canvas);
890 }
891
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const892 void RSPixelStretchDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
893 {
894 RSPropertiesPainter::DrawPixelStretch(content.GetRenderProperties(), canvas);
895 }
896
Update(const RSRenderContent & content)897 bool RSPixelStretchDrawable::Update(const RSRenderContent& content)
898 {
899 auto& properties = content.GetRenderProperties();
900 return properties.GetPixelStretch().has_value();
901 }
902
Generate(const RSRenderContent & content)903 RSPropertyDrawable::DrawablePtr RSPixelStretchDrawable::Generate(const RSRenderContent& content)
904 {
905 auto& properties = content.GetRenderProperties();
906 auto& pixelStretch = properties.GetPixelStretch();
907 if (!pixelStretch.has_value()) {
908 return nullptr;
909 }
910 return std::make_unique<RSPixelStretchDrawable>();
911 }
912
913 // ============================================================================
914 // Background
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const915 void RSBackgroundDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
916 {
917 auto& properties = content.GetRenderProperties();
918 Drawing::Brush brush = brush_;
919 // use drawrrect to avoid texture update in phone screen rotation scene
920 if (RSSystemProperties::IsPhoneType() && RSSystemProperties::GetCacheEnabledForRotation()) {
921 bool antiAlias = RSPropertiesPainter::GetBgAntiAlias() || !properties.GetCornerRadius().IsZero();
922 brush.SetAntiAlias(antiAlias);
923 canvas.AttachBrush(brush);
924 if (properties.GetBorderColorIsTransparent() ||
925 properties.GetBorderStyle().x_ != static_cast<uint32_t>(BorderStyle::SOLID)) {
926 canvas.DrawRoundRect(RSPropertiesPainter::RRect2DrawingRRect(properties.GetRRect()));
927 } else {
928 canvas.DrawRoundRect(RSPropertiesPainter::RRect2DrawingRRect(properties.GetInnerRRect()));
929 }
930 } else {
931 canvas.AttachBrush(brush);
932 if (properties.GetBorderColorIsTransparent() ||
933 properties.GetBorderStyle().x_ != static_cast<uint32_t>(BorderStyle::SOLID)) {
934 canvas.DrawRect(RSPropertiesPainter::Rect2DrawingRect(properties.GetBoundsRect()));
935 } else {
936 canvas.DrawRect(RSPropertiesPainter::RRect2DrawingRRect(properties.GetInnerRRect()).GetRect());
937 }
938 }
939 canvas.DetachBrush();
940 }
941
Generate(const RSRenderContent & content)942 RSPropertyDrawable::DrawablePtr RSBackgroundColorDrawable::Generate(const RSRenderContent& content)
943 {
944 auto& properties = content.GetRenderProperties();
945 auto& bgColor = properties.GetBackgroundColor();
946 bool isTransparent = (bgColor == RgbPalette::Transparent());
947 if (isTransparent) {
948 return nullptr;
949 }
950 return std::make_unique<RSBackgroundColorDrawable>(bgColor.AsArgbInt());
951 }
952
Update(const RSRenderContent & content)953 bool RSBackgroundColorDrawable::Update(const RSRenderContent& content)
954 {
955 auto& properties = content.GetRenderProperties();
956 auto& bgColor = properties.GetBackgroundColor();
957 if (bgColor == RgbPalette::Transparent()) {
958 return false;
959 }
960 brush_.SetColor(bgColor.AsArgbInt());
961 return true;
962 }
963
Generate(const RSRenderContent & content)964 RSPropertyDrawable::DrawablePtr RSBackgroundShaderDrawable::Generate(const RSRenderContent& content)
965 {
966 auto& properties = content.GetRenderProperties();
967 auto bgShader = properties.GetBackgroundShader();
968 if (!bgShader) {
969 return nullptr;
970 }
971 return std::make_unique<RSBackgroundShaderDrawable>(bgShader->GetDrawingShader());
972 }
973
Update(const RSRenderContent & content)974 bool RSBackgroundShaderDrawable::Update(const RSRenderContent& content)
975 {
976 auto& properties = content.GetRenderProperties();
977 auto bgShader = properties.GetBackgroundShader();
978 if (!bgShader) {
979 return false;
980 }
981 brush_.SetShaderEffect(bgShader->GetDrawingShader());
982 return true;
983 }
984
Generate(const RSRenderContent & content)985 RSPropertyDrawable::DrawablePtr RSBackgroundImageDrawable::Generate(const RSRenderContent& content)
986 {
987 auto& properties = content.GetRenderProperties();
988 const auto& bgImage = properties.GetBgImage();
989 if (!bgImage) {
990 return nullptr;
991 }
992 bgImage->SetDstRect(properties.GetBgImageRect());
993 return std::make_unique<RSBackgroundImageDrawable>();
994 }
995
Update(const RSRenderContent & content)996 bool RSBackgroundImageDrawable::Update(const RSRenderContent& content)
997 {
998 auto& properties = content.GetRenderProperties();
999 const auto& bgImage = properties.GetBgImage();
1000 if (!bgImage) {
1001 return false;
1002 }
1003 bgImage->SetDstRect(properties.GetBgImageRect());
1004 return true;
1005 }
1006
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const1007 void RSBackgroundImageDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
1008 {
1009 auto& properties = content.GetRenderProperties();
1010 const auto& image = properties.GetBgImage();
1011 if (image == nullptr) {
1012 RS_LOGE("RSBackgroundImageDrawable::Draw image is nullptr");
1013 return;
1014 }
1015
1016 auto boundsRect = RSPropertiesPainter::Rect2DrawingRect(properties.GetBoundsRect());
1017 auto innerRect = properties.GetBgImageInnerRect();
1018 canvas.AttachBrush(brush_);
1019 if (innerRect != Vector4f()) {
1020 image->SetInnerRect(std::make_optional<Drawing::RectI>(
1021 innerRect.x_, innerRect.y_, innerRect.x_ + innerRect.z_, innerRect.y_ + innerRect.w_));
1022 }
1023 image->CanvasDrawImage(canvas, boundsRect, Drawing::SamplingOptions(), true);
1024 canvas.DetachBrush();
1025 }
1026
1027 // blend mode save and restore
BlendSaveDrawableGenerate(const RSRenderContent & content)1028 std::unique_ptr<RSPropertyDrawable> BlendSaveDrawableGenerate(const RSRenderContent& content)
1029 {
1030 auto& properties = content.GetRenderProperties();
1031 auto blendMode = properties.GetColorBlendMode();
1032 int blendModeApplyType = properties.GetColorBlendApplyType();
1033 if (blendMode == 0) {
1034 // no blend
1035 return nullptr;
1036 }
1037 RS_OPTIONAL_TRACE_NAME_FMT_LEVEL(TRACE_LEVEL_TWO,
1038 "BlendSaveDrawableGenerate::BlendMode, blendMode: %d, blendModeApplyType: %d", blendMode, blendModeApplyType);
1039 if (blendModeApplyType == static_cast<int>(RSColorBlendApplyType::FAST)) {
1040 return std::make_unique<RSBlendFastDrawable>(blendMode);
1041 }
1042 return std::make_unique<RSBlendSaveLayerDrawable>(blendMode);
1043 }
1044
BlendRestoreDrawableGenerate(const RSRenderContent & content)1045 std::unique_ptr<RSPropertyDrawable> BlendRestoreDrawableGenerate(const RSRenderContent& content)
1046 {
1047 auto& properties = content.GetRenderProperties();
1048 auto blendMode = properties.GetColorBlendMode();
1049 int blendModeApplyType = properties.GetColorBlendApplyType();
1050 if (blendMode == 0) {
1051 // no blend
1052 return nullptr;
1053 }
1054 if (blendModeApplyType == static_cast<int>(RSColorBlendApplyType::SAVE_LAYER)) {
1055 return std::make_unique<RSBlendSaveLayerRestoreDrawable>();
1056 }
1057 return std::make_unique<RSBlendFastRestoreDrawable>();
1058 }
1059
RSBlendSaveLayerDrawable(int blendMode)1060 RSBlendSaveLayerDrawable::RSBlendSaveLayerDrawable(int blendMode)
1061 {
1062 blendBrush_.SetBlendMode(static_cast<Drawing::BlendMode>(blendMode - 1)); // map blendMode to Drawing::BlendMode
1063 }
1064
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const1065 void RSBlendSaveLayerDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
1066 {
1067 if (!canvas.HasOffscreenLayer() &&
1068 RSPropertiesPainter::IsDangerousBlendMode(
1069 static_cast<int>(blendBrush_.GetBlendMode()), static_cast<int>(RSColorBlendApplyType::SAVE_LAYER))) {
1070 Drawing::SaveLayerOps maskLayerRec(nullptr, nullptr, 0);
1071 canvas.SaveLayer(maskLayerRec);
1072 ROSEN_LOGD("Dangerous offscreen blendmode may produce transparent pixels, add extra offscreen here.");
1073 }
1074 auto matrix = canvas.GetTotalMatrix();
1075 matrix.Set(Drawing::Matrix::TRANS_X, std::ceil(matrix.Get(Drawing::Matrix::TRANS_X)));
1076 matrix.Set(Drawing::Matrix::TRANS_Y, std::ceil(matrix.Get(Drawing::Matrix::TRANS_Y)));
1077 canvas.SetMatrix(matrix);
1078 auto brush = blendBrush_;
1079 brush.SetAlphaF(canvas.GetAlpha());
1080 Drawing::SaveLayerOps maskLayerRec(nullptr, &brush, 0);
1081 canvas.SaveLayer(maskLayerRec);
1082 canvas.SetBlendMode(std::nullopt);
1083 canvas.SaveAlpha();
1084 canvas.SetAlpha(1.0f);
1085 }
1086
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const1087 void RSBlendFastDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
1088 {
1089 if (!canvas.HasOffscreenLayer() &&
1090 RSPropertiesPainter::IsDangerousBlendMode(blendMode_ - 1, static_cast<int>(RSColorBlendApplyType::FAST))) {
1091 Drawing::SaveLayerOps maskLayerRec(nullptr, nullptr, 0);
1092 canvas.SaveLayer(maskLayerRec);
1093 ROSEN_LOGD("Dangerous fast blendmode may produce transparent pixels, add extra offscreen here.");
1094 }
1095 canvas.SetBlendMode({ blendMode_ - 1 }); // map blendMode to SkBlendMode
1096 }
1097
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const1098 void RSBlendSaveLayerRestoreDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
1099 {
1100 // SAVE_ALL slot will do all necessary restore
1101 }
1102
Draw(const RSRenderContent & content,RSPaintFilterCanvas & canvas) const1103 void RSBlendFastRestoreDrawable::Draw(const RSRenderContent& content, RSPaintFilterCanvas& canvas) const
1104 {
1105 // SAVE_ALL slot will do all necessary restore
1106 }
1107
1108 } // namespace OHOS::Rosen
1109