11 #include "flutter/fml/logging.h"
27 Initialize(std::nullopt);
31 Initialize(cull_rect);
41 void Canvas::Initialize(std::optional<Rect> cull_rect) {
42 initial_cull_rect_ = cull_rect;
43 base_pass_ = std::make_unique<EntityPass>();
44 current_pass_ = base_pass_.get();
47 FML_DCHECK(base_pass_->GetSubpassesDepth() == 1u);
50 void Canvas::Reset() {
52 current_pass_ =
nullptr;
53 xformation_stack_ = {};
62 const std::shared_ptr<ImageFilter>& backdrop_filter) {
64 entry.
xformation = xformation_stack_.back().xformation;
65 entry.cull_rect = xformation_stack_.back().cull_rect;
66 entry.stencil_depth = xformation_stack_.back().stencil_depth;
69 auto subpass = std::make_unique<EntityPass>();
70 subpass->SetEnableOffscreenCheckerboard(
72 if (backdrop_filter) {
74 [backdrop_filter = backdrop_filter->Clone()](
77 auto filter = backdrop_filter->WrapInput(input);
78 filter->SetEffectTransform(effect_transform);
79 filter->SetRenderingMode(rendering_mode);
82 subpass->SetBackdropFilter(backdrop_filter_proc);
84 subpass->SetBlendMode(blend_mode);
85 current_pass_ = GetCurrentPass().
AddSubpass(std::move(subpass));
89 xformation_stack_.emplace_back(entry);
93 FML_DCHECK(xformation_stack_.size() > 0);
94 if (xformation_stack_.size() == 1) {
97 if (xformation_stack_.back().rendering_mode ==
100 FML_DCHECK(current_pass_);
103 bool contains_clips = xformation_stack_.back().contains_clips;
104 xformation_stack_.pop_back();
106 if (contains_clips) {
122 xformation_stack_.back().xformation = {};
130 return xformation_stack_.back().xformation;
134 auto cull_rect = xformation_stack_.back().cull_rect;
135 if (cull_rect.has_value()) {
136 Matrix inverse = xformation_stack_.back().xformation.Invert();
137 cull_rect = cull_rect.value().TransformBounds(inverse);
163 return xformation_stack_.size();
194 bool Canvas::AttemptDrawBlurredRRect(
const Rect& rect,
196 const Paint& paint) {
197 Paint new_paint = paint;
217 auto contents = std::make_shared<SolidRRectBlurContents>();
218 contents->SetColor(new_paint.
color);
220 contents->SetRRect(rect, corner_radius);
226 entity.SetStencilDepth(GetStencilDepth());
228 entity.SetContents(new_paint.
WithFilters(std::move(contents)));
241 if (AttemptDrawBlurredRRect(rect, 0, paint)) {
256 if (AttemptDrawBlurredRRect(rect, corner_radius, paint)) {
278 Size half_size(radius, radius);
279 if (AttemptDrawBlurredRRect(
Rect(center - half_size, half_size * 2), radius,
294 if (bounds.has_value()) {
295 IntersectCulling(bounds.value());
302 auto& cull_rect = xformation_stack_.back().cull_rect;
304 cull_rect.has_value() &&
305 geometry->CoversArea(xformation_stack_.back().xformation, *cull_rect)
310 ClipGeometry(std::move(geometry), clip_op);
313 IntersectCulling(rect);
316 SubtractCulling(rect);
329 std::optional<Rect> inner_rect = (corner_radius * 2 < rect.
size.
width &&
331 ? rect.
Expand(-corner_radius)
332 : std::make_optional<Rect>();
334 auto& cull_rect = xformation_stack_.back().cull_rect;
336 cull_rect.has_value() &&
337 geometry->CoversArea(xformation_stack_.back().xformation, *cull_rect)
342 ClipGeometry(std::move(geometry), clip_op);
345 IntersectCulling(rect);
348 if (corner_radius <= 0) {
349 SubtractCulling(rect);
356 if (corner_radius * 2 < rect.
size.
width) {
371 void Canvas::ClipGeometry(std::unique_ptr<Geometry> geometry,
373 auto contents = std::make_shared<ClipContents>();
374 contents->SetGeometry(std::move(geometry));
375 contents->SetClipOperation(clip_op);
384 ++xformation_stack_.back().stencil_depth;
385 xformation_stack_.back().contains_clips =
true;
388 void Canvas::IntersectCulling(
Rect clip_rect) {
390 std::optional<Rect>& cull_rect = xformation_stack_.back().cull_rect;
391 if (cull_rect.has_value()) {
392 cull_rect = cull_rect
394 .Intersection(clip_rect)
397 cull_rect = clip_rect;
401 void Canvas::SubtractCulling(
Rect clip_rect) {
402 std::optional<Rect>& cull_rect = xformation_stack_.back().cull_rect;
403 if (cull_rect.has_value()) {
405 cull_rect = cull_rect
413 void Canvas::RestoreClip() {
418 entity.SetContents(std::make_shared<ClipRestoreContents>());
419 entity.SetStencilDepth(GetStencilDepth());
449 auto pass = picture.
pass->Clone();
451 pass->IterateAllElements([&](
auto& element) ->
bool {
452 if (
auto entity = std::get_if<Entity>(&element)) {
453 entity->IncrementStencilDepth(GetStencilDepth());
455 entity->GetTransformation());
459 if (
auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
460 subpass->get()->SetStencilDepth(subpass->get()->GetStencilDepth() +
485 DrawImageRect(image, source, dest, paint, std::move(sampler));
497 auto size = image->GetSize();
499 if (size.IsEmpty()) {
504 contents->SetTexture(image->GetTexture());
505 contents->SetSourceRect(source);
506 contents->SetSamplerDescriptor(std::move(sampler));
521 picture.
pass = std::move(base_pass_);
524 Initialize(initial_cull_rect_);
530 FML_DCHECK(current_pass_ !=
nullptr);
531 return *current_pass_;
534 size_t Canvas::GetStencilDepth()
const {
535 return xformation_stack_.back().stencil_depth;
539 std::optional<Rect> bounds,
540 const std::shared_ptr<ImageFilter>& backdrop_filter) {
548 xformation_stack_.back().cull_rect = std::nullopt;
551 auto& new_layer_pass = GetCurrentPass();
552 new_layer_pass.SetBoundsLimit(bounds);
556 new_layer_pass.SetDelegate(
557 std::make_shared<OpacityPeepholePassDelegate>(paint));
559 new_layer_pass.SetDelegate(std::make_shared<PaintPassDelegate>(paint));
565 const Paint& paint) {
570 auto text_contents = std::make_shared<TextContents>();
571 text_contents->SetTextFrame(text_frame);
572 text_contents->SetColor(paint.
color);
590 const std::shared_ptr<VerticesGeometry>& vertices,
591 const Paint& paint) {
595 if (vertices->HasVertexColors()) {
598 if (vertices->HasTextureCoordinates() &&
603 return !vertices->HasTextureCoordinates();
608 const Paint& paint) {
630 auto src_paint = paint;
633 std::shared_ptr<Contents> src_contents =
634 src_paint.CreateContentsForGeometry(vertices);
635 if (vertices->HasTextureCoordinates()) {
642 auto size = src_contents->GetColorSourceSize();
643 if (size.has_value()) {
646 auto cvg = vertices->GetCoverage(
Matrix{});
647 FML_CHECK(cvg.has_value());
651 vertices->GetTextureCoordinateCoverge().value_or(cvg.value());
657 auto contents = std::make_shared<VerticesContents>();
659 contents->SetBlendMode(blend_mode);
660 contents->SetGeometry(vertices);
661 contents->SetSourceContents(std::move(src_contents));
668 std::vector<Matrix> transforms,
669 std::vector<Rect> texture_coordinates,
670 std::vector<Color> colors,
673 std::optional<Rect> cull_rect,
674 const Paint& paint) {
679 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
680 contents->SetColors(std::move(colors));
681 contents->SetTransforms(std::move(transforms));
682 contents->SetTextureCoordinates(std::move(texture_coordinates));
683 contents->SetTexture(atlas->GetTexture());
684 contents->SetSamplerDescriptor(std::move(sampler));
685 contents->SetBlendMode(blend_mode);
686 contents->SetCullRect(cull_rect);