Flutter Engine
The Flutter Engine
Public Member Functions | 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

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, bool can_distribute_opacity=false)
 
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 ()
 

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 60 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

Definition at line 838 of file canvas.cc.

838 {
839 GetCurrentPass().PushClip(std::move(entity));
840}
void PushClip(Entity entity)
Definition: entity_pass.cc:112

◆ AddRenderEntityToCurrentPass()

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

Definition at line 829 of file canvas.cc.

829 {
830 if (!reuse_depth) {
832 }
833 entity.SetClipDepth(current_depth_);
834 entity.SetInheritedOpacity(transform_stack_.back().distributed_opacity);
835 GetCurrentPass().AddEntity(std::move(entity));
836}
std::deque< CanvasStackEntry > transform_stack_
Definition: canvas.h:181
uint64_t current_depth_
Definition: canvas.h:183
void AddEntity(Entity entity)
Add an entity to the current entity pass.
Definition: entity_pass.cc:100

◆ ClipOval()

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

Definition at line 620 of file canvas.cc.

620 {
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) //
626 ) {
627 return; // This clip will do nothing, so skip it.
628 }
629
630 ClipGeometry(geometry, clip_op);
631 switch (clip_op) {
633 IntersectCulling(bounds);
634 break;
636 break;
637 }
638}
static std::shared_ptr< Geometry > MakeOval(const Rect &rect)
Definition: geometry.cc:93
Optional< SkRect > bounds
Definition: SkRecords.h:189

◆ ClipPath()

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

Definition at line 589 of file canvas.cc.

589 {
590 auto bounds = path.GetBoundingBox();
591 ClipGeometry(Geometry::MakeFillPath(path), clip_op);
592 if (clip_op == Entity::ClipOperation::kIntersect) {
593 if (bounds.has_value()) {
594 IntersectCulling(bounds.value());
595 }
596 }
597}
static std::shared_ptr< Geometry > MakeFillPath(const Path &path, std::optional< Rect > inner_rect=std::nullopt)
Definition: geometry.cc:60
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 599 of file canvas.cc.

599 {
600 auto geometry = Geometry::MakeRect(rect);
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) //
605 ) {
606 return; // This clip will do nothing, so skip it.
607 }
608
609 ClipGeometry(geometry, clip_op);
610 switch (clip_op) {
612 IntersectCulling(rect);
613 break;
615 SubtractCulling(rect);
616 break;
617 }
618}
static std::shared_ptr< Geometry > MakeRect(const Rect &rect)
Definition: geometry.cc:89
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350

◆ ClipRRect()

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

Definition at line 640 of file canvas.cc.

642 {
643 // Does the rounded rect have a flat part on the top/bottom or left/right?
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) //
651 ) {
652 return; // This clip will do nothing, so skip it.
653 }
654
655 ClipGeometry(geometry, clip_op);
656 switch (clip_op) {
658 IntersectCulling(rect);
659 break;
661 if (corner_radii.IsEmpty()) {
662 SubtractCulling(rect);
663 } else {
664 // We subtract the inner "tall" and "wide" rectangle pieces
665 // that fit inside the corners which cover the greatest area
666 // without involving the curved corners
667 // Since this is a subtract operation, we can subtract each
668 // rectangle piece individually without fear of interference.
669 if (flat_on_TB) {
670 SubtractCulling(rect.Expand(Size{-corner_radii.width, 0.0}));
671 }
672 if (flat_on_LR) {
673 SubtractCulling(rect.Expand(Size{0.0, -corner_radii.height}));
674 }
675 }
676 break;
677 }
678}
static std::shared_ptr< Geometry > MakeRoundRect(const Rect &rect, const Size &radii)
Definition: geometry.cc:115
TSize< Scalar > Size
Definition: size.h:137

◆ Concat()

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

Definition at line 282 of file canvas.cc.

282 {
283 transform_stack_.back().transform = GetCurrentTransform() * transform;
284}
const Matrix & GetCurrentTransform() const
Definition: canvas.cc:298
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 1020 of file canvas.cc.

1027 {
1028 if (!atlas) {
1029 return;
1030 }
1031
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);
1041
1042 Entity entity;
1043 entity.SetTransform(GetCurrentTransform());
1044 entity.SetBlendMode(paint.blend_mode);
1045 entity.SetContents(paint.WithFilters(contents));
1046
1047 AddRenderEntityToCurrentPass(std::move(entity));
1048}
virtual void AddRenderEntityToCurrentPass(Entity entity, bool reuse_depth=false)
Definition: canvas.cc:829
const Paint & paint
Definition: color_source.cc:38
sk_sp< const SkImage > atlas
Definition: SkRecords.h:331
PODArray< SkColor > colors
Definition: SkRecords.h:276

