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