Flutter Impeller
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
 

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 }

References Initialize().

◆ Canvas() [2/3]

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

Definition at line 153 of file canvas.cc.

153  {
154  Initialize(cull_rect);
155 }

References Initialize().

◆ 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 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), Initialize(), and impeller::TRect< Scalar >::MakeLTRB().

◆ ~Canvas()

impeller::Canvas::~Canvas ( )
virtualdefault

Member Function Documentation

◆ 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 }

Referenced by impeller::DlDispatcherBase::clipPath(), impeller::DlDispatcherBase::clipRRect(), and impeller::testing::TEST_P().

◆ 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 }

References impeller::Path::GetBoundingBox().

Referenced by impeller::DlDispatcherBase::clipPath(), impeller::DlDispatcherBase::clipRRect(), impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ 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 }

Referenced by impeller::DlDispatcherBase::clipPath(), impeller::DlDispatcherBase::clipRect(), impeller::DlDispatcherBase::clipRRect(), impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ 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 }

References impeller::TRect< T >::Expand(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetWidth(), impeller::TSize< T >::height, impeller::TSize< T >::IsEmpty(), and impeller::TSize< T >::width.

Referenced by impeller::DlDispatcherBase::clipPath(), impeller::DlDispatcherBase::clipRRect(), impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ 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 }

References GetCurrentTransform(), transform, and transform_stack_.

Referenced by Rotate(), Scale(), Skew(), Transform(), and Translate().

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

1034  {
1035  if (!atlas) {
1036  return;
1037  }
1038 
1039  std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1040  contents->SetColors(std::move(colors));
1041  contents->SetTransforms(std::move(transforms));
1042  contents->SetTextureCoordinates(std::move(texture_coordinates));
1043  contents->SetTexture(atlas->GetTexture());
1044  contents->SetSamplerDescriptor(std::move(sampler));
1045  contents->SetBlendMode(blend_mode);
1046  contents->SetCullRect(cull_rect);
1047  contents->SetAlpha(paint.color.alpha);
1048 
1049  Entity entity;
1050  entity.SetTransform(GetCurrentTransform());
1051  entity.SetBlendMode(paint.blend_mode);
1052  entity.SetContents(paint.WithFilters(contents));
1053 
1054  AddRenderEntityToCurrentPass(std::move(entity));
1055 }

References paint, impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

Referenced by impeller::DlDispatcherBase::drawAtlas().

◆ 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 }

References paint, impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

Referenced by impeller::DlDispatcherBase::drawCircle(), impeller::testing::MaskBlurVariantTest(), and impeller::testing::TEST_P().

◆ 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 }

References offset, and paint.

Referenced by impeller::testing::TEST_P().

◆ 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 }

References impeller::TRect< T >::IsEmpty(), paint, impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

Referenced by impeller::DlDispatcherBase::drawImageRect(), impeller::NinePatchConverter::DrawNinePatch(), and impeller::testing::TEST_P().

◆ 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 }

References paint, impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

Referenced by impeller::DlDispatcherBase::drawLine(), impeller::DlDispatcherBase::drawPoints(), and impeller::testing::TEST_P().

◆ 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 }

References impeller::PathBuilder::AddOval(), impeller::TRect< T >::GetCenter(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::IsSquare(), paint, impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

Referenced by impeller::DlDispatcherBase::drawOval(), impeller::testing::MaskBlurVariantTest(), and impeller::testing::TEST_P().

◆ 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 }

References GetCurrentTransform(), paint, impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

Referenced by impeller::testing::BlendModeTest(), impeller::DlDispatcherBase::drawColor(), impeller::DlDispatcherBase::drawPaint(), impeller::testing::MaskBlurVariantTest(), and impeller::testing::TEST_P().

◆ 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 }

References GetCurrentTransform(), paint, impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