◆ DrawCircle()

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

Definition at line 566 of file canvas.cc.

568 {
569 Size half_size(radius, radius);
570 if (AttemptDrawBlurredRRect(
571 Rect::MakeOriginSize(center - half_size, half_size * 2),
572 {radius, radius}, paint)) {
573 return;
574 }
575
576 Entity entity;
577 entity.SetTransform(GetCurrentTransform());
578 entity.SetBlendMode(paint.blend_mode);
579 auto geometry =
581 ? Geometry::MakeStrokedCircle(center, radius, paint.stroke_width)
582 : Geometry::MakeCircle(center, radius);
583 entity.SetContents(
584 CreateContentsForGeometryWithFilters(paint, std::move(geometry)));
585
586 AddRenderEntityToCurrentPass(std::move(entity));
587}
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 752 of file canvas.cc.

755 {
756 if (!image) {
757 return;
758 }
759
760 const auto source = Rect::MakeSize(image->GetSize());
761 const auto dest = source.Shift(offset);
762
763 DrawImageRect(image, source, dest, paint, std::move(sampler));
764}
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:766
SkBitmap source
Definition: examples.cpp:28
sk_sp< const SkImage > image
Definition: SkRecords.h:269
dest
Definition: zip.py:79
SeparatedVector2 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 766 of file canvas.cc.

771 {
772 if (!image || source.IsEmpty() || dest.IsEmpty()) {
773 return;
774 }
775
776 auto size = image->GetSize();
777
778 if (size.IsEmpty()) {
779 return;
780 }
781
782 auto texture_contents = TextureContents::MakeRect(dest);
783 texture_contents->SetTexture(image->GetTexture());
784 texture_contents->SetSourceRect(source);
785 texture_contents->SetStrictSourceRect(src_rect_constraint ==
787 texture_contents->SetSamplerDescriptor(std::move(sampler));
788 texture_contents->SetOpacity(paint.color.alpha);
789 texture_contents->SetDeferApplyingOpacity(paint.HasColorFilter());
790
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);
794 }
795
796 Entity entity;
797 entity.SetBlendMode(paint.blend_mode);
798 entity.SetContents(paint.WithFilters(contents));
799 entity.SetTransform(GetCurrentTransform());
800
801 AddRenderEntityToCurrentPass(std::move(entity));
802}
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 485 of file canvas.cc.

485 {
486 Entity entity;
487 entity.SetTransform(GetCurrentTransform());
488 entity.SetBlendMode(paint.blend_mode);
489 entity.SetContents(CreateContentsForGeometryWithFilters(
490 paint, Geometry::MakeLine(p0, p1, paint.stroke_width, paint.stroke_cap)));
491
492 AddRenderEntityToCurrentPass(std::move(entity));
493}
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 514 of file canvas.cc.

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

◆ DrawPaint()

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

Definition at line 352 of file canvas.cc.

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

◆ DrawPath()

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

Definition at line 343 of file canvas.cc.

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

◆ DrawPoints()

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

Definition at line 733 of file canvas.cc.

736 {
737 if (radius <= 0) {
738 return;
739 }
740
741 Entity entity;
742 entity.SetTransform(GetCurrentTransform());
743 entity.SetBlendMode(paint.blend_mode);
744 entity.SetContents(CreateContentsForGeometryWithFilters(
745 paint,
746 Geometry::MakePointField(std::move(points), radius,
747 /*round=*/point_style == PointStyle::kRound)));
748
749 AddRenderEntityToCurrentPass(std::move(entity));
750}
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 495 of file canvas.cc.

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

◆ DrawRRect()

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

Definition at line 540 of file canvas.cc.

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

◆ 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 884 of file canvas.cc.

886 {
887 Entity entity;
888 entity.SetBlendMode(paint.blend_mode);
889
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, //
897 paint.stroke_width, //
898 paint.stroke_cap, //
899 paint.stroke_join, //
900 paint.stroke_miter //
901 );
902
903 entity.SetTransform(GetCurrentTransform() *
904 Matrix::MakeTranslation(position));
905
906 // TODO(bdero): This mask blur application is a hack. It will always wind up
907 // doing a gaussian blur that affects the color source itself
908 // instead of just the mask. The color filter text support
909 // needs to be reworked in order to interact correctly with
910 // mask filters.
911 // https://github.com/flutter/flutter/issues/133297
912 entity.SetContents(paint.WithFilters(paint.WithMaskBlur(
913 std::move(text_contents), true, GetCurrentTransform())));
914
915 AddRenderEntityToCurrentPass(std::move(entity));
916}
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 933 of file canvas.cc.

