Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Public Member Functions | Public Attributes | Static Public Attributes | Protected Member Functions | Protected Attributes | Private Member Functions | List of all members
impeller::Canvas Class Reference

#include <canvas.h>

Inheritance diagram for impeller::Canvas:
impeller::ExperimentalCanvas

Classes

struct  DebugOptions
 

Public Member Functions

 Canvas ()
 
 Canvas (Rect cull_rect)
 
 Canvas (IRect cull_rect)
 
virtual ~Canvas ()
 
virtual void Save (uint32_t total_content_depth=kMaxDepth)
 
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)
 
virtual bool Restore ()
 
size_t GetSaveCount () const
 
void RestoreToCount (size_t count)
 
const MatrixGetCurrentTransform () const
 
const std::optional< RectGetCurrentLocalCullingBounds () const
 
void ResetTransform ()
 
void Transform (const Matrix &transform)
 
void Concat (const Matrix &transform)
 
void PreConcat (const Matrix &transform)
 
void Translate (const Vector3 &offset)
 
void Scale (const Vector2 &scale)
 
void Scale (const Vector3 &scale)
 
void Skew (Scalar sx, Scalar sy)
 
void Rotate (Radians radians)
 
void DrawPath (const Path &path, const Paint &paint)
 
void DrawPaint (const Paint &paint)
 
void DrawLine (const Point &p0, const Point &p1, const Paint &paint)
 
void DrawRect (const Rect &rect, const Paint &paint)
 
void DrawOval (const Rect &rect, const Paint &paint)
 
void DrawRRect (const Rect &rect, const Size &corner_radii, const Paint &paint)
 
void DrawCircle (const Point &center, Scalar radius, const Paint &paint)
 
void DrawPoints (std::vector< Point > points, Scalar radius, const Paint &paint, PointStyle point_style)
 
void DrawImage (const std::shared_ptr< Image > &image, Point offset, const Paint &paint, SamplerDescriptor sampler={})
 
void DrawImageRect (const std::shared_ptr< Image > &image, Rect source, Rect dest, const Paint &paint, SamplerDescriptor sampler={}, SourceRectConstraint src_rect_constraint=SourceRectConstraint::kFast)
 
