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