935 {
936 // Override the blend mode with kDestination in order to match the behavior
937 // of Skia's SK_LEGACY_IGNORE_DRAW_VERTICES_BLEND_WITH_NO_SHADER flag, which
938 // is enabled when the Flutter engine builds Skia.
939 if (paint.color_source.GetType() == ColorSource::Type::kColor) {
940 blend_mode = BlendMode::kDestination;
941 }
942
943 Entity entity;
944 entity.SetTransform(GetCurrentTransform());
945 entity.SetBlendMode(paint.blend_mode);
946
947 // If there are no vertex colors.
948 if (UseColorSourceContents(vertices, paint)) {
949 entity.SetContents(CreateContentsForGeometryWithFilters(paint, vertices));
950 AddRenderEntityToCurrentPass(std::move(entity));
951 return;
952 }
953
954 // If the blend mode is destination don't bother to bind or create a texture.
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);
960 entity.SetContents(paint.WithFilters(std::move(contents)));
961 AddRenderEntityToCurrentPass(std::move(entity));
962 return;
963 }
964
965 // If there is a texture, use this directly. Otherwise render the color
966 // source to a texture.
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);
974 contents->SetEffectTransform(image_data.effect_transform);
975 contents->SetTexture(image_data.texture);
976 contents->SetTileMode(image_data.x_tile_mode, image_data.y_tile_mode);
977
978 entity.SetContents(paint.WithFilters(std::move(contents)));
979 AddRenderEntityToCurrentPass(std::move(entity));
980 return;
981 }
982
983 auto src_paint = paint;
984 src_paint.color = paint.color.WithAlpha(1.0);
985
986 std::shared_ptr<Contents> src_contents =
987 src_paint.CreateContentsForGeometry(vertices);
988
989 // If the color source has an intrinsic size, then we use that to
990 // create the src contents as a simplification. Otherwise we use
991 // the extent of the texture coordinates to determine how large
992 // the src contents should be. If neither has a value we fall back
993 // to using the geometry coverage data.
994 Rect src_coverage;
995 auto size = src_contents->GetColorSourceSize();
996 if (size.has_value()) {
997 src_coverage = Rect::MakeXYWH(0, 0, size->width, size->height);
998 } else {
999 auto cvg = vertices->GetCoverage(Matrix{});
1000 FML_CHECK(cvg.has_value());
1001 src_coverage =
1002 // Covered by FML_CHECK.
1003 // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
1004 vertices->GetTextureCoordinateCoverge().value_or(cvg.value());
1005 }
1006 src_contents =
1007 src_paint.CreateContentsForGeometry(Geometry::MakeRect(src_coverage));
1008
1009 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1010 contents->SetBlendMode(blend_mode);
1011 contents->SetAlpha(paint.color.alpha);
1012 contents->SetGeometry(vertices);
1013 contents->SetLazyTexture([src_contents](const ContentContext& renderer) {
1014 return src_contents->RenderToSnapshot(renderer, {})->texture;
1015 });
1016 entity.SetContents(paint.WithFilters(std::move(contents)));
1017 AddRenderEntityToCurrentPass(std::move(entity));
1018}
#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:918
TRect< Scalar > Rect
Definition: rect.h:769
SK_API sk_sp< PrecompileColorFilter > Matrix()
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136

◆ EndRecordingAsPicture()

Picture impeller::Canvas::EndRecordingAsPicture ( )

Definition at line 804 of file canvas.cc.

804 {
805 // Assign clip depths to any outstanding clip entities.
806 while (current_pass_ != nullptr) {
807 current_pass_->PopAllClips(current_depth_);
808 current_pass_ = current_pass_->GetSuperpass();
809 }
810
812 picture.pass = std::move(base_pass_);
813
814 Reset();
816
817 return picture;
818}
std::optional< Rect > initial_cull_rect_
Definition: canvas.h:182
void Reset()
Definition: canvas.cc:177
EntityPass * GetSuperpass() const
Definition: entity_pass.cc:263
void PopAllClips(uint64_t depth)
Definition: entity_pass.cc:135
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 825 of file canvas.cc.

825 {
826 return transform_stack_.back().clip_height;
827}

◆ GetCurrentLocalCullingBounds()

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

Definition at line 302 of file canvas.cc.

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

◆ GetCurrentTransform()

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

Definition at line 298 of file canvas.cc.

298 {
299 return transform_stack_.back().transform;
300}

◆ GetSaveCount()

size_t impeller::Canvas::GetSaveCount ( ) const

Definition at line 331 of file canvas.cc.

331 {
332 return transform_stack_.size();
333}

◆ 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:62
size_t GetSaveCount() const
Definition: canvas.cc:331
#define FML_DCHECK(condition)
Definition: logging.h:103