void ClipPath (const Path &path, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
 
void ClipRect (const Rect &rect, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
 
void ClipOval (const Rect &bounds, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
 
void ClipRRect (const Rect &rect, const Size &corner_radii, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
 
virtual void DrawTextFrame (const std::shared_ptr< TextFrame > &text_frame, Point position, const Paint &paint)
 
void DrawVertices (const std::shared_ptr< VerticesGeometry > &vertices, BlendMode blend_mode, const Paint &paint)
 
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)
 
Picture EndRecordingAsPicture ()
 

Public Attributes

struct impeller::Canvas::DebugOptions debug_options
 

Static Public Attributes

static constexpr uint32_t kMaxDepth = 1 << 24
 

Protected Member Functions

size_t GetClipHeight () const
 
void Initialize (std::optional< Rect > cull_rect)
 
void Reset ()
 

Protected Attributes

std::deque< CanvasStackEntrytransform_stack_
 
std::optional< Rectinitial_cull_rect_
 
uint64_t current_depth_ = 0u
 

Private Member Functions

virtual void AddRenderEntityToCurrentPass (Entity entity, bool reuse_depth=false)
 
virtual void AddClipEntityToCurrentPass (Entity entity)
 
virtual void Save (bool create_subpass, uint32_t total_content_depth, BlendMode=BlendMode::kSourceOver, const std::shared_ptr< ImageFilter > &backdrop_filter=nullptr)
 

Detailed Description

Definition at line 59 of file canvas.h.

Constructor & Destructor Documentation

◆ Canvas() [1/3]

impeller::Canvas::Canvas ( )

Definition at line 149 of file canvas.cc.

149 {
150 Initialize(std::nullopt);
151}
void Initialize(std::optional< Rect > cull_rect)
Definition canvas.cc:164

◆ Canvas() [2/3]

impeller::Canvas::Canvas ( Rect  cull_rect)
explicit

Definition at line 153 of file canvas.cc.

153 {
154 Initialize(cull_rect);
155}

◆ Canvas() [3/3]

impeller::Canvas::Canvas ( IRect  cull_rect)
explicit

Definition at line 157 of file canvas.cc.

157 {
158 Initialize(Rect::MakeLTRB(cull_rect.GetLeft(), cull_rect.GetTop(),
159 cull_rect.GetRight(), cull_rect.GetBottom()));
160}
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition rect.h:129

◆ ~Canvas()

impeller::Canvas::~Canvas ( )
virtualdefault

Member Function Documentation

◆ AddClipEntityToCurrentPass()

void impeller::Canvas::AddClipEntityToCurrentPass ( Entity  entity)
privatevirtual

Reimplemented in impeller::ExperimentalCanvas.

Definition at line 835 of file canvas.cc.

835 {
836 GetCurrentPass().PushClip(std::move(entity));
837}
void PushClip(Entity entity)

◆ AddRenderEntityToCurrentPass()

void impeller::Canvas::AddRenderEntityToCurrentPass ( Entity  entity,
bool  reuse_depth = false 
)
privatevirtual

Reimplemented in impeller::ExperimentalCanvas.

Definition at line 827 of file canvas.cc.

827 {
828 if (!reuse_depth) {
830 }
831 entity.SetClipDepth(current_depth_);
832 GetCurrentPass().AddEntity(std::move(entity));
833}
uint64_t current_depth_
Definition canvas.h:189
void AddEntity(Entity entity)
Add an entity to the current entity pass.

◆ ClipOval()

void impeller::Canvas::ClipOval ( const Rect bounds,
Entity::ClipOperation  clip_op = Entity::ClipOperation::kIntersect 
)

Definition at line 618 of file canvas.cc.

618 {
619 auto geometry = Geometry::MakeOval(bounds);
620 auto& cull_rect = transform_stack_.back().cull_rect;
621 if (clip_op == Entity::ClipOperation::kIntersect && //
622 cull_rect.has_value() && //
623 geometry->CoversArea(transform_stack_.back().transform, *cull_rect) //
624 ) {
625 return; // This clip will do nothing, so skip it.
626 }
627
628 ClipGeometry(geometry, clip_op);
629 switch (clip_op) {
631 IntersectCulling(bounds);
632 break;
634 break;
635 }
636}
std::deque< CanvasStackEntry > transform_stack_
Definition canvas.h:187
static std::shared_ptr< Geometry > MakeOval(const Rect &rect)
Definition geometry.cc:93

◆ ClipPath()

void impeller::Canvas::ClipPath ( const Path path,
Entity::ClipOperation  clip_op = Entity::ClipOperation::kIntersect 
)

Definition at line 587 of file canvas.cc.

587 {
588 auto bounds = path.GetBoundingBox();
589 ClipGeometry(Geometry::MakeFillPath(path), clip_op);
590 if (clip_op == Entity::ClipOperation::kIntersect) {
591 if (bounds.has_value()) {
592 IntersectCulling(bounds.value());
593 }
594 }
595}
static std::shared_ptr< Geometry > MakeFillPath(const Path &path, std::optional< Rect > inner_rect=std::nullopt)
Definition geometry.cc:60
Optional< SkRect > bounds
Definition SkRecords.h:189
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
Definition switches.h:57

◆ ClipRect()

void impeller::Canvas::ClipRect ( const Rect rect,
Entity::ClipOperation  clip_op = Entity::ClipOperation::kIntersect 
)

Definition at line 597 of file canvas.cc.

597 {
598 auto geometry = Geometry::MakeRect(rect);
599 auto& cull_rect = transform_stack_.back().cull_rect;
600 if (clip_op == Entity::ClipOperation::kIntersect && //
601 cull_rect.has_value() && //
602 geometry->CoversArea(transform_stack_.back().transform, *cull_rect) //
603 ) {
604 return; // This clip will do nothing, so skip it.
605 }
606
607 ClipGeometry(geometry, clip_op);
608 switch (clip_op) {
610 IntersectCulling(rect);
611 break;
613 SubtractCulling(rect);
614 break;
615 }
616}
static std::shared_ptr< Geometry > MakeRect(const Rect &rect)
Definition geometry.cc:89

◆ ClipRRect()

void impeller::Canvas::ClipRRect ( const Rect rect,
const Size corner_radii,
Entity::ClipOperation  clip_op = Entity::ClipOperation::kIntersect 
)

Definition at line 638 of file canvas.cc.

640 {
641 // Does the rounded rect have a flat part on the top/bottom or left/right?
642 bool flat_on_TB = corner_radii.width * 2 < rect.GetWidth();
643 bool flat_on_LR = corner_radii.height * 2 < rect.GetHeight();
644 auto geometry = Geometry::MakeRoundRect(rect, corner_radii);
645 auto& cull_rect = transform_stack_.back().cull_rect;
646 if (clip_op == Entity::ClipOperation::kIntersect && //
647 cull_rect.has_value() && //
648 geometry->CoversArea(transform_stack_.back().transform, *cull_rect) //
649 ) {
650 return; // This clip will do nothing, so skip it.
651 }
652
653 ClipGeometry(geometry, clip_op);
654 switch (clip_op) {
656 IntersectCulling(rect);
657 break;
659 if (corner_radii.IsEmpty()) {
660 SubtractCulling(rect);
661 } else {
662 // We subtract the inner "tall" and "wide" rectangle pieces
663 // that fit inside the corners which cover the greatest area
664 // without involving the curved corners
665 // Since this is a subtract operation, we can subtract each
666 // rectangle piece individually without fear of interference.
667 if (flat_on_TB) {
668 SubtractCulling(rect.Expand(Size{-corner_radii.width, 0.0}));
669 }
670 if (flat_on_LR) {
671 SubtractCulling(rect.Expand(Size{0.0, -corner_radii.height}));
672 }
673 }
674 break;
675 }
676}
static std::shared_ptr< Geometry > MakeRoundRect(const Rect &rect, const Size &radii)
Definition geometry.cc:115
sk_sp< SkBlender > blender SkRect rect
Definition SkRecords.h:350
TSize< Scalar > Size
Definition size.h:137

◆ Concat()

void impeller::Canvas::Concat ( const Matrix transform)

Definition at line 280 of file canvas.cc.

280 {
281 transform_stack_.back().transform = GetCurrentTransform() * transform;
282}
const Matrix & GetCurrentTransform() const
Definition canvas.cc:296
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition p3.cpp:47

◆ DrawAtlas()

void impeller::Canvas::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 
)

Definition at line 1003 of file canvas.cc.

1010 {
1011 if (!atlas) {
1012 return;
1013 }
1014
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);
1024
1025 Entity entity;
1026 entity.SetTransform(GetCurrentTransform());
1027 entity.SetBlendMode(paint.blend_mode);
1028 entity.SetContents(paint.WithFilters(contents));
1029
1030 AddRenderEntityToCurrentPass(std::move(entity));
1031}
virtual void AddRenderEntityToCurrentPass(Entity entity, bool reuse_depth=false)
Definition canvas.cc:827
const Paint & paint
sk_sp< const SkImage > atlas
Definition SkRecords.h:331

◆ DrawCircle()

void impeller::Canvas::DrawCircle ( const Point center,
Scalar  radius,
const Paint paint 
)

Definition at line 564 of file canvas.cc.

566 {
567 Size half_size(radius, radius);
568 if (AttemptDrawBlurredRRect(
569 Rect::MakeOriginSize(center - half_size, half_size * 2),
570 {radius, radius}, paint)) {
571 return;
572 }
573
574 Entity entity;
575 entity.SetTransform(GetCurrentTransform());
576 entity.SetBlendMode(paint.blend_mode);
577 auto geometry =
579 ? Geometry::MakeStrokedCircle(center, radius, paint.stroke_width)
580 : Geometry::MakeCircle(center, radius);
581 entity.SetContents(
582 CreateContentsForGeometryWithFilters(paint, std::move(geometry)));
583
584 AddRenderEntityToCurrentPass(std::move(entity));
585}
static SkScalar center(float pos0, float pos1)
static std::shared_ptr< Geometry > MakeStrokedCircle(const Point &center, Scalar radius, Scalar stroke_width)
Definition geometry.cc:109
static constexpr TRect MakeOriginSize(const TPoint< Type > &origin, const TSize< Type > &size)
Definition rect.h:140

◆ DrawImage()

void impeller::Canvas::DrawImage ( const std::shared_ptr< Image > &  image,
Point  offset,
const Paint paint,
SamplerDescriptor  sampler = {} 
)

Definition at line 750 of file canvas.cc.

753 {
754 if (!image) {
755 return;
756 }
757
758 const auto source = Rect::MakeSize(image->GetSize());
759 const auto dest = source.Shift(offset);
760
761 DrawImageRect(image, source, dest, paint, std::move(sampler));
762}
void DrawImageRect(const std::shared_ptr< Image > &image, Rect source, Rect dest, const Paint &paint, SamplerDescriptor sampler={}, SourceRectConstraint src_rect_constraint=SourceRectConstraint::kFast)
Definition canvas.cc:764
sk_sp< SkImage > image
Definition examples.cpp:29
SkBitmap source
Definition examples.cpp:28
dest
Definition zip.py:79
Point offset
static constexpr TRect MakeSize(const TSize< U > &size)
Definition rect.h:146

◆ DrawImageRect()

void impeller::Canvas::DrawImageRect ( const std::shared_ptr< Image > &  image,
Rect  source,
Rect  dest,
const Paint paint,
SamplerDescriptor  sampler = {},
SourceRectConstraint  src_rect_constraint = SourceRectConstraint::kFast 
)

Definition at line 764 of file canvas.cc.

769 {
770 if (!image || source.IsEmpty() || dest.IsEmpty()) {
771 return;
772 }
773
774 auto size = image->GetSize();
775
776 if (size.IsEmpty()) {
777 return;
778 }
779
780 auto texture_contents = TextureContents::MakeRect(dest);
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());
788
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);
792 }
793
794 Entity entity;
795 entity.SetBlendMode(paint.blend_mode);
796 entity.SetContents(paint.WithFilters(contents));
797 entity.SetTransform(GetCurrentTransform());
798
799 AddRenderEntityToCurrentPass(std::move(entity));
800}
static std::shared_ptr< TextureContents > MakeRect(Rect destination)
A common case factory that marks the texture contents as having a destination rectangle....
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
Definition switches.h:259
@ kStrict
Sample only within the source rectangle. May be slower.

