| Flutter Impeller |

Classes | Public Member Functions | Public Attributes | List of all members
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 Matrix & | GetCurrentTransformation () const
const std::optional< Rect > | GetCurrentLocalCullingBounds () const
void | ResetTransform ()
void | Transform (const Matrix &xformation)
void | Concat (const Matrix &xformation)
void | PreConcat (const Matrix &xformation)
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 | DrawRect (Rect rect, const Paint &paint)
void | DrawRRect (Rect rect, Scalar corner_radius, const Paint &paint)
void | DrawCircle (Point center, Scalar radius, const Paint &paint)
void | DrawPoints (std::vector< Point >, 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 (const Path &path, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
void | ClipRect (const Rect &rect, Entity::ClipOperation clip_op=Entity::ClipOperation::kIntersect)
void | ClipRRect (const Rect &rect, Scalar corner_radius, 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 50 of file canvas.h.

## Constructor & Destructor Documentation

## ◆ Canvas() [1/3]

impeller::Canvas::Canvas | ( |  | ) |

Definition at line 26 of file canvas.cc.

26 {
27 Initialize(std::nullopt);
28 }

## ◆ Canvas() [2/3]

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

Definition at line 30 of file canvas.cc.

30 {
31 Initialize(cull_rect);
32 }

## ◆ Canvas() [3/3]

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

Definition at line 34 of file canvas.cc.

34 {
35 Initialize(Rect::MakeLTRB(cull_rect.GetLeft(), cull_rect.GetTop(),
36 cull_rect.GetRight(), cull_rect.GetBottom()));
37 }

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

## ◆ ClipPath()

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

Definition at line 290 of file canvas.cc.

290 {
291 ClipGeometry(Geometry::MakeFillPath(path), clip_op);
292 if (clip_op == Entity::ClipOperation::kIntersect) {
293 auto bounds = path.GetBoundingBox();
294 if (bounds.has_value()) {
295 IntersectCulling(bounds.value());
296 }
297 }
298 }

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

300 {
301 auto geometry = Geometry::MakeRect(rect);
302 auto& cull_rect = xformation_stack_.back().cull_rect;
303 if (clip_op == Entity::ClipOperation::kIntersect && //
304 cull_rect.has_value() && //
305 geometry->CoversArea(xformation_stack_.back().xformation, *cull_rect) //
306 ) {
307 return; // This clip will do nothing, so skip it.
308 }
309
310 ClipGeometry(std::move(geometry), clip_op);
311 switch (clip_op) {
312 case Entity::ClipOperation::kIntersect:
313 IntersectCulling(rect);
314 break;
315 case Entity::ClipOperation::kDifference:
316 SubtractCulling(rect);
317 break;
318 }
319 }

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

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

## ◆ ClipRRect()

void impeller::Canvas::ClipRRect | ( | const Rect & | rect,
|  | Scalar | corner_radius,
|  | Entity::ClipOperation | clip_op = `Entity::ClipOperation::kIntersect`
| ) |  |

Definition at line 321 of file canvas.cc.

323 {
324 auto path = PathBuilder{}
325 .SetConvexity(Convexity::kConvex)
326 .AddRoundedRect(rect, corner_radius)
327 .TakePath();
328
329 std::optional<Rect> inner_rect = (corner_radius * 2 < rect.size.width &&
330 corner_radius * 2 < rect.size.height)
331 ? rect.Expand(-corner_radius)
332 : std::make_optional<Rect>();
333 auto geometry = Geometry::MakeFillPath(path, inner_rect);
334 auto& cull_rect = xformation_stack_.back().cull_rect;
335 if (clip_op == Entity::ClipOperation::kIntersect && //
336 cull_rect.has_value() && //
337 geometry->CoversArea(xformation_stack_.back().xformation, *cull_rect) //
338 ) {
339 return; // This clip will do nothing, so skip it.
340 }
341
342 ClipGeometry(std::move(geometry), clip_op);
343 switch (clip_op) {
344 case Entity::ClipOperation::kIntersect:
345 IntersectCulling(rect);
346 break;
347 case Entity::ClipOperation::kDifference:
348 if (corner_radius <= 0) {
349 SubtractCulling(rect);
350 } else {
351 // We subtract the inner "tall" and "wide" rectangle pieces
352 // that fit inside the corners which cover the greatest area
353 // without involving the curved corners
354 // Since this is a subtract operation, we can subtract each
355 // rectangle piece individually without fear of interference.
356 if (corner_radius * 2 < rect.size.width) {
357 SubtractCulling(Rect::MakeLTRB(
358 rect.GetLeft() + corner_radius, rect.GetTop(),
359 rect.GetRight() - corner_radius, rect.GetBottom()));
360 }
361 if (corner_radius * 2 < rect.size.height) {
362 SubtractCulling(Rect::MakeLTRB(
363 rect.GetLeft(), rect.GetTop() + corner_radius, //
364 rect.GetRight(), rect.GetBottom() - corner_radius));
365 }
366 }
367 break;
368 }
369 }

References impeller::PathBuilder::AddRoundedRect(), impeller::TRect< T >::Expand(), impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TSize< T >::height, impeller::kConvex, impeller::Entity::kDifference, impeller::Entity::kIntersect, impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), impeller::PathBuilder::SetConvexity(), impeller::TRect< T >::size, impeller::PathBuilder::TakePath(), and impeller::TSize< T >::width.

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

## ◆ Concat()

void impeller::Canvas::Concat | ( | const Matrix & | xformation | ) |

Definition at line 113 of file canvas.cc.

113 {
114 xformation_stack_.back().xformation = GetCurrentTransformation() * xformation;
115 }

References GetCurrentTransformation().

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

674 {
675 if (!atlas) {
676 return;
677 }
678
679 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
680 contents->SetColors(std::move(colors));
681 contents->SetTransforms(std::move(transforms));
682 contents->SetTextureCoordinates(std::move(texture_coordinates));
683 contents->SetTexture(atlas->GetTexture());
684 contents->SetSamplerDescriptor(std::move(sampler));
685 contents->SetBlendMode(blend_mode);
686 contents->SetCullRect(cull_rect);
687 contents->SetAlpha(paint.color.alpha);
688
689 Entity entity;
690 entity.SetTransformation(GetCurrentTransformation());
691 entity.SetStencilDepth(GetStencilDepth());
692 entity.SetBlendMode(paint.blend_mode);
693 entity.SetContents(paint.WithFilters(contents));
694
695 GetCurrentPass().AddEntity(entity);
696 }

References impeller::EntityPass::AddEntity(), impeller::Color::alpha, impeller::Paint::blend_mode, impeller::Paint::color, GetCurrentTransformation(), impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Entity::SetStencilDepth(), impeller::Entity::SetTransformation(), and impeller::Paint::WithFilters().

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

## ◆ DrawCircle()

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

Definition at line 277 of file canvas.cc.

277 {
278 Size half_size(radius, radius);
279 if (AttemptDrawBlurredRRect(Rect(center - half_size, half_size * 2), radius,
280 paint)) {
281 return;
282 }
283 auto circle_path = PathBuilder{}
284 .AddCircle(center, radius)
285 .SetConvexity(Convexity::kConvex)
286 .TakePath();
287 DrawPath(circle_path, paint);
288 }

References impeller::PathBuilder::AddCircle(), DrawPath(), impeller::kConvex, impeller::PathBuilder::SetConvexity(), and impeller::PathBuilder::TakePath().

Referenced by impeller::DlDispatcher::drawCircle(), impeller::DlDispatcher::drawOval(), impeller::DlDispatcher::drawPath(), impeller::DlDispatcher::drawShadow(), 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 473 of file canvas.cc.

476 {
477 if (!image) {
478 return;
479 }
480
481 const auto source = Rect::MakeSize(image->GetSize());
482 const auto dest =
483 Rect::MakeXYWH(offset.x, offset.y, source.size.width, source.size.height);
484
485 DrawImageRect(image, source, dest, paint, std::move(sampler));
486 }

References DrawImageRect(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

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

492 {
493 if (!image || source.size.IsEmpty() || dest.size.IsEmpty()) {
494 return;
495 }
496
497 auto size = image->GetSize();
498
499 if (size.IsEmpty()) {
500 return;
501 }
502
503 auto contents = TextureContents::MakeRect(dest);
504 contents->SetTexture(image->GetTexture());
505 contents->SetSourceRect(source);
506 contents->SetSamplerDescriptor(std::move(sampler));
507 contents->SetOpacity(paint.color.alpha);
508 contents->SetDeferApplyingOpacity(paint.HasColorFilter());
509
510 Entity entity;
511 entity.SetBlendMode(paint.blend_mode);
512 entity.SetStencilDepth(GetStencilDepth());
513 entity.SetContents(paint.WithFilters(contents));
514 entity.SetTransformation(GetCurrentTransformation());
515
516 GetCurrentPass().AddEntity(entity);
517 }

References impeller::EntityPass::AddEntity(), impeller::Color::alpha, impeller::Paint::blend_mode, impeller::Paint::color, GetCurrentTransformation(), impeller::Paint::HasColorFilter(), impeller::TSize< T >::IsEmpty(), impeller::TextureContents::MakeRect(), impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Entity::SetStencilDepth(), impeller::Entity::SetTransformation(), impeller::TRect< T >::size, and impeller::Paint::WithFilters().

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

## ◆ DrawPaint()

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

Definition at line 184 of file canvas.cc.

184 {
185 Entity entity;
186 entity.SetTransformation(GetCurrentTransformation());
187 entity.SetStencilDepth(GetStencilDepth());
188 entity.SetBlendMode(paint.blend_mode);
189 entity.SetContents(paint.CreateContentsForEntity({}, true));
190
191 GetCurrentPass().AddEntity(entity);
192 }

References impeller::EntityPass::AddEntity(), impeller::Paint::blend_mode, impeller::Paint::CreateContentsForEntity(), GetCurrentTransformation(), impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Entity::SetStencilDepth(), and impeller::Entity::SetTransformation().

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

## ◆ DrawPath()

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

Definition at line 174 of file canvas.cc.

174 {
175 Entity entity;
176 entity.SetTransformation(GetCurrentTransformation());
177 entity.SetStencilDepth(GetStencilDepth());
178 entity.SetBlendMode(paint.blend_mode);
179 entity.SetContents(paint.WithFilters(paint.CreateContentsForEntity(path)));
180
181 GetCurrentPass().AddEntity(entity);
182 }

References impeller::EntityPass::AddEntity(), impeller::Paint::blend_mode, impeller::Paint::CreateContentsForEntity(), GetCurrentTransformation(), impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Entity::SetStencilDepth(), impeller::Entity::SetTransformation(), and impeller::Paint::WithFilters().

Referenced by impeller::DlDispatcher::drawArc(), DrawCircle(), impeller::DlDispatcher::drawDRRect(), impeller::DlDispatcher::drawLine(), impeller::DlDispatcher::drawOval(), impeller::DlDispatcher::drawPath(), impeller::DlDispatcher::drawPoints(), DrawRect(), DrawRRect(), impeller::DlDispatcher::drawRRect(), impeller::DlDispatcher::drawShadow(), and impeller::testing::TEST_P().

## ◆ DrawPicture()

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

Definition at line 443 of file canvas.cc.

443 {
444 if (!picture.pass) {
445 return;
446 }
447
448 // Clone the base pass and account for the CTM updates.
449 auto pass = picture.pass->Clone();
450
451 pass->IterateAllElements([&](auto& element) -> bool {
452 if (auto entity = std::get_if<Entity>(&element)) {
453 entity->IncrementStencilDepth(GetStencilDepth());
454 entity->SetTransformation(GetCurrentTransformation() *
455 entity->GetTransformation());
456 return true;
457 }
458
459 if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
460 subpass->get()->SetStencilDepth(subpass->get()->GetStencilDepth() +
461 GetStencilDepth());
462 return true;
463 }
464
465 FML_UNREACHABLE();
466 });
467
468 GetCurrentPass().AddSubpassInline(std::move(pass));
469
470 RestoreClip();
471 }

References impeller::EntityPass::AddSubpassInline(), GetCurrentTransformation(), 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 424 of file canvas.cc.

427 {
428 if (radius <= 0) {
429 return;
430 }
431
432 Entity entity;
433 entity.SetTransformation(GetCurrentTransformation());
434 entity.SetStencilDepth(GetStencilDepth());
435 entity.SetBlendMode(paint.blend_mode);
436 entity.SetContents(paint.WithFilters(paint.CreateContentsForGeometry(
437 Geometry::MakePointField(std::move(points), radius,
438 /*round=*/point_style == PointStyle::kRound))));
439
440 GetCurrentPass().AddEntity(entity);
441 }

References impeller::EntityPass::AddEntity(), impeller::Paint::blend_mode, impeller::Paint::CreateContentsForGeometry(), GetCurrentTransformation(), impeller::kRound, impeller::Geometry::MakePointField(), impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Entity::SetStencilDepth(), impeller::Entity::SetTransformation(), and impeller::Paint::WithFilters().

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

## ◆ DrawRect()

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

Definition at line 235 of file canvas.cc.

235 {
236 if (paint.style == Paint::Style::kStroke) {
237 DrawPath(PathBuilder{}.AddRect(rect).TakePath(), paint);
238 return;
239 }
240
241 if (AttemptDrawBlurredRRect(rect, 0, paint)) {
242 return;
243 }
244
245 Entity entity;
246 entity.SetTransformation(GetCurrentTransformation());
247 entity.SetStencilDepth(GetStencilDepth());
248 entity.SetBlendMode(paint.blend_mode);
249 entity.SetContents(paint.WithFilters(
250 paint.CreateContentsForGeometry(Geometry::MakeRect(rect))));
251
252 GetCurrentPass().AddEntity(entity);
253 }

References impeller::EntityPass::AddEntity(), impeller::PathBuilder::AddRect(), impeller::Paint::blend_mode, impeller::Paint::CreateContentsForGeometry(), DrawPath(), GetCurrentTransformation(), impeller::Paint::kStroke, impeller::Geometry::MakeRect(), impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Entity::SetStencilDepth(), impeller::Entity::SetTransformation(), impeller::Paint::style, and impeller::Paint::WithFilters().

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

## ◆ DrawRRect()

void impeller::Canvas::DrawRRect | ( | Rect | rect,
|  | Scalar | corner_radius,
|  | const Paint & | paint
| ) |  |

Definition at line 255 of file canvas.cc.

255 {
256 if (AttemptDrawBlurredRRect(rect, corner_radius, paint)) {
257 return;
258 }
259 auto path = PathBuilder{}
260 .SetConvexity(Convexity::kConvex)
261 .AddRoundedRect(rect, corner_radius)
262 .TakePath();
263 if (paint.style == Paint::Style::kFill) {
264 Entity entity;
265 entity.SetTransformation(GetCurrentTransformation());
266 entity.SetStencilDepth(GetStencilDepth());
267 entity.SetBlendMode(paint.blend_mode);
268 entity.SetContents(paint.WithFilters(
269 paint.CreateContentsForGeometry(Geometry::MakeFillPath(path))));
270
271 GetCurrentPass().AddEntity(entity);
272 return;
273 }
274 DrawPath(path, paint);
275 }

References impeller::EntityPass::AddEntity(), impeller::PathBuilder::AddRoundedRect(), impeller::Paint::blend_mode, impeller::Paint::CreateContentsForGeometry(), DrawPath(), GetCurrentTransformation(), impeller::kConvex, impeller::Paint::kFill, impeller::Geometry::MakeFillPath(), impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::PathBuilder::SetConvexity(), impeller::Entity::SetStencilDepth(), impeller::Entity::SetTransformation(), impeller::Paint::style, impeller::PathBuilder::TakePath(), and impeller::Paint::WithFilters().

Referenced by impeller::DlDispatcher::drawPath(), impeller::DlDispatcher::drawRRect(), impeller::DlDispatcher::drawShadow(), 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 563 of file canvas.cc.

565 {
566 Entity entity;
567 entity.SetStencilDepth(GetStencilDepth());
568 entity.SetBlendMode(paint.blend_mode);
569
570 auto text_contents = std::make_shared<TextContents>();
571 text_contents->SetTextFrame(text_frame);
572 text_contents->SetColor(paint.color);
573
574 entity.SetTransformation(GetCurrentTransformation() *
575 Matrix::MakeTranslation(position));
576
577 // TODO(bdero): This mask blur application is a hack. It will always wind up
578 // doing a gaussian blur that affects the color source itself
579 // instead of just the mask. The color filter text support
580 // needs to be reworked in order to interact correctly with
581 // mask filters.
582 // https://github.com/flutter/flutter/issues/133297
583 entity.SetContents(
584 paint.WithFilters(paint.WithMaskBlur(std::move(text_contents), true)));
585
586 GetCurrentPass().AddEntity(entity);
587 }

References impeller::EntityPass::AddEntity(), impeller::Paint::blend_mode, impeller::Paint::color, GetCurrentTransformation(), impeller::Matrix::MakeTranslation(), impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Entity::SetStencilDepth(), impeller::Entity::SetTransformation(), 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 606 of file canvas.cc.

608 {
609 // Override the blend mode with kDestination in order to match the behavior
610 // of Skia's SK_LEGACY_IGNORE_DRAW_VERTICES_BLEND_WITH_NO_SHADER flag, which
611 // is enabled when the Flutter engine builds Skia.
612 if (paint.color_source.GetType() == ColorSource::Type::kColor) {
613 blend_mode = BlendMode::kDestination;
614 }
615
616 Entity entity;
617 entity.SetTransformation(GetCurrentTransformation());
618 entity.SetStencilDepth(GetStencilDepth());
619 entity.SetBlendMode(paint.blend_mode);
620
621 // If there are no vertex color or texture coordinates. Or if there
622 // are vertex coordinates then only if the contents are an image.
623 if (UseColorSourceContents(vertices, paint)) {
624 auto contents = paint.CreateContentsForGeometry(vertices);
625 entity.SetContents(paint.WithFilters(std::move(contents)));
626 GetCurrentPass().AddEntity(entity);
627 return;
628 }
629
630 auto src_paint = paint;
631 src_paint.color = paint.color.WithAlpha(1.0);
632
633 std::shared_ptr<Contents> src_contents =
634 src_paint.CreateContentsForGeometry(vertices);
635 if (vertices->HasTextureCoordinates()) {
636 // If the color source has an intrinsic size, then we use that to
637 // create the src contents as a simplification. Otherwise we use
638 // the extent of the texture coordinates to determine how large
639 // the src contents should be. If neither has a value we fall back
640 // to using the geometry coverage data.
641 Rect src_coverage;
642 auto size = src_contents->GetColorSourceSize();
643 if (size.has_value()) {
644 src_coverage = Rect::MakeXYWH(0, 0, size->width, size->height);
645 } else {
646 auto cvg = vertices->GetCoverage(Matrix{});
647 FML_CHECK(cvg.has_value());
648 src_coverage =
649 // Covered by FML_CHECK.
650 // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
651 vertices->GetTextureCoordinateCoverge().value_or(cvg.value());
652 }
653 src_contents =
654 src_paint.CreateContentsForGeometry(Geometry::MakeRect(src_coverage));
655 }
656
657 auto contents = std::make_shared<VerticesContents>();
658 contents->SetAlpha(paint.color.alpha);
659 contents->SetBlendMode(blend_mode);
660 contents->SetGeometry(vertices);
661 contents->SetSourceContents(std::move(src_contents));
662 entity.SetContents(paint.WithFilters(std::move(contents)));
663
664 GetCurrentPass().AddEntity(entity);
665 }

References impeller::EntityPass::AddEntity(), impeller::Color::alpha, impeller::Paint::blend_mode, impeller::Paint::color, impeller::Paint::color_source, impeller::Paint::CreateContentsForGeometry(), GetCurrentTransformation(), impeller::ColorSource::GetType(), impeller::ColorSource::kColor, impeller::kDestination, impeller::Geometry::MakeRect(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Entity::SetStencilDepth(), impeller::Entity::SetTransformation(), 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 519 of file canvas.cc.

519 {
520 Picture picture;
521 picture.pass = std::move(base_pass_);
522
523 Reset();
524 Initialize(initial_cull_rect_);
525
526 return picture;
527 }

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

133 {
134 auto cull_rect = xformation_stack_.back().cull_rect;
135 if (cull_rect.has_value()) {
136 Matrix inverse = xformation_stack_.back().xformation.Invert();
137 cull_rect = cull_rect.value().TransformBounds(inverse);
138 }
139 return cull_rect;
140 }

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

## ◆ GetCurrentTransformation()

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

Definition at line 129 of file canvas.cc.

129 {
130 return xformation_stack_.back().xformation;
131 }

Referenced by Concat(), DrawAtlas(), impeller::DlDispatcher::drawDisplayList(), DrawImageRect(), DrawPaint(), DrawPath(), DrawPicture(), DrawPoints(), DrawRect(), DrawRRect(), impeller::DlDispatcher::drawShadow(), DrawTextFrame(), DrawVertices(), PreConcat(), and impeller::testing::TEST_P().

## ◆ GetSaveCount()

size_t impeller::Canvas::GetSaveCount | ( |  | ) | const

Definition at line 162 of file canvas.cc.

162 {
163 return xformation_stack_.size();
164 }

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

## ◆ PreConcat()

void impeller::Canvas::PreConcat | ( | const Matrix & | xformation | ) |

Definition at line 117 of file canvas.cc.

117 {
118 xformation_stack_.back().xformation = xformation * GetCurrentTransformation();
119 }

References GetCurrentTransformation().

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

## ◆ ResetTransform()

void impeller::Canvas::ResetTransform | ( |  | ) |

Definition at line 121 of file canvas.cc.

121 {
122 xformation_stack_.back().xformation = {};
123 }

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

## ◆ Restore()

bool impeller::Canvas::Restore | ( |  | ) |

Definition at line 92 of file canvas.cc.

92 {
93 FML_DCHECK(xformation_stack_.size() > 0);
94 if (xformation_stack_.size() == 1) {
95 return false;
96 }
97 if (xformation_stack_.back().rendering_mode ==
98 Entity::RenderingMode::kSubpass) {
99 current_pass_ = GetCurrentPass().GetSuperpass();
100 FML_DCHECK(current_pass_);
101 }
102
103 bool contains_clips = xformation_stack_.back().contains_clips;
104 xformation_stack_.pop_back();
105
106 if (contains_clips) {
107 RestoreClip();
108 }
109
110 return true;
111 }

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

166 {
167 while (GetSaveCount() > count) {
168 if (!Restore()) {
169 return;
170 }
171 }
172 }

References GetSaveCount(), and Restore().

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

## ◆ Rotate()

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

Definition at line 158 of file canvas.cc.

158 {
159 Concat(Matrix::MakeRotationZ(radians));
160 }

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

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

## ◆ Save()

void impeller::Canvas::Save | ( |  | ) |

Definition at line 56 of file canvas.cc.

56 {
57 Save(false);
58 }

Referenced by impeller::DlDispatcher::drawDisplayList(), impeller::DlDispatcher::drawShadow(), impeller::DlDispatcher::save(), SaveLayer(), 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`
| ) |  |

Definition at line 538 of file canvas.cc.

540 {
541 Save(true, paint.blend_mode, backdrop_filter);
542
543 // The DisplayList bounds/rtree doesn't account for filters applied to parent
544 // layers, and so sub-DisplayLists are getting culled as if no filters are
545 // applied.
546 // See also: https://github.com/flutter/flutter/issues/139294
547 if (paint.image_filter) {
548 xformation_stack_.back().cull_rect = std::nullopt;
549 }
550
551 auto& new_layer_pass = GetCurrentPass();
552 new_layer_pass.SetBoundsLimit(bounds);
553
554 // Only apply opacity peephole on default blending.
555 if (paint.blend_mode == BlendMode::kSourceOver) {
556 new_layer_pass.SetDelegate(
557 std::make_shared<OpacityPeepholePassDelegate>(paint));
558 } else {
559 new_layer_pass.SetDelegate(std::make_shared<PaintPassDelegate>(paint));
560 }
561 }

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]

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

Definition at line 146 of file canvas.cc.

146 {
147 Concat(Matrix::MakeScale(scale));
148 }

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

Referenced by impeller::testing::CanRenderConicalGradientWithDithering(), impeller::testing::CanRenderSweepGradientWithDithering(), impeller::DlDispatcher::scale(), impeller::testing::TEST(), and impeller::testing::TEST_P().

## ◆ Scale() [2/2]

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

Definition at line 150 of file canvas.cc.

150 {
151 Concat(Matrix::MakeScale(scale));
152 }

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

## ◆ Skew()

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

Definition at line 154 of file canvas.cc.

154 {
155 Concat(Matrix::MakeSkew(sx, sy));
156 }

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

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

## ◆ Transform()

void impeller::Canvas::Transform | ( | const Matrix & | xformation | ) |

Definition at line 125 of file canvas.cc.

125 {
126 Concat(xformation);
127 }

References Concat().

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

## ◆ Translate()

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

Definition at line 142 of file canvas.cc.

142 {
143 Concat(Matrix::MakeTranslation(offset));
144 }

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

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

## Member Data Documentation

## ◆ debug_options

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

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

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:116
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:245
impeller::Entity::ClipOperation::kIntersect
@ kIntersect
impeller::Entity::ClipOperation::kDifference
@ kDifference
impeller::Paint::Style::kStroke
@ kStroke
impeller::TRect< Scalar >::MakeXYWH
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:47
impeller::PointStyle::kRound
@ kRound
Points are drawn as squares.
impeller::Geometry::MakeRect
static std::unique_ptr< Geometry > MakeRect(Rect rect)
Definition: geometry.cc:142
impeller::Size
TSize< Scalar > Size
Definition: size.h:135
impeller::Matrix::MakeTranslation
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:94
impeller::UseColorSourceContents
static bool UseColorSourceContents(const std::shared_ptr< VerticesGeometry > &vertices, const Paint &paint)
Definition: canvas.cc:589
impeller::Canvas::DrawImageRect
void DrawImageRect(const std::shared_ptr< Image > &image, Rect source, Rect dest, const Paint &paint, SamplerDescriptor sampler={})
Definition: canvas.cc:488
impeller::BlendMode::kSourceOver
@ kSourceOver
impeller::EntityPass::GetSuperpass
EntityPass * GetSuperpass() const
Definition: entity_pass.cc:222
impeller::BlendMode::kDestination
@ kDestination
impeller::Canvas::Save
void Save()
Definition: canvas.cc:56
impeller::Paint::Style::kFill
@ kFill
impeller::Canvas::Restore
bool Restore()
Definition: canvas.cc:92
impeller::Canvas::DrawPath
void DrawPath(const Path &path, const Paint &paint)
Definition: canvas.cc:174
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:306
impeller::Canvas::GetSaveCount
size_t GetSaveCount() const
Definition: canvas.cc:162
impeller::Entity::RenderingMode::kSubpass
@ kSubpass
impeller::Matrix::MakeRotationZ
static Matrix MakeRotationZ(Radians r)
Definition: matrix.h:208
impeller::Geometry::MakePointField
static std::unique_ptr< Geometry > MakePointField(std::vector< Point > points, Scalar radius, bool round)
Definition: geometry.cc:119
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:52
impeller::Canvas::GetCurrentTransformation
const Matrix & GetCurrentTransformation() const
Definition: canvas.cc:129
impeller::Geometry::MakeFillPath
static std::unique_ptr< Geometry > MakeFillPath(const Path &path, std::optional< Rect > inner_rect=std::nullopt)
Definition: geometry.cc:113
impeller::Canvas::Concat
void Concat(const Matrix &xformation)
Definition: canvas.cc:113
impeller::TRect< Scalar >::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:40
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:28
impeller::Matrix::MakeScale
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:103
impeller::ColorSource::Type::kColor
@ kColor
impeller::EntityPass::AddEntity
void AddEntity(Entity entity)
Definition: entity_pass.cc:77