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) {
102 std::optional<ImageData> operator()(
const ImageData& data) {
return 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) {
227 if (create_subpass) {
229 auto subpass = std::make_unique<EntityPass>();
230 subpass->SetEnableOffscreenCheckerboard(
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));
302 if (cull_rect.has_value()) {
304 cull_rect = cull_rect.value().TransformBounds(inverse);
359bool Canvas::AttemptDrawBlurredRRect(
const Rect& rect,
367 if (!
paint.mask_blur_descriptor.has_value()) {
380 paint.HasColorFilter()
382 ?
paint.GetColorFilter()->GetCPUColorFilterProc()(
paint.color)
385 Paint rrect_paint = {.mask_blur_descriptor =
paint.mask_blur_descriptor};
406 if ((
paint.mask_blur_descriptor->style !=
408 paint.image_filter) ||
410 (!rrect_color.IsOpaque() ||
413 if (
paint.mask_blur_descriptor->style !=
416 render_bounds.Expand(
paint.mask_blur_descriptor->sigma.sigma * 4.0);
420 .blend_mode =
paint.blend_mode,
421 .image_filter =
paint.image_filter},
424 rrect_paint.color = rrect_color.WithAlpha(1);
426 rrect_paint.color = rrect_color;
427 rrect_paint.blend_mode =
paint.blend_mode;
428 rrect_paint.image_filter =
paint.image_filter;
432 auto draw_blurred_rrect = [
this, &
rect, &corner_radii, &rrect_paint]() {
433 auto contents = std::make_shared<SolidRRectBlurContents>();
435 contents->SetColor(rrect_paint.color);
436 contents->SetSigma(rrect_paint.mask_blur_descriptor->sigma);
437 contents->SetRRect(rect, corner_radii);
439 Entity blurred_rrect_entity;
441 blurred_rrect_entity.SetBlendMode(rrect_paint.blend_mode);
443 rrect_paint.mask_blur_descriptor = std::nullopt;
444 blurred_rrect_entity.SetContents(
445 rrect_paint.WithFilters(std::move(contents)));
449 switch (rrect_paint.mask_blur_descriptor->style) {
451 draw_blurred_rrect();
456 draw_blurred_rrect();
460 entity.SetBlendMode(rrect_paint.blend_mode);
461 entity.SetContents(CreateContentsForGeometryWithFilters(
468 draw_blurred_rrect();
473 draw_blurred_rrect();
487 entity.
SetContents(CreateContentsForGeometryWithFilters(
499 if (AttemptDrawBlurredRRect(rect, {},
paint)) {
513 if (rect.IsSquare()) {
525 if (AttemptDrawBlurredRRect(rect, rect.GetSize() * 0.5f,
paint)) {
539 const Size& corner_radii,
541 if (AttemptDrawBlurredRRect(rect, corner_radii,
paint)) {
549 entity.
SetContents(CreateContentsForGeometryWithFilters(
567 Size half_size(radius, radius);
568 if (AttemptDrawBlurredRRect(
570 {radius, radius},
paint)) {
582 CreateContentsForGeometryWithFilters(
paint, std::move(geometry)));
588 auto bounds = path.GetBoundingBox();
591 if (bounds.has_value()) {
592 IntersectCulling(bounds.value());
601 cull_rect.has_value() &&
607 ClipGeometry(geometry, clip_op);
610 IntersectCulling(rect);
613 SubtractCulling(rect);
622 cull_rect.has_value() &&
628 ClipGeometry(geometry, clip_op);
631 IntersectCulling(bounds);
639 const Size& corner_radii,
642 bool flat_on_TB = corner_radii.
width * 2 < rect.GetWidth();
643 bool flat_on_LR = corner_radii.
height * 2 < rect.GetHeight();
647 cull_rect.has_value() &&
653 ClipGeometry(geometry, clip_op);
656 IntersectCulling(rect);
660 SubtractCulling(rect);
668 SubtractCulling(rect.Expand(
Size{-corner_radii.width, 0.0}));
671 SubtractCulling(rect.Expand(
Size{0.0, -corner_radii.height}));
678void Canvas::ClipGeometry(
const std::shared_ptr<Geometry>& geometry,
680 auto contents = std::make_shared<ClipContents>();
681 contents->SetGeometry(geometry);
682 contents->SetClipOperation(clip_op);
694void Canvas::IntersectCulling(
Rect clip_rect) {
697 if (cull_rect.has_value()) {
698 cull_rect = cull_rect
700 .Intersection(clip_rect)
703 cull_rect = clip_rect;
707void Canvas::SubtractCulling(
Rect clip_rect) {
709 if (cull_rect.has_value()) {
711 cull_rect = cull_rect
719void Canvas::RestoreClip() {
724 auto clip_restore = std::make_shared<ClipRestoreContents>();
726 entity.SetContents(std::move(clip_restore));
742 entity.
SetContents(CreateContentsForGeometryWithFilters(
770 if (!
image ||
source.IsEmpty() || dest.IsEmpty()) {
774 auto size =
image->GetSize();
776 if (size.IsEmpty()) {
781 texture_contents->SetTexture(
image->GetTexture());
782 texture_contents->SetSourceRect(
source);
783 texture_contents->SetStrictSourceRect(src_rect_constraint ==
785 texture_contents->SetSamplerDescriptor(std::move(sampler));
786 texture_contents->SetOpacity(
paint.color.alpha);
787 texture_contents->SetDeferApplyingOpacity(
paint.HasColorFilter());
789 std::shared_ptr<Contents> contents = texture_contents;
790 if (
paint.mask_blur_descriptor.has_value()) {
791 contents =
paint.mask_blur_descriptor->CreateMaskBlur(texture_contents);
804 while (current_pass_ !=
nullptr) {
810 picture.pass = std::move(base_pass_);
820 return *current_pass_;
832 GetCurrentPass().
AddEntity(std::move(entity));
836 GetCurrentPass().
PushClip(std::move(entity));
840 std::optional<Rect> bounds,
841 const std::shared_ptr<ImageFilter>& backdrop_filter,
843 uint32_t total_content_depth) {
845 Save(
true, total_content_depth,
paint.blend_mode, backdrop_filter);
851 if (
paint.image_filter) {
855 auto& new_layer_pass = GetCurrentPass();
857 new_layer_pass.SetBoundsLimit(bounds, bounds_promise);
860 if (
paint.image_filter) {
861 MipCountVisitor mip_count_visitor;
862 paint.image_filter->Visit(mip_count_visitor);
863 new_layer_pass.SetRequiredMipCount(mip_count_visitor.GetRequiredMipCount());
868 new_layer_pass.SetDelegate(
869 std::make_shared<OpacityPeepholePassDelegate>(
paint));
871 new_layer_pass.SetDelegate(std::make_shared<PaintPassDelegate>(
paint));
881 auto text_contents = std::make_shared<TextContents>();
882 text_contents->SetTextFrame(text_frame);
883 text_contents->SetColor(
paint.color);
884 text_contents->SetForceTextColor(
paint.mask_blur_descriptor.has_value());
896 paint.WithFilters(
paint.WithMaskBlur(std::move(text_contents),
true)));
902 const std::shared_ptr<VerticesGeometry>& vertices,
906 if (vertices->HasVertexColors()) {
909 if (vertices->HasTextureCoordinates() &&
913 return !vertices->HasTextureCoordinates();
939 auto contents = std::make_shared<VerticesSimpleBlendContents>();
940 contents->SetBlendMode(blend_mode);
941 contents->SetAlpha(
paint.color.alpha);
942 contents->SetGeometry(vertices);
950 if (std::optional<ImageData> maybe_image_data =
951 GetImageColorSourceData(
paint.color_source)) {
952 const ImageData& image_data = maybe_image_data.value();
953 auto contents = std::make_shared<VerticesSimpleBlendContents>();
954 contents->SetBlendMode(blend_mode);
955 contents->SetAlpha(
paint.color.alpha);
956 contents->SetGeometry(vertices);
958 contents->SetTexture(image_data.
texture);
966 auto src_paint =
paint;
967 src_paint.color =
paint.color.WithAlpha(1.0);
969 std::shared_ptr<Contents> src_contents =
970 src_paint.CreateContentsForGeometry(vertices);
978 auto size = src_contents->GetColorSourceSize();
979 if (size.has_value()) {
982 auto cvg = vertices->GetCoverage(
Matrix{});
987 vertices->GetTextureCoordinateCoverge().value_or(cvg.value());
992 auto contents = std::make_shared<VerticesSimpleBlendContents>();
993 contents->SetBlendMode(blend_mode);
994 contents->SetAlpha(
paint.color.alpha);
995 contents->SetGeometry(vertices);
996 contents->SetLazyTexture([src_contents](
const ContentContext& renderer) {
997 return src_contents->RenderToSnapshot(renderer, {})->
texture;
1004 std::vector<Matrix> transforms,
1005 std::vector<Rect> texture_coordinates,
1006 std::vector<Color> colors,
1009 std::optional<Rect> cull_rect,
1015 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1016 contents->SetColors(std::move(colors));
1017 contents->SetTransforms(std::move(transforms));
1018 contents->SetTextureCoordinates(std::move(texture_coordinates));
1019 contents->SetTexture(atlas->GetTexture());
1020 contents->SetSamplerDescriptor(std::move(sampler));
1021 contents->SetBlendMode(blend_mode);
1022 contents->SetCullRect(cull_rect);
1023 contents->SetAlpha(
paint.color.alpha);
static const int points[]
static sk_sp< SkImage > color_filter(const SkImage *image, SkColorFilter *colorFilter)
static SkScalar center(float pos0, float pos1)
void DrawLine(const Point &p0, const Point &p1, const Paint &paint)
static constexpr uint32_t kMaxDepth
void Initialize(std::optional< Rect > cull_rect)
const Matrix & GetCurrentTransform() const
void DrawImageRect(const std::shared_ptr< Image > &image, Rect source, Rect dest, const Paint &paint, SamplerDescriptor sampler={}, SourceRectConstraint src_rect_constraint=SourceRectConstraint::kFast)
void DrawVertices(const std::shared_ptr< VerticesGeometry > &vertices, BlendMode blend_mode, const Paint &paint)
virtual void SaveLayer(const Paint &paint, std::optional< Rect > bounds=std::nullopt, const std::shared_ptr< ImageFilter > &backdrop_filter=nullptr, ContentBoundsPromise bounds_promise=ContentBoundsPromise::kUnknown, uint32_t total_content_depth=kMaxDepth)
void DrawOval(const Rect &rect, const Paint &paint)
void RestoreToCount(size_t count)
void ClipPath(const Path &path, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
virtual void AddClipEntityToCurrentPass(Entity entity)
size_t GetClipHeight() const
void ClipRRect(const Rect &rect, const Size &corner_radii, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
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 DrawImage(const std::shared_ptr< Image > &image, Point offset, const Paint &paint, SamplerDescriptor sampler={})
void Rotate(Radians radians)
std::deque< CanvasStackEntry > transform_stack_
virtual void DrawTextFrame(const std::shared_ptr< TextFrame > &text_frame, Point position, const Paint &paint)
void DrawPaint(const Paint &paint)
void ClipRect(const Rect &rect, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
void Skew(Scalar sx, Scalar sy)
void Scale(const Vector2 &scale)
const std::optional< Rect > GetCurrentLocalCullingBounds() const
Picture EndRecordingAsPicture()
void DrawPath(const Path &path, const Paint &paint)
virtual void Save(uint32_t total_content_depth=kMaxDepth)
void DrawPoints(std::vector< Point > points, Scalar radius, const Paint &paint, PointStyle point_style)
void ClipOval(const Rect &bounds, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
void DrawRect(const Rect &rect, const Paint &paint)
void DrawRRect(const Rect &rect, const Size &corner_radii, const Paint &paint)
virtual void AddRenderEntityToCurrentPass(Entity entity, bool reuse_depth=false)
void DrawAtlas(const std::shared_ptr< Image > &atlas, std::vector< Matrix > transforms, std::vector< Rect > texture_coordinates, std::vector< Color > colors, BlendMode blend_mode, SamplerDescriptor sampler, std::optional< Rect > cull_rect, const Paint &paint)
void Translate(const Vector3 &offset)
void DrawCircle(const Point ¢er, Scalar radius, const Paint &paint)
struct impeller::Canvas::DebugOptions debug_options
std::shared_ptr< ColorSourceContents > GetContents(const Paint &paint) const
void SetRequiredMipCount(int32_t mip_count)
void SetClipDepth(size_t clip_depth)
void AddEntity(Entity entity)
Add an entity to the current entity pass.
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)
void PopAllClips(uint64_t depth)
EntityPass * AddSubpass(std::unique_ptr< EntityPass > pass)
Appends a given pass as a subpass.
void PushClip(Entity entity)
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.
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 > MakeOval(const Rect &rect)
static std::shared_ptr< Geometry > MakeLine(const Point &p0, const Point &p1, Scalar width, Cap cap)
static std::shared_ptr< Geometry > MakeCircle(const Point ¢er, Scalar radius)
static std::shared_ptr< Geometry > MakeRect(const Rect &rect)
static std::shared_ptr< Geometry > MakePointField(std::vector< Point > points, Scalar radius, bool round)
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 > MakeStrokedCircle(const Point ¢er, Scalar radius, Scalar stroke_width)
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....
static std::shared_ptr< TextureContents > MakeRect(Rect destination)
A common case factory that marks the texture contents as having a destination rectangle....
#define FML_CHECK(condition)
#define FML_DCHECK(condition)
sk_sp< SkBlender > blender SkRect rect
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
SourceRectConstraint
Controls the behavior of the source rectangle given to DrawImageRect.
@ kStrict
Sample only within the source rectangle. May be slower.
static bool UseColorSourceContents(const std::shared_ptr< VerticesGeometry > &vertices, const Paint &paint)
constexpr float kEhCloseEnough
@ kRound
Points are drawn as squares.
@ kContainsContents
The caller claims the bounds are a reasonably tight estimate of the coverage of the contents and shou...
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
std::optional< Rect > cull_rect
bool offscreen_texture_checkerboard
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
static constexpr TRect MakeOriginSize(const TPoint< Type > &origin, const TSize< Type > &size)
constexpr auto GetRight() const
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
static constexpr TRect MakeSize(const TSize< U > &size)
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.
#define TRACE_EVENT0(category_group, name)