◆ DrawLine()

void impeller::Canvas::DrawLine ( const Point p0,
const Point p1,
const Paint paint 
)

Definition at line 483 of file canvas.cc.

483 {
484 Entity entity;
485 entity.SetTransform(GetCurrentTransform());
486 entity.SetBlendMode(paint.blend_mode);
487 entity.SetContents(CreateContentsForGeometryWithFilters(
488 paint, Geometry::MakeLine(p0, p1, paint.stroke_width, paint.stroke_cap)));
489
490 AddRenderEntityToCurrentPass(std::move(entity));
491}
static std::shared_ptr< Geometry > MakeLine(const Point &p0, const Point &p1, Scalar width, Cap cap)
Definition geometry.cc:97

◆ DrawOval()

void impeller::Canvas::DrawOval ( const Rect rect,
const Paint paint 
)

Definition at line 512 of file canvas.cc.

512 {
513 if (rect.IsSquare()) {
514 // Circles have slightly less overhead and can do stroking
515 DrawCircle(rect.GetCenter(), rect.GetWidth() * 0.5f, paint);
516 return;
517 }
518
519 if (paint.style == Paint::Style::kStroke) {
520 // No stroked ellipses yet
521 DrawPath(PathBuilder{}.AddOval(rect).TakePath(), paint);
522 return;
523 }
524
525 if (AttemptDrawBlurredRRect(rect, rect.GetSize() * 0.5f, paint)) {
526 return;
527 }
528
529 Entity entity;
530 entity.SetTransform(GetCurrentTransform());
531 entity.SetBlendMode(paint.blend_mode);
532 entity.SetContents(
533 CreateContentsForGeometryWithFilters(paint, Geometry::MakeOval(rect)));
534
535 AddRenderEntityToCurrentPass(std::move(entity));
536}
void DrawPath(const Path &path, const Paint &paint)
Definition canvas.cc:341
void DrawCircle(const Point &center, Scalar radius, const Paint &paint)
Definition canvas.cc:564