◆ PreConcat()

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

Definition at line 286 of file canvas.cc.

286 {
287 transform_stack_.back().transform = transform * GetCurrentTransform();
288}

◆ 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 290 of file canvas.cc.

290 {
291 transform_stack_.back().transform = {};
292}

◆ 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 transform_stack_.back().rendering_mode ==
269 current_pass_->SetClipDepth(++current_depth_);
270 current_pass_ = GetCurrentPass().GetSuperpass();
271 FML_DCHECK(current_pass_);
272 }
273
274 transform_stack_.pop_back();
275 if (num_clips > 0) {
276 RestoreClip();
277 }
278
279 return true;
280}
void SetClipDepth(size_t clip_depth)
void PopClips(size_t num_clips, uint64_t depth)
Definition: entity_pass.cc:117

◆ RestoreToCount()

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

Definition at line 335 of file canvas.cc.

335 {
336 while (GetSaveCount() > count) {
337 if (!Restore()) {
338 return;
339 }
340 }
341}
int count
Definition: FontMgrTest.cpp:50
virtual bool Restore()
Definition: canvas.cc:257

◆ Rotate()

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

Definition at line 327 of file canvas.cc.

327 {
329}
void Concat(const Matrix &transform)
Definition: canvas.cc:282
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 entry.distributed_opacity = transform_stack_.back().distributed_opacity;
228 if (create_subpass) {
229 entry.rendering_mode =
231 auto subpass = std::make_unique<EntityPass>();
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}
void SetRequiredMipCount(int32_t mip_count)
Definition: entity_pass.h:177
int32_t GetRequiredMipCount() const
Definition: entity_pass.h:175
void SetClipHeight(size_t clip_height)
void SetTransform(Matrix transform)
EntityPass * AddSubpass(std::unique_ptr< EntityPass > pass)
Appends a given pass as a subpass.
Definition: entity_pass.cc:267
std::function< std::shared_ptr< FilterContents >(FilterInput::Ref, const Matrix &effect_transform, Entity::RenderingMode rendering_mode)> BackdropFilterProc
Definition: entity_pass.h:59
std::shared_ptr< FilterInput > Ref
Definition: filter_input.h:32
static float max(float r, float g, float b)
Definition: hsl.cpp:49

◆ 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,
bool  can_distribute_opacity = false 
)
virtual

Reimplemented in impeller::ExperimentalCanvas.

Definition at line 842 of file canvas.cc.

847 {
848 if (can_distribute_opacity && !backdrop_filter &&
850 Save(false, total_content_depth, paint.blend_mode, backdrop_filter);
851 transform_stack_.back().distributed_opacity *= paint.color.alpha;
852 return;
853 }
854 TRACE_EVENT0("flutter", "Canvas::saveLayer");
855
856 Save(true, total_content_depth, paint.blend_mode, backdrop_filter);
857
858 // The DisplayList bounds/rtree doesn't account for filters applied to parent
859 // layers, and so sub-DisplayLists are getting culled as if no filters are
860 // applied.
861 // See also: https://github.com/flutter/flutter/issues/139294
862 if (paint.image_filter) {
863 transform_stack_.back().cull_rect = std::nullopt;
864 }
865
866 auto& new_layer_pass = GetCurrentPass();
867 if (bounds) {
868 new_layer_pass.SetBoundsLimit(bounds, bounds_promise);
869 }
870
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());
875 }
876 // When applying a save layer, absorb any pending distributed opacity.
877 Paint paint_copy = paint;
878 paint_copy.color.alpha *= transform_stack_.back().distributed_opacity;
879 transform_stack_.back().distributed_opacity = 1.0;
880
881 new_layer_pass.SetDelegate(std::make_shared<PaintPassDelegate>(paint_copy));
882}
static bool CanApplyOpacityPeephole(const Paint &paint)
Whether or not a save layer with the provided paint can perform the opacity peephole optimization.
Definition: paint.h:36
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131

◆ Scale() [1/2]

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

Definition at line 315 of file canvas.cc.

315 {
317}
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 319 of file canvas.cc.

319 {
321}

◆ Skew()

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

Definition at line 323 of file canvas.cc.

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

◆ Transform()

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

Definition at line 294 of file canvas.cc.

294 {
296}

◆ Translate()

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

Definition at line 311 of file canvas.cc.

Member Data Documentation

◆ current_depth_

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

Definition at line 183 of file canvas.h.

◆ initial_cull_rect_

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

Definition at line 182 of file canvas.h.

◆ kMaxDepth

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

Definition at line 62 of file canvas.h.

◆ transform_stack_

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

Definition at line 181 of file canvas.h.


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