11 #include "flutter/fml/logging.h"
26 Initialize(std::nullopt);
30 Initialize(cull_rect);
40 void Canvas::Initialize(std::optional<Rect> cull_rect) {
41 initial_cull_rect_ = cull_rect;
42 base_pass_ = std::make_unique<EntityPass>();
43 current_pass_ = base_pass_.get();
46 FML_DCHECK(base_pass_->GetSubpassesDepth() == 1u);
49 void Canvas::Reset() {
51 current_pass_ =
nullptr;
52 xformation_stack_ = {};
61 const std::shared_ptr<ImageFilter>& backdrop_filter) {
63 entry.
xformation = xformation_stack_.back().xformation;
64 entry.cull_rect = xformation_stack_.back().cull_rect;
65 entry.stencil_depth = xformation_stack_.back().stencil_depth;
68 auto subpass = std::make_unique<EntityPass>();
69 subpass->SetEnableOffscreenCheckerboard(
71 if (backdrop_filter) {
73 [backdrop_filter = backdrop_filter->Clone()](
76 auto filter = backdrop_filter->WrapInput(input);
77 filter->SetEffectTransform(effect_transform);
78 filter->SetRenderingMode(rendering_mode);
81 subpass->SetBackdropFilter(backdrop_filter_proc);
83 subpass->SetBlendMode(blend_mode);
84 current_pass_ = GetCurrentPass().
AddSubpass(std::move(subpass));
88 xformation_stack_.emplace_back(entry);
92 FML_DCHECK(xformation_stack_.size() > 0);
93 if (xformation_stack_.size() == 1) {
96 if (xformation_stack_.back().rendering_mode ==
99 FML_DCHECK(current_pass_);
102 bool contains_clips = xformation_stack_.back().contains_clips;
103 xformation_stack_.pop_back();
105 if (contains_clips) {
121 xformation_stack_.back().xformation = {};
129 return xformation_stack_.back().xformation;
133 auto cull_rect = xformation_stack_.back().cull_rect;
134 if (cull_rect.has_value()) {
135 Matrix inverse = xformation_stack_.back().xformation.Invert();
136 cull_rect = cull_rect.value().TransformBounds(inverse);
162 return xformation_stack_.size();
193 bool Canvas::AttemptDrawBlurredRRect(
const Rect& rect,
195 const Paint& paint) {
196 Paint new_paint = paint;
211 auto contents = std::make_shared<SolidRRectBlurContents>();
212 contents->SetColor(new_paint.
color);
214 contents->SetRRect(rect, corner_radius);
220 entity.SetStencilDepth(GetStencilDepth());
222 entity.SetContents(new_paint.
WithFilters(std::move(contents)));
235 if (AttemptDrawBlurredRRect(rect, 0, paint)) {
250 if (AttemptDrawBlurredRRect(rect, corner_radius, paint)) {
272 Size half_size(radius, radius);
273 if (AttemptDrawBlurredRRect(
Rect(center - half_size, half_size * 2), radius,
288 if (bounds.has_value()) {
289 IntersectCulling(bounds.value());
296 auto& cull_rect = xformation_stack_.back().cull_rect;
298 cull_rect.has_value() &&
299 geometry->CoversArea(xformation_stack_.back().xformation, *cull_rect)
304 ClipGeometry(std::move(geometry), clip_op);
307 IntersectCulling(rect);
310 SubtractCulling(rect);
323 std::optional<Rect> inner_rect = (corner_radius * 2 < rect.
size.
width &&
325 ? rect.
Expand(-corner_radius)
326 : std::make_optional<Rect>();
328 auto& cull_rect = xformation_stack_.back().cull_rect;
330 cull_rect.has_value() &&
331 geometry->CoversArea(xformation_stack_.back().xformation, *cull_rect)
336 ClipGeometry(std::move(geometry), clip_op);
339 IntersectCulling(rect);
342 if (corner_radius <= 0) {
343 SubtractCulling(rect);
350 if (corner_radius * 2 < rect.
size.
width) {
365 void Canvas::ClipGeometry(std::unique_ptr<Geometry> geometry,
367 auto contents = std::make_shared<ClipContents>();
368 contents->SetGeometry(std::move(geometry));
369 contents->SetClipOperation(clip_op);
378 ++xformation_stack_.back().stencil_depth;
379 xformation_stack_.back().contains_clips =
true;
382 void Canvas::IntersectCulling(
Rect clip_rect) {
384 std::optional<Rect>& cull_rect = xformation_stack_.back().cull_rect;
385 if (cull_rect.has_value()) {
386 cull_rect = cull_rect
388 .Intersection(clip_rect)
391 cull_rect = clip_rect;
395 void Canvas::SubtractCulling(
Rect clip_rect) {
396 std::optional<Rect>& cull_rect = xformation_stack_.back().cull_rect;
397 if (cull_rect.has_value()) {
399 cull_rect = cull_rect
407 void Canvas::RestoreClip() {
412 entity.SetContents(std::make_shared<ClipRestoreContents>());
413 entity.SetStencilDepth(GetStencilDepth());
443 auto pass = picture.
pass->Clone();
445 pass->IterateAllElements([&](
auto& element) ->
bool {
446 if (
auto entity = std::get_if<Entity>(&element)) {
447 entity->IncrementStencilDepth(GetStencilDepth());
449 entity->GetTransformation());
453 if (
auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
454 subpass->get()->SetStencilDepth(subpass->get()->GetStencilDepth() +
479 DrawImageRect(image, source, dest, paint, std::move(sampler));
491 auto size = image->GetSize();
493 if (size.IsEmpty()) {
498 contents->SetTexture(image->GetTexture());
499 contents->SetSourceRect(source);
500 contents->SetSamplerDescriptor(std::move(sampler));
515 picture.
pass = std::move(base_pass_);
518 Initialize(initial_cull_rect_);
524 FML_DCHECK(current_pass_ !=
nullptr);
525 return *current_pass_;
528 size_t Canvas::GetStencilDepth()
const {
529 return xformation_stack_.back().stencil_depth;
533 std::optional<Rect> bounds,
534 const std::shared_ptr<ImageFilter>& backdrop_filter) {
537 auto& new_layer_pass = GetCurrentPass();
538 new_layer_pass.SetBoundsLimit(bounds);
542 new_layer_pass.SetDelegate(
543 std::make_shared<OpacityPeepholePassDelegate>(paint));
545 new_layer_pass.SetDelegate(std::make_shared<PaintPassDelegate>(paint));
551 const Paint& paint) {
556 auto text_contents = std::make_shared<TextContents>();
557 text_contents->SetTextFrame(text_frame);
558 text_contents->SetColor(paint.
color);
576 const std::shared_ptr<VerticesGeometry>& vertices,
577 const Paint& paint) {
581 if (vertices->HasVertexColors()) {
584 if (vertices->HasTextureCoordinates() &&
589 return !vertices->HasTextureCoordinates();
594 const Paint& paint) {
616 auto src_paint = paint;
619 std::shared_ptr<Contents> src_contents =
620 src_paint.CreateContentsForGeometry(vertices);
621 if (vertices->HasTextureCoordinates()) {
628 auto size = src_contents->GetColorSourceSize();
629 if (size.has_value()) {
632 auto cvg = vertices->GetCoverage(
Matrix{});
633 FML_CHECK(cvg.has_value());
637 vertices->GetTextureCoordinateCoverge().value_or(cvg.value());
643 auto contents = std::make_shared<VerticesContents>();
645 contents->SetBlendMode(blend_mode);
646 contents->SetGeometry(vertices);
647 contents->SetSourceContents(std::move(src_contents));
654 std::vector<Matrix> transforms,
655 std::vector<Rect> texture_coordinates,
656 std::vector<Color> colors,
659 std::optional<Rect> cull_rect,
660 const Paint& paint) {
665 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
666 contents->SetColors(std::move(colors));
667 contents->SetTransforms(std::move(transforms));
668 contents->SetTextureCoordinates(std::move(texture_coordinates));
669 contents->SetTexture(atlas->GetTexture());
670 contents->SetSamplerDescriptor(std::move(sampler));
671 contents->SetBlendMode(blend_mode);
672 contents->SetCullRect(cull_rect);