| Flutter Impeller |

Public Member Functions | Static Public Attributes | Protected Member Functions | Protected Attributes | List of all members
impeller::Canvas Class Reference

`#include <canvas.h>`

Inheritance diagram for impeller::Canvas:

## 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 Matrix & | GetCurrentTransform () const
const std::optional< Rect > | GetCurrentLocalCullingBounds () 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< CanvasStackEntry > | transform_stack_
std::optional< Rect > | initial_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 | ( |  | ) |
| virtual default

## 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) {
632 case Entity::ClipOperation::kIntersect:
633 IntersectCulling(bounds);
634 break;
635 case Entity::ClipOperation::kDifference:
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) {
611 case Entity::ClipOperation::kIntersect:
612 IntersectCulling(rect);
613 break;
614 case Entity::ClipOperation::kDifference:
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) {
657 case Entity::ClipOperation::kIntersect:
658 IntersectCulling(rect);
659 break;
660 case Entity::ClipOperation::kDifference:
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 =
580 paint.style == Paint::Style::kStroke
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 ==
786 SourceRectConstraint::kStrict);
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 Rect translated_coverage = Rect::MakeSize(src_coverage.GetSize());
1007 src_contents = src_paint.CreateContentsForGeometry(
1008 Geometry::MakeRect(translated_coverage));
1009
1010 auto contents = std::make_shared<VerticesSimpleBlendContents>();
1011 contents->SetBlendMode(blend_mode);
1012 contents->SetAlpha(paint.color.alpha);
1013 contents->SetGeometry(vertices);
1014 contents->SetLazyTextureCoverage(src_coverage);
1015 contents->SetLazyTexture(
1016 [src_contents, translated_coverage](const ContentContext& renderer) {
1017 // Applying the src coverage as the coverage limit prevents the 1px
1018 // coverage pad from adding a border that is picked up by developer
1019 // specified UVs.
1020 return src_contents->RenderToSnapshot(renderer, {}, translated_coverage)
1021 ->texture;
1022 });
1023 entity.SetContents(paint.WithFilters(std::move(contents)));
1024 AddRenderEntityToCurrentPass(std::move(entity));
1025 }

References impeller::ImageData::effect_transform, impeller::TRect< T >::GetSize(), 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();
815 Initialize(initial_cull_rect_);
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()

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

Definition at line 298 of file canvas.cc.

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

References transform_stack_.

Referenced by Concat(), impeller::DlDispatcherBase::drawDisplayList(), DrawPaint(), DrawPath(), impeller::DlDispatcherBase::drawShadow(), impeller::ExperimentalCanvas::DrawTextFrame(), PreConcat(), impeller::ExperimentalCanvas::Restore(), impeller::ExperimentalCanvas::SaveLayer(), and impeller::testing::TEST_P().

## ◆ 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 ==
266 Entity::RenderingMode::kSubpassAppendSnapshotTransform ||
267 transform_stack_.back().rendering_mode ==
268 Entity::RenderingMode::kSubpassPrependSnapshotTransform) {
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

Reimplemented in impeller::ExperimentalCanvas.

Definition at line 184 of file canvas.cc.

184 {
185 Save(false, total_content_depth);
186 }

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

## ◆ 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 &&
849 Paint::CanApplyOpacityPeephole(paint)) {
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 | ) |

Definition at line 315 of file canvas.cc.

315 {
316 Concat(Matrix::MakeScale(scale));
317 }

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

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

## ◆ Scale() [2/2]

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

Definition at line 319 of file canvas.cc.

319 {
320 Concat(Matrix::MakeScale(scale));
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 | ) |

Definition at line 294 of file canvas.cc.

294 {
295 Concat(transform);
296 }

References Concat(), and transform.

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

## ◆ Translate()

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

Definition at line 311 of file canvas.cc.

311 {
312 Concat(Matrix::MakeTranslation(offset));
313 }

References Concat(), impeller::Matrix::MakeTranslation(), and offset.

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

## Member Data Documentation

## ◆ current_depth_

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

Definition at line 183 of file canvas.h.

Referenced by Initialize(), Reset(), impeller::ExperimentalCanvas::Restore(), Restore(), impeller::ExperimentalCanvas::Save(), and impeller::ExperimentalCanvas::SaveLayer().

## ◆ 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
| static constexpr

Definition at line 62 of file canvas.h.

Referenced by Initialize().

## ◆ transform_stack_

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

Definition at line 181 of file canvas.h.

Referenced by Concat(), GetCurrentLocalCullingBounds(), GetCurrentTransform(), GetSaveCount(), Initialize(), PreConcat(), Reset(), ResetTransform(), impeller::ExperimentalCanvas::Restore(), Restore(), impeller::ExperimentalCanvas::Save(), and impeller::ExperimentalCanvas::SaveLayer().

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

- impeller/aiks/canvas.h
- impeller/aiks/canvas.cc

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