Referenced by impeller::DlDispatcherBase::drawArc(), impeller::DlDispatcherBase::drawDashedLine(), impeller::DlDispatcherBase::drawDRRect(), impeller::DlDispatcherBase::drawRRect(), impeller::testing::MaskBlurVariantTest(), and impeller::testing::TEST_P().

◆ 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 }

References paint, impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

Referenced by impeller::DlDispatcherBase::drawPoints(), and impeller::testing::TEST_P().

◆ 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 }

References impeller::PathBuilder::AddRect(), paint, impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

Referenced by impeller::DlDispatcherBase::drawRect(), impeller::testing::MaskBlurVariantTest(), impeller::testing::TEST_F(), and impeller::testing::TEST_P().

◆ 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();
563  DrawPath(path, paint);
564 }

References impeller::PathBuilder::AddRoundedRect(), paint, impeller::Entity::SetBlendMode(), impeller::PathBuilder::SetBounds(), impeller::Entity::SetContents(), impeller::PathBuilder::SetConvexity(), impeller::Entity::SetTransform(), and impeller::PathBuilder::TakePath().

Referenced by impeller::DlDispatcherBase::drawRRect(), impeller::testing::MaskBlurVariantTest(), and impeller::testing::TEST_P().

◆ 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 }

References paint, impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

Referenced by impeller::DlDispatcherBase::drawTextFrame(), and impeller::testing::TEST_P().

◆ 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 = src_paint.CreateContentsForGeometry(
1007  Geometry::MakeRect(Rect::Round(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->SetLazyTextureCoverage(src_coverage);
1014  contents->SetLazyTexture(
1015  [src_contents, src_coverage](const ContentContext& renderer) {
1016  // Applying the src coverage as the coverage limit prevents the 1px
1017  // coverage pad from adding a border that is picked up by developer
1018  // specified UVs.
1019  return src_contents
1020  ->RenderToSnapshot(renderer, {}, Rect::Round(src_coverage))
1021  ->texture;
1022  });
1023  entity.SetContents(paint.WithFilters(std::move(contents)));
1024  AddRenderEntityToCurrentPass(std::move(entity));
1025 }

References impeller::ImageData::effect_transform, paint, impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), impeller::ImageData::texture, impeller::UseColorSourceContents(), impeller::ImageData::x_tile_mode, and impeller::ImageData::y_tile_mode.

Referenced by impeller::DlDispatcherBase::drawVertices().

◆ 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 
811  Picture picture;
812  picture.pass = std::move(base_pass_);
813 
814  Reset();
816 
817  return picture;
818 }

References impeller::Picture::pass.

Referenced by impeller::DlDispatcherBase::EndRecordingAsPicture(), impeller::testing::MaskBlurVariantTest(), impeller::testing::TEST_F(), and impeller::testing::TEST_P().

◆ 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 }

Referenced by impeller::ExperimentalCanvas::DrawTextFrame(), impeller::ExperimentalCanvas::Restore(), and impeller::ExperimentalCanvas::SaveLayer().

◆ 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 }

References transform_stack_.

Referenced by impeller::DlDispatcherBase::drawDisplayList(), and impeller::testing::TEST().

◆ GetCurrentTransform()

◆ GetSaveCount()

size_t impeller::Canvas::GetSaveCount ( ) const

Definition at line 331 of file canvas.cc.

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

References transform_stack_.

Referenced by impeller::DlDispatcherBase::drawDisplayList(), Initialize(), RestoreToCount(), and impeller::testing::TEST_P().

◆ 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 }

References impeller::CanvasStackEntry::cull_rect, current_depth_, GetSaveCount(), initial_cull_rect_, kMaxDepth, and transform_stack_.

Referenced by Canvas(), and impeller::ExperimentalCanvas::EndReplay().

◆ 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 }

References GetCurrentTransform(), transform, and transform_stack_.

Referenced by impeller::DlDispatcherBase::drawShadow().

◆ 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 }

References current_depth_, and transform_stack_.

Referenced by impeller::ExperimentalCanvas::EndReplay().

◆ ResetTransform()

void impeller::Canvas::ResetTransform ( )