◆ DrawPaint()

void impeller::Canvas::DrawPaint ( const Paint paint)

Definition at line 350 of file canvas.cc.

350 {
351 Entity entity;
352 entity.SetTransform(GetCurrentTransform());
353 entity.SetBlendMode(paint.blend_mode);
354 entity.SetContents(CreateCoverContentsWithFilters(paint));
355
356 AddRenderEntityToCurrentPass(std::move(entity));
357}

◆ DrawPath()

void impeller::Canvas::DrawPath ( const Path path,
const Paint paint 
)

Definition at line 341 of file canvas.cc.

341 {
342 Entity entity;
343 entity.SetTransform(GetCurrentTransform());
344 entity.SetBlendMode(paint.blend_mode);
345 entity.SetContents(CreatePathContentsWithFilters(paint, path));
346
347 AddRenderEntityToCurrentPass(std::move(entity));
348}

◆ DrawPoints()

void impeller::Canvas::DrawPoints ( std::vector< Point points,
Scalar  radius,
const Paint paint,
PointStyle  point_style 
)

Definition at line 731 of file canvas.cc.

734 {
735 if (radius <= 0) {
736 return;
737 }
738
739 Entity entity;
740 entity.SetTransform(GetCurrentTransform());
741 entity.SetBlendMode(paint.blend_mode);
742 entity.SetContents(CreateContentsForGeometryWithFilters(
743 paint,
744 Geometry::MakePointField(std::move(points), radius,
745 /*round=*/point_style == PointStyle::kRound)));
746
747 AddRenderEntityToCurrentPass(std::move(entity));
748}
static const int points[]
static std::shared_ptr< Geometry > MakePointField(std::vector< Point > points, Scalar radius, bool round)
Definition geometry.cc:66
@ kRound
Points are drawn as squares.

