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