Definition at line 290 of file canvas.cc.

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

References transform_stack_.

Referenced by impeller::DlDispatcherBase::transformReset().

◆ 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 }

References current_depth_, impeller::EntityPass::GetSuperpass(), impeller::Entity::kSubpassAppendSnapshotTransform, impeller::Entity::kSubpassPrependSnapshotTransform, impeller::EntityPass::PopClips(), impeller::EntityPass::SetClipDepth(), and transform_stack_.

Referenced by impeller::DlDispatcherBase::drawShadow(), impeller::DlDispatcherBase::restore(), RestoreToCount(), impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ 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 }

References GetSaveCount(), and Restore().

Referenced by impeller::DlDispatcherBase::drawDisplayList().

◆ Rotate()

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

Definition at line 327 of file canvas.cc.

327  {
328  Concat(Matrix::MakeRotationZ(radians));
329 }

References Concat(), and impeller::Matrix::MakeRotationZ().

Referenced by impeller::DlDispatcherBase::rotate(), and impeller::testing::TEST_P().

◆ Save()

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

◆ 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 }

References impeller::Color::alpha, impeller::Paint::color, and paint.

Referenced by impeller::DlDispatcherBase::drawDisplayList(), impeller::DlDispatcherBase::saveLayer(), impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ Scale() [1/2]

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

◆ Scale() [2/2]

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

Definition at line 319 of file canvas.cc.

319  {
321 }

References Concat(), impeller::Matrix::MakeScale(), and scale.

◆ 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 }

References Concat(), and impeller::Matrix::MakeSkew().

Referenced by impeller::DlDispatcherBase::skew(), and impeller::testing::TEST_P().

◆ Transform()

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

◆ Translate()

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

Member Data Documentation

◆ current_depth_

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

◆ initial_cull_rect_

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

Definition at line 182 of file canvas.h.

Referenced by impeller::ExperimentalCanvas::EndReplay(), and Initialize().

◆ kMaxDepth

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

Definition at line 62 of file canvas.h.

Referenced by Initialize().

◆ transform_stack_