◆ DrawRect()

void impeller::Canvas::DrawRect ( const Rect rect,
const Paint paint 
)

Definition at line 493 of file canvas.cc.

493 {
494 if (paint.style == Paint::Style::kStroke) {
495 DrawPath(PathBuilder{}.AddRect(rect).TakePath(), paint);
496 return;
497 }
498
499 if (AttemptDrawBlurredRRect(rect, {}, paint)) {
500 return;
501 }
502
503 Entity entity;
504 entity.SetTransform(GetCurrentTransform());
505 entity.SetBlendMode(paint.blend_mode);
506 entity.SetContents(
507 CreateContentsForGeometryWithFilters(paint, Geometry::MakeRect(rect)));
508
509 AddRenderEntityToCurrentPass(std::move(entity));
510}

◆ DrawRRect()

void impeller::Canvas::DrawRRect ( const Rect rect,
const Size corner_radii,
const Paint paint 
)

Definition at line 538 of file canvas.cc.

540 {
541 if (AttemptDrawBlurredRRect(rect, corner_radii, paint)) {
542 return;
543 }
544
545 if (paint.style == Paint::Style::kFill) {
546 Entity entity;
547 entity.SetTransform(GetCurrentTransform());
548 entity.SetBlendMode(paint.blend_mode);
549 entity.SetContents(CreateContentsForGeometryWithFilters(
550 paint, Geometry::MakeRoundRect(rect, corner_radii)));
551
552 AddRenderEntityToCurrentPass(std::move(entity));
553 return;
554 }
555
556 auto path = PathBuilder{}
557 .SetConvexity(Convexity::kConvex)
558 .AddRoundedRect(rect, corner_radii)
559 .SetBounds(rect)
560 .TakePath();
561 DrawPath(path, paint);
562}

◆ DrawTextFrame()

void impeller::Canvas::DrawTextFrame ( const std::shared_ptr< TextFrame > &  text_frame,
Point  position,
const Paint paint 
)
virtual

Reimplemented in impeller::ExperimentalCanvas.

Definition at line 875 of file canvas.cc.

877 {
878 Entity entity;
879 entity.SetBlendMode(paint.blend_mode);
880
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());
885
886 entity.SetTransform(GetCurrentTransform() *
887 Matrix::MakeTranslation(position));
888
889 // TODO(bdero): This mask blur application is a hack. It will always wind up
890 // doing a gaussian blur that affects the color source itself
891 // instead of just the mask. The color filter text support
892 // needs to be reworked in order to interact correctly with
893 // mask filters.
894 // https://github.com/flutter/flutter/issues/133297
895 entity.SetContents(
896 paint.WithFilters(paint.WithMaskBlur(std::move(text_contents), true)));
897
898 AddRenderEntityToCurrentPass(std::move(entity));
899}
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition matrix.h:95

◆ DrawVertices()

void impeller::Canvas::DrawVertices ( const std::shared_ptr< VerticesGeometry > &  vertices,
BlendMode  blend_mode,
const Paint paint 
)

Definition at line 916 of file canvas.cc.

