| 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 & | 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 (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) {
462 case Entity::ClipOperation::kIntersect:
463 IntersectCulling(bounds);
464 break;
465 case Entity::ClipOperation::kDifference:
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) {
441 case Entity::ClipOperation::kIntersect:
442 IntersectCulling(rect);
443 break;
444 case Entity::ClipOperation::kDifference:
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) {
487 case Entity::ClipOperation::kIntersect:
488 IntersectCulling(rect);
489 break;
490 case Entity::ClipOperation::kDifference:
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

Definition at line 205 of file canvas.cc.

205 {
206 return transform_stack_.back().transform;
207 }

Referenced by Concat(), DrawAtlas(), DrawCircle(), impeller::DlDispatcher::drawDisplayList(), DrawImageRect(), DrawLine(), DrawOval(), 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 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 ==
174 Entity::RenderingMode::kSubpass) {
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()

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

Definition at line 132 of file canvas.cc.

132 {
133 Save(false);
134 }

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

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

Definition at line 222 of file canvas.cc.

222 {
223 Concat(Matrix::MakeScale(scale));
224 }

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 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()

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

Definition at line 218 of file canvas.cc.

218 {
219 Concat(Matrix::MakeTranslation(offset));
220 }

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