The documentation for this class was generated from the following files:
impeller::Matrix::MakeSkew
static constexpr Matrix MakeSkew(Scalar sx, Scalar sy)
Definition: matrix.h:117
impeller::Entity::ClipOperation::kIntersect
@ kIntersect
impeller::Geometry::MakePointField
static std::shared_ptr< Geometry > MakePointField(std::vector< Point > points, Scalar radius, bool round)
Definition: geometry.cc:66
impeller::Geometry::MakeStrokedCircle
static std::shared_ptr< Geometry > MakeStrokedCircle(const Point &center, Scalar radius, Scalar stroke_width)
Definition: geometry.cc:109
impeller::Entity::ClipOperation::kDifference
@ kDifference
impeller::EntityPass::PopAllClips
void PopAllClips(uint64_t depth)
Definition: entity_pass.cc:135
impeller::Canvas::DrawImageRect
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
impeller::Geometry::MakeRoundRect
static std::shared_ptr< Geometry > MakeRoundRect(const Rect &rect, const Size &radii)
Definition: geometry.cc:115
impeller::Paint::Style::kStroke
@ kStroke
impeller::TRect< Scalar >::MakeXYWH
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
impeller::BlendMode::kDestination
@ kDestination
impeller::Entity::RenderingMode::kSubpassAppendSnapshotTransform
@ kSubpassAppendSnapshotTransform
impeller::PointStyle::kRound
@ kRound
Points are drawn as squares.
impeller::TRect< Scalar >::Round
Round(const TRect< U > &r)
Definition: rect.h:674
impeller::Size
TSize< Scalar > Size
Definition: size.h:137
impeller::Matrix::MakeTranslation
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
impeller::Canvas::initial_cull_rect_
std::optional< Rect > initial_cull_rect_
Definition: canvas.h:182
offset
SeparatedVector2 offset
Definition: stroke_path_geometry.cc:311
impeller::Canvas::GetCurrentTransform
const Matrix & GetCurrentTransform() const
Definition: canvas.cc:298
impeller::EntityPass::SetClipDepth
void SetClipDepth(size_t clip_depth)
Definition: entity_pass.cc:1107
impeller::Geometry::MakeOval
static std::shared_ptr< Geometry > MakeOval(const Rect &rect)
Definition: geometry.cc:93
impeller::Canvas::Concat
void Concat(const Matrix &transform)
Definition: canvas.cc:282
impeller::UseColorSourceContents
static bool UseColorSourceContents(const std::shared_ptr< VerticesGeometry > &vertices, const Paint &paint)
Definition: canvas.cc:918
impeller::Canvas::Initialize
void Initialize(std::optional< Rect > cull_rect)
Definition: canvas.cc:164
impeller::SourceRectConstraint::kStrict
@ kStrict
Sample only within the source rectangle. May be slower.
impeller::Geometry::MakeFillPath
static std::shared_ptr< Geometry > MakeFillPath(const Path &path, std::optional< Rect > inner_rect=std::nullopt)
Definition: geometry.cc:60
impeller::EntityPass::GetSuperpass
EntityPass * GetSuperpass() const
Definition: entity_pass.cc:263
transform
Matrix transform
Definition: gaussian_blur_filter_contents.cc:231
impeller::Paint::Style::kFill
@ kFill
impeller::TRect< Scalar >::MakeOriginSize
constexpr static TRect MakeOriginSize(const TPoint< Type > &origin, const TSize< Type > &size)
Definition: rect.h:140
impeller::Canvas::DrawCircle
void DrawCircle(const Point &center, Scalar radius, const Paint &paint)
Definition: canvas.cc:566
impeller::Canvas::Restore
virtual bool Restore()
Definition: canvas.cc:257
impeller::Canvas::DrawPath
void DrawPath(const Path &path, const Paint &paint)
Definition: canvas.cc:343
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:769
impeller::Canvas::GetSaveCount
size_t GetSaveCount() const
Definition: canvas.cc:331
impeller::Canvas::current_depth_
uint64_t current_depth_
Definition: canvas.h:183
impeller::Geometry::MakeRect
static std::shared_ptr< Geometry > MakeRect(const Rect &rect)
Definition: geometry.cc:89
impeller::Matrix::MakeRotationZ
static Matrix MakeRotationZ(Radians r)
Definition: matrix.h:213
impeller::Entity::RenderingMode::kSubpassPrependSnapshotTransform
@ kSubpassPrependSnapshotTransform
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:146
impeller::EntityPass::PopClips
void PopClips(size_t num_clips, uint64_t depth)
Definition: entity_pass.cc:117
impeller::Canvas::Save
virtual void Save(uint32_t total_content_depth=kMaxDepth)
Definition: canvas.cc:184
scale
const Scalar scale
Definition: stroke_path_geometry.cc:308
paint
const Paint & paint
Definition: color_source.cc:38
impeller::Paint::CanApplyOpacityPeephole
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
impeller::TRect< Scalar >::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
impeller::Convexity::kConvex
@ kConvex
impeller::TextureContents::MakeRect
static std::shared_ptr< TextureContents > MakeRect(Rect destination)
A common case factory that marks the texture contents as having a destination rectangle....
Definition: texture_contents.cc:27
impeller::Matrix::MakeScale
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104
impeller::Canvas::transform_stack_
std::deque< CanvasStackEntry > transform_stack_
Definition: canvas.h:181
impeller::ColorSource::Type::kColor
@ kColor
impeller::Canvas::Reset
void Reset()
Definition: canvas.cc:177
impeller::Geometry::MakeLine
static std::shared_ptr< Geometry > MakeLine(const Point &p0, const Point &p1, Scalar width, Cap cap)
Definition: geometry.cc:97
impeller::Canvas::kMaxDepth
static constexpr uint32_t kMaxDepth
Definition: canvas.h:62