918 {
919 // Override the blend mode with kDestination in order to match the behavior
920 // of Skia's SK_LEGACY_IGNORE_DRAW_VERTICES_BLEND_WITH_NO_SHADER flag, which
921 // is enabled when the Flutter engine builds Skia.
922 if (paint.color_source.GetType() == ColorSource::Type::kColor) {
923 blend_mode = BlendMode::kDestination;
924 }
925
926 Entity entity;
927 entity.SetTransform(GetCurrentTransform());
928 entity.SetBlendMode(paint.blend_mode);
929
930 // If there are no vertex colors.
931 if (UseColorSourceContents(vertices, paint)) {
932 entity.SetContents(CreateContentsForGeometryWithFilters(paint, vertices));
933 AddRenderEntityToCurrentPass(std::move(entity));
934 return;
935 }
936
937 // If the blend mode is destination don't bother to bind or create a texture.
938 if (blend_mode == BlendMode::kDestination) {
939 auto contents = std::make_shared<VerticesSimpleBlendContents>();
940 contents->SetBlendMode(blend_mode);
941 contents->SetAlpha(paint.color.alpha);
942 contents->SetGeometry(vertices);
943 entity.SetContents(paint.WithFilters(std::move(contents)));
944 AddRenderEntityToCurrentPass(std::move(entity));
945 return;
946 }
947
948 // If there is a texture, use this directly. Otherwise render the color
949 // source to a texture.
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);
957 contents->SetEffectTransform(image_data.effect_transform);
958 contents->SetTexture(image_data.texture);
959 contents->SetTileMode(image_data.x_tile_mode, image_data.y_tile_mode);
960
961 entity.SetContents(paint.WithFilters(std::move(contents)));
962 AddRenderEntityToCurrentPass(std::move(entity));
963 return;
964 }
965
966 auto src_paint = paint;
967 src_paint.color = paint.color.WithAlpha(1.0);
968
969 std::shared_ptr<Contents> src_contents =
970 src_paint.CreateContentsForGeometry(vertices);
971
972 // If the color source has an intrinsic size, then we use that to
973 // create the src contents as a simplification. Otherwise we use
974 // the extent of the texture coordinates to determine how large
975 // the src contents should be. If neither has a value we fall back
976 // to using the geometry coverage data.
977 Rect src_coverage;
978 auto size = src_contents->GetColorSourceSize();
979 if (size.has_value()) {
980 src_coverage = Rect::MakeXYWH(0, 0, size->width, size->height);
981 } else {
982 auto cvg = vertices->GetCoverage(Matrix{});
983 FML_CHECK(cvg.has_value());
984 src_coverage =
985 // Covered by FML_CHECK.
986 // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
987 vertices->GetTextureCoordinateCoverge().value_or(cvg.value());
988 }
989 src_contents =
990 src_paint.CreateContentsForGeometry(Geometry::MakeRect(src_coverage));
991
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;
998 });
999 entity.SetContents(paint.WithFilters(std::move(contents)));
1000 AddRenderEntityToCurrentPass(std::move(entity));
1001}
#define FML_CHECK(condition)
Definition logging.h:85
FlTexture * texture
static bool UseColorSourceContents(const std::shared_ptr< VerticesGeometry > &vertices, const Paint &paint)
Definition canvas.cc:901
TRect< Scalar > Rect
Definition rect.h:746
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition rect.h:136

◆ EndRecordingAsPicture()

Picture impeller::Canvas::EndRecordingAsPicture ( )

Definition at line 802 of file canvas.cc.

802 {
803 // Assign clip depths to any outstanding clip entities.
804 while (current_pass_ != nullptr) {
805 current_pass_->PopAllClips(current_depth_);
806 current_pass_ = current_pass_->GetSuperpass();
807 }
808
810 picture.pass = std::move(base_pass_);
811
812 Reset();
814
815 return picture;
816}
std::optional< Rect > initial_cull_rect_
Definition canvas.h:188
EntityPass * GetSuperpass() const
void PopAllClips(uint64_t depth)
sk_sp< const SkPicture > picture
Definition SkRecords.h:299
SK_API sk_sp< PrecompileShader > Picture()

◆ GetClipHeight()

size_t impeller::Canvas::GetClipHeight ( ) const
protected

Definition at line 823 of file canvas.cc.

823 {
824 return transform_stack_.back().clip_height;
825}

◆ GetCurrentLocalCullingBounds()

const std::optional< Rect > impeller::Canvas::GetCurrentLocalCullingBounds ( ) const

Definition at line 300 of file canvas.cc.

300 {
301 auto cull_rect = transform_stack_.back().cull_rect;
302 if (cull_rect.has_value()) {
303 Matrix inverse = transform_stack_.back().transform.Invert();
304 cull_rect = cull_rect.value().TransformBounds(inverse);
305 }
306 return cull_rect;
307}

◆ GetCurrentTransform()

const Matrix & impeller::Canvas::GetCurrentTransform ( ) const

Definition at line 296 of file canvas.cc.

296 {
297 return transform_stack_.back().transform;
298}

◆ GetSaveCount()

size_t impeller::Canvas::GetSaveCount ( ) const

