Flutter Impeller
impeller::Canvas Class Reference

#include <canvas.h>

Classes

struct  DebugOptions
 

Public Member Functions

 Canvas ()
 
 Canvas (Rect cull_rect)
 
 Canvas (IRect cull_rect)
 
 ~Canvas ()
 
void Save ()
 
void SaveLayer (const Paint &paint, std::optional< Rect > bounds=std::nullopt, const std::shared_ptr< ImageFilter > &backdrop_filter=nullptr)
 
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 (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={})
 
void ClipPath (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)
 
void DrawPicture (const Picture &picture)
 
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
 

Detailed Description

Definition at line 48 of file canvas.h.

Constructor & Destructor Documentation

◆ Canvas() [1/3]

impeller::Canvas::Canvas ( )

Definition at line 102 of file canvas.cc.

102  {
103  Initialize(std::nullopt);
104 }

◆ Canvas() [2/3]

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

Definition at line 106 of file canvas.cc.

106  {
107  Initialize(cull_rect);
108 }

◆ Canvas() [3/3]

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

Definition at line 110 of file canvas.cc.

110  {
111  Initialize(Rect::MakeLTRB(cull_rect.GetLeft(), cull_rect.GetTop(),
112  cull_rect.GetRight(), cull_rect.GetBottom()));
113 }

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

◆ ~Canvas()

impeller::Canvas::~Canvas ( )
default

Member Function Documentation

◆ ClipOval()

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

Definition at line 450 of file canvas.cc.

450  {
451  auto geometry = Geometry::MakeOval(bounds);
452  auto& cull_rect = transform_stack_.back().cull_rect;
453  if (clip_op == Entity::ClipOperation::kIntersect && //
454  cull_rect.has_value() && //
455  geometry->CoversArea(transform_stack_.back().transform, *cull_rect) //
456  ) {
457  return; // This clip will do nothing, so skip it.
458  }
459 
460  ClipGeometry(geometry, clip_op);
461  switch (clip_op) {
463  IntersectCulling(bounds);
464  break;
466  break;
467  }
468 }

References impeller::Entity::kDifference, impeller::Entity::kIntersect, and impeller::Geometry::MakeOval().

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

◆ ClipPath()

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

Definition at line 419 of file canvas.cc.

419  {
420  auto bounds = path.GetBoundingBox();
421  ClipGeometry(Geometry::MakeFillPath(std::move(path)), clip_op);
422  if (clip_op == Entity::ClipOperation::kIntersect) {
423  if (bounds.has_value()) {
424  IntersectCulling(bounds.value());
425  }
426  }
427 }

References impeller::Path::GetBoundingBox(), impeller::Entity::kIntersect, and impeller::Geometry::MakeFillPath().

Referenced by impeller::DlDispatcher::clipPath(), impeller::DlDispatcher::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 429 of file canvas.cc.

429  {
430  auto geometry = Geometry::MakeRect(rect);
431  auto& cull_rect = transform_stack_.back().cull_rect;
432  if (clip_op == Entity::ClipOperation::kIntersect && //
433  cull_rect.has_value() && //
434  geometry->CoversArea(transform_stack_.back().transform, *cull_rect) //
435  ) {
436  return; // This clip will do nothing, so skip it.
437  }
438 
439  ClipGeometry(geometry, clip_op);
440  switch (clip_op) {
442  IntersectCulling(rect);
443  break;
445  SubtractCulling(rect);
446  break;
447  }
448 }

References impeller::Entity::kDifference, impeller::Entity::kIntersect, and impeller::Geometry::MakeRect().

Referenced by impeller::DlDispatcher::clipPath(), impeller::DlDispatcher::clipRect(), impeller::DlDispatcher::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 470 of file canvas.cc.

