11#include "flutter/fml/logging.h"
12#include "flutter/fml/trace_event.h"
34static std::shared_ptr<Contents> CreateContentsForGeometryWithFilters(
36 std::shared_ptr<Geometry> geometry) {
37 std::shared_ptr<ColorSourceContents> contents =
44 if (needs_color_filter) {
46 if (contents->ApplyColorFilter(
color_filter->GetCPUColorFilterProc())) {
47 needs_color_filter =
false;
51 bool can_apply_mask_filter = geometry->CanApplyMaskFilter();
52 contents->SetGeometry(std::move(geometry));
62 std::shared_ptr<Contents> contents_copy = std::move(contents);
65 if (needs_color_filter &&
83struct GetTextureColorSourceDataVisitor {
84 GetTextureColorSourceDataVisitor() {}
86 std::optional<ImageData> operator()(
const LinearGradientData&
data) {
90 std::optional<ImageData> operator()(
const RadialGradientData&
data) {
94 std::optional<ImageData> operator()(
const ConicalGradientData&
data) {
98 std::optional<ImageData> operator()(
const SweepGradientData&
data) {
104 std::optional<ImageData> operator()(
const RuntimeEffectData&
data) {
108 std::optional<ImageData> operator()(
const std::monostate&
data) {
112#if IMPELLER_ENABLE_3D
113 std::optional<ImageData> operator()(
const SceneData&
data) {
119static std::optional<ImageData> GetImageColorSourceData(
120 const ColorSource& color_source) {
121 return std::visit(GetTextureColorSourceDataVisitor{}, color_source.GetData());
124static std::shared_ptr<Contents> CreatePathContentsWithFilters(
127 std::shared_ptr<Geometry> geometry;
139 return CreateContentsForGeometryWithFilters(
paint, std::move(geometry));
142static std::shared_ptr<Contents> CreateCoverContentsWithFilters(
166 base_pass_ = std::make_unique<EntityPass>();
168 current_pass_ = base_pass_.get();
174 FML_DCHECK(base_pass_->GetSubpassesDepth() == 1u);
178 base_pass_ =
nullptr;
179 current_pass_ =
nullptr;
185 Save(
false, total_content_depth);
194 virtual void Visit(
const LocalMatrixImageFilter& filter) {
195 required_mip_count_ = 1;
197 virtual void Visit(
const DilateImageFilter& filter) {
198 required_mip_count_ = 1;
200 virtual void Visit(
const ErodeImageFilter& filter) {
201 required_mip_count_ = 1;
203 virtual void Visit(
const MatrixImageFilter& filter) {
204 required_mip_count_ = 1;
206 virtual void Visit(
const ComposeImageFilter& filter) {
207 required_mip_count_ = 1;
209 virtual void Visit(
const ColorImageFilter& filter) {
210 required_mip_count_ = 1;
212 int32_t GetRequiredMipCount()
const {
return required_mip_count_; }
215 int32_t required_mip_count_ = -1;
220 uint32_t total_content_depth,
222 const std::shared_ptr<ImageFilter>& backdrop_filter) {
228 if (create_subpass) {
229 entry.rendering_mode =
231 auto subpass = std::make_unique<EntityPass>();
232 if (backdrop_filter) {
234 [backdrop_filter = backdrop_filter->Clone()](
237 auto filter = backdrop_filter->WrapInput(input);
238 filter->SetEffectTransform(effect_transform);
239 filter->SetRenderingMode(rendering_mode);
242 subpass->SetBackdropFilter(backdrop_filter_proc);
243 MipCountVisitor mip_count_visitor;
244 backdrop_filter->Visit(mip_count_visitor);
247 mip_count_visitor.GetRequiredMipCount()));
249 subpass->SetBlendMode(blend_mode);
250 current_pass_ = GetCurrentPass().
AddSubpass(std::move(subpass));
304 if (cull_rect.has_value()) {
306 cull_rect = cull_rect.value().TransformBounds(inverse);
361bool Canvas::AttemptDrawBlurredRRect(
const Rect&
rect,
369 if (!
paint.mask_blur_descriptor.has_value()) {
382 paint.HasColorFilter()
384 ?
paint.GetColorFilter()->GetCPUColorFilterProc()(
paint.color)
387 Paint rrect_paint = {.mask_blur_descriptor =
paint.mask_blur_descriptor};
412 (!rrect_color.IsOpaque() ||
426 rrect_paint.color = rrect_color.WithAlpha(1);
428 rrect_paint.color = rrect_color;
434 auto draw_blurred_rrect = [
this, &
rect, &corner_radii, &rrect_paint]() {
435 auto contents = std::make_shared<SolidRRectBlurContents>();
437 contents->SetColor(rrect_paint.color);
438 contents->SetSigma(rrect_paint.mask_blur_descriptor->sigma);
439 contents->SetRRect(
rect, corner_radii);
441 Entity blurred_rrect_entity;
442 blurred_rrect_entity.SetTransform(GetCurrentTransform());
443 blurred_rrect_entity.SetBlendMode(rrect_paint.blend_mode);
445 rrect_paint.mask_blur_descriptor = std::nullopt;
446 blurred_rrect_entity.SetContents(
447 rrect_paint.WithFilters(std::move(contents)));
448 AddRenderEntityToCurrentPass(std::move(blurred_rrect_entity));
451 switch (rrect_paint.mask_blur_descriptor->style) {
453 draw_blurred_rrect();
458 draw_blurred_rrect();
461 entity.SetTransform(GetCurrentTransform());
462 entity.SetBlendMode(rrect_paint.blend_mode);
463 entity.SetContents(CreateContentsForGeometryWithFilters(
465 AddRenderEntityToCurrentPass(std::move(entity),
true);
470 draw_blurred_rrect();
475 draw_blurred_rrect();
489 entity.
SetContents(CreateContentsForGeometryWithFilters(
490 paint, Geometry::MakeLine(p0, p1,
paint.stroke_width,
paint.stroke_cap)));
492 AddRenderEntityToCurrentPass(std::move(entity));
496 if (
paint.style == Paint::Style::kStroke) {
501 if (AttemptDrawBlurredRRect(
rect, {},
paint)) {
511 AddRenderEntityToCurrentPass(std::move(entity));
515 if (
rect.IsSquare()) {
521 if (
paint.style == Paint::Style::kStroke) {
527 if (AttemptDrawBlurredRRect(
rect,
rect.GetSize() * 0.5f,
paint)) {
535 CreateContentsForGeometryWithFilters(
paint, Geometry::MakeOval(
rect)));
537 AddRenderEntityToCurrentPass(std::move(entity));
541 const Size& corner_radii,
543 if (AttemptDrawBlurredRRect(
rect, corner_radii,
paint)) {
547 if (
paint.style == Paint::Style::kFill) {
551 entity.
SetContents(CreateContentsForGeometryWithFilters(
552 paint, Geometry::MakeRoundRect(
rect, corner_radii)));
554 AddRenderEntityToCurrentPass(std::move(entity));
569 Size half_size(radius, radius);
570 if (AttemptDrawBlurredRRect(
571 Rect::MakeOriginSize(
center - half_size, half_size * 2),
572 {radius, radius},
paint)) {
580 paint.style == Paint::Style::kStroke
581 ? Geometry::MakeStrokedCircle(
center, radius,
paint.stroke_width)
582 : Geometry::MakeCircle(
center, radius);
584 CreateContentsForGeometryWithFilters(
paint, std::move(geometry)));
586 AddRenderEntityToCurrentPass(std::move(entity));
591 ClipGeometry(Geometry::MakeFillPath(
path), clip_op);
592 if (clip_op == Entity::ClipOperation::kIntersect) {
594 IntersectCulling(
bounds.value());
601 auto& cull_rect = transform_stack_.back().cull_rect;
602 if (clip_op == Entity::ClipOperation::kIntersect &&
603 cull_rect.has_value() &&
604 geometry->CoversArea(transform_stack_.back().transform, *cull_rect)
609 ClipGeometry(geometry, clip_op);
611 case Entity::ClipOperation::kIntersect:
612 IntersectCulling(
rect);
614 case Entity::ClipOperation::kDifference:
615 SubtractCulling(
rect);
621 auto geometry = Geometry::MakeOval(
bounds);
622 auto& cull_rect = transform_stack_.back().cull_rect;
623 if (clip_op == Entity::ClipOperation::kIntersect &&
624 cull_rect.has_value() &&
625 geometry->CoversArea(transform_stack_.back().transform, *cull_rect)
630 ClipGeometry(geometry, clip_op);
632 case Entity::ClipOperation::kIntersect:
635 case Entity::ClipOperation::kDifference:
641 const Size& corner_radii,
644 bool flat_on_TB = corner_radii.
width * 2 <
rect.GetWidth();
645 bool flat_on_LR = corner_radii.
height * 2 <
rect.GetHeight();
646 auto geometry = Geometry::MakeRoundRect(
rect, corner_radii);
647 auto& cull_rect = transform_stack_.back().cull_rect;
648 if (clip_op == Entity::ClipOperation::kIntersect &&
649 cull_rect.has_value() &&
650 geometry->CoversArea(transform_stack_.back().transform, *cull_rect)
655 ClipGeometry(geometry, clip_op);
657 case Entity::ClipOperation::kIntersect:
658 IntersectCulling(
rect);
660 case Entity::ClipOperation::kDifference:
662 SubtractCulling(
rect);
670 SubtractCulling(
rect.Expand(
Size{-corner_radii.width, 0.0}));
673 SubtractCulling(
rect.Expand(
Size{0.0, -corner_radii.height}));
680void Canvas::ClipGeometry(
const std::shared_ptr<Geometry>& geometry,
682 auto contents = std::make_shared<ClipContents>();
683 contents->SetGeometry(geometry);
684 contents->SetClipOperation(clip_op);
690 AddClipEntityToCurrentPass(std::move(entity));
692 ++transform_stack_.back().clip_height;
693 ++transform_stack_.back().num_clips;
696void Canvas::IntersectCulling(
Rect clip_rect) {
697 clip_rect = clip_rect.TransformBounds(GetCurrentTransform());
698 std::optional<Rect>& cull_rect = transform_stack_.back().cull_rect;
699 if (cull_rect.has_value()) {
700 cull_rect = cull_rect
702 .Intersection(clip_rect)
705 cull_rect = clip_rect;
709void Canvas::SubtractCulling(
Rect clip_rect) {
710 std::optional<Rect>& cull_rect = transform_stack_.back().cull_rect;
711 if (cull_rect.has_value()) {
712 clip_rect = clip_rect.TransformBounds(GetCurrentTransform());
713 cull_rect = cull_rect
721void Canvas::RestoreClip() {
726 auto clip_restore = std::make_shared<ClipRestoreContents>();
727 clip_restore->SetRestoreHeight(GetClipHeight());
728 entity.SetContents(std::move(clip_restore));
730 AddRenderEntityToCurrentPass(std::move(entity));
733void Canvas::DrawPoints(std::vector<Point>
points,
744 entity.
SetContents(CreateContentsForGeometryWithFilters(
746 Geometry::MakePointField(std::move(
points), radius,
747 point_style == PointStyle::kRound)));
749 AddRenderEntityToCurrentPass(std::move(entity));
760 const auto source = Rect::MakeSize(
image->GetSize());
778 if (
size.IsEmpty()) {
783 texture_contents->SetTexture(
image->GetTexture());
784 texture_contents->SetSourceRect(
source);
785 texture_contents->SetStrictSourceRect(src_rect_constraint ==
786 SourceRectConstraint::kStrict);
787 texture_contents->SetSamplerDescriptor(std::move(sampler));
788 texture_contents->SetOpacity(
paint.color.alpha);
789 texture_contents->SetDeferApplyingOpacity(
paint.HasColorFilter());
791 std::shared_ptr<Contents> contents = texture_contents;
792 if (
paint.mask_blur_descriptor.has_value()) {
793 contents =
paint.mask_blur_descriptor->CreateMaskBlur(texture_contents);
801 AddRenderEntityToCurrentPass(std::move(entity));
806 while (current_pass_ !=
nullptr) {
807 current_pass_->PopAllClips(current_depth_);
808 current_pass_ = current_pass_->GetSuperpass();
812 picture.pass = std::move(base_pass_);
822 return *current_pass_;
825size_t Canvas::GetClipHeight()
const {
826 return transform_stack_.back().clip_height;
829void Canvas::AddRenderEntityToCurrentPass(
Entity entity,
bool reuse_depth) {
835 GetCurrentPass().AddEntity(std::move(entity));
838void Canvas::AddClipEntityToCurrentPass(
Entity entity) {
839 GetCurrentPass().PushClip(std::move(entity));
843 std::optional<Rect>
bounds,
844 const std::shared_ptr<ImageFilter>& backdrop_filter,
846 uint32_t total_content_depth,
847 bool can_distribute_opacity) {
848 if (can_distribute_opacity && !backdrop_filter &&
849 Paint::CanApplyOpacityPeephole(
paint)) {
850 Save(
false, total_content_depth,
paint.blend_mode, backdrop_filter);
851 transform_stack_.back().distributed_opacity *=
paint.color.alpha;
856 Save(
true, total_content_depth,
paint.blend_mode, backdrop_filter);
862 if (
paint.image_filter) {
863 transform_stack_.back().cull_rect = std::nullopt;
866 auto& new_layer_pass = GetCurrentPass();
868 new_layer_pass.SetBoundsLimit(
bounds, bounds_promise);
871 if (
paint.image_filter) {
872 MipCountVisitor mip_count_visitor;
873 paint.image_filter->Visit(mip_count_visitor);
874 new_layer_pass.SetRequiredMipCount(mip_count_visitor.GetRequiredMipCount());
878 paint_copy.
color.
alpha *= transform_stack_.back().distributed_opacity;
879 transform_stack_.back().distributed_opacity = 1.0;
881 new_layer_pass.SetDelegate(std::make_shared<PaintPassDelegate>(paint_copy));
884void Canvas::DrawTextFrame(
const std::shared_ptr<TextFrame>& text_frame,
890 auto text_contents = std::make_shared<TextContents>();
891 text_contents->SetTextFrame(text_frame);
892 text_contents->SetForceTextColor(
paint.mask_blur_descriptor.has_value());
893 text_contents->SetOffset(position);
894 text_contents->SetColor(
paint.color);
895 text_contents->SetTextProperties(
paint.color,
896 paint.style == Paint::Style::kStroke,
904 Matrix::MakeTranslation(position));
913 std::move(text_contents),
true, GetCurrentTransform())));
915 AddRenderEntityToCurrentPass(std::move(entity));
919 const std::shared_ptr<VerticesGeometry>& vertices,
923 if (vertices->HasVertexColors()) {
926 if (vertices->HasTextureCoordinates() &&
930 return !vertices->HasTextureCoordinates();
933void Canvas::DrawVertices(
const std::shared_ptr<VerticesGeometry>& vertices,
940 blend_mode = BlendMode::kDestination;
950 AddRenderEntityToCurrentPass(std::move(entity));
955 if (blend_mode == BlendMode::kDestination) {
956 auto contents = std::make_shared<VerticesSimpleBlendContents>();
957 contents->SetBlendMode(blend_mode);
958 contents->SetAlpha(
paint.color.alpha);
959 contents->SetGeometry(vertices);
961 AddRenderEntityToCurrentPass(std::move(entity));
967 if (std::optional<ImageData> maybe_image_data =
968 GetImageColorSourceData(
paint.color_source)) {
969 const ImageData& image_data = maybe_image_data.value();
970 auto contents = std::make_shared<VerticesSimpleBlendContents>();
971 contents->SetBlendMode(blend_mode);
972 contents->SetAlpha(
paint.color.alpha);
973 contents->SetGeometry(vertices);
975 contents->SetTexture(image_data.
texture);
979 AddRenderEntityToCurrentPass(std::move(entity));
983 auto src_paint =
paint;
984 src_paint.color =
paint.color.WithAlpha(1.0);
986 std::shared_ptr<Contents> src_contents =
987 src_paint.CreateContentsForGeometry(vertices);
995 auto size = src_contents->GetColorSourceSize();
996 if (
size.has_value()) {
997 src_coverage = Rect::MakeXYWH(0, 0,
size->width,
size->height);
999 auto cvg = vertices->GetCoverage(
Matrix{});
1004 vertices->GetTextureCoordinateCoverge().value_or(cvg.value());
1009 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1010 contents->SetBlendMode(blend_mode);
1011 contents->SetAlpha(
paint.color.alpha);
1012 contents->SetGeometry(vertices);
1017 AddRenderEntityToCurrentPass(std::move(entity));
1021 std::vector<Matrix> transforms,
1022 std::vector<Rect> texture_coordinates,
1023 std::vector<Color>
colors,
1026 std::optional<Rect> cull_rect,
1032 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1033 contents->SetColors(std::move(
colors));
1034 contents->SetTransforms(std::move(transforms));
1035 contents->SetTextureCoordinates(std::move(texture_coordinates));
1036 contents->SetTexture(
atlas->GetTexture());
1037 contents->SetSamplerDescriptor(std::move(sampler));
1038 contents->SetBlendMode(blend_mode);
1039 contents->SetCullRect(cull_rect);
1040 contents->SetAlpha(
paint.color.alpha);
1047 AddRenderEntityToCurrentPass(std::move(entity));
static constexpr SkColor kColor
static const int points[]
static sk_sp< SkImage > color_filter(const SkImage *image, SkColorFilter *colorFilter)
static SkScalar center(float pos0, float pos1)
static constexpr uint32_t kMaxDepth
void Initialize(std::optional< Rect > cull_rect)
const Matrix & GetCurrentTransform() const
void RestoreToCount(size_t count)
size_t GetSaveCount() const
void Concat(const Matrix &transform)
void Transform(const Matrix &transform)
std::optional< Rect > initial_cull_rect_
void PreConcat(const Matrix &transform)
void Rotate(Radians radians)
std::deque< CanvasStackEntry > transform_stack_
void DrawPaint(const Paint &paint)
void Skew(Scalar sx, Scalar sy)
void Scale(const Vector2 &scale)
const std::optional< Rect > GetCurrentLocalCullingBounds() const
void DrawPath(const Path &path, const Paint &paint)
virtual void Save(uint32_t total_content_depth=kMaxDepth)
virtual void AddRenderEntityToCurrentPass(Entity entity, bool reuse_depth=false)
void Translate(const Vector3 &offset)
std::shared_ptr< ColorSourceContents > GetContents(const Paint &paint) const
void SetRequiredMipCount(int32_t mip_count)
void SetClipDepth(size_t clip_depth)
EntityPass * GetSuperpass() const
void PopClips(size_t num_clips, uint64_t depth)
int32_t GetRequiredMipCount() const
void SetClipHeight(size_t clip_height)
void SetTransform(Matrix transform)
EntityPass * AddSubpass(std::unique_ptr< EntityPass > pass)
Appends a given pass as a subpass.
std::function< std::shared_ptr< FilterContents >(FilterInput::Ref, const Matrix &effect_transform, Entity::RenderingMode rendering_mode)> BackdropFilterProc
void SetTransform(const Matrix &transform)
Set the global transform matrix for this Entity.
bool SetInheritedOpacity(Scalar alpha)
@ kSubpassPrependSnapshotTransform
@ kSubpassAppendSnapshotTransform
void SetClipDepth(uint32_t clip_depth)
void SetContents(std::shared_ptr< Contents > contents)
void SetBlendMode(BlendMode blend_mode)
static const int32_t kBlurFilterRequiredMipCount
@ kNormal
Blurred inside and outside.
@ kOuter
Nothing inside, blurred outside.
@ kInner
Blurred inside, nothing outside.
@ kSolid
Solid inside, blurred outside.
static std::shared_ptr< Geometry > MakeCover()
static std::shared_ptr< Geometry > MakeRoundRect(const Rect &rect, const Size &radii)
static std::shared_ptr< Geometry > MakeStrokePath(const Path &path, Scalar stroke_width=0.0, Scalar miter_limit=4.0, Cap stroke_cap=Cap::kButt, Join stroke_join=Join::kMiter)
static std::shared_ptr< Geometry > MakeFillPath(const Path &path, std::optional< Rect > inner_rect=std::nullopt)
PathBuilder & AddRect(Rect rect)
Path TakePath(FillType fill=FillType::kNonZero)
PathBuilder & SetBounds(Rect bounds)
Set the bounding box that will be used by Path.GetBoundingBox in place of performing the computation.
PathBuilder & AddOval(const Rect &rect)
PathBuilder & AddRoundedRect(Rect rect, RoundingRadii radii)
PathBuilder & SetConvexity(Convexity value)
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
#define FML_CHECK(condition)
#define FML_DCHECK(condition)
static float max(float r, float g, float b)
sk_sp< const SkImage > atlas
Optional< SkRect > bounds
sk_sp< const SkImage > image
sk_sp< const SkPicture > picture
sk_sp< SkBlender > blender SkRect rect
PODArray< SkColor > colors
SK_API sk_sp< SkShader > Color(SkColor)
void DrawImage(SkCanvas *canvas, const SkImage *image, SkScalar x, SkScalar y, const SkSamplingOptions &sampling={}, const SkPaint *paint=nullptr, SkCanvas::SrcRectConstraint constraint=SkCanvas::kFast_SrcRectConstraint)
SK_API void DrawImageRect(SkCanvas *canvas, const SkImage *image, const SkRect &src, const SkRect &dst, const SkSamplingOptions &sampling={}, const SkPaint *paint=nullptr, SkCanvas::SrcRectConstraint constraint=SkCanvas::kFast_SrcRectConstraint)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
void Initialize(zx::channel directory_request, std::optional< zx::eventpair > view_ref)
Initializes Dart bindings for the Fuchsia application model.
SourceRectConstraint
Controls the behavior of the source rectangle given to DrawImageRect.
static bool UseColorSourceContents(const std::shared_ptr< VerticesGeometry > &vertices, const Paint &paint)
constexpr float kEhCloseEnough
@ kContainsContents
The caller claims the bounds are a reasonably tight estimate of the coverage of the contents and shou...
GrOp::Owner MakeRect(GrRecordingContext *context, GrPaint &&paint, const SkRect &drawRect, const SkRect &localRect, const SkMatrix &localM)
skgpu::graphite::DrawAtlas DrawAtlas
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
std::optional< Rect > cull_rect
static constexpr Color White()
constexpr Color WithAlpha(Scalar new_alpha) const
std::shared_ptr< Texture > texture
Entity::TileMode y_tile_mode
Entity::TileMode x_tile_mode
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeTranslation(const Vector3 &t)
static constexpr Matrix MakeSkew(Scalar sx, Scalar sy)
static Matrix MakeRotationZ(Radians r)
static constexpr Matrix MakeScale(const Vector3 &s)
std::shared_ptr< ColorFilter > GetColorFilter() const
bool HasColorFilter() const
Whether this paint has a color filter that can apply opacity.
std::shared_ptr< ImageFilter > image_filter
std::optional< MaskBlurDescriptor > mask_blur_descriptor
constexpr auto GetBottom() const
constexpr auto GetTop() const
constexpr auto GetLeft() const
constexpr auto GetRight() const
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
std::shared_ptr< const fml::Mapping > data
#define TRACE_EVENT0(category_group, name)