Definition at line 329 of file canvas.cc.

329 {
330 return transform_stack_.size();
331}

◆ Initialize()

void impeller::Canvas::Initialize ( std::optional< Rect cull_rect)
protected

Definition at line 164 of file canvas.cc.

164 {
165 initial_cull_rect_ = cull_rect;
166 base_pass_ = std::make_unique<EntityPass>();
167 base_pass_->SetClipDepth(++current_depth_);
168 current_pass_ = base_pass_.get();
169 transform_stack_.emplace_back(CanvasStackEntry{
170 .cull_rect = cull_rect,
171 .clip_depth = kMaxDepth,
172 });
173 FML_DCHECK(GetSaveCount() == 1u);
174 FML_DCHECK(base_pass_->GetSubpassesDepth() == 1u);
175}
static constexpr uint32_t kMaxDepth
Definition canvas.h:61
size_t GetSaveCount() const
Definition canvas.cc:329
#define FML_DCHECK(condition)
Definition logging.h:103

◆ PreConcat()

void impeller::Canvas::PreConcat ( const Matrix transform)

Definition at line 284 of file canvas.cc.

284 {
285 transform_stack_.back().transform = transform * GetCurrentTransform();
286}

◆ Reset()

void impeller::Canvas::Reset ( )
protected

Definition at line 177 of file canvas.cc.

177 {
178 base_pass_ = nullptr;
179 current_pass_ = nullptr;
180 current_depth_ = 0u;
181 transform_stack_ = {};
182}

◆ ResetTransform()

void impeller::Canvas::ResetTransform ( )

Definition at line 288 of file canvas.cc.

288 {
289 transform_stack_.back().transform = {};
290}

◆ Restore()

bool impeller::Canvas::Restore ( )
virtual

Reimplemented in impeller::ExperimentalCanvas.

Definition at line 257 of file canvas.cc.

257 {
258 FML_DCHECK(transform_stack_.size() > 0);
259 if (transform_stack_.size() == 1) {
260 return false;
261 }
262 size_t num_clips = transform_stack_.back().num_clips;
263 current_pass_->PopClips(num_clips, current_depth_);
264
265 if (transform_stack_.back().rendering_mode ==
267 current_pass_->SetClipDepth(++current_depth_);
268 current_pass_ = GetCurrentPass().GetSuperpass();
269 FML_DCHECK(current_pass_);
270 }
271
272 transform_stack_.pop_back();
273 if (num_clips > 0) {
274 RestoreClip();
275 }
276
277 return true;
278}
void SetClipDepth(size_t clip_depth)
void PopClips(size_t num_clips, uint64_t depth)

◆ RestoreToCount()

void impeller::Canvas::RestoreToCount ( size_t  count)

Definition at line 333 of file canvas.cc.

333 {
334 while (GetSaveCount() > count) {
335 if (!Restore()) {
336 return;
337 }
338 }
339}
int count
virtual bool Restore()
Definition canvas.cc:257

◆ Rotate()

void impeller::Canvas::Rotate ( Radians  radians)

Definition at line 325 of file canvas.cc.

325 {
327}
void Concat(const Matrix &transform)
Definition canvas.cc:280
static Matrix MakeRotationZ(Radians r)
Definition matrix.h:213

◆ Save() [1/2]

void impeller::Canvas::Save ( bool  create_subpass,
uint32_t  total_content_depth,
BlendMode  blend_mode = BlendMode::kSourceOver,
const std::shared_ptr< ImageFilter > &  backdrop_filter = nullptr 
)
privatevirtual

Definition at line 219 of file canvas.cc.