472  {
473  // Does the rounded rect have a flat part on the top/bottom or left/right?
474  bool flat_on_TB = corner_radii.width * 2 < rect.GetWidth();
475  bool flat_on_LR = corner_radii.height * 2 < rect.GetHeight();
476  auto geometry = Geometry::MakeRoundRect(rect, corner_radii);
477  auto& cull_rect = transform_stack_.back().cull_rect;
478  if (clip_op == Entity::ClipOperation::kIntersect && //
479  cull_rect.has_value() && //
480  geometry->CoversArea(transform_stack_.back().transform, *cull_rect) //
481  ) {
482  return; // This clip will do nothing, so skip it.
483  }
484 
485  ClipGeometry(geometry, clip_op);
486  switch (clip_op) {
488  IntersectCulling(rect);
489  break;
491  if (corner_radii.IsEmpty()) {
492  SubtractCulling(rect);
493  } else {
494  // We subtract the inner "tall" and "wide" rectangle pieces
495  // that fit inside the corners which cover the greatest area
496  // without involving the curved corners
497  // Since this is a subtract operation, we can subtract each
498  // rectangle piece individually without fear of interference.
499  if (flat_on_TB) {
500  SubtractCulling(rect.Expand(Size{-corner_radii.width, 0.0}));
501  }
502  if (flat_on_LR) {
503  SubtractCulling(rect.Expand(Size{0.0, -corner_radii.height}));
504  }
505  }
506  break;
507  }
508 }

References impeller::TRect< T >::Expand(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetWidth(), impeller::TSize< T >::height, impeller::TSize< T >::IsEmpty(), impeller::Entity::kDifference, impeller::Entity::kIntersect, impeller::Geometry::MakeRoundRect(), and impeller::TSize< T >::width.

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

◆ Concat()

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

Definition at line 189 of file canvas.cc.

189  {
190  transform_stack_.back().transform = GetCurrentTransform() * transform;
191 }

References GetCurrentTransform().

Referenced by Rotate(), Scale(), Skew(), impeller::testing::TEST_P(), 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 806 of file canvas.cc.

813  {
814  if (!atlas) {
815  return;
816  }
817 
818  std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
819  contents->SetColors(std::move(colors));
820  contents->SetTransforms(std::move(transforms));
821  contents->SetTextureCoordinates(std::move(texture_coordinates));
822  contents->SetTexture(atlas->GetTexture());
823  contents->SetSamplerDescriptor(std::move(sampler));
824  contents->SetBlendMode(blend_mode);
825  contents->SetCullRect(cull_rect);
826  contents->SetAlpha(paint.color.alpha);
827 
828  Entity entity;
829  entity.SetTransform(GetCurrentTransform());
830  entity.SetClipDepth(GetClipDepth());
831  entity.SetBlendMode(paint.blend_mode);
832  entity.SetContents(paint.WithFilters(contents));
833 
834  GetCurrentPass().AddEntity(std::move(entity));
835 }

References impeller::EntityPass::AddEntity(), impeller::Color::alpha, impeller::Paint::blend_mode, impeller::Paint::color, GetCurrentTransform(), impeller::Entity::SetBlendMode(), impeller::Entity::SetClipDepth(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::Paint::WithFilters().

Referenced by impeller::DlDispatcher::drawAtlas(), and impeller::testing::TEST_P().

◆ DrawCircle()

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

Definition at line 395 of file canvas.cc.

397  {
398  Size half_size(radius, radius);
399  if (AttemptDrawBlurredRRect(
400  Rect::MakeOriginSize(center - half_size, half_size * 2),
401  {radius, radius}, paint)) {
402  return;
403  }
404 
405  Entity entity;
406  entity.SetTransform(GetCurrentTransform());
407  entity.SetClipDepth(GetClipDepth());
408  entity.SetBlendMode(paint.blend_mode);
409  auto geometry =
410  paint.style == Paint::Style::kStroke
411  ? Geometry::MakeStrokedCircle(center, radius, paint.stroke_width)
412  : Geometry::MakeCircle(center, radius);
413  entity.SetContents(
414  CreateContentsForGeometryWithFilters(paint, std::move(geometry)));
415 
416  GetCurrentPass().AddEntity(std::move(entity));
417 }

References impeller::EntityPass::AddEntity(), impeller::Paint::blend_mode, GetCurrentTransform(), impeller::Paint::kStroke, impeller::Geometry::MakeCircle(), impeller::TRect< Scalar >::MakeOriginSize(), impeller::Geometry::MakeStrokedCircle(), impeller::Entity::SetBlendMode(), impeller::Entity::SetClipDepth(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), impeller::Paint::stroke_width, and impeller::Paint::style.

Referenced by impeller::DlDispatcher::drawCircle(), DrawOval(), 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 612 of file canvas.cc.

615  {
616  if (!image) {
617  return;
618  }
619 
620  const auto source = Rect::MakeSize(image->GetSize());
621  const auto dest = source.Shift(offset);
622 
623  DrawImageRect(image, source, dest, paint, std::move(sampler));
624 }

References DrawImageRect(), and impeller::TRect< Scalar >::MakeSize().

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 = {} 
)

Definition at line 626 of file canvas.cc.

630  {
631  if (!image || source.IsEmpty() || dest.IsEmpty()) {
632  return;
633  }
634 
635  auto size = image->GetSize();
636 
637  if (size.IsEmpty()) {
638  return;
639  }
640 
641  auto contents = TextureContents::MakeRect(dest);
642  contents->SetTexture(image->GetTexture());
643  contents->SetSourceRect(source);
644  contents->SetSamplerDescriptor(std::move(sampler));
645  contents->SetOpacity(paint.color.alpha);
646  contents->SetDeferApplyingOpacity(paint.HasColorFilter());
647 
648  Entity entity;
649  entity.SetBlendMode(paint.blend_mode);
650  entity.SetClipDepth(GetClipDepth());
651  entity.SetContents(paint.WithFilters(contents));
652  entity.SetTransform(GetCurrentTransform());
653 
654  GetCurrentPass().AddEntity(std::move(entity));
655 }

References impeller::EntityPass::AddEntity(), impeller::Color::alpha, impeller::Paint::blend_mode, impeller::Paint::color, GetCurrentTransform(), impeller::Paint::HasColorFilter(), impeller::TRect< T >::IsEmpty(), impeller::TextureContents::MakeRect(), impeller::Entity::SetBlendMode(), impeller::Entity::SetClipDepth(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::Paint::WithFilters().

Referenced by DrawImage(), impeller::DlDispatcher::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 310 of file canvas.cc.

310  {
311  Entity entity;
312  entity.SetTransform(GetCurrentTransform());
313  entity.SetClipDepth(GetClipDepth());
314  entity.SetBlendMode(paint.blend_mode);
315  entity.SetContents(CreateContentsForGeometryWithFilters(
316  paint, Geometry::MakeLine(p0, p1, paint.stroke_width, paint.stroke_cap)));
317 
318  GetCurrentPass().AddEntity(std::move(entity));
319 }

References impeller::EntityPass::AddEntity(), impeller::Paint::blend_mode, GetCurrentTransform(), impeller::Geometry::MakeLine(), impeller::Entity::SetBlendMode(), impeller::Entity::SetClipDepth(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), impeller::Paint::stroke_cap, and impeller::Paint::stroke_width.

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

◆ DrawOval()

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

Definition at line 341 of file canvas.cc.

341  {
342  if (rect.IsSquare()) {
343  // Circles have slightly less overhead and can do stroking
344  DrawCircle(rect.GetCenter(), rect.GetWidth() * 0.5f, paint);
345  return;
346  }
347 
348  if (paint.style == Paint::Style::kStroke) {
349  // No stroked ellipses yet
350  DrawPath(PathBuilder{}.AddOval(rect).TakePath(), paint);
351  return;
352  }
353 
354  if (AttemptDrawBlurredRRect(rect, rect.GetSize() * 0.5f, paint)) {
355  return;
356  }
357 
358  Entity entity;
359  entity.SetTransform(GetCurrentTransform());
360  entity.SetClipDepth(GetClipDepth());
361  entity.SetBlendMode(paint.blend_mode);
362  entity.SetContents(
363  CreateContentsForGeometryWithFilters(paint, Geometry::MakeOval(rect)));
364 
365  GetCurrentPass().AddEntity(std::move(entity));
366 }

References impeller::EntityPass::AddEntity(), impeller::PathBuilder::AddOval(), impeller::Paint::blend_mode, DrawCircle(), DrawPath(), impeller::TRect< T >::GetCenter(), GetCurrentTransform(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::IsSquare(), impeller::Paint::kStroke, impeller::Geometry::MakeOval(), impeller::Entity::SetBlendMode(), impeller::Entity::SetClipDepth(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::Paint::style.

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

◆ DrawPaint()

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

Definition at line 260 of file canvas.cc.

260  {
261  Entity entity;
262  entity.SetTransform(GetCurrentTransform());
263  entity.SetClipDepth(GetClipDepth());
264  entity.SetBlendMode(paint.blend_mode);
265  entity.SetContents(CreateCoverContentsWithFilters(paint));
266 
267  GetCurrentPass().AddEntity(std::move(entity));
268 }

References impeller::EntityPass::AddEntity(), impeller::Paint::blend_mode, GetCurrentTransform(), impeller::Entity::SetBlendMode(), impeller::Entity::SetClipDepth(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

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

◆ DrawPath()

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

Definition at line 250 of file canvas.cc.

250  {
251  Entity entity;
252  entity.SetTransform(GetCurrentTransform());
253  entity.SetClipDepth(GetClipDepth());
254  entity.SetBlendMode(paint.blend_mode);
255  entity.SetContents(CreatePathContentsWithFilters(paint, std::move(path)));
256 
257  GetCurrentPass().AddEntity(std::move(entity));
258 }

References impeller::EntityPass::AddEntity(), impeller::Paint::blend_mode, GetCurrentTransform(), impeller::Entity::SetBlendMode(), impeller::Entity::SetClipDepth(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

Referenced by impeller::DlDispatcher::drawArc(), impeller::DlDispatcher::drawDRRect(), DrawOval(), DrawRect(), DrawRRect(), impeller::DlDispatcher::drawRRect(), and impeller::testing::TEST_P().

◆ DrawPicture()

void impeller::Canvas::DrawPicture ( const Picture picture)

Definition at line 583 of file canvas.cc.

583  {
584  if (!picture.pass) {
585  return;
586  }
587 
588  // Clone the base pass and account for the CTM updates.
589  auto pass = picture.pass->Clone();
590 
591  pass->IterateAllElements([&](auto& element) -> bool {
592  if (auto entity = std::get_if<Entity>(&element)) {
593  entity->IncrementStencilDepth(GetClipDepth());
594  entity->SetTransform(GetCurrentTransform() * entity->GetTransform());
595  return true;
596  }
597 
598  if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
599  subpass->get()->SetClipDepth(subpass->get()->GetClipDepth() +
600  GetClipDepth());
601  return true;
602  }
603 
604  FML_UNREACHABLE();
605  });
606 
607  GetCurrentPass().AddSubpassInline(std::move(pass));
608 
609  RestoreClip();
610 }

References impeller::EntityPass::AddSubpassInline(), GetCurrentTransform(), and impeller::Picture::pass.

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

◆ DrawPoints()

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

Definition at line 563 of file canvas.cc.

566  {
567  if (radius <= 0) {
568  return;
569  }
570 
571  Entity entity;
572  entity.SetTransform(GetCurrentTransform());
573  entity.SetClipDepth(GetClipDepth());
574  entity.SetBlendMode(paint.blend_mode);
575  entity.SetContents(CreateContentsForGeometryWithFilters(
576  paint,
577  Geometry::MakePointField(std::move(points), radius,
578  /*round=*/point_style == PointStyle::kRound)));
579 
580  GetCurrentPass().AddEntity(std::move(entity));
581 }

References impeller::EntityPass::AddEntity(), impeller::Paint::blend_mode, GetCurrentTransform(), impeller::kRound, impeller::Geometry::MakePointField(), impeller::Entity::SetBlendMode(), impeller::Entity::SetClipDepth(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

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

◆ DrawRect()

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

Definition at line 321 of file canvas.cc.

321  {
322  if (paint.style == Paint::Style::kStroke) {
323  DrawPath(PathBuilder{}.AddRect(rect).TakePath(), paint);
324  return;
325  }
326 
327  if (AttemptDrawBlurredRRect(rect, {}, paint)) {
328  return;
329  }
330 
331  Entity entity;
332  entity.SetTransform(GetCurrentTransform());
333  entity.SetClipDepth(GetClipDepth());
334  entity.SetBlendMode(paint.blend_mode);
335  entity.SetContents(
336  CreateContentsForGeometryWithFilters(paint, Geometry::MakeRect(rect)));
337 
338  GetCurrentPass().AddEntity(std::move(entity));
339 }

References impeller::EntityPass::AddEntity(), impeller::PathBuilder::AddRect(), impeller::Paint::blend_mode, DrawPath(), GetCurrentTransform(), impeller::Paint::kStroke, impeller::Geometry::MakeRect(), impeller::Entity::SetBlendMode(), impeller::Entity::SetClipDepth(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::Paint::style.

Referenced by impeller::testing::CanRenderConicalGradientWithDithering(), impeller::testing::CanRenderLinearGradientWithDithering(), impeller::testing::CanRenderRadialGradientWithDithering(), impeller::testing::CanRenderSweepGradientWithDithering(), impeller::DlDispatcher::drawRect(), 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 368 of file canvas.cc.

370  {
371  if (AttemptDrawBlurredRRect(rect, corner_radii, paint)) {
372  return;
373  }
374 
375  if (paint.style == Paint::Style::kFill) {
376  Entity entity;
377  entity.SetTransform(GetCurrentTransform());
378  entity.SetClipDepth(GetClipDepth());
379  entity.SetBlendMode(paint.blend_mode);
380  entity.SetContents(CreateContentsForGeometryWithFilters(
381  paint, Geometry::MakeRoundRect(rect, corner_radii)));
382 
383  GetCurrentPass().AddEntity(std::move(entity));
384  return;
385  }
386 
387  auto path = PathBuilder{}
388  .SetConvexity(Convexity::kConvex)
389  .AddRoundedRect(rect, corner_radii)
390  .SetBounds(rect)
391  .TakePath();
392  DrawPath(std::move(path), paint);
393 }

References impeller::EntityPass::AddEntity(), impeller::PathBuilder::AddRoundedRect(), impeller::Paint::blend_mode, DrawPath(), GetCurrentTransform(), impeller::kConvex, impeller::Paint::kFill, impeller::Geometry::MakeRoundRect(), impeller::Entity::SetBlendMode(), impeller::PathBuilder::SetBounds(), impeller::Entity::SetClipDepth(), impeller::Entity::SetContents(), impeller::PathBuilder::SetConvexity(), impeller::Entity::SetTransform(), impeller::Paint::style, and impeller::PathBuilder::TakePath().

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

◆ DrawTextFrame()

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

Definition at line 702 of file canvas.cc.

704  {
705  Entity entity;
706  entity.SetClipDepth(GetClipDepth());
707  entity.SetBlendMode(paint.blend_mode);
708 
709  auto text_contents = std::make_shared<TextContents>();
710  text_contents->SetTextFrame(text_frame);
711  text_contents->SetColor(paint.color);
712  text_contents->SetForceTextColor(paint.mask_blur_descriptor.has_value());
713 
714  entity.SetTransform(GetCurrentTransform() *
715  Matrix::MakeTranslation(position));
716 
717  // TODO(bdero): This mask blur application is a hack. It will always wind up
718  // doing a gaussian blur that affects the color source itself
719  // instead of just the mask. The color filter text support
720  // needs to be reworked in order to interact correctly with
721  // mask filters.
722  // https://github.com/flutter/flutter/issues/133297
723  entity.SetContents(
724  paint.WithFilters(paint.WithMaskBlur(std::move(text_contents), true)));
725 
726  GetCurrentPass().AddEntity(std::move(entity));
727 }

References impeller::EntityPass::AddEntity(), impeller::Paint::blend_mode, impeller::Paint::color, GetCurrentTransform(), impeller::Matrix::MakeTranslation(), impeller::Paint::mask_blur_descriptor, impeller::Entity::SetBlendMode(), impeller::Entity::SetClipDepth(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), impeller::Paint::WithFilters(), and impeller::Paint::WithMaskBlur().

Referenced by impeller::DlDispatcher::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 746 of file canvas.cc.

748  {
749  // Override the blend mode with kDestination in order to match the behavior
750  // of Skia's SK_LEGACY_IGNORE_DRAW_VERTICES_BLEND_WITH_NO_SHADER flag, which
751  // is enabled when the Flutter engine builds Skia.
752  if (paint.color_source.GetType() == ColorSource::Type::kColor) {
753  blend_mode = BlendMode::kDestination;
754  }
755 
756  Entity entity;
757  entity.SetTransform(GetCurrentTransform());
758  entity.SetClipDepth(GetClipDepth());
759  entity.SetBlendMode(paint.blend_mode);
760 
761  // If there are no vertex color or texture coordinates. Or if there
762  // are vertex coordinates then only if the contents are an image.
763  if (UseColorSourceContents(vertices, paint)) {
764  entity.SetContents(CreateContentsForGeometryWithFilters(paint, vertices));
765  GetCurrentPass().AddEntity(std::move(entity));
766  return;
767  }
768 
769  auto src_paint = paint;
770  src_paint.color = paint.color.WithAlpha(1.0);
771 
772  std::shared_ptr<Contents> src_contents =
773  src_paint.CreateContentsForGeometry(vertices);
774  if (vertices->HasTextureCoordinates()) {
775  // If the color source has an intrinsic size, then we use that to
776  // create the src contents as a simplification. Otherwise we use
777  // the extent of the texture coordinates to determine how large
778  // the src contents should be. If neither has a value we fall back
779  // to using the geometry coverage data.
780  Rect src_coverage;
781  auto size = src_contents->GetColorSourceSize();
782  if (size.has_value()) {
783  src_coverage = Rect::MakeXYWH(0, 0, size->width, size->height);
784  } else {
785  auto cvg = vertices->GetCoverage(Matrix{});
786  FML_CHECK(cvg.has_value());
787  src_coverage =
788  // Covered by FML_CHECK.
789  // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
790  vertices->GetTextureCoordinateCoverge().value_or(cvg.value());
791  }
792  src_contents =
793  src_paint.CreateContentsForGeometry(Geometry::MakeRect(src_coverage));
794  }
795 
796  auto contents = std::make_shared<VerticesContents>();
797  contents->SetAlpha(paint.color.alpha);
798  contents->SetBlendMode(blend_mode);
799  contents->SetGeometry(vertices);
800  contents->SetSourceContents(std::move(src_contents));
801  entity.SetContents(paint.WithFilters(std::move(contents)));
802 
803  GetCurrentPass().AddEntity(std::move(entity));
804 }

References impeller::EntityPass::AddEntity(), impeller::Color::alpha, impeller::Paint::blend_mode, impeller::Paint::color, impeller::Paint::color_source, GetCurrentTransform(), impeller::ColorSource::GetType(), impeller::ColorSource::kColor, impeller::kDestination, impeller::Geometry::MakeRect(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Entity::SetBlendMode(), impeller::Entity::SetClipDepth(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), impeller::UseColorSourceContents(), impeller::Color::WithAlpha(), and impeller::Paint::WithFilters().

Referenced by impeller::DlDispatcher::drawVertices(), and impeller::testing::TEST_P().

◆ EndRecordingAsPicture()

Picture impeller::Canvas::EndRecordingAsPicture ( )

Definition at line 657 of file canvas.cc.

657  {
658  Picture picture;
659  picture.pass = std::move(base_pass_);
660 
661  Reset();
662  Initialize(initial_cull_rect_);
663 
664  return picture;
665 }

References impeller::Picture::pass.

Referenced by impeller::testing::CanRenderConicalGradientWithDithering(), impeller::testing::CanRenderLinearGradientWithDithering(), impeller::testing::CanRenderRadialGradientWithDithering(), impeller::testing::CanRenderSweepGradientWithDithering(), impeller::DlDispatcher::EndRecordingAsPicture(), impeller::testing::TEST_F(), and impeller::testing::TEST_P().

◆ GetCurrentLocalCullingBounds()

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

Definition at line 209 of file canvas.cc.

209  {
210  auto cull_rect = transform_stack_.back().cull_rect;
211  if (cull_rect.has_value()) {
212  Matrix inverse = transform_stack_.back().transform.Invert();
213  cull_rect = cull_rect.value().TransformBounds(inverse);
214  }
215  return cull_rect;
216 }

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

◆ GetCurrentTransform()

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

◆ GetSaveCount()

size_t impeller::Canvas::GetSaveCount ( ) const

Definition at line 238 of file canvas.cc.

238  {
239  return transform_stack_.size();
240 }

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

◆ PreConcat()

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

Definition at line 193 of file canvas.cc.

193  {
194  transform_stack_.back().transform = transform * GetCurrentTransform();
195 }

References GetCurrentTransform().

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

◆ ResetTransform()

void impeller::Canvas::ResetTransform ( )

Definition at line 197 of file canvas.cc.

197  {
198  transform_stack_.back().transform = {};
199 }

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

◆ Restore()

bool impeller::Canvas::Restore ( )

Definition at line 168 of file canvas.cc.

168  {
169  FML_DCHECK(transform_stack_.size() > 0);
170  if (transform_stack_.size() == 1) {
171  return false;
172  }
173  if (transform_stack_.back().rendering_mode ==
175  current_pass_ = GetCurrentPass().GetSuperpass();
176  FML_DCHECK(current_pass_);
177  }
178 
179  bool contains_clips = transform_stack_.back().contains_clips;
180  transform_stack_.pop_back();
181 
182  if (contains_clips) {
183  RestoreClip();
184  }
185 
186  return true;
187 }

References impeller::EntityPass::GetSuperpass(), and impeller::Entity::kSubpass.

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

◆ RestoreToCount()

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

Definition at line 242 of file canvas.cc.

242  {
243  while (GetSaveCount() > count) {
244  if (!Restore()) {
245  return;
246  }
247  }
248 }

References GetSaveCount(), and Restore().

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

◆ Rotate()

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

Definition at line 234 of file canvas.cc.

234  {
235  Concat(Matrix::MakeRotationZ(radians));
236 }

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

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

◆ Save()

◆ SaveLayer()

void impeller::Canvas::SaveLayer ( const Paint paint,
std::optional< Rect bounds = std::nullopt,
const std::shared_ptr< ImageFilter > &  backdrop_filter = nullptr 
)

Definition at line 676 of file canvas.cc.

678  {
679  TRACE_EVENT0("flutter", "Canvas::saveLayer");
680  Save(true, paint.blend_mode, backdrop_filter);
681 
682  // The DisplayList bounds/rtree doesn't account for filters applied to parent
683  // layers, and so sub-DisplayLists are getting culled as if no filters are
684  // applied.
685  // See also: https://github.com/flutter/flutter/issues/139294
686  if (paint.image_filter) {
687  transform_stack_.back().cull_rect = std::nullopt;
688  }
689 
690  auto& new_layer_pass = GetCurrentPass();
691  new_layer_pass.SetBoundsLimit(bounds);
692 
693  // Only apply opacity peephole on default blending.
694  if (paint.blend_mode == BlendMode::kSourceOver) {
695  new_layer_pass.SetDelegate(
696  std::make_shared<OpacityPeepholePassDelegate>(paint));
697  } else {
698  new_layer_pass.SetDelegate(std::make_shared<PaintPassDelegate>(paint));
699  }
700 }

References impeller::Paint::blend_mode, impeller::Paint::image_filter, impeller::kSourceOver, and Save().

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

◆ Scale() [1/2]

◆ Scale() [2/2]

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

Definition at line 226 of file canvas.cc.

226  {
227  Concat(Matrix::MakeScale(scale));
228 }

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

◆ Skew()

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

Definition at line 230 of file canvas.cc.

230  {
231  Concat(Matrix::MakeSkew(sx, sy));
232 }

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

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

◆ Transform()

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

Definition at line 201 of file canvas.cc.

201  {
202  Concat(transform);
203 }

References Concat().

Referenced by impeller::testing::TEST_P(), impeller::DlDispatcher::transformFullPerspective(), and impeller::DlDispatcher::transformReset().

◆ Translate()

Member Data Documentation

◆ debug_options

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

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::EntityPass::AddSubpassInline
void AddSubpassInline(std::unique_ptr< EntityPass > pass)
Merges a given pass into this pass. Useful for drawing pre-recorded pictures that don't require rende...
Definition: entity_pass.cc:224
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:156
impeller::Geometry::MakeStrokedCircle
static std::shared_ptr< Geometry > MakeStrokedCircle(const Point &center, Scalar radius, Scalar stroke_width)
Definition: geometry.cc:199
impeller::Entity::ClipOperation::kDifference
@ kDifference
impeller::Canvas::DrawPath
void DrawPath(Path path, const Paint &paint)
Definition: canvas.cc:250
impeller::Geometry::MakeRoundRect
static std::shared_ptr< Geometry > MakeRoundRect(const Rect &rect, const Size &radii)
Definition: geometry.cc:205
impeller::Paint::Style::kStroke
@ kStroke
impeller::TRect< Scalar >::MakeXYWH
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:34
impeller::BlendMode::kDestination
@ kDestination
impeller::PointStyle::kRound
@ kRound
Points are drawn as squares.
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::GetCurrentTransform
const Matrix & GetCurrentTransform() const
Definition: canvas.cc:205
impeller::Geometry::MakeOval
static std::shared_ptr< Geometry > MakeOval(const Rect &rect)
Definition: geometry.cc:183
impeller::Canvas::Concat
void Concat(const Matrix &transform)
Definition: canvas.cc:189
impeller::UseColorSourceContents
static bool UseColorSourceContents(const std::shared_ptr< VerticesGeometry > &vertices, const Paint &paint)
Definition: canvas.cc:729
impeller::Canvas::DrawImageRect
void DrawImageRect(const std::shared_ptr< Image > &image, Rect source, Rect dest, const Paint &paint, SamplerDescriptor sampler={})
Definition: canvas.cc:626
impeller::EntityPass::GetSuperpass
EntityPass * GetSuperpass() const
Definition: entity_pass.cc:201
impeller::Canvas::Save
void Save()
Definition: canvas.cc:132
impeller::Paint::Style::kFill
@ kFill
impeller::TRect< Scalar >::MakeOriginSize
constexpr static TRect MakeOriginSize(const TPoint< Type > &origin, const TSize< Type > &size)
Definition: rect.h:38
impeller::Canvas::DrawCircle
void DrawCircle(const Point &center, Scalar radius, const Paint &paint)
Definition: canvas.cc:395
impeller::Canvas::Restore
bool Restore()
Definition: canvas.cc:168
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:488
impeller::Canvas::GetSaveCount
size_t GetSaveCount() const
Definition: canvas.cc:238
impeller::Entity::RenderingMode::kSubpass
@ kSubpass
impeller::Geometry::MakeFillPath
static std::shared_ptr< Geometry > MakeFillPath(Path path, std::optional< Rect > inner_rect=std::nullopt)
Definition: geometry.cc:150
impeller::Geometry::MakeRect
static std::shared_ptr< Geometry > MakeRect(const Rect &rect)
Definition: geometry.cc:179
impeller::Matrix::MakeRotationZ
static Matrix MakeRotationZ(Radians r)
Definition: matrix.h:209
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:44
impeller::TRect< Scalar >::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:27
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::ColorSource::Type::kColor
@ kColor
impeller::BlendMode::kSourceOver
@ kSourceOver
impeller::EntityPass::AddEntity
void AddEntity(Entity entity)
Add an entity to the current entity pass.
Definition: entity_pass.cc:70
impeller::Geometry::MakeLine
static std::shared_ptr< Geometry > MakeLine(const Point &p0, const Point &p1, Scalar width, Cap cap)
Definition: geometry.cc:187