222 {
223 auto entry = CanvasStackEntry{};
224 entry.transform = transform_stack_.back().transform;
225 entry.cull_rect = transform_stack_.back().cull_rect;
226 entry.clip_height = transform_stack_.back().clip_height;
227 if (create_subpass) {
228 entry.rendering_mode = Entity::RenderingMode::kSubpass;
229 auto subpass = std::make_unique<EntityPass>();
230 subpass->SetEnableOffscreenCheckerboard(
232 if (backdrop_filter) {
233 EntityPass::BackdropFilterProc backdrop_filter_proc =
234 [backdrop_filter = backdrop_filter->Clone()](
235 const FilterInput::Ref& input, const Matrix& effect_transform,
236 Entity::RenderingMode rendering_mode) {
237 auto filter = backdrop_filter->WrapInput(input);
238 filter->SetEffectTransform(effect_transform);
239 filter->SetRenderingMode(rendering_mode);
240 return filter;
241 };
242 subpass->SetBackdropFilter(backdrop_filter_proc);
243 MipCountVisitor mip_count_visitor;
244 backdrop_filter->Visit(mip_count_visitor);
245 current_pass_->SetRequiredMipCount(
246 std::max(current_pass_->GetRequiredMipCount(),
247 mip_count_visitor.GetRequiredMipCount()));
248 }
249 subpass->SetBlendMode(blend_mode);
250 current_pass_ = GetCurrentPass().AddSubpass(std::move(subpass));
251 current_pass_->SetTransform(transform_stack_.back().transform);
252 current_pass_->SetClipHeight(transform_stack_.back().clip_height);
253 }
254 transform_stack_.emplace_back(entry);
255}
struct impeller::Canvas::DebugOptions debug_options
void SetRequiredMipCount(int32_t mip_count)
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
Definition entity_pass.h:61
std::shared_ptr< FilterInput > Ref

◆ Save() [2/2]

void impeller::Canvas::Save ( uint32_t  total_content_depth = kMaxDepth)
virtual

Reimplemented in impeller::ExperimentalCanvas.

Definition at line 184 of file canvas.cc.

184 {
185 Save(false, total_content_depth);
186}
virtual void Save(uint32_t total_content_depth=kMaxDepth)
Definition canvas.cc:184

◆ SaveLayer()

void impeller::Canvas::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 
)
virtual

Reimplemented in impeller::ExperimentalCanvas.

Definition at line 839 of file canvas.cc.

843 {
844 TRACE_EVENT0("flutter", "Canvas::saveLayer");
845 Save(true, total_content_depth, paint.blend_mode, backdrop_filter);
846
847 // The DisplayList bounds/rtree doesn't account for filters applied to parent
848 // layers, and so sub-DisplayLists are getting culled as if no filters are
849 // applied.
850 // See also: https://github.com/flutter/flutter/issues/139294
851 if (paint.image_filter) {
852 transform_stack_.back().cull_rect = std::nullopt;
853 }
854
855 auto& new_layer_pass = GetCurrentPass();
856 if (bounds) {
857 new_layer_pass.SetBoundsLimit(bounds, bounds_promise);
858 }
859
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());
864 }
865
866 // Only apply opacity peephole on default blending.
867 if (paint.blend_mode == BlendMode::kSourceOver) {
868 new_layer_pass.SetDelegate(
869 std::make_shared<OpacityPeepholePassDelegate>(paint));
870 } else {
871 new_layer_pass.SetDelegate(std::make_shared<PaintPassDelegate>(paint));
872 }
873}
#define TRACE_EVENT0(category_group, name)

◆ Scale() [1/2]

void impeller::Canvas::Scale ( const Vector2 scale)

Definition at line 313 of file canvas.cc.

313 {
315}
const Scalar scale
static constexpr Matrix MakeScale(const Vector3 &s)
Definition matrix.h:104

◆ Scale() [2/2]

void impeller::Canvas::Scale ( const Vector3 scale)

Definition at line 317 of file canvas.cc.

317 {
319}

◆ Skew()

void impeller::Canvas::Skew ( Scalar  sx,
Scalar  sy 
)

Definition at line 321 of file canvas.cc.

321 {
322 Concat(Matrix::MakeSkew(sx, sy));
323}
static constexpr Matrix MakeSkew(Scalar sx, Scalar sy)
Definition matrix.h:117

◆ Transform()

void impeller::Canvas::Transform ( const Matrix transform)

Definition at line 292 of file canvas.cc.

292 {
294}

◆ Translate()

void impeller::Canvas::Translate ( const Vector3 offset)

Definition at line 309 of file canvas.cc.

Member Data Documentation

◆ current_depth_

uint64_t impeller::Canvas::current_depth_ = 0u
protected

Definition at line 189 of file canvas.h.

◆ debug_options

struct impeller::Canvas::DebugOptions impeller::Canvas::debug_options

◆ initial_cull_rect_

std::optional<Rect> impeller::Canvas::initial_cull_rect_
protected

Definition at line 188 of file canvas.h.

◆ kMaxDepth

constexpr uint32_t impeller::Canvas::kMaxDepth = 1 << 24
staticconstexpr

Definition at line 61 of file canvas.h.

◆ transform_stack_

std::deque<CanvasStackEntry> impeller::Canvas::transform_stack_
protected

Definition at line 187 of file canvas.h.


The documentation for this class was generated from the following files: