| Flutter Impeller |

Classes | Typedefs | Functions | Variables
impeller::testing Namespace Reference

## Classes
class | ArchivistFixture
struct | BlendModeSelection
class | CompareFunctionUIData
struct | Foo
class | GoldenDigest
| Manages a global variable for tracking instances of golden images. More...
class | GoldenTests
class | MetalScreenshot
| A screenshot that was produced from `MetalScreenshoter`. More...
class | MetalScreenshoter
| Converts `Picture`s to `MetalScreenshot`s with the playground backend. More...
class | RendererDartTest
struct | RWFoo
class | Sample
class | SampleWithVector
class | TestAllocator
class | TestPassDelegate
class | TestRenderTargetAllocator
struct | TextRenderOptions
class | WorkingDirectory

## Typedefs
using | AiksTest = AiksPlayground
using | AiksCanvasTest = ::testing::Test
using | ArchiveTest = ArchivistFixture
using | DisplayListTest = DlPlayground
using | EntityTest = EntityPlayground
using | ComputeSubgroupTest = ComputePlaygroundTest
using | ComputeTest = ComputePlaygroundTest
using | DeviceBufferTest = Playground
using | RendererTest = PlaygroundTest
using | RuntimeStageTest = RuntimeStagePlayground
using | TypographerTest = PlaygroundTest

## Functions
| INSTANTIATE_PLAYGROUND_SUITE (AiksTest)
| TEST_P (AiksTest, RotateColorFilteredPath)
| TEST_P (AiksTest, CanvasCTMCanBeUpdated)
| TEST_P (AiksTest, CanvasCanPushPopCTM)
| TEST_P (AiksTest, CanRenderColoredRect)
| TEST_P (AiksTest, CanRenderImage)
| TEST_P (AiksTest, CanRenderInvertedImage)
| TEST_P (AiksTest, CanRenderTiledTextureClamp)
| TEST_P (AiksTest, CanRenderTiledTextureRepeat)
| TEST_P (AiksTest, CanRenderTiledTextureMirror)
| TEST_P (AiksTest, CanRenderTiledTextureDecal)
| TEST_P (AiksTest, CanRenderTiledTextureClampWithTranslate)
| TEST_P (AiksTest, CanRenderImageRect)
| TEST_P (AiksTest, CanRenderStrokes)
| TEST_P (AiksTest, CanRenderCurvedStrokes)
| TEST_P (AiksTest, CanRenderClips)
| TEST_P (AiksTest, CanRenderNestedClips)
| TEST_P (AiksTest, CanRenderDifferenceClips)
| TEST_P (AiksTest, CanRenderWithContiguousClipRestores)
| TEST_P (AiksTest, ClipsUseCurrentTransform)
| TEST_P (AiksTest, CanSaveLayerStandalone)
| TEST_P (AiksTest, CanRenderLinearGradientClamp)
| TEST_P (AiksTest, CanRenderLinearGradientRepeat)
| TEST_P (AiksTest, CanRenderLinearGradientMirror)
| TEST_P (AiksTest, CanRenderLinearGradientDecal)
| TEST_P (AiksTest, CanRenderLinearGradientDecalWithColorFilter)
static void | CanRenderLinearGradientWithDithering (AiksTest *aiks_test, bool use_dithering)
| TEST_P (AiksTest, CanRenderLinearGradientWithDitheringDisabled)
| TEST_P (AiksTest, CanRenderLinearGradientWithDitheringEnabled)
static void | CanRenderRadialGradientWithDithering (AiksTest *aiks_test, bool use_dithering)
| TEST_P (AiksTest, CanRenderRadialGradientWithDitheringDisabled)
| TEST_P (AiksTest, CanRenderRadialGradientWithDitheringEnabled)
static void | CanRenderSweepGradientWithDithering (AiksTest *aiks_test, bool use_dithering)
| TEST_P (AiksTest, CanRenderSweepGradientWithDitheringDisabled)
| TEST_P (AiksTest, CanRenderSweepGradientWithDitheringEnabled)
static void | CanRenderConicalGradientWithDithering (AiksTest *aiks_test, bool use_dithering)
| TEST_P (AiksTest, CanRenderConicalGradientWithDitheringDisabled)
| TEST_P (AiksTest, CanRenderConicalGradientWithDitheringEnabled)
| TEST_P (AiksTest, CanRenderLinearGradientWithOverlappingStopsClamp)
| TEST_P (AiksTest, CanRenderLinearGradientManyColorsClamp)
| TEST_P (AiksTest, CanRenderLinearGradientManyColorsRepeat)
| TEST_P (AiksTest, CanRenderLinearGradientManyColorsMirror)
| TEST_P (AiksTest, CanRenderLinearGradientManyColorsDecal)
| TEST_P (AiksTest, CanRenderLinearGradientWayManyColorsClamp)
| TEST_P (AiksTest, CanRenderLinearGradientManyColorsUnevenStops)
| TEST_P (AiksTest, CanRenderLinearGradientMaskBlur)
| TEST_P (AiksTest, CanRenderRadialGradient)
| TEST_P (AiksTest, CanRenderRadialGradientManyColors)
| TEST_P (AiksTest, CanRenderSweepGradientClamp)
| TEST_P (AiksTest, CanRenderSweepGradientRepeat)
| TEST_P (AiksTest, CanRenderSweepGradientMirror)
| TEST_P (AiksTest, CanRenderSweepGradientDecal)
| TEST_P (AiksTest, CanRenderSweepGradientManyColorsClamp)
| TEST_P (AiksTest, CanRenderSweepGradientManyColorsRepeat)
| TEST_P (AiksTest, CanRenderSweepGradientManyColorsMirror)
| TEST_P (AiksTest, CanRenderSweepGradientManyColorsDecal)
| TEST_P (AiksTest, CanRenderConicalGradient)
| TEST_P (AiksTest, CanRenderGradientDecalWithBackground)
| TEST_P (AiksTest, CanRenderDifferentShapesWithSameColorSource)
| TEST_P (AiksTest, CanPictureConvertToImage)
| TEST_P (AiksTest, BlendModeShouldCoverWholeScreen)
| TEST_P (AiksTest, CanRenderGroupOpacity)
| TEST_P (AiksTest, CoordinateConversionsAreCorrect)
| TEST_P (AiksTest, CanPerformFullScreenMSAA)
| TEST_P (AiksTest, CanPerformSkew)
| TEST_P (AiksTest, CanPerformSaveLayerWithBounds)
| TEST_P (AiksTest, CanPerformSaveLayerWithBoundsAndLargerIntermediateIsNotAllocated)
| TEST_P (AiksTest, CanRenderRoundedRectWithNonUniformRadii)
| TEST_P (AiksTest, CanRenderDifferencePaths)
| TEST_P (AiksTest, CanDrawAnOpenPath)
| TEST_P (AiksTest, CanDrawAnOpenPathThatIsntARect)
static sk_sp< SkData > | OpenFixtureAsSkData (const char *fixture_name)
bool | RenderTextInCanvasSkia (const std::shared_ptr< Context > &context, Canvas &canvas, const std::string &text, const std::string &font_fixture, TextRenderOptions options={})
bool | RenderTextInCanvasSTB (const std::shared_ptr< Context > &context, Canvas &canvas, const std::string &text, const std::string &font_fixture, TextRenderOptions options={})
| TEST_P (AiksTest, CanRenderTextFrame)
| TEST_P (AiksTest, CanRenderTextFrameSTB)
| TEST_P (AiksTest, TextFrameSubpixelAlignment)
| TEST_P (AiksTest, CanRenderItalicizedText)
| TEST_P (AiksTest, CanRenderEmojiTextFrame)
| TEST_P (AiksTest, CanRenderEmojiTextFrameWithAlpha)
| TEST_P (AiksTest, CanRenderTextInSaveLayer)
| TEST_P (AiksTest, CanRenderTextOutsideBoundaries)
| TEST_P (AiksTest, TextRotated)
| TEST_P (AiksTest, CanDrawPaint)
| TEST_P (AiksTest, CanDrawPaintMultipleTimes)
| TEST_P (AiksTest, CanDrawPaintWithAdvancedBlend)
| TEST_P (AiksTest, DrawPaintWithAdvancedBlendOverFilter)
| TEST_P (AiksTest, DrawAdvancedBlendPartlyOffscreen)
static BlendModeSelection | GetBlendModeSelection ()
| TEST_P (AiksTest, CanDrawPaintMultipleTimesInteractive)
| TEST_P (AiksTest, PaintBlendModeIsRespected)
| TEST_P (AiksTest, ColorWheel)
| TEST_P (AiksTest, TransformMultipliesCorrectly)
| TEST_P (AiksTest, SolidStrokesRenderCorrectly)
| TEST_P (AiksTest, GradientStrokesRenderCorrectly)
| TEST_P (AiksTest, CoverageOriginShouldBeAccountedForInSubpasses)
| TEST_P (AiksTest, DrawRectStrokesRenderCorrectly)
| TEST_P (AiksTest, SaveLayerDrawsBehindSubsequentEntities)
| TEST_P (AiksTest, SiblingSaveLayerBoundsAreRespected)
| TEST_P (AiksTest, CanRenderClippedLayers)
| TEST_P (AiksTest, SaveLayerFiltersScaleWithTransform)
| TEST_P (AiksTest, PaintWithFilters)
| TEST_P (AiksTest, OpacityPeepHoleApplicationTest)
| TEST_P (AiksTest, DrawPaintAbsorbsClears)
| TEST_P (AiksTest, ParentSaveLayerCreatesRenderPassWhenChildBackdropFilterIsPresent)
| TEST_P (AiksTest, DrawRectAbsorbsClears)
| TEST_P (AiksTest, DrawRectAbsorbsClearsNegativeRRect)
| TEST_P (AiksTest, DrawRectAbsorbsClearsNegativeRotation)
| TEST_P (AiksTest, DrawRectAbsorbsClearsNegative)
| TEST_P (AiksTest, ClipRectElidesNoOpClips)
| TEST_P (AiksTest, ClearColorOptimizationDoesNotApplyForBackdropFilters)
| TEST_P (AiksTest, CollapsedDrawPaintInSubpass)
| TEST_P (AiksTest, CollapsedDrawPaintInSubpassBackdropFilter)
| TEST_P (AiksTest, ForegroundBlendSubpassCollapseOptimization)
| TEST_P (AiksTest, ColorMatrixFilterSubpassCollapseOptimization)
| TEST_P (AiksTest, LinearToSrgbFilterSubpassCollapseOptimization)
| TEST_P (AiksTest, SrgbToLinearFilterSubpassCollapseOptimization)
static Picture | BlendModeTest (BlendMode blend_mode, const std::shared_ptr< Image > &src_image, const std::shared_ptr< Image > &dst_image)
| TEST_P (AiksTest, TranslucentSaveLayerDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithBlendColorFilterDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithBlendImageFilterDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithColorAndImageFilterDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerImageDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithColorMatrixColorFilterDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithColorMatrixImageFilterDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithColorFilterAndImageFilterDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithAdvancedBlendModeDrawsCorrectly)
| TEST_P (AiksTest, CanRenderTinyOverlappingSubpasses)
| TEST_P (AiksTest, CanRenderOffscreenCheckerboard)
| TEST_P (AiksTest, OpaqueEntitiesGetCoercedToSource)
| TEST_P (AiksTest, CanRenderDestructiveSaveLayer)
| TEST_P (AiksTest, CanRenderMaskBlurHugeSigma)
| TEST_P (AiksTest, CanRenderBackdropBlurInteractive)
| TEST_P (AiksTest, CanRenderBackdropBlur)
| TEST_P (AiksTest, CanRenderBackdropBlurHugeSigma)
| TEST_P (AiksTest, CanRenderClippedBlur)
| TEST_P (AiksTest, CanRenderForegroundBlendWithMaskBlur)
| TEST_P (AiksTest, CanRenderForegroundAdvancedBlendWithMaskBlur)
| TEST_P (AiksTest, CanRenderClippedRuntimeEffects)
| TEST_P (AiksTest, DrawPaintTransformsBounds)
| TEST_P (AiksTest, CanDrawPoints)
| TEST_P (AiksTest, DrawAtlasWithColorAdvancedAndTransform)
| TEST_P (AiksTest, DrawAtlasAdvancedAndTransform)
| TEST_P (AiksTest, CanDrawPointsWithTextureMap)
| TEST_P (AiksTest, TextForegroundShaderWithTransform)
| TEST_P (AiksTest, CanCanvasDrawPicture)
| TEST_P (AiksTest, CanCanvasDrawPictureWithAdvancedBlend)
| TEST_P (AiksTest, CanCanvasDrawPictureWithBackdropFilter)
| TEST_P (AiksTest, DrawPictureWithText)
| TEST_P (AiksTest, DrawPictureClipped)
| TEST_P (AiksTest, MatrixSaveLayerFilter)
| TEST_P (AiksTest, MatrixBackdropFilter)
| TEST_P (AiksTest, SolidColorApplyColorFilter)
| APPLY_COLOR_FILTER_GRADIENT_TEST (Linear)
| APPLY_COLOR_FILTER_GRADIENT_TEST (Radial)
| APPLY_COLOR_FILTER_GRADIENT_TEST (Conical)
| APPLY_COLOR_FILTER_GRADIENT_TEST (Sweep)
| TEST_P (AiksTest, DrawScaledTextWithPerspectiveNoSaveLayer)
| TEST_P (AiksTest, DrawScaledTextWithPerspectiveSaveLayer)
| TEST_P (AiksTest, PipelineBlendSingleParameter)
| TEST_P (AiksTest, ClippedBlurFilterRendersCorrectlyInteractive)
| TEST_P (AiksTest, ClippedBlurFilterRendersCorrectly)
| TEST_P (AiksTest, CaptureContext)
| TEST_P (AiksTest, CaptureInactivatedByDefault)
| TEST_P (AiksTest, ReleasesTextureOnTeardown)
| TEST_P (AiksTest, VerticesGeometryUVPositionData)
| TEST_P (AiksTest, ClearBlendWithBlur)
| TEST_P (AiksTest, ClearBlend)
| TEST_P (AiksTest, MatrixImageFilterMagnify)
| TEST_P (AiksTest, ClearColorOptimizationWhenSubpassIsBiggerThanParentPass)
| TEST_P (AiksTest, MaskBlurWithZeroSigmaIsSkipped)
| TEST_P (AiksTest, SubpassWithClearColorOptimization)
| TEST (AiksCanvasTest, EmptyCullRect)
| TEST (AiksCanvasTest, InitialCullRect)
| TEST (AiksCanvasTest, TranslatedCullRect)
| TEST (AiksCanvasTest, ScaledCullRect)
| TEST (AiksCanvasTest, RectClipIntersectAgainstEmptyCullRect)
| TEST (AiksCanvasTest, RectClipDiffAgainstEmptyCullRect)
| TEST (AiksCanvasTest, RectClipIntersectAgainstCullRect)
| TEST (AiksCanvasTest, RectClipDiffAgainstNonCoveredCullRect)
| TEST (AiksCanvasTest, RectClipDiffAboveCullRect)
| TEST (AiksCanvasTest, RectClipDiffBelowCullRect)
| TEST (AiksCanvasTest, RectClipDiffLeftOfCullRect)
| TEST (AiksCanvasTest, RectClipDiffRightOfCullRect)
| TEST (AiksCanvasTest, RectClipDiffAgainstVCoveredCullRect)
| TEST (AiksCanvasTest, RectClipDiffAgainstHCoveredCullRect)
| TEST (AiksCanvasTest, RRectClipIntersectAgainstEmptyCullRect)
| TEST (AiksCanvasTest, RRectClipDiffAgainstEmptyCullRect)
| TEST (AiksCanvasTest, RRectClipIntersectAgainstCullRect)
| TEST (AiksCanvasTest, RRectClipDiffAgainstNonCoveredCullRect)
| TEST (AiksCanvasTest, RRectClipDiffAgainstVPartiallyCoveredCullRect)
| TEST (AiksCanvasTest, RRectClipDiffAgainstVFullyCoveredCullRect)
| TEST (AiksCanvasTest, RRectClipDiffAgainstHPartiallyCoveredCullRect)
| TEST (AiksCanvasTest, RRectClipDiffAgainstHFullyCoveredCullRect)
| TEST (AiksCanvasTest, PathClipIntersectAgainstEmptyCullRect)
| TEST (AiksCanvasTest, PathClipDiffAgainstEmptyCullRect)
| TEST (AiksCanvasTest, PathClipIntersectAgainstCullRect)
| TEST (AiksCanvasTest, PathClipDiffAgainstNonCoveredCullRect)
| TEST (AiksCanvasTest, PathClipDiffAgainstFullyCoveredCullRect)
| TEST (AiksCanvasTest, DisableLocalBoundsRectForFilteredSaveLayers)
| TEST_F (ArchiveTest, SimpleInitialization)
| TEST_F (ArchiveTest, AddStorageClass)
| TEST_F (ArchiveTest, AddData)
| TEST_F (ArchiveTest, AddDataMultiple)
| TEST_F (ArchiveTest, ReadData)
| TEST_F (ArchiveTest, ReadDataWithNames)
| TEST_F (ArchiveTest, CanReadWriteVectorOfArchivables)
| TEST (ThreadTest, CanCreateMutex)
| TEST (ThreadTest, CanCreateMutexLock)
| TEST (ThreadTest, CanCreateRWMutex)
| TEST (ThreadTest, CanCreateRWMutexLock)
| TEST (StringsTest, CanSPrintF)
static std::shared_ptr< fml::Mapping > | CreateMappingFromString (std::string p_string)
const std::string | CreateStringFromMapping (const fml::Mapping &mapping)
| TEST (BlobTest, CanReadAndWriteBlobs)
| TEST (AllocatorTest, TextureDescriptorCompatibility)
flutter::DlColor | toColor (const float *components)
| INSTANTIATE_PLAYGROUND_SUITE (DisplayListTest)
| TEST_P (DisplayListTest, DrawPictureWithAClip)
| TEST_P (DisplayListTest, CanDrawRect)
| TEST_P (DisplayListTest, CanDrawTextBlob)
| TEST_P (DisplayListTest, CanDrawTextBlobWithGradient)
| TEST_P (DisplayListTest, CanDrawTextWithSaveLayer)
| TEST_P (DisplayListTest, CanDrawImage)
| TEST_P (DisplayListTest, CanDrawCapsAndJoins)
| TEST_P (DisplayListTest, CanDrawArc)
| TEST_P (DisplayListTest, StrokedPathsDrawCorrectly)
| TEST_P (DisplayListTest, CanDrawWithOddPathWinding)
| TEST_P (DisplayListTest, CanDrawAnOpenPath)
| TEST_P (DisplayListTest, CanDrawWithMaskBlur)
| TEST_P (DisplayListTest, CanDrawStrokedText)
| TEST_P (DisplayListTest, StrokedTextNotOffsetFromNormalText)
| TEST_P (DisplayListTest, IgnoreMaskFilterWhenSavingLayer)
| TEST_P (DisplayListTest, CanDrawWithBlendColorFilter)
| TEST_P (DisplayListTest, CanDrawWithColorFilterImageFilter)
| TEST_P (DisplayListTest, CanDrawWithImageBlurFilter)
| TEST_P (DisplayListTest, CanDrawWithComposeImageFilter)
| TEST_P (DisplayListTest, CanClampTheResultingColorOfColorMatrixFilter)
| TEST_P (DisplayListTest, CanDrawBackdropFilter)
| TEST_P (DisplayListTest, CanDrawNinePatchImage)
| TEST_P (DisplayListTest, CanDrawNinePatchImageCenterWidthBiggerThanDest)
| TEST_P (DisplayListTest, CanDrawNinePatchImageCenterHeightBiggerThanDest)
| TEST_P (DisplayListTest, CanDrawNinePatchImageCenterBiggerThanDest)
| TEST_P (DisplayListTest, CanDrawNinePatchImageCornersScaledDown)
| TEST_P (DisplayListTest, CanDrawPoints)
| TEST_P (DisplayListTest, CanDrawZeroLengthLine)
| TEST_P (DisplayListTest, CanDrawShadow)
| TEST_P (DisplayListTest, DispatcherDoesNotCullPerspectiveTransformedChildDisplayLists)
| TEST_P (DisplayListTest, TransparentShadowProducesCorrectColor)
| TEST_P (DisplayListTest, CanConvertTriangleFanToTriangles)
| TEST_P (DisplayListTest, CanDrawZeroWidthLine)
| TEST_P (DisplayListTest, CanDrawWithMatrixFilter)
| TEST_P (DisplayListTest, CanDrawWithMatrixFilterWhenSavingLayer)
| TEST_P (DisplayListTest, CanDrawRectWithLinearToSrgbColorFilter)
| TEST_P (DisplayListTest, CanDrawPaintWithColorSource)
| TEST_P (DisplayListTest, CanBlendDstOverAndDstCorrectly)
| TEST_P (DisplayListTest, CanDrawCorrectlyWithColorFilterAndImageFilter)
| TEST_P (DisplayListTest, MaskBlursApplyCorrectlyToColorSources)
| TEST_P (DisplayListTest, DrawVerticesSolidColorTrianglesWithoutIndices)
| TEST_P (DisplayListTest, DrawVerticesLinearGradientWithoutIndices)
| TEST_P (DisplayListTest, DrawVerticesLinearGradientWithTextureCoordinates)
| TEST_P (DisplayListTest, DrawVerticesImageSourceWithTextureCoordinates)
| TEST_P (DisplayListTest, DrawVerticesImageSourceWithTextureCoordinatesAndColorBlending)
| TEST_P (DisplayListTest, DrawVerticesSolidColorTrianglesWithIndices)
| TEST_P (DisplayListTest, DrawVerticesPremultipliesColors)
| TEST_P (DisplayListTest, DrawShapes)
| TEST_P (DisplayListTest, DrawVerticesBlendModes)
| TEST (SkiaConversionsTest, ToColor)
| TEST (SkiaConversionsTest, GradientStopConversion)
| TEST (SkiaConversionsTest, GradientMissing0)
| TEST (SkiaConversionsTest, GradientMissingLastValue)
| TEST (SkiaConversionsTest, GradientStopGreaterThan1)
| TEST (SkiaConversionsTest, GradientConversionNonMonotonic)
| TEST (FilterInputTest, CanSetLocalTransformForTexture)
| TEST (FilterInputTest, IsLeaf)
| TEST (FilterInputTest, SetCoverageInputs)
| INSTANTIATE_PLAYGROUND_SUITE (EntityTest)
| TEST_P (EntityTest, CanCreateEntity)
auto | CreatePassWithRectPath (Rect rect, std::optional< Rect > bounds_hint, bool collapse=false)
| TEST_P (EntityTest, EntityPassRespectsSubpassBoundsLimit)
| TEST_P (EntityTest, EntityPassCanMergeSubpassIntoParent)
| TEST_P (EntityTest, EntityPassCoverageRespectsCoverageLimit)
| TEST_P (EntityTest, FilterCoverageRespectsCropRect)
| TEST_P (EntityTest, CanDrawRect)
| TEST_P (EntityTest, CanDrawRRect)
| TEST_P (EntityTest, GeometryBoundsAreTransformed)
| TEST_P (EntityTest, ThreeStrokesInOnePath)
| TEST_P (EntityTest, StrokeWithTextureContents)
| TEST_P (EntityTest, TriangleInsideASquare)
| TEST_P (EntityTest, StrokeCapAndJoinTest)
| TEST_P (EntityTest, CubicCurveTest)
| TEST_P (EntityTest, CanDrawCorrectlyWithRotatedTransformation)
| TEST_P (EntityTest, CubicCurveAndOverlapTest)
| TEST_P (EntityTest, SolidColorContentsStrokeSetStrokeCapsAndJoins)
| TEST_P (EntityTest, SolidColorContentsStrokeSetMiterLimit)
| TEST_P (EntityTest, BlendingModeOptions)
| TEST_P (EntityTest, BezierCircleScaled)
| TEST_P (EntityTest, Filters)
| TEST_P (EntityTest, GaussianBlurFilter)
| TEST_P (EntityTest, MorphologyFilter)
| TEST_P (EntityTest, SetBlendMode)
| TEST_P (EntityTest, ContentsGetBoundsForEmptyPathReturnsNullopt)
| TEST_P (EntityTest, SolidStrokeCoverageIsCorrect)
| TEST_P (EntityTest, BorderMaskBlurCoverageIsCorrect)
| TEST_P (EntityTest, DrawAtlasNoColor)
| TEST_P (EntityTest, DrawAtlasWithColorAdvanced)
| TEST_P (EntityTest, DrawAtlasWithColorSimple)
| TEST_P (EntityTest, DrawAtlasUsesProvidedCullRectForCoverage)
| TEST_P (EntityTest, DrawAtlasWithOpacity)
| TEST_P (EntityTest, DrawAtlasNoColorFullSize)
| TEST_P (EntityTest, SolidFillCoverageIsCorrect)
| TEST_P (EntityTest, SolidFillShouldRenderIsCorrect)
| TEST_P (EntityTest, DoesNotCullEntitiesByDefault)
| TEST_P (EntityTest, ClipContentsShouldRenderIsCorrect)
| TEST_P (EntityTest, ClipContentsGetStencilCoverageIsCorrect)
| TEST_P (EntityTest, RRectShadowTest)
| TEST_P (EntityTest, ColorMatrixFilterCoverageIsCorrect)
| TEST_P (EntityTest, ColorMatrixFilterEditable)
| TEST_P (EntityTest, LinearToSrgbFilterCoverageIsCorrect)
| TEST_P (EntityTest, LinearToSrgbFilter)
| TEST_P (EntityTest, SrgbToLinearFilterCoverageIsCorrect)
| TEST_P (EntityTest, SrgbToLinearFilter)
| TEST_P (EntityTest, AtlasContentsSubAtlas)
static Vector3 | RGBToYUV (Vector3 rgb, YUVColorSpace yuv_color_space)
static std::vector< std::shared_ptr< Texture > > | CreateTestYUVTextures (Context *context, YUVColorSpace yuv_color_space)
| TEST_P (EntityTest, YUVToRGBFilter)
| TEST_P (EntityTest, RuntimeEffect)
| TEST_P (EntityTest, InheritOpacityTest)
| TEST_P (EntityTest, ColorFilterWithForegroundColorAdvancedBlend)
| TEST_P (EntityTest, ColorFilterWithForegroundColorClearBlend)
| TEST_P (EntityTest, ColorFilterWithForegroundColorSrcBlend)
| TEST_P (EntityTest, ColorFilterWithForegroundColorDstBlend)
| TEST_P (EntityTest, ColorFilterWithForegroundColorSrcInBlend)
| TEST_P (EntityTest, CoverageForStrokePathWithNegativeValuesInTransform)
| TEST_P (EntityTest, SolidColorContentsIsOpaque)
| TEST_P (EntityTest, ConicalGradientContentsIsOpaque)
| TEST_P (EntityTest, LinearGradientContentsIsOpaque)
| TEST_P (EntityTest, RadialGradientContentsIsOpaque)
| TEST_P (EntityTest, SweepGradientContentsIsOpaque)
| TEST_P (EntityTest, TiledTextureContentsIsOpaque)
| TEST_P (EntityTest, TessellateConvex)
| TEST_P (EntityTest, PointFieldGeometryDivisions)
| TEST_P (EntityTest, PointFieldGeometryCoverage)
| TEST_P (EntityTest, ColorFilterContentsWithLargeGeometry)
| TEST_P (EntityTest, TextContentsCeilsGlyphScaleToDecimal)
| TEST_P (EntityTest, AdvancedBlendCoverageHintIsNotResetByEntityPass)
| TEST (EntityGeometryTest, RectGeometryCoversArea)
| TEST (EntityGeometryTest, FillPathGeometryCoversArea)
| TEST (EntityGeometryTest, FillPathGeometryCoversAreaNoInnerRect)
| TEST (RenderTargetCacheTest, CachesUsedTexturesAcrossFrames)
| TEST (RenderTargetCacheTest, DoesNotPersistFailedAllocations)
| TEST (GeometryTest, ScalarNearlyEqual)
| TEST (GeometryTest, MakeColumn)
| TEST (GeometryTest, MakeRow)
| TEST (GeometryTest, RotationMatrix)
| TEST (GeometryTest, InvertMultMatrix)
| TEST (GeometryTest, MatrixBasis)
| TEST (GeometryTest, MutliplicationMatrix)
| TEST (GeometryTest, DeterminantTest)
| TEST (GeometryTest, InvertMatrix)
| TEST (GeometryTest, TestDecomposition)
| TEST (GeometryTest, TestDecomposition2)
| TEST (GeometryTest, TestRecomposition)
| TEST (GeometryTest, TestRecomposition2)
| TEST (GeometryTest, MatrixVectorMultiplication)
| TEST (GeometryTest, MatrixMakeRotationFromQuaternion)
| TEST (GeometryTest, MatrixTransformDirection)
| TEST (GeometryTest, MatrixGetMaxBasisLength)
| TEST (GeometryTest, MatrixGetMaxBasisLengthXY)
| TEST (GeometryTest, MatrixMakeOrthographic)
| TEST (GeometryTest, MatrixMakePerspective)
| TEST (GeometryTest, MatrixGetBasisVectors)
| TEST (GeometryTest, MatrixGetDirectionScale)
| TEST (GeometryTest, MatrixIsAligned)
| TEST (GeometryTest, MatrixTranslationScaleOnly)
| TEST (GeometryTest, MatrixLookAt)
| TEST (GeometryTest, QuaternionLerp)
| TEST (GeometryTest, QuaternionVectorMultiply)
| TEST (GeometryTest, EmptyPath)
| TEST (GeometryTest, SimplePath)
| TEST (GeometryTest, BoundingBoxCubic)
| TEST (GeometryTest, BoundingBoxOfCompositePathIsCorrect)
| TEST (GeometryTest, ExtremaOfCubicPathComponentIsCorrect)
| TEST (GeometryTest, PathGetBoundingBoxForCubicWithNoDerivativeRootsIsCorrect)
| TEST (GeometryTest, CanGenerateMipCounts)
| TEST (GeometryTest, CanConvertTTypesExplicitly)
| TEST (GeometryTest, CanPerformAlgebraicPointOps)
| TEST (GeometryTest, CanPerformAlgebraicPointOpsWithArithmeticTypes)
| TEST (GeometryTest, PointIntegerCoercesToFloat)
| TEST (GeometryTest, SizeCoercesToPoint)
| TEST (GeometryTest, CanUsePointAssignmentOperators)
| TEST (GeometryTest, PointDotProduct)
| TEST (GeometryTest, PointCrossProduct)
| TEST (GeometryTest, PointReflect)
| TEST (GeometryTest, PointAbs)
| TEST (GeometryTest, PointAngleTo)
| TEST (GeometryTest, PointMin)
| TEST (GeometryTest, Vector3Min)
| TEST (GeometryTest, Vector4Min)
| TEST (GeometryTest, PointMax)
| TEST (GeometryTest, Vector3Max)
| TEST (GeometryTest, Vector4Max)
| TEST (GeometryTest, PointFloor)
| TEST (GeometryTest, Vector3Floor)
| TEST (GeometryTest, Vector4Floor)
| TEST (GeometryTest, PointCeil)
| TEST (GeometryTest, Vector3Ceil)
| TEST (GeometryTest, Vector4Ceil)
| TEST (GeometryTest, PointRound)
| TEST (GeometryTest, Vector3Round)
| TEST (GeometryTest, Vector4Round)
| TEST (GeometryTest, PointLerp)
| TEST (GeometryTest, Vector3Lerp)
| TEST (GeometryTest, Vector4Lerp)
| TEST (GeometryTest, CanUseVector3AssignmentOperators)
| TEST (GeometryTest, CanPerformAlgebraicVector3Ops)
| TEST (GeometryTest, CanPerformAlgebraicVector3OpsWithArithmeticTypes)
| TEST (GeometryTest, ColorPremultiply)
| TEST (GeometryTest, ColorR8G8B8A8)
| TEST (GeometryTest, ColorLerp)
| TEST (GeometryTest, ColorClamp01)
| TEST (GeometryTest, ColorMakeRGBA8)
| TEST (GeometryTest, ColorApplyColorMatrix)
| TEST (GeometryTest, ColorLinearToSRGB)
| TEST (GeometryTest, ColorSRGBToLinear)
| TEST (GeometryTest, BlendModeToString)
| TEST (GeometryTest, CanConvertBetweenDegressAndRadians)
| TEST (GeometryTest, RectMakeSize)
| TEST (GeometryTest, RectUnion)
| TEST (GeometryTest, RectIntersection)
| TEST (GeometryTest, RectIntersectsWithRect)
| TEST (GeometryTest, RectCutout)
| TEST (GeometryTest, RectContainsPoint)
| TEST (GeometryTest, RectContainsRect)
| TEST (GeometryTest, RectGetPoints)
| TEST (GeometryTest, RectShift)
| TEST (GeometryTest, RectGetTransformedPoints)
| TEST (GeometryTest, RectMakePointBounds)
| TEST (GeometryTest, RectExpand)
| TEST (GeometryTest, RectGetPositive)
| TEST (GeometryTest, RectScale)
| TEST (GeometryTest, RectDirections)
| TEST (GeometryTest, RectProject)
| TEST (GeometryTest, CubicPathComponentPolylineDoesNotIncludePointOne)
| TEST (GeometryTest, PathCreatePolyLineDoesNotDuplicatePoints)
| TEST (GeometryTest, PathBuilderSetsCorrectContourPropertiesForAddCommands)
| TEST (GeometryTest, PathCreatePolylineGeneratesCorrectContourData)
| TEST (GeometryTest, PolylineGetContourPointBoundsReturnsCorrectRanges)
| TEST (GeometryTest, PathAddRectPolylineHasCorrectContourData)
| TEST (GeometryTest, PathPolylineDuplicatesAreRemovedForSameContour)
| TEST (GeometryTest, MatrixPrinting)
| TEST (GeometryTest, PointPrinting)
| TEST (GeometryTest, Vector3Printing)
| TEST (GeometryTest, Vector4Printing)
| TEST (GeometryTest, ColorPrinting)
| TEST (GeometryTest, ToIColor)
| TEST (GeometryTest, Gradient)
| TEST (GeometryTest, HalfConversions)
| TEST (GeometryTest, PathShifting)
| TEST (GeometryTest, PathBuilderWillComputeBounds)
| TEST_F (GoldenTests, ConicalGradient)
| TEST (BlitCommandVkTest, BlitCopyTextureToTextureCommandVK)
| TEST (BlitCommandVkTest, BlitCopyTextureToBufferCommandVK)
| TEST (BlitCommandVkTest, BlitCopyBufferToTextureCommandVK)
| TEST (BlitCommandVkTest, BlitGenerateMipmapCommandVK)
| TEST (CommandEncoderVKTest, DeleteEncoderAfterThreadDies)
| TEST (CommandEncoderVKTest, CleanupAfterSubmit)
| TEST (CommandPoolRecyclerVKTest, GetsACommandPoolPerThread)
| TEST (CommandPoolRecyclerVKTest, GetsTheSameCommandPoolOnSameThread)
| TEST (CommandPoolRecyclerVKTest, ReclaimMakesCommandPoolAvailable)
| TEST (ContextVKTest, DeletesCommandPools)
| TEST (ContextVKTest, DeletesCommandPoolsOnAllThreads)
| TEST (ContextVKTest, DeletePipelineAfterContext)
| TEST (ContextVKTest, DeleteShaderFunctionAfterContext)
| TEST (ContextVKTest, DeletePipelineLibraryAfterContext)
| TEST (ContextVKTest, CanCreateContextInAbsenceOfValidationLayers)
| TEST (ContextVKTest, CanCreateContextWithValidationLayers)
| TEST (FenceWaiterVKTest, IgnoresNullFence)
| TEST (FenceWaiterVKTest, IgnoresNullCallback)
| TEST (FenceWaiterVKTest, ExecutesFenceCallback)
| TEST (FenceWaiterVKTest, ExecutesFenceCallbackX2)
| TEST (FenceWaiterVKTest, ExecutesNewFenceThenOldFence)
| TEST (FenceWaiterVKTest, AddFenceDoesNothingIfTerminating)
| TEST (FenceWaiterVKTest, InProgressFencesStillWaitIfTerminated)
| TEST (PassBindingsCacheTest, bindPipeline)
| TEST (PassBindingsCacheTest, setStencilReference)
| TEST (PassBindingsCacheTest, setScissor)
| TEST (PassBindingsCacheTest, setViewport)
| TEST (ResourceManagerVKTest, CreatesANewInstance)
| TEST (ResourceManagerVKTest, ReclaimMovesAResourceAndDestroysIt)
| TEST (ResourceManagerVKTest, TerminatesWhenOutOfScope)
| TEST (ResourceManagerVKTest, IsThreadSafe)
| CAPABILITY_TEST (SupportsOffscreenMSAA, false)
| CAPABILITY_TEST (SupportsSSBO, false)
| CAPABILITY_TEST (SupportsBufferToTextureBlits, false)
| CAPABILITY_TEST (SupportsTextureToTextureBlits, false)
| CAPABILITY_TEST (SupportsFramebufferFetch, false)
| CAPABILITY_TEST (SupportsCompute, false)
| CAPABILITY_TEST (SupportsComputeSubgroups, false)
| CAPABILITY_TEST (SupportsReadFromOnscreenTexture, false)
| CAPABILITY_TEST (SupportsReadFromResolve, false)
| CAPABILITY_TEST (SupportsDecalSamplerAddressMode, false)
| CAPABILITY_TEST (SupportsDeviceTransientTextures, false)
| TEST (CapabilitiesTest, DefaultColorFormat)
| TEST (CapabilitiesTest, DefaultStencilFormat)
| TEST (CapabilitiesTest, DefaultDepthStencilFormat)
| INSTANTIATE_COMPUTE_SUITE (ComputeSubgroupTest)
| TEST_P (ComputeSubgroupTest, CapabilitiesSuportSubgroups)
| TEST_P (ComputeSubgroupTest, PathPlayground)
| TEST_P (ComputeSubgroupTest, LargePath)
| TEST_P (ComputeSubgroupTest, QuadAndCubicInOnePath)
| TEST_P (ComputeTest, CapabilitiesReportSupport)
| TEST_P (ComputeTest, CanCreateComputePass)
| TEST_P (ComputeTest, CanComputePrefixSum)
| TEST_P (ComputeTest, 1DThreadgroupSizingIsCorrect)
| TEST_P (ComputeTest, CanComputePrefixSumLargeInteractive)
| TEST_P (ComputeTest, MultiStageInputAndOutput)
| TEST_P (ComputeTest, CanCompute1DimensionalData)
| TEST_P (ComputeTest, ReturnsEarlyWhenAnyGridDimensionIsZero)
| TEST (HostBufferTest, TestInitialization)
| TEST (HostBufferTest, CanEmplace)
| TEST (HostBufferTest, CanEmplaceWithAlignment)
| TEST (PipelineDescriptorTest, PrimitiveTypeHashEquality)
| TEST (PoolTest, Simple)
| TEST (PoolTest, Overload)
| INSTANTIATE_PLAYGROUND_SUITE (RendererDartTest)
| TEST_P (RendererDartTest, CanRunDartInPlaygroundFrame)
| TEST_P (RendererDartTest, CanInstantiateFlutterGPUContext)
| TEST_P (RendererDartTest, CanEmplaceHostBuffer)
| INSTANTIATE_PLAYGROUND_SUITE (RendererTest)
| TEST_P (RendererTest, CanCreateBoxPrimitive)
| TEST_P (RendererTest, CanRenderPerspectiveCube)
| TEST_P (RendererTest, CanRenderMultiplePrimitives)
| TEST_P (RendererTest, CanRenderToTexture)
| TEST_P (RendererTest, CanRenderInstanced)
| TEST_P (RendererTest, CanBlitTextureToTexture)
| TEST_P (RendererTest, CanBlitTextureToBuffer)
| TEST_P (RendererTest, CanGenerateMipmaps)
| TEST_P (RendererTest, TheImpeller)
| TEST_P (RendererTest, ArrayUniforms)
| TEST_P (RendererTest, InactiveUniforms)
| TEST_P (RendererTest, CanCreateCPUBackedTexture)
| TEST_P (RendererTest, DefaultIndexSize)
| TEST_P (RendererTest, DefaultIndexBehavior)
| TEST_P (RendererTest, VertexBufferBuilder)
static const CompareFunctionUIData & | CompareFunctionUI ()
| TEST_P (RendererTest, StencilMask)
| INSTANTIATE_PLAYGROUND_SUITE (RuntimeStageTest)
| TEST (RuntimeStageTest, CanReadValidBlob)
| TEST (RuntimeStageTest, CanRejectInvalidBlob)
| TEST (RuntimeStageTest, CanReadUniforms)
| TEST_P (RuntimeStageTest, CanRegisterStage)
| TEST_P (RuntimeStageTest, CanCreatePipelineFromRuntimeStage)
| TEST (TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus)
static std::shared_ptr< GlyphAtlas > | CreateGlyphAtlas (Context &context, const TypographerContext *typographer_context, GlyphAtlas::Type type, Scalar scale, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const TextFrame &frame)
| TEST_P (TypographerTest, CanConvertTextBlob)
| TEST_P (TypographerTest, CanCreateRenderContext)
| TEST_P (TypographerTest, CanCreateGlyphAtlas)
static sk_sp< SkData > | OpenFixtureAsSkData (const char *fixture_name)
| TEST_P (TypographerTest, LazyAtlasTracksColor)
| TEST_P (TypographerTest, GlyphAtlasWithOddUniqueGlyphSize)
| TEST_P (TypographerTest, GlyphAtlasIsRecycledIfUnchanged)
| TEST_P (TypographerTest, GlyphAtlasWithLotsOfdUniqueGlyphSize)
| TEST_P (TypographerTest, GlyphAtlasTextureIsRecycledIfUnchanged)
| TEST_P (TypographerTest, GlyphAtlasTextureIsRecreatedIfTypeChanges)
| TEST_P (TypographerTest, MaybeHasOverlapping)
| TEST_P (TypographerTest, RectanglePackerAddsNonoverlapingRectangles)

## Variables
static int64_t | LastSample = 0
std::vector< Point > | golden_cubic_and_quad_points

## Typedef Documentation

## ◆ AiksCanvasTest

using impeller::testing::AiksCanvasTest = typedef ::testing::Test

Definition at line 16 of file canvas_unittests.cc.

## ◆ AiksTest

using impeller::testing::AiksTest = typedef AiksPlayground

Definition at line 52 of file aiks_unittests.cc.

## ◆ ArchiveTest

using impeller::testing::ArchiveTest = typedef ArchivistFixture

Definition at line 106 of file archivist_unittests.cc.

## ◆ ComputeSubgroupTest

using impeller::testing::ComputeSubgroupTest = typedef ComputePlaygroundTest

Definition at line 39 of file compute_subgroup_unittests.cc.

## ◆ ComputeTest

using impeller::testing::ComputeTest = typedef ComputePlaygroundTest

Definition at line 26 of file compute_unittests.cc.

## ◆ DeviceBufferTest

using impeller::testing::DeviceBufferTest = typedef Playground

Definition at line 12 of file device_buffer_unittests.cc.

## ◆ DisplayListTest

using impeller::testing::DisplayListTest = typedef DlPlayground

Definition at line 45 of file dl_unittests.cc.

## ◆ EntityTest

using impeller::testing::EntityTest = typedef EntityPlayground

Definition at line 67 of file entity_unittests.cc.

## ◆ RendererTest

using impeller::testing::RendererTest = typedef PlaygroundTest

Definition at line 49 of file renderer_unittests.cc.

## ◆ RuntimeStageTest

using impeller::testing::RuntimeStageTest = typedef RuntimeStagePlayground

Definition at line 23 of file runtime_stage_unittests.cc.

## ◆ TypographerTest

using impeller::testing::TypographerTest = typedef PlaygroundTest

Definition at line 22 of file typographer_unittests.cc.

## Function Documentation

## ◆ APPLY_COLOR_FILTER_GRADIENT_TEST() [1/4]

impeller::testing::APPLY_COLOR_FILTER_GRADIENT_TEST | ( | Conical |  | ) |

## ◆ APPLY_COLOR_FILTER_GRADIENT_TEST() [2/4]

impeller::testing::APPLY_COLOR_FILTER_GRADIENT_TEST | ( | Linear |  | ) |

## ◆ APPLY_COLOR_FILTER_GRADIENT_TEST() [3/4]

impeller::testing::APPLY_COLOR_FILTER_GRADIENT_TEST | ( | Radial |  | ) |

## ◆ APPLY_COLOR_FILTER_GRADIENT_TEST() [4/4]

impeller::testing::APPLY_COLOR_FILTER_GRADIENT_TEST | ( | Sweep |  | ) |

## ◆ BlendModeTest()

static Picture impeller::testing::BlendModeTest | ( | BlendMode | blend_mode,
|  | const std::shared_ptr< Image > & | src_image,
|  | const std::shared_ptr< Image > & | dst_image
| ) |  |
| static

1. Save layer blending (top squares).
2. CPU blend modes (bottom squares).
3. Image blending (top right).

Compare these results with the images in the Flutter blend mode documentation: https://api.flutter.dev/flutter/dart-ui/BlendMode.html

Definition at line 2523 of file aiks_unittests.cc.

2525 {
2526 Color destination_color = Color::CornflowerBlue().WithAlpha(0.75);
2527 auto source_colors = std::vector<Color>({Color::White().WithAlpha(0.75),
2528 Color::LimeGreen().WithAlpha(0.75),
2529 Color::Black().WithAlpha(0.75)});
2530
2531 Canvas canvas;
2532
2533 canvas.DrawPaint({.color = Color::Black()});
2534
2535 //----------------------------------------------------------------------------
2536 /// 1. Save layer blending (top squares).
2537 ///
2538
2539 canvas.Save();
2540 for (const auto& color : source_colors) {
2541 canvas.Save();
2542 {
2543 canvas.ClipRect(Rect::MakeXYWH(50, 50, 100, 100));
2544 // Perform the blend in a SaveLayer so that the initial backdrop color is
2545 // fully transparent black. SourceOver blend the result onto the parent
2546 // pass.
2547 canvas.SaveLayer({});
2548 {
2549 canvas.DrawPaint({.color = destination_color});
2550 // Draw the source color in an offscreen pass and blend it to the parent
2551 // pass.
2552 canvas.SaveLayer({.blend_mode = blend_mode});
2553 { //
2554 canvas.DrawRect({50, 50, 100, 100}, {.color = color});
2555 }
2556 canvas.Restore();
2557 }
2558 canvas.Restore();
2559 }
2560 canvas.Restore();
2561 canvas.Translate(Vector2(100, 0));
2562 }
2563 canvas.RestoreToCount(0);
2564
2565 //----------------------------------------------------------------------------
2566 /// 2. CPU blend modes (bottom squares).
2567 ///
2568
2569 canvas.Save();
2570 canvas.Translate({0, 100});
2571
2572 // Perform the blend in a SaveLayer so that the initial backdrop color is
2573 // fully transparent black. SourceOver blend the result onto the parent pass.
2574 canvas.SaveLayer({});
2575 // canvas.DrawPaint({.color = destination_color});
2576 for (const auto& color : source_colors) {
2577 // Simply write the CPU blended color to the pass.
2578 canvas.DrawRect({50, 50, 100, 100},
2579 {.color = destination_color.Blend(color, blend_mode),
2580 .blend_mode = BlendMode::kSourceOver});
2581 canvas.Translate(Vector2(100, 0));
2582 }
2583 canvas.RestoreToCount(0);
2584
2585 //----------------------------------------------------------------------------
2586 /// 3. Image blending (top right).
2587 ///
2588 /// Compare these results with the images in the Flutter blend mode
2589 /// documentation: https://api.flutter.dev/flutter/dart-ui/BlendMode.html
2590 ///
2591
2592 canvas.Save();
2593 // canvas.ClipRect(Rect::MakeXYWH(500, 0, 500, 500));
2594 canvas.SaveLayer({.blend_mode = BlendMode::kSourceOver});
2595 {
2596 canvas.DrawImage(dst_image, {400, 50}, {.blend_mode = BlendMode::kSource});
2597 canvas.DrawImage(src_image, {400, 50}, {.blend_mode = blend_mode});
2598 }
2599 canvas.RestoreToCount(0);
2600
2601 return canvas.EndRecordingAsPicture();
2602 }

References impeller::Color::Blend(), impeller::Canvas::DrawPaint(), and impeller::Color::WithAlpha().

## ◆ CanRenderConicalGradientWithDithering()

static void impeller::testing::CanRenderConicalGradientWithDithering | ( | AiksTest * | aiks_test,
|  | bool | use_dithering
| ) |  |
| static

Definition at line 509 of file aiks_unittests.cc.

510 {
511 Canvas canvas;
512 canvas.Scale(aiks_test->GetContentScale());
513 Paint paint;
514 canvas.Translate({100.0, 100.0, 0});
515
516 // #FFF -> #000
517 std::vector<Color> colors = {Color{1.0, 1.0, 1.0, 1.0},
518 Color{0.0, 0.0, 0.0, 1.0}};
519 std::vector<Scalar> stops = {0.0, 1.0};
520
521 paint.color_source = ColorSource::MakeConicalGradient(
522 {100, 100}, 100, std::move(colors), std::move(stops), {0, 1}, 0,
523 Entity::TileMode::kMirror, {});
524 paint.dither = use_dithering;
525
526 canvas.DrawRect({0, 0, 600, 600}, paint);
527 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
528 }

References impeller::Paint::color_source, impeller::Paint::dither, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Playground::GetContentScale(), impeller::Entity::kMirror, impeller::ColorSource::MakeConicalGradient(), impeller::AiksPlayground::OpenPlaygroundHere(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

Referenced by TEST_P().

## ◆ CanRenderLinearGradientWithDithering()

static void impeller::testing::CanRenderLinearGradientWithDithering | ( | AiksTest * | aiks_test,
|  | bool | use_dithering
| ) |  |
| static

Definition at line 425 of file aiks_unittests.cc.

426 {
427 Canvas canvas;
428 Paint paint;
429 canvas.Translate({100.0, 100.0, 0});
430
431 // 0xffcccccc --> 0xff333333, taken from
432 // https://github.com/flutter/flutter/issues/118073#issue-1521699748
433 std::vector<Color> colors = {Color{0.8, 0.8, 0.8, 1.0},
434 Color{0.2, 0.2, 0.2, 1.0}};
435 std::vector<Scalar> stops = {0.0, 1.0};
436
437 paint.color_source = ColorSource::MakeLinearGradient(
438 {0, 0}, {800, 500}, std::move(colors), std::move(stops),
439 Entity::TileMode::kClamp, {});
440 paint.dither = use_dithering;
441 canvas.DrawRect({0, 0, 800, 500}, paint);
442 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
443 }

References impeller::Paint::color_source, impeller::Paint::dither, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::ColorSource::MakeLinearGradient(), impeller::AiksPlayground::OpenPlaygroundHere(), and impeller::Canvas::Translate().

Referenced by TEST_P().

## ◆ CanRenderRadialGradientWithDithering()

static void impeller::testing::CanRenderRadialGradientWithDithering | ( | AiksTest * | aiks_test,
|  | bool | use_dithering
| ) |  |
| static

Definition at line 453 of file aiks_unittests.cc.

454 {
455 Canvas canvas;
456 Paint paint;
457 canvas.Translate({100.0, 100.0, 0});
458
459 // #FFF -> #000
460 std::vector<Color> colors = {Color{1.0, 1.0, 1.0, 1.0},
461 Color{0.0, 0.0, 0.0, 1.0}};
462 std::vector<Scalar> stops = {0.0, 1.0};
463
464 paint.color_source = ColorSource::MakeRadialGradient(
465 {600, 600}, 600, std::move(colors), std::move(stops),
466 Entity::TileMode::kClamp, {});
467 paint.dither = use_dithering;
468 canvas.DrawRect({0, 0, 1200, 1200}, paint);
469 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
470 }

References impeller::Paint::color_source, impeller::Paint::dither, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::ColorSource::MakeRadialGradient(), impeller::AiksPlayground::OpenPlaygroundHere(), and impeller::Canvas::Translate().

Referenced by TEST_P().

## ◆ CanRenderSweepGradientWithDithering()

static void impeller::testing::CanRenderSweepGradientWithDithering | ( | AiksTest * | aiks_test,
|  | bool | use_dithering
| ) |  |
| static

Definition at line 480 of file aiks_unittests.cc.

481 {
482 Canvas canvas;
483 canvas.Scale(aiks_test->GetContentScale());
484 Paint paint;
485 canvas.Translate({100.0, 100.0, 0});
486
487 // #FFF -> #000
488 std::vector<Color> colors = {Color{1.0, 1.0, 1.0, 1.0},
489 Color{0.0, 0.0, 0.0, 1.0}};
490 std::vector<Scalar> stops = {0.0, 1.0};
491
492 paint.color_source = ColorSource::MakeSweepGradient(
493 {100, 100}, Degrees(45), Degrees(135), std::move(colors),
494 std::move(stops), Entity::TileMode::kMirror, {});
495 paint.dither = use_dithering;
496
497 canvas.DrawRect({0, 0, 600, 600}, paint);
498 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
499 }

References impeller::Paint::color_source, impeller::Paint::dither, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Playground::GetContentScale(), impeller::Entity::kMirror, impeller::ColorSource::MakeSweepGradient(), impeller::AiksPlayground::OpenPlaygroundHere(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

Referenced by TEST_P().

## ◆ CAPABILITY_TEST() [1/11]

impeller::testing::CAPABILITY_TEST | ( | SupportsBufferToTextureBlits | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [2/11]

impeller::testing::CAPABILITY_TEST | ( | SupportsCompute | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [3/11]

impeller::testing::CAPABILITY_TEST | ( | SupportsComputeSubgroups | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [4/11]

impeller::testing::CAPABILITY_TEST | ( | SupportsDecalSamplerAddressMode | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [5/11]

impeller::testing::CAPABILITY_TEST | ( | SupportsDeviceTransientTextures | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [6/11]

impeller::testing::CAPABILITY_TEST | ( | SupportsFramebufferFetch | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [7/11]

impeller::testing::CAPABILITY_TEST | ( | SupportsOffscreenMSAA | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [8/11]

impeller::testing::CAPABILITY_TEST | ( | SupportsReadFromOnscreenTexture | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [9/11]

impeller::testing::CAPABILITY_TEST | ( | SupportsReadFromResolve | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [10/11]

impeller::testing::CAPABILITY_TEST | ( | SupportsSSBO | ,
|  | false |
| ) |  |

## ◆ CAPABILITY_TEST() [11/11]

impeller::testing::CAPABILITY_TEST | ( | SupportsTextureToTextureBlits | ,
|  | false |
| ) |  |

## ◆ CompareFunctionUI()

static const CompareFunctionUIData& impeller::testing::CompareFunctionUI | ( |  | ) |
| static

Definition at line 1104 of file renderer_unittests.cc.

1104 {
1105 static CompareFunctionUIData data;
1106 return data;
1107 }

Referenced by TEST_P().

## ◆ CreateGlyphAtlas()

static std::shared_ptr<GlyphAtlas> impeller::testing::CreateGlyphAtlas | ( | Context & | context,
|  | const TypographerContext * | typographer_context,
|  | GlyphAtlas::Type | type,
|  | Scalar | scale,
|  | const std::shared_ptr< GlyphAtlasContext > & | atlas_context,
|  | const TextFrame & | frame
| ) |  |
| static

Definition at line 25 of file typographer_unittests.cc.

31 {
32 FontGlyphMap font_glyph_map;
33 frame.CollectUniqueFontGlyphPairs(font_glyph_map, scale);
34 return typographer_context->CreateGlyphAtlas(context, type, atlas_context,
35 font_glyph_map);
36 }

References impeller::TextFrame::CollectUniqueFontGlyphPairs(), and impeller::TypographerContext::CreateGlyphAtlas().

Referenced by TEST_P().

## ◆ CreateMappingFromString()

static std::shared_ptr<fml::Mapping> impeller::testing::CreateMappingFromString | ( | std::string | p_string | ) |
| static

Definition at line 15 of file blobcat_unittests.cc.

16 {
17 auto string = std::make_shared<std::string>(std::move(p_string));
18 return std::make_shared<fml::NonOwnedMapping>(
19 reinterpret_cast<const uint8_t*>(string->data()), string->size(),
20 [string](auto, auto) {});
21 }

Referenced by TEST().

## ◆ CreatePassWithRectPath()

auto impeller::testing::CreatePassWithRectPath | ( | Rect | rect,
|  | std::optional< Rect > | bounds_hint,
|  | bool | collapse = `false`
| ) |  |

Definition at line 109 of file entity_unittests.cc.

111 {
112 auto subpass = std::make_unique<EntityPass>();
113 Entity entity;
114 entity.SetContents(SolidColorContents::Make(
115 PathBuilder{}.AddRect(rect).TakePath(), Color::Red()));
116 subpass->AddEntity(entity);
117 subpass->SetDelegate(std::make_unique<TestPassDelegate>(collapse));
118 subpass->SetBoundsLimit(bounds_hint);
119 return subpass;
120 }

References impeller::PathBuilder::AddRect(), impeller::SolidColorContents::Make(), impeller::Color::Red(), and impeller::Entity::SetContents().

Referenced by TEST_P().

## ◆ CreateStringFromMapping()

const std::string impeller::testing::CreateStringFromMapping | ( | const fml::Mapping & | mapping | ) |

Definition at line 23 of file blobcat_unittests.cc.

23 {
24 return std::string{reinterpret_cast<const char*>(mapping.GetMapping()),
25 mapping.GetSize()};
26 }

Referenced by TEST().

## ◆ CreateTestYUVTextures()

static std::vector<std::shared_ptr<Texture> > impeller::testing::CreateTestYUVTextures | ( | Context * | context,
|  | YUVColorSpace | yuv_color_space
| ) |  |
| static

Definition at line 2029 of file entity_unittests.cc.

2031 {
2032 Vector3 red = {244.0 / 255.0, 67.0 / 255.0, 54.0 / 255.0};
2033 Vector3 green = {76.0 / 255.0, 175.0 / 255.0, 80.0 / 255.0};
2034 Vector3 blue = {33.0 / 255.0, 150.0 / 255.0, 243.0 / 255.0};
2035 Vector3 white = {1.0, 1.0, 1.0};
2036 Vector3 red_yuv = RGBToYUV(red, yuv_color_space);
2037 Vector3 green_yuv = RGBToYUV(green, yuv_color_space);
2038 Vector3 blue_yuv = RGBToYUV(blue, yuv_color_space);
2039 Vector3 white_yuv = RGBToYUV(white, yuv_color_space);
2040 std::vector<Vector3> yuvs{red_yuv, green_yuv, blue_yuv, white_yuv};
2041 std::vector<uint8_t> y_data;
2042 std::vector<uint8_t> uv_data;
2043 for (int i = 0; i < 4; i++) {
2044 auto yuv = yuvs[i];
2045 uint8_t y = std::round(yuv.x * 255.0);
2046 uint8_t u = std::round(yuv.y * 255.0);
2047 uint8_t v = std::round(yuv.z * 255.0);
2048 for (int j = 0; j < 16; j++) {
2049 y_data.push_back(y);
2050 }
2051 for (int j = 0; j < 8; j++) {
2052 uv_data.push_back(j % 2 == 0 ? u : v);
2053 }
2054 }
2055 impeller::TextureDescriptor y_texture_descriptor;
2056 y_texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
2057 y_texture_descriptor.format = PixelFormat::kR8UNormInt;
2058 y_texture_descriptor.size = {8, 8};
2059 auto y_texture =
2060 context->GetResourceAllocator()->CreateTexture(y_texture_descriptor);
2061 auto y_mapping = std::make_shared<fml::DataMapping>(y_data);
2062 if (!y_texture->SetContents(y_mapping)) {
2063 FML_DLOG(ERROR) << "Could not copy contents into Y texture.";
2064 }
2065
2066 impeller::TextureDescriptor uv_texture_descriptor;
2067 uv_texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
2068 uv_texture_descriptor.format = PixelFormat::kR8G8UNormInt;
2069 uv_texture_descriptor.size = {4, 4};
2070 auto uv_texture =
2071 context->GetResourceAllocator()->CreateTexture(uv_texture_descriptor);
2072 auto uv_mapping = std::make_shared<fml::DataMapping>(uv_data);
2073 if (!uv_texture->SetContents(uv_mapping)) {
2074 FML_DLOG(ERROR) << "Could not copy contents into UV texture.";
2075 }
2076
2077 return {y_texture, uv_texture};
2078 }

References impeller::TextureDescriptor::format, impeller::Context::GetResourceAllocator(), impeller::kHostVisible, impeller::kR8G8UNormInt, impeller::kR8UNormInt, RGBToYUV(), impeller::TextureDescriptor::size, and impeller::TextureDescriptor::storage_mode.

Referenced by TEST_P().

## ◆ GetBlendModeSelection()

static BlendModeSelection impeller::testing::GetBlendModeSelection | ( |  | ) |
| static

Definition at line 1610 of file aiks_unittests.cc.

1610 {
1611 std::vector<const char*> blend_mode_names;
1612 std::vector<BlendMode> blend_mode_values;
1613 {
1614 const std::vector<std::tuple<const char*, BlendMode>> blends = {
1615 IMPELLER_FOR_EACH_BLEND_MODE(BLEND_MODE_TUPLE)};
1616 assert(blends.size() ==
1617 static_cast<size_t>(Entity::kLastAdvancedBlendMode) + 1);
1618 for (const auto& [name, mode] : blends) {
1619 blend_mode_names.push_back(name);
1620 blend_mode_values.push_back(mode);
1621 }
1622 }
1623
1624 return {blend_mode_names, blend_mode_values};
1625 }

References BLEND_MODE_TUPLE, and IMPELLER_FOR_EACH_BLEND_MODE.

Referenced by TEST_P().

## ◆ INSTANTIATE_COMPUTE_SUITE()

impeller::testing::INSTANTIATE_COMPUTE_SUITE | ( | ComputeSubgroupTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [1/6]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | AiksTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [2/6]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | DisplayListTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [3/6]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | EntityTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [4/6]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | RendererDartTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [5/6]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | RendererTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [6/6]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | RuntimeStageTest |  | ) |

## ◆ OpenFixtureAsSkData() [1/2]

static sk_sp<SkData> impeller::testing::OpenFixtureAsSkData | ( | const char * | fixture_name | ) |
| static

Definition at line 89 of file typographer_unittests.cc.

89 {
90 auto mapping = flutter::testing::OpenFixtureAsMapping(fixture_name);
91 if (!mapping) {
92 return nullptr;
93 }
94 auto data = SkData::MakeWithProc(
95 mapping->GetMapping(), mapping->GetSize(),
96 [](const void* ptr, void* context) {
97 delete reinterpret_cast<fml::Mapping*>(context);
98 },
99 mapping.get());
100 mapping.release();
101 return data;
102 }

## ◆ OpenFixtureAsSkData() [2/2]

static sk_sp<SkData> impeller::testing::OpenFixtureAsSkData | ( | const char * | fixture_name | ) |
| static

Definition at line 1282 of file aiks_unittests.cc.

1282 {
1283 auto mapping = flutter::testing::OpenFixtureAsMapping(fixture_name);
1284 if (!mapping) {
1285 return nullptr;
1286 }
1287 auto data = SkData::MakeWithProc(
1288 mapping->GetMapping(), mapping->GetSize(),
1289 [](const void* ptr, void* context) {
1290 delete reinterpret_cast<fml::Mapping*>(context);
1291 },
1292 mapping.get());
1293 mapping.release();
1294 return data;
1295 }

Referenced by TEST_P().

## ◆ RenderTextInCanvasSkia()

bool impeller::testing::RenderTextInCanvasSkia | ( | const std::shared_ptr< Context > & | context,
|  | Canvas & | canvas,
|  | const std::string & | text,
|  | const std::string & | font_fixture,
|  | TextRenderOptions | options = `{}`
| ) |  |

Definition at line 1303 of file aiks_unittests.cc.

1307 {}) {
1308 // Draw the baseline.
1309 canvas.DrawRect({options.position.x - 50, options.position.y, 900, 10},
1310 Paint{.color = Color::Aqua().WithAlpha(0.25)});
1311
1312 // Mark the point at which the text is drawn.
1313 canvas.DrawCircle(options.position, 5.0,
1314 Paint{.color = Color::Red().WithAlpha(0.25)});
1315
1316 // Construct the text blob.
1317 auto mapping = OpenFixtureAsSkData(font_fixture.c_str());
1318 if (!mapping) {
1319 return false;
1320 }
1321 SkFont sk_font(SkTypeface::MakeFromData(mapping), options.font_size);
1322 auto blob = SkTextBlob::MakeFromString(text.c_str(), sk_font);
1323 if (!blob) {
1324 return false;
1325 }
1326
1327 // Create the Impeller text frame and draw it at the designated baseline.
1328 auto frame = MakeTextFrameFromTextBlobSkia(blob);
1329
1330 Paint text_paint;
1331 text_paint.color = Color::Yellow().WithAlpha(options.alpha);
1332 canvas.DrawTextFrame(frame, options.position, text_paint);
1333 return true;
1334 }

Referenced by TEST_P().

## ◆ RenderTextInCanvasSTB()

bool impeller::testing::RenderTextInCanvasSTB | ( | const std::shared_ptr< Context > & | context,
|  | Canvas & | canvas,
|  | const std::string & | text,
|  | const std::string & | font_fixture,
|  | TextRenderOptions | options = `{}`
| ) |  |

Definition at line 1336 of file aiks_unittests.cc.

1340 {}) {
1341 // Draw the baseline.
1342 canvas.DrawRect({options.position.x - 50, options.position.y, 900, 10},
1343 Paint{.color = Color::Aqua().WithAlpha(0.25)});
1344
1345 // Mark the point at which the text is drawn.
1346 canvas.DrawCircle(options.position, 5.0,
1347 Paint{.color = Color::Red().WithAlpha(0.25)});
1348
1349 // Construct the text blob.
1350 auto mapping = flutter::testing::OpenFixtureAsMapping(font_fixture.c_str());
1351 if (!mapping) {
1352 return false;
1353 }
1354 auto typeface_stb = std::make_shared<TypefaceSTB>(std::move(mapping));
1355
1356 auto frame = MakeTextFrameSTB(
1357 typeface_stb, Font::Metrics{.point_size = options.font_size}, text);
1358
1359 Paint text_paint;
1360 text_paint.color = Color::Yellow().WithAlpha(options.alpha);
1361 canvas.DrawTextFrame(frame, options.position, text_paint);
1362 return true;
1363 }

Referenced by TEST_P().

## ◆ RGBToYUV()

static Vector3 impeller::testing::RGBToYUV | ( | Vector3 | rgb,
|  | YUVColorSpace | yuv_color_space
| ) |  |
| static

Definition at line 2012 of file entity_unittests.cc.

2012 {
2013 Vector3 yuv;
2014 switch (yuv_color_space) {
2015 case YUVColorSpace::kBT601FullRange:
2016 yuv.x = rgb.x * 0.299 + rgb.y * 0.587 + rgb.z * 0.114;
2017 yuv.y = rgb.x * -0.169 + rgb.y * -0.331 + rgb.z * 0.5 + 0.5;
2018 yuv.z = rgb.x * 0.5 + rgb.y * -0.419 + rgb.z * -0.081 + 0.5;
2019 break;
2020 case YUVColorSpace::kBT601LimitedRange:
2021 yuv.x = rgb.x * 0.257 + rgb.y * 0.516 + rgb.z * 0.100 + 0.063;
2022 yuv.y = rgb.x * -0.145 + rgb.y * -0.291 + rgb.z * 0.439 + 0.5;
2023 yuv.z = rgb.x * 0.429 + rgb.y * -0.368 + rgb.z * -0.071 + 0.5;
2024 break;
2025 }
2026 return yuv;
2027 }

References impeller::kBT601FullRange, impeller::kBT601LimitedRange, impeller::Vector3::x, impeller::Vector3::y, and impeller::Vector3::z.

Referenced by CreateTestYUVTextures().

## ◆ TEST() [1/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | DisableLocalBoundsRectForFilteredSaveLayers |
| ) |  |

Definition at line 340 of file canvas_unittests.cc.

340 {
341 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
342
343 Canvas canvas(initial_cull);
344 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
345
346 canvas.Save();
347 canvas.SaveLayer(
348 Paint{.image_filter = ImageFilter::MakeBlur(
349 Sigma(10), Sigma(10), FilterContents::BlurStyle::kNormal,
350 Entity::TileMode::kDecal)});
351 ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
352
353 canvas.Restore();
354 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
355 }

References impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Paint::image_filter, impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), impeller::Canvas::Save(), and impeller::Canvas::SaveLayer().

## ◆ TEST() [2/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | EmptyCullRect |
| ) |  |

Definition at line 18 of file canvas_unittests.cc.

18 {
19 Canvas canvas;
20
21 ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
22 }

References impeller::Canvas::GetCurrentLocalCullingBounds().

## ◆ TEST() [3/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | InitialCullRect |
| ) |  |

Definition at line 24 of file canvas_unittests.cc.

24 {
25 Rect initial_cull(0, 0, 10, 10);
26
27 Canvas canvas(initial_cull);
28
29 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
30 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), initial_cull);
31 }

References impeller::Canvas::GetCurrentLocalCullingBounds().

## ◆ TEST() [4/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | PathClipDiffAgainstEmptyCullRect |
| ) |  |

Definition at line 277 of file canvas_unittests.cc.

277 {
278 PathBuilder builder;
279 builder.AddRect({5, 5, 1, 1});
280 builder.AddRect({5, 14, 1, 1});
281 builder.AddRect({14, 5, 1, 1});
282 builder.AddRect({14, 14, 1, 1});
283 Path path = builder.TakePath();
284
285 Canvas canvas;
286 canvas.ClipPath(path, Entity::ClipOperation::kDifference);
287
288 ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
289 }

References impeller::PathBuilder::AddRect(), impeller::Canvas::ClipPath(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, and impeller::PathBuilder::TakePath().

## ◆ TEST() [5/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | PathClipDiffAgainstFullyCoveredCullRect |
| ) |  |

Definition at line 325 of file canvas_unittests.cc.

325 {
326 Rect initial_cull(5, 5, 10, 10);
327 PathBuilder builder;
328 builder.AddRect({0, 0, 100, 100});
329 Path path = builder.TakePath();
330 // Diff clip of Paths is ignored due to complexity
331 Rect result_cull(5, 5, 10, 10);
332
333 Canvas canvas(initial_cull);
334 canvas.ClipPath(path, Entity::ClipOperation::kDifference);
335
336 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
337 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
338 }

References impeller::PathBuilder::AddRect(), impeller::Canvas::ClipPath(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, and impeller::PathBuilder::TakePath().

## ◆ TEST() [6/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | PathClipDiffAgainstNonCoveredCullRect |
| ) |  |

Definition at line 308 of file canvas_unittests.cc.

308 {
309 Rect initial_cull(0, 0, 10, 10);
310 PathBuilder builder;
311 builder.AddRect({5, 5, 1, 1});
312 builder.AddRect({5, 14, 1, 1});
313 builder.AddRect({14, 5, 1, 1});
314 builder.AddRect({14, 14, 1, 1});
315 Path path = builder.TakePath();
316 Rect result_cull(0, 0, 10, 10);
317
318 Canvas canvas(initial_cull);
319 canvas.ClipPath(path, Entity::ClipOperation::kDifference);
320
321 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
322 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
323 }

References impeller::PathBuilder::AddRect(), impeller::Canvas::ClipPath(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, and impeller::PathBuilder::TakePath().

## ◆ TEST() [7/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | PathClipIntersectAgainstCullRect |
| ) |  |

Definition at line 291 of file canvas_unittests.cc.

291 {
292 Rect initial_cull(0, 0, 10, 10);
293 PathBuilder builder;
294 builder.AddRect({5, 5, 1, 1});
295 builder.AddRect({5, 14, 1, 1});
296 builder.AddRect({14, 5, 1, 1});
297 builder.AddRect({14, 14, 1, 1});
298 Path path = builder.TakePath();
299 Rect result_cull(5, 5, 5, 5);
300
301 Canvas canvas(initial_cull);
302 canvas.ClipPath(path, Entity::ClipOperation::kIntersect);
303
304 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
305 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
306 }

References impeller::PathBuilder::AddRect(), impeller::Canvas::ClipPath(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kIntersect, and impeller::PathBuilder::TakePath().

## ◆ TEST() [8/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | PathClipIntersectAgainstEmptyCullRect |
| ) |  |

Definition at line 261 of file canvas_unittests.cc.

261 {
262 PathBuilder builder;
263 builder.AddRect({5, 5, 1, 1});
264 builder.AddRect({5, 14, 1, 1});
265 builder.AddRect({14, 5, 1, 1});
266 builder.AddRect({14, 14, 1, 1});
267 Path path = builder.TakePath();
268 Rect rect_clip(5, 5, 10, 10);
269
270 Canvas canvas;
271 canvas.ClipPath(path, Entity::ClipOperation::kIntersect);
272
273 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
274 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), rect_clip);
275 }

References impeller::PathBuilder::AddRect(), impeller::Canvas::ClipPath(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kIntersect, and impeller::PathBuilder::TakePath().

## ◆ TEST() [9/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipDiffAboveCullRect |
| ) |  |

Definition at line 98 of file canvas_unittests.cc.

98 {
99 Rect initial_cull(5, 5, 10, 10);
100 Rect rect_clip(0, 0, 20, 4);
101 Rect result_cull(5, 5, 10, 10);
102
103 Canvas canvas(initial_cull);
104 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
105
106 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
107 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
108 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Entity::kDifference.

## ◆ TEST() [10/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipDiffAgainstEmptyCullRect |
| ) |  |

Definition at line 65 of file canvas_unittests.cc.

65 {
66 Rect rect_clip(5, 5, 10, 10);
67
68 Canvas canvas;
69 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
70
71 ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
72 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Entity::kDifference.

## ◆ TEST() [11/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipDiffAgainstHCoveredCullRect |
| ) |  |

Definition at line 158 of file canvas_unittests.cc.

158 {
159 Rect initial_cull(0, 0, 10, 10);
160 Rect rect_clip(0, 5, 10, 10);
161 Rect result_cull(0, 0, 10, 5);
162
163 Canvas canvas(initial_cull);
164 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
165
166 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
167 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
168 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Entity::kDifference.

## ◆ TEST() [12/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipDiffAgainstNonCoveredCullRect |
| ) |  |

Definition at line 86 of file canvas_unittests.cc.

86 {
87 Rect initial_cull(0, 0, 10, 10);
88 Rect rect_clip(5, 5, 10, 10);
89 Rect result_cull(0, 0, 10, 10);
90
91 Canvas canvas(initial_cull);
92 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
93
94 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
95 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
96 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Entity::kDifference.

## ◆ TEST() [13/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipDiffAgainstVCoveredCullRect |
| ) |  |

Definition at line 146 of file canvas_unittests.cc.

146 {
147 Rect initial_cull(0, 0, 10, 10);
148 Rect rect_clip(5, 0, 10, 10);
149 Rect result_cull(0, 0, 5, 10);
150
151 Canvas canvas(initial_cull);
152 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
153
154 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
155 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
156 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Entity::kDifference.

## ◆ TEST() [14/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipDiffBelowCullRect |
| ) |  |

Definition at line 110 of file canvas_unittests.cc.

110 {
111 Rect initial_cull(5, 5, 10, 10);
112 Rect rect_clip(0, 16, 20, 4);
113 Rect result_cull(5, 5, 10, 10);
114
115 Canvas canvas(initial_cull);
116 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
117
118 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
119 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
120 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Entity::kDifference.

## ◆ TEST() [15/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipDiffLeftOfCullRect |
| ) |  |

Definition at line 122 of file canvas_unittests.cc.

122 {
123 Rect initial_cull(5, 5, 10, 10);
124 Rect rect_clip(0, 0, 4, 20);
125 Rect result_cull(5, 5, 10, 10);
126
127 Canvas canvas(initial_cull);
128 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
129
130 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
131 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
132 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Entity::kDifference.

## ◆ TEST() [16/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipDiffRightOfCullRect |
| ) |  |

Definition at line 134 of file canvas_unittests.cc.

134 {
135 Rect initial_cull(5, 5, 10, 10);
136 Rect rect_clip(16, 0, 4, 20);
137 Rect result_cull(5, 5, 10, 10);
138
139 Canvas canvas(initial_cull);
140 canvas.ClipRect(rect_clip, Entity::ClipOperation::kDifference);
141
142 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
143 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
144 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Entity::kDifference.

## ◆ TEST() [17/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipIntersectAgainstCullRect |
| ) |  |

Definition at line 74 of file canvas_unittests.cc.

74 {
75 Rect initial_cull(0, 0, 10, 10);
76 Rect rect_clip(5, 5, 10, 10);
77 Rect result_cull(5, 5, 5, 5);
78
79 Canvas canvas(initial_cull);
80 canvas.ClipRect(rect_clip, Entity::ClipOperation::kIntersect);
81
82 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
83 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
84 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Entity::kIntersect.

## ◆ TEST() [18/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RectClipIntersectAgainstEmptyCullRect |
| ) |  |

Definition at line 55 of file canvas_unittests.cc.

55 {
56 Rect rect_clip(5, 5, 10, 10);
57
58 Canvas canvas;
59 canvas.ClipRect(rect_clip, Entity::ClipOperation::kIntersect);
60
61 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
62 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), rect_clip);
63 }

References impeller::Canvas::ClipRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Entity::kIntersect.

## ◆ TEST() [19/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RRectClipDiffAgainstEmptyCullRect |
| ) |  |

Definition at line 180 of file canvas_unittests.cc.

180 {
181 Rect rect_clip(5, 5, 10, 10);
182
183 Canvas canvas;
184 canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kDifference);
185
186 ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value());
187 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Entity::kDifference.

## ◆ TEST() [20/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RRectClipDiffAgainstHFullyCoveredCullRect |
| ) |  |

Definition at line 249 of file canvas_unittests.cc.

249 {
250 Rect initial_cull(0, 0, 10, 10);
251 Rect rect_clip(-2, 5, 14, 10);
252 Rect result_cull(0, 0, 10, 5);
253
254 Canvas canvas(initial_cull);
255 canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kDifference);
256
257 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
258 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
259 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Entity::kDifference.

## ◆ TEST() [21/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RRectClipDiffAgainstHPartiallyCoveredCullRect |
| ) |  |

Definition at line 237 of file canvas_unittests.cc.

237 {
238 Rect initial_cull(0, 0, 10, 10);
239 Rect rect_clip(0, 5, 10, 10);
240 Rect result_cull(0, 0, 10, 6);
241
242 Canvas canvas(initial_cull);
243 canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kDifference);
244
245 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
246 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
247 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Entity::kDifference.

## ◆ TEST() [22/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RRectClipDiffAgainstNonCoveredCullRect |
| ) |  |

Definition at line 201 of file canvas_unittests.cc.

201 {
202 Rect initial_cull(0, 0, 10, 10);
203 Rect rect_clip(5, 5, 10, 10);
204 Rect result_cull(0, 0, 10, 10);
205
206 Canvas canvas(initial_cull);
207 canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kDifference);
208
209 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
210 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
211 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Entity::kDifference.

## ◆ TEST() [23/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RRectClipDiffAgainstVFullyCoveredCullRect |
| ) |  |

Definition at line 225 of file canvas_unittests.cc.

225 {
226 Rect initial_cull(0, 0, 10, 10);
227 Rect rect_clip(5, -2, 10, 14);
228 Rect result_cull(0, 0, 5, 10);
229
230 Canvas canvas(initial_cull);
231 canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kDifference);
232
233 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
234 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
235 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Entity::kDifference.

## ◆ TEST() [24/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RRectClipDiffAgainstVPartiallyCoveredCullRect |
| ) |  |

Definition at line 213 of file canvas_unittests.cc.

213 {
214 Rect initial_cull(0, 0, 10, 10);
215 Rect rect_clip(5, 0, 10, 10);
216 Rect result_cull(0, 0, 6, 10);
217
218 Canvas canvas(initial_cull);
219 canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kDifference);
220
221 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
222 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
223 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Entity::kDifference.

## ◆ TEST() [25/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RRectClipIntersectAgainstCullRect |
| ) |  |

Definition at line 189 of file canvas_unittests.cc.

189 {
190 Rect initial_cull(0, 0, 10, 10);
191 Rect rect_clip(5, 5, 10, 10);
192 Rect result_cull(5, 5, 5, 5);
193
194 Canvas canvas(initial_cull);
195 canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kIntersect);
196
197 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
198 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull);
199 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Entity::kIntersect.

## ◆ TEST() [26/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | RRectClipIntersectAgainstEmptyCullRect |
| ) |  |

Definition at line 170 of file canvas_unittests.cc.

170 {
171 Rect rect_clip(5, 5, 10, 10);
172
173 Canvas canvas;
174 canvas.ClipRRect(rect_clip, 1, Entity::ClipOperation::kIntersect);
175
176 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
177 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), rect_clip);
178 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Entity::kIntersect.

## ◆ TEST() [27/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | ScaledCullRect |
| ) |  |

Definition at line 44 of file canvas_unittests.cc.

44 {
45 Rect initial_cull(5, 5, 10, 10);
46 Rect scaled_cull(10, 10, 20, 20);
47
48 Canvas canvas(initial_cull);
49 canvas.Scale(Vector2(0.5, 0.5));
50
51 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
52 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), scaled_cull);
53 }

References impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Canvas::Scale().

## ◆ TEST() [28/202]

impeller::testing::TEST | ( | AiksCanvasTest | ,
|  | TranslatedCullRect |
| ) |  |

Definition at line 33 of file canvas_unittests.cc.

33 {
34 Rect initial_cull(5, 5, 10, 10);
35 Rect translated_cull(0, 0, 10, 10);
36
37 Canvas canvas(initial_cull);
38 canvas.Translate(Vector3(5, 5, 0));
39
40 ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value());
41 ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), translated_cull);
42 }

References impeller::Canvas::GetCurrentLocalCullingBounds(), and impeller::Canvas::Translate().

## ◆ TEST() [29/202]

impeller::testing::TEST | ( | AllocatorTest | ,
|  | TextureDescriptorCompatibility |
| ) |  |

Definition at line 16 of file allocator_unittests.cc.

16 {
17 // Size.
18 {
19 TextureDescriptor desc_a = {.size = ISize(100, 100)};
20 TextureDescriptor desc_b = {.size = ISize(100, 100)};
21 TextureDescriptor desc_c = {.size = ISize(101, 100)};
22
23 ASSERT_EQ(desc_a, desc_b);
24 ASSERT_NE(desc_a, desc_c);
25 }
26 // Storage Mode.
27 {
28 TextureDescriptor desc_a = {.storage_mode = StorageMode::kDevicePrivate};
29 TextureDescriptor desc_b = {.storage_mode = StorageMode::kDevicePrivate};
30 TextureDescriptor desc_c = {.storage_mode = StorageMode::kHostVisible};
31
32 ASSERT_EQ(desc_a, desc_b);
33 ASSERT_NE(desc_a, desc_c);
34 }
35 // Format.
36 {
37 TextureDescriptor desc_a = {.format = PixelFormat::kR8G8B8A8UNormInt};
38 TextureDescriptor desc_b = {.format = PixelFormat::kR8G8B8A8UNormInt};
39 TextureDescriptor desc_c = {.format = PixelFormat::kB10G10R10A10XR};
40
41 ASSERT_EQ(desc_a, desc_b);
42 ASSERT_NE(desc_a, desc_c);
43 }
44 // Sample Count.
45 {
46 TextureDescriptor desc_a = {.sample_count = SampleCount::kCount4};
47 TextureDescriptor desc_b = {.sample_count = SampleCount::kCount4};
48 TextureDescriptor desc_c = {.sample_count = SampleCount::kCount1};
49
50 ASSERT_EQ(desc_a, desc_b);
51 ASSERT_NE(desc_a, desc_c);
52 }
53 // Sample Count.
54 {
55 TextureDescriptor desc_a = {.type = TextureType::kTexture2DMultisample};
56 TextureDescriptor desc_b = {.type = TextureType::kTexture2DMultisample};
57 TextureDescriptor desc_c = {.type = TextureType::kTexture2D};
58
59 ASSERT_EQ(desc_a, desc_b);
60 ASSERT_NE(desc_a, desc_c);
61 }
62 // Compression.
63 {
64 TextureDescriptor desc_a = {.compression_type = CompressionType::kLossless};
65 TextureDescriptor desc_b = {.compression_type = CompressionType::kLossless};
66 TextureDescriptor desc_c = {.compression_type = CompressionType::kLossy};
67
68 ASSERT_EQ(desc_a, desc_b);
69 ASSERT_NE(desc_a, desc_c);
70 }
71 // Mip Count.
72 {
73 TextureDescriptor desc_a = {.mip_count = 1};
74 TextureDescriptor desc_b = {.mip_count = 1};
75 TextureDescriptor desc_c = {.mip_count = 4};
76
77 ASSERT_EQ(desc_a, desc_b);
78 ASSERT_NE(desc_a, desc_c);
79 }
80 }

References impeller::TextureDescriptor::compression_type, impeller::TextureDescriptor::format, impeller::kB10G10R10A10XR, impeller::kCount1, impeller::kCount4, impeller::kDevicePrivate, impeller::kHostVisible, impeller::kLossless, impeller::kLossy, impeller::kR8G8B8A8UNormInt, impeller::kTexture2D, impeller::kTexture2DMultisample, impeller::TextureDescriptor::mip_count, impeller::TextureDescriptor::sample_count, impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, and impeller::TextureDescriptor::type.

## ◆ TEST() [30/202]

impeller::testing::TEST | ( | BlitCommandVkTest | ,
|  | BlitCopyBufferToTextureCommandVK |
| ) |  |

Definition at line 46 of file blit_command_vk_unittests.cc.

46 {
47 auto context = MockVulkanContextBuilder().Build();
48 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
49 BlitCopyBufferToTextureCommandVK cmd;
50 cmd.destination = context->GetResourceAllocator()->CreateTexture({
51 .size = ISize(100, 100),
52 });
53 cmd.source = context->GetResourceAllocator()
54 ->CreateBuffer({
55 .size = 1,
56 })
57 ->AsBufferView();
58 bool result = cmd.Encode(*encoder.get());
59 EXPECT_TRUE(result);
60 EXPECT_TRUE(encoder->IsTracking(cmd.source.buffer));
61 EXPECT_TRUE(encoder->IsTracking(cmd.destination));
62 }

References impeller::BufferView::buffer, impeller::BlitCopyBufferToTextureCommand::destination, impeller::BlitCopyBufferToTextureCommandVK::Encode(), and impeller::BlitCopyBufferToTextureCommand::source.

## ◆ TEST() [31/202]

impeller::testing::TEST | ( | BlitCommandVkTest | ,
|  | BlitCopyTextureToBufferCommandVK |
| ) |  |

Definition at line 30 of file blit_command_vk_unittests.cc.

30 {
31 auto context = MockVulkanContextBuilder().Build();
32 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
33 BlitCopyTextureToBufferCommandVK cmd;
34 cmd.source = context->GetResourceAllocator()->CreateTexture({
35 .size = ISize(100, 100),
36 });
37 cmd.destination = context->GetResourceAllocator()->CreateBuffer({
38 .size = 1,
39 });
40 bool result = cmd.Encode(*encoder.get());
41 EXPECT_TRUE(result);
42 EXPECT_TRUE(encoder->IsTracking(cmd.source));
43 EXPECT_TRUE(encoder->IsTracking(cmd.destination));
44 }

References impeller::BlitCopyTextureToBufferCommand::destination, impeller::BlitCopyTextureToBufferCommandVK::Encode(), and impeller::BlitCopyTextureToBufferCommand::source.

## ◆ TEST() [32/202]

impeller::testing::TEST | ( | BlitCommandVkTest | ,
|  | BlitCopyTextureToTextureCommandVK |
| ) |  |

Definition at line 13 of file blit_command_vk_unittests.cc.

13 {
14 auto context = MockVulkanContextBuilder().Build();
15 auto pool = context->GetCommandPoolRecycler()->Get();
16 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
17 BlitCopyTextureToTextureCommandVK cmd;
18 cmd.source = context->GetResourceAllocator()->CreateTexture({
19 .size = ISize(100, 100),
20 });
21 cmd.destination = context->GetResourceAllocator()->CreateTexture({
22 .size = ISize(100, 100),
23 });
24 bool result = cmd.Encode(*encoder.get());
25 EXPECT_TRUE(result);
26 EXPECT_TRUE(encoder->IsTracking(cmd.source));
27 EXPECT_TRUE(encoder->IsTracking(cmd.destination));
28 }

References impeller::BlitCopyTextureToTextureCommand::destination, impeller::BlitCopyTextureToTextureCommandVK::Encode(), and impeller::BlitCopyTextureToTextureCommand::source.

## ◆ TEST() [33/202]

impeller::testing::TEST | ( | BlitCommandVkTest | ,
|  | BlitGenerateMipmapCommandVK |
| ) |  |

Definition at line 64 of file blit_command_vk_unittests.cc.

64 {
65 auto context = MockVulkanContextBuilder().Build();
66 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
67 BlitGenerateMipmapCommandVK cmd;
68 cmd.texture = context->GetResourceAllocator()->CreateTexture({
69 .size = ISize(100, 100),
70 .mip_count = 2,
71 });
72 bool result = cmd.Encode(*encoder.get());
73 EXPECT_TRUE(result);
74 EXPECT_TRUE(encoder->IsTracking(cmd.texture));
75 }

References impeller::BlitGenerateMipmapCommandVK::Encode(), and impeller::BlitGenerateMipmapCommand::texture.

## ◆ TEST() [34/202]

impeller::testing::TEST | ( | BlobTest | ,
|  | CanReadAndWriteBlobs |
| ) |  |

Definition at line 28 of file blobcat_unittests.cc.

28 {
29 BlobWriter writer;
30 ASSERT_TRUE(writer.AddBlob(BlobShaderType::kVertex, "Hello",
31 CreateMappingFromString("World")));
32 ASSERT_TRUE(writer.AddBlob(BlobShaderType::kFragment, "Foo",
33 CreateMappingFromString("Bar")));
34 ASSERT_TRUE(writer.AddBlob(BlobShaderType::kVertex, "Baz",
35 CreateMappingFromString("Bang")));
36 ASSERT_TRUE(writer.AddBlob(BlobShaderType::kVertex, "Ping",
37 CreateMappingFromString("Pong")));
38 ASSERT_TRUE(writer.AddBlob(BlobShaderType::kFragment, "Pang",
39 CreateMappingFromString("World")));
40
41 auto mapping = writer.CreateMapping();
42 ASSERT_NE(mapping, nullptr);
43
44 BlobLibrary library(mapping);
45 ASSERT_TRUE(library.IsValid());
46 ASSERT_EQ(library.GetShaderCount(), 5u);
47
48 // Wrong type.
49 ASSERT_EQ(library.GetMapping(BlobShaderType::kFragment, "Hello"), nullptr);
50
51 auto hello_vtx = library.GetMapping(BlobShaderType::kVertex, "Hello");
52 ASSERT_NE(hello_vtx, nullptr);
53 ASSERT_EQ(CreateStringFromMapping(*hello_vtx), "World");
54 }

References impeller::BlobWriter::AddBlob(), impeller::BlobWriter::CreateMapping(), CreateMappingFromString(), CreateStringFromMapping(), impeller::BlobLibrary::GetMapping(), impeller::BlobLibrary::GetShaderCount(), impeller::BlobLibrary::IsValid(), impeller::kFragment, and impeller::kVertex.

## ◆ TEST() [35/202]

impeller::testing::TEST | ( | CapabilitiesTest | ,
|  | DefaultColorFormat |
| ) |  |

Definition at line 33 of file capabilities_unittests.cc.

33 {
34 auto defaults = CapabilitiesBuilder().Build();
35 ASSERT_EQ(defaults->GetDefaultColorFormat(), PixelFormat::kUnknown);
36 auto mutated = CapabilitiesBuilder()
37 .SetDefaultColorFormat(PixelFormat::kB10G10R10A10XR)
38 .Build();
39 ASSERT_EQ(mutated->GetDefaultColorFormat(), PixelFormat::kB10G10R10A10XR);
40 }

References impeller::CapabilitiesBuilder::Build(), impeller::kB10G10R10A10XR, impeller::kUnknown, and impeller::CapabilitiesBuilder::SetDefaultColorFormat().

## ◆ TEST() [36/202]

impeller::testing::TEST | ( | CapabilitiesTest | ,
|  | DefaultDepthStencilFormat |
| ) |  |

Definition at line 51 of file capabilities_unittests.cc.

51 {
52 auto defaults = CapabilitiesBuilder().Build();
53 ASSERT_EQ(defaults->GetDefaultDepthStencilFormat(), PixelFormat::kUnknown);
54 auto mutated = CapabilitiesBuilder()
55 .SetDefaultDepthStencilFormat(PixelFormat::kD32FloatS8UInt)
56 .Build();
57 ASSERT_EQ(mutated->GetDefaultDepthStencilFormat(),
58 PixelFormat::kD32FloatS8UInt);
59 }

References impeller::CapabilitiesBuilder::Build(), impeller::kD32FloatS8UInt, impeller::kUnknown, and impeller::CapabilitiesBuilder::SetDefaultDepthStencilFormat().

## ◆ TEST() [37/202]

impeller::testing::TEST | ( | CapabilitiesTest | ,
|  | DefaultStencilFormat |
| ) |  |

Definition at line 42 of file capabilities_unittests.cc.

42 {
43 auto defaults = CapabilitiesBuilder().Build();
44 ASSERT_EQ(defaults->GetDefaultStencilFormat(), PixelFormat::kUnknown);
45 auto mutated = CapabilitiesBuilder()
46 .SetDefaultStencilFormat(PixelFormat::kS8UInt)
47 .Build();
48 ASSERT_EQ(mutated->GetDefaultStencilFormat(), PixelFormat::kS8UInt);
49 }

References impeller::CapabilitiesBuilder::Build(), impeller::kS8UInt, impeller::kUnknown, and impeller::CapabilitiesBuilder::SetDefaultStencilFormat().

## ◆ TEST() [38/202]

impeller::testing::TEST | ( | CommandEncoderVKTest | ,
|  | CleanupAfterSubmit |
| ) |  |

Definition at line 41 of file command_encoder_vk_unittests.cc.

41 {
42 // This tests deleting the TrackedObjects where the thread is killed before
43 // the fence waiter has disposed of them, making sure the command buffer and
44 // its pools are deleted in that order.
45 std::shared_ptr<std::vector<std::string>> called_functions;
46 {
47 fml::AutoResetWaitableEvent wait_for_submit;
48 fml::AutoResetWaitableEvent wait_for_thread_join;
49 auto context = MockVulkanContextBuilder().Build();
50 std::thread thread([&] {
51 CommandEncoderFactoryVK factory(context);
52 std::shared_ptr<CommandEncoderVK> encoder = factory.Create();
53 encoder->Submit([&](bool success) {
54 ASSERT_TRUE(success);
55 wait_for_thread_join.Wait();
56 wait_for_submit.Signal();
57 });
58 });
59 thread.join();
60 wait_for_thread_join.Signal();
61 wait_for_submit.Wait();
62 called_functions = GetMockVulkanFunctions(context->GetDevice());
63 context->Shutdown();
64 }
65
66 auto destroy_pool =
67 std::find(called_functions->begin(), called_functions->end(),
68 "vkDestroyCommandPool");
69 auto free_buffers =
70 std::find(called_functions->begin(), called_functions->end(),
71 "vkFreeCommandBuffers");
72 EXPECT_TRUE(destroy_pool != called_functions->end());
73 EXPECT_TRUE(free_buffers != called_functions->end());
74 EXPECT_TRUE(free_buffers < destroy_pool);
75 }

References impeller::CommandEncoderFactoryVK::Create().

## ◆ TEST() [39/202]

impeller::testing::TEST | ( | CommandEncoderVKTest | ,
|  | DeleteEncoderAfterThreadDies |
| ) |  |

Definition at line 15 of file command_encoder_vk_unittests.cc.

15 {
16 // Tests that when a CommandEncoderVK is deleted that it will clean up its
17 // command buffers before it cleans up its command pool.
18 std::shared_ptr<std::vector<std::string>> called_functions;
19 {
20 auto context = MockVulkanContextBuilder().Build();
21 called_functions = GetMockVulkanFunctions(context->GetDevice());
22 std::shared_ptr<CommandEncoderVK> encoder;
23 std::thread thread([&] {
24 CommandEncoderFactoryVK factory(context);
25 encoder = factory.Create();
26 });
27 thread.join();
28 context->Shutdown();
29 }
30 auto destroy_pool =
31 std::find(called_functions->begin(), called_functions->end(),
32 "vkDestroyCommandPool");
33 auto free_buffers =
34 std::find(called_functions->begin(), called_functions->end(),
35 "vkFreeCommandBuffers");
36 EXPECT_TRUE(destroy_pool != called_functions->end());
37 EXPECT_TRUE(free_buffers != called_functions->end());
38 EXPECT_TRUE(free_buffers < destroy_pool);
39 }

References impeller::CommandEncoderFactoryVK::Create().

## ◆ TEST() [40/202]

impeller::testing::TEST | ( | CommandPoolRecyclerVKTest | ,
|  | GetsACommandPoolPerThread |
| ) |  |

Definition at line 14 of file command_pool_vk_unittests.cc.

14 {
15 auto const context = MockVulkanContextBuilder().Build();
16
17 {
18 // Record the memory location of each pointer to a command pool.
19 //
20 // These pools have to be held at this context, otherwise they will be
21 // dropped and recycled and potentially reused by another thread, causing
22 // flaky tests.
23 std::shared_ptr<CommandPoolVK> pool1;
24 std::shared_ptr<CommandPoolVK> pool2;
25
26 // Create a command pool in two threads and record the memory location.
27 std::thread thread1(
28 [&]() { pool1 = context->GetCommandPoolRecycler()->Get(); });
29
30 std::thread thread2(
31 [&]() { pool2 = context->GetCommandPoolRecycler()->Get(); });
32
33 thread1.join();
34 thread2.join();
35
36 // The two command pools should be different.
37 EXPECT_NE(pool1, pool2);
38 }
39
40 context->Shutdown();
41 }

## ◆ TEST() [41/202]

impeller::testing::TEST | ( | CommandPoolRecyclerVKTest | ,
|  | GetsTheSameCommandPoolOnSameThread |
| ) |  |

Definition at line 43 of file command_pool_vk_unittests.cc.

43 {
44 auto const context = MockVulkanContextBuilder().Build();
45
46 auto const pool1 = context->GetCommandPoolRecycler()->Get();
47 auto const pool2 = context->GetCommandPoolRecycler()->Get();
48
49 // The two command pools should be the same.
50 EXPECT_EQ(pool1.get(), pool2.get());
51
52 context->Shutdown();
53 }

## ◆ TEST() [42/202]

impeller::testing::TEST | ( | CommandPoolRecyclerVKTest | ,
|  | ReclaimMakesCommandPoolAvailable |
| ) |  |

Definition at line 76 of file command_pool_vk_unittests.cc.

76 {
77 auto const context = MockVulkanContextBuilder().Build();
78
79 {
80 // Fetch a pool (which will be created).
81 auto const recycler = context->GetCommandPoolRecycler();
82 auto const pool = recycler->Get();
83
84 // This normally is called at the end of a frame.
85 recycler->Dispose();
86 }
87
88 // Add something to the resource manager and have it notify us when it's
89 // destroyed. That should give us a non-flaky signal that the pool has been
90 // reclaimed as well.
91 auto waiter = fml::AutoResetWaitableEvent();
92 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
93 {
94 UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
95 std::move(rattle));
96 }
97 waiter.Wait();
98
99 // On another thread explicitly, request a new pool.
100 std::thread thread([&]() {
101 auto const pool = context->GetCommandPoolRecycler()->Get();
102 EXPECT_NE(pool.get(), nullptr);
103 });
104
105 thread.join();
106
107 // Now check that we only ever created one pool.
108 auto const called = GetMockVulkanFunctions(context->GetDevice());
109 EXPECT_EQ(std::count(called->begin(), called->end(), "vkCreateCommandPool"),
110 1u);
111
112 context->Shutdown();
113 }

## ◆ TEST() [43/202]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | CanCreateContextInAbsenceOfValidationLayers |
| ) |  |

Definition at line 117 of file context_vk_unittests.cc.

117 {
118 // The mocked methods don't report the presence of a validation layer but we
119 // explicitly ask for validation. Context creation should continue anyway.
120 auto context = MockVulkanContextBuilder()
121 .SetSettingsCallback([](auto& settings) {
122 settings.enable_validation = true;
123 })
124 .Build();
125 ASSERT_NE(context, nullptr);
126 const CapabilitiesVK* capabilites_vk =
127 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
128 ASSERT_FALSE(capabilites_vk->AreValidationsEnabled());
129 }

References impeller::CapabilitiesVK::AreValidationsEnabled().

## ◆ TEST() [44/202]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | CanCreateContextWithValidationLayers |
| ) |  |

Definition at line 131 of file context_vk_unittests.cc.

131 {
132 auto context =
133 MockVulkanContextBuilder()
134 .SetSettingsCallback(
135 [](auto& settings) { settings.enable_validation = true; })
136 .SetInstanceExtensions(
137 {"VK_KHR_surface", "VK_MVK_macos_surface", "VK_EXT_debug_utils"})
138 .SetInstanceLayers({"VK_LAYER_KHRONOS_validation"})
139 .Build();
140 ASSERT_NE(context, nullptr);
141 const CapabilitiesVK* capabilites_vk =
142 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
143 ASSERT_TRUE(capabilites_vk->AreValidationsEnabled());
144 }

References impeller::CapabilitiesVK::AreValidationsEnabled().

## ◆ TEST() [45/202]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | DeletePipelineAfterContext |
| ) |  |

Definition at line 60 of file context_vk_unittests.cc.

60 {
61 std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline;
62 std::shared_ptr<std::vector<std::string>> functions;
63 {
64 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
65 PipelineDescriptor pipeline_desc;
66 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
67 PipelineFuture<PipelineDescriptor> pipeline_future =
68 context->GetPipelineLibrary()->GetPipeline(pipeline_desc);
69 pipeline = pipeline_future.Get();
70 ASSERT_TRUE(pipeline);
71 functions = GetMockVulkanFunctions(context->GetDevice());
72 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
73 "vkCreateGraphicsPipelines") != functions->end());
74 }
75 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
76 "vkDestroyDevice") != functions->end());
77 }

References impeller::PipelineFuture< T >::Get(), and impeller::PipelineDescriptor::SetVertexDescriptor().

## ◆ TEST() [46/202]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | DeletePipelineLibraryAfterContext |
| ) |  |

Definition at line 101 of file context_vk_unittests.cc.

101 {
102 std::shared_ptr<PipelineLibrary> pipeline_library;
103 std::shared_ptr<std::vector<std::string>> functions;
104 {
105 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
106 PipelineDescriptor pipeline_desc;
107 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
108 pipeline_library = context->GetPipelineLibrary();
109 functions = GetMockVulkanFunctions(context->GetDevice());
110 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
111 "vkCreatePipelineCache") != functions->end());
112 }
113 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
114 "vkDestroyDevice") != functions->end());
115 }

References impeller::PipelineDescriptor::SetVertexDescriptor().

## ◆ TEST() [47/202]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | DeletesCommandPools |
| ) |  |

Definition at line 14 of file context_vk_unittests.cc.

14 {
15 std::weak_ptr<ContextVK> weak_context;
16 std::weak_ptr<CommandPoolVK> weak_pool;
17 {
18 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
19 auto const pool = context->GetCommandPoolRecycler()->Get();
20 weak_pool = pool;
21 weak_context = context;
22 ASSERT_TRUE(weak_pool.lock());
23 ASSERT_TRUE(weak_context.lock());
24 }
25 ASSERT_FALSE(weak_pool.lock());
26 ASSERT_FALSE(weak_context.lock());
27 }

## ◆ TEST() [48/202]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | DeletesCommandPoolsOnAllThreads |
| ) |  |

Definition at line 29 of file context_vk_unittests.cc.

29 {
30 std::weak_ptr<ContextVK> weak_context;
31 std::weak_ptr<CommandPoolVK> weak_pool_main;
32
33 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
34 weak_pool_main = context->GetCommandPoolRecycler()->Get();
35 weak_context = context;
36 ASSERT_TRUE(weak_pool_main.lock());
37 ASSERT_TRUE(weak_context.lock());
38
39 // Start a second thread that obtains a command pool.
40 fml::AutoResetWaitableEvent latch1, latch2;
41 std::weak_ptr<CommandPoolVK> weak_pool_thread;
42 std::thread thread([&]() {
43 weak_pool_thread = context->GetCommandPoolRecycler()->Get();
44 latch1.Signal();
45 latch2.Wait();
46 });
47
48 // Delete the ContextVK on the main thread.
49 latch1.Wait();
50 context.reset();
51 ASSERT_FALSE(weak_pool_main.lock());
52 ASSERT_FALSE(weak_context.lock());
53
54 // Stop the second thread and check that its command pool has been deleted.
55 latch2.Signal();
56 thread.join();
57 ASSERT_FALSE(weak_pool_thread.lock());
58 }

## ◆ TEST() [49/202]

impeller::testing::TEST | ( | ContextVKTest | ,
|  | DeleteShaderFunctionAfterContext |
| ) |  |

Definition at line 79 of file context_vk_unittests.cc.

79 {
80 std::shared_ptr<const ShaderFunction> shader_function;
81 std::shared_ptr<std::vector<std::string>> functions;
82 {
83 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
84 PipelineDescriptor pipeline_desc;
85 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
86 std::vector<uint8_t> data = {0x03, 0x02, 0x23, 0x07};
87 context->GetShaderLibrary()->RegisterFunction(
88 "foobar", ShaderStage::kFragment,
89 std::make_shared<fml::DataMapping>(data), [](bool) {});
90 shader_function = context->GetShaderLibrary()->GetFunction(
91 "foobar_fragment_main", ShaderStage::kFragment);
92 ASSERT_TRUE(shader_function);
93 functions = GetMockVulkanFunctions(context->GetDevice());
94 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
95 "vkCreateShaderModule") != functions->end());
96 }
97 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
98 "vkDestroyDevice") != functions->end());
99 }

References impeller::kFragment, and impeller::PipelineDescriptor::SetVertexDescriptor().

## ◆ TEST() [50/202]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | FillPathGeometryCoversArea |
| ) |  |

Definition at line 20 of file geometry_unittests.cc.

20 {
21 auto path = PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath();
22 auto geometry = Geometry::MakeFillPath(
23 path, /* inner rect */ Rect::MakeLTRB(0, 0, 100, 100));
24 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
25 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
26 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
27 ASSERT_TRUE(geometry->CoversArea({}, Rect()));
28 }

References impeller::PathBuilder::AddRect(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [51/202]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | FillPathGeometryCoversAreaNoInnerRect |
| ) |  |

Definition at line 30 of file geometry_unittests.cc.

30 {
31 auto path = PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath();
32 auto geometry = Geometry::MakeFillPath(path);
33 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
34 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
35 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
36 ASSERT_FALSE(geometry->CoversArea({}, Rect()));
37 }

References impeller::PathBuilder::AddRect(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [52/202]

impeller::testing::TEST | ( | EntityGeometryTest | ,
|  | RectGeometryCoversArea |
| ) |  |

Definition at line 12 of file geometry_unittests.cc.

12 {
13 auto geometry = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 100, 100));
14 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
15 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
16 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
17 ASSERT_TRUE(geometry->CoversArea({}, Rect()));
18 }

References impeller::TRect< Scalar >::MakeLTRB(), and impeller::Geometry::MakeRect().

## ◆ TEST() [53/202]

impeller::testing::TEST | ( | FenceWaiterVKTest | ,
|  | AddFenceDoesNothingIfTerminating |
| ) |  |

Definition at line 86 of file fence_waiter_vk_unittests.cc.

86 {
87 auto signal = fml::ManualResetWaitableEvent();
88
89 {
90 auto const context = MockVulkanContextBuilder().Build();
91 auto const device = context->GetDevice();
92 auto const waiter = context->GetFenceWaiter();
93 waiter->Terminate();
94
95 auto fence = device.createFenceUnique({}).value;
96 waiter->AddFence(std::move(fence), [&signal]() { signal.Signal(); });
97 }
98
99 // Ensure the fence did _not_ signal.
100 EXPECT_TRUE(signal.WaitWithTimeout(fml::TimeDelta::FromMilliseconds(100)));
101 }

## ◆ TEST() [54/202]

impeller::testing::TEST | ( | FenceWaiterVKTest | ,
|  | ExecutesFenceCallback |
| ) |  |

Definition at line 28 of file fence_waiter_vk_unittests.cc.

28 {
29 auto const context = MockVulkanContextBuilder().Build();
30 auto const device = context->GetDevice();
31 auto const waiter = context->GetFenceWaiter();
32
33 auto signal = fml::ManualResetWaitableEvent();
34 auto fence = device.createFenceUnique({}).value;
35 waiter->AddFence(std::move(fence), [&signal]() { signal.Signal(); });
36
37 signal.Wait();
38 }

## ◆ TEST() [55/202]

impeller::testing::TEST | ( | FenceWaiterVKTest | ,
|  | ExecutesFenceCallbackX2 |
| ) |  |

Definition at line 40 of file fence_waiter_vk_unittests.cc.

40 {
41 auto const context = MockVulkanContextBuilder().Build();
42 auto const device = context->GetDevice();
43 auto const waiter = context->GetFenceWaiter();
44
45 auto signal = fml::ManualResetWaitableEvent();
46 auto fence = device.createFenceUnique({}).value;
47 waiter->AddFence(std::move(fence), [&signal]() { signal.Signal(); });
48
49 auto signal2 = fml::ManualResetWaitableEvent();
50 auto fence2 = device.createFenceUnique({}).value;
51 waiter->AddFence(std::move(fence2), [&signal2]() { signal2.Signal(); });
52
53 signal.Wait();
54 signal2.Wait();
55 }

## ◆ TEST() [56/202]

impeller::testing::TEST | ( | FenceWaiterVKTest | ,
|  | ExecutesNewFenceThenOldFence |
| ) |  |

Definition at line 57 of file fence_waiter_vk_unittests.cc.

57 {
58 auto const context = MockVulkanContextBuilder().Build();
59 auto const device = context->GetDevice();
60 auto const waiter = context->GetFenceWaiter();
61
62 auto signal = fml::ManualResetWaitableEvent();
63 auto fence = device.createFenceUnique({}).value;
64 MockFence::SetStatus(fence, vk::Result::eNotReady);
65 auto raw_fence = MockFence::GetRawPointer(fence);
66 waiter->AddFence(std::move(fence), [&signal]() { signal.Signal(); });
67
68 // The easiest way to verify that the callback was _not_ called is to wait
69 // for a timeout, but that could introduce flakiness. Instead, we'll add a
70 // second fence that will signal immediately, and wait for that one instead.
71 {
72 auto signal2 = fml::ManualResetWaitableEvent();
73 auto fence2 = device.createFenceUnique({}).value;
74 MockFence::SetStatus(fence2, vk::Result::eSuccess);
75 waiter->AddFence(std::move(fence2), [&signal2]() { signal2.Signal(); });
76 signal2.Wait();
77 }
78
79 // Now, we'll signal the first fence, and wait for the callback to be called.
80 raw_fence->SetStatus(vk::Result::eSuccess);
81
82 // Now, we'll signal the first fence, and wait for the callback to be called.
83 signal.Wait();
84 }

## ◆ TEST() [57/202]

impeller::testing::TEST | ( | FenceWaiterVKTest | ,
|  | IgnoresNullCallback |
| ) |  |

Definition at line 19 of file fence_waiter_vk_unittests.cc.

19 {
20 auto const context = MockVulkanContextBuilder().Build();
21 auto const device = context->GetDevice();
22 auto const waiter = context->GetFenceWaiter();
23
24 auto fence = device.createFenceUnique({}).value;
25 EXPECT_FALSE(waiter->AddFence(std::move(fence), nullptr));
26 }

## ◆ TEST() [58/202]

impeller::testing::TEST | ( | FenceWaiterVKTest | ,
|  | IgnoresNullFence |
| ) |  |

Definition at line 13 of file fence_waiter_vk_unittests.cc.

13 {
14 auto const context = MockVulkanContextBuilder().Build();
15 auto const waiter = context->GetFenceWaiter();
16 EXPECT_FALSE(waiter->AddFence(vk::UniqueFence(), []() {}));
17 }

## ◆ TEST() [59/202]

impeller::testing::TEST | ( | FenceWaiterVKTest | ,
|  | InProgressFencesStillWaitIfTerminated |
| ) |  |

Definition at line 103 of file fence_waiter_vk_unittests.cc.

103 {
104 MockFence* raw_fence = nullptr;
105 auto signal = fml::ManualResetWaitableEvent();
106
107 auto const context = MockVulkanContextBuilder().Build();
108 auto const device = context->GetDevice();
109 auto const waiter = context->GetFenceWaiter();
110
111 // Add a fence that isn't signalled yet.
112 auto fence = device.createFenceUnique({}).value;
113
114 // Even if the fence is eSuccess, it's not guaranteed to be called in time.
115 MockFence::SetStatus(fence, vk::Result::eNotReady);
116 raw_fence = MockFence::GetRawPointer(fence);
117 waiter->AddFence(std::move(fence), [&signal]() { signal.Signal(); });
118
119 // Terminate the waiter.
120 waiter->Terminate();
121
122 // Signal the fence.
123 raw_fence->SetStatus(vk::Result::eSuccess);
124
125 // This will hang if the fence was not signalled.
126 signal.Wait();
127 }

## ◆ TEST() [60/202]

impeller::testing::TEST | ( | FilterInputTest | ,
|  | CanSetLocalTransformForTexture |
| ) |  |

Definition at line 17 of file filter_input_unittests.cc.

17 {
18 std::shared_ptr<Texture> texture = nullptr;
19 auto input =
20 FilterInput::Make(texture, Matrix::MakeTranslation({1.0, 0.0, 0.0}));
21 Entity e;
22 e.SetTransformation(Matrix::MakeTranslation({0.0, 2.0, 0.0}));
23
24 ASSERT_MATRIX_NEAR(input->GetLocalTransform(e),
25 Matrix::MakeTranslation({1.0, 0.0, 0.0}));
26 ASSERT_MATRIX_NEAR(input->GetTransform(e),
27 Matrix::MakeTranslation({1.0, 2.0, 0.0}));
28 }

References ASSERT_MATRIX_NEAR, impeller::FilterInput::Make(), impeller::Matrix::MakeTranslation(), and impeller::Entity::SetTransformation().

## ◆ TEST() [61/202]

impeller::testing::TEST | ( | FilterInputTest | ,
|  | IsLeaf |
| ) |  |

Definition at line 30 of file filter_input_unittests.cc.

30 {
31 std::shared_ptr<FilterContents> leaf =
32 ColorFilterContents::MakeBlend(BlendMode::kSource, {});
33 ASSERT_TRUE(leaf->IsLeaf());
34
35 auto base = ColorFilterContents::MakeMatrixFilter(FilterInput::Make(leaf),
36 Matrix(), {});
37
38 ASSERT_TRUE(leaf->IsLeaf());
39 ASSERT_FALSE(base->IsLeaf());
40 }

References impeller::kSource, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), and impeller::FilterContents::MakeMatrixFilter().

## ◆ TEST() [62/202]

impeller::testing::TEST | ( | FilterInputTest | ,
|  | SetCoverageInputs |
| ) |  |

Definition at line 42 of file filter_input_unittests.cc.

42 {
43 std::shared_ptr<FilterContents> leaf =
44 ColorFilterContents::MakeBlend(BlendMode::kSource, {});
45 ASSERT_TRUE(leaf->IsLeaf());
46
47 auto base = ColorFilterContents::MakeMatrixFilter(FilterInput::Make(leaf),
48 Matrix(), {});
49
50 {
51 auto result = base->GetCoverage({});
52 ASSERT_FALSE(result.has_value());
53 }
54
55 auto coverage_rect = Rect::MakeLTRB(100, 100, 200, 200);
56 base->SetLeafInputs(FilterInput::Make({coverage_rect}));
57
58 {
59 auto result = base->GetCoverage({});
60 ASSERT_TRUE(result.has_value());
61 // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
62 ASSERT_RECT_NEAR(result.value(), coverage_rect);
63 }
64 }

References ASSERT_RECT_NEAR, impeller::kSource, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::FilterContents::MakeMatrixFilter().

## ◆ TEST() [63/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | BlendModeToString |
| ) |  |

Definition at line 1566 of file geometry_unittests.cc.

1566 {
1567 using BlendT = std::underlying_type_t<BlendMode>;
1568 for (BlendT i = 0; i <= static_cast<BlendT>(BlendMode::kLast); i++) {
1569 auto mode = static_cast<BlendMode>(i);
1570 auto result = BlendModeToString(mode);
1571 switch (mode) { IMPELLER_FOR_EACH_BLEND_MODE(_BLEND_MODE_NAME_CHECK) }
1572 }
1573 }

References _BLEND_MODE_NAME_CHECK, impeller::BlendModeToString(), IMPELLER_FOR_EACH_BLEND_MODE, and impeller::kLast.

## ◆ TEST() [64/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | BoundingBoxCubic |
| ) |  |

Definition at line 667 of file geometry_unittests.cc.

667 {
668 PathBuilder builder;
669 auto path =
670 builder.AddCubicCurve({120, 160}, {25, 200}, {220, 260}, {220, 40})
671 .TakePath();
672 auto box = path.GetBoundingBox();
673 Rect expected(93.9101, 40, 126.09, 158.862);
674 ASSERT_TRUE(box.has_value());
675 ASSERT_RECT_NEAR(box.value(), expected);
676 }

References impeller::PathBuilder::AddCubicCurve(), and ASSERT_RECT_NEAR.

## ◆ TEST() [65/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | BoundingBoxOfCompositePathIsCorrect |
| ) |  |

Definition at line 678 of file geometry_unittests.cc.

678 {
679 PathBuilder builder;
680 builder.AddRoundedRect({{10, 10}, {300, 300}}, {50, 50, 50, 50});
681 auto path = builder.TakePath();
682 auto actual = path.GetBoundingBox();
683 Rect expected(10, 10, 300, 300);
684 ASSERT_TRUE(actual.has_value());
685 ASSERT_RECT_NEAR(actual.value(), expected);
686 }

References impeller::PathBuilder::AddRoundedRect(), ASSERT_RECT_NEAR, impeller::Path::GetBoundingBox(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [66/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CanConvertBetweenDegressAndRadians |
| ) |  |

Definition at line 1575 of file geometry_unittests.cc.

1575 {
1576 {
1577 auto deg = Degrees{90.0};
1578 Radians rad = deg;
1579 ASSERT_FLOAT_EQ(rad.radians, kPiOver2);
1580 }
1581 }

References impeller::kPiOver2, and impeller::Radians::radians.

## ◆ TEST() [67/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CanConvertTTypesExplicitly |
| ) |  |

Definition at line 722 of file geometry_unittests.cc.

722 {
723 {
724 Point p1(1.0, 2.0);
725 IPoint p2 = static_cast<IPoint>(p1);
726 ASSERT_EQ(p2.x, 1u);
727 ASSERT_EQ(p2.y, 2u);
728 }
729
730 {
731 Size s1(1.0, 2.0);
732 ISize s2 = static_cast<ISize>(s1);
733 ASSERT_EQ(s2.width, 1u);
734 ASSERT_EQ(s2.height, 2u);
735 }
736
737 {
738 Size s1(1.0, 2.0);
739 Point p1 = static_cast<Point>(s1);
740 ASSERT_EQ(p1.x, 1u);
741 ASSERT_EQ(p1.y, 2u);
742 }
743
744 {
745 Rect r1(1.0, 2.0, 3.0, 4.0);
746 IRect r2 = static_cast<IRect>(r1);
747 ASSERT_EQ(r2.origin.x, 1u);
748 ASSERT_EQ(r2.origin.y, 2u);
749 ASSERT_EQ(r2.size.width, 3u);
750 ASSERT_EQ(r2.size.height, 4u);
751 }
752 }

References impeller::TSize< T >::height, impeller::TRect< T >::origin, impeller::TRect< T >::size, impeller::TSize< T >::width, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST() [68/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CanGenerateMipCounts |
| ) |  |

Definition at line 709 of file geometry_unittests.cc.

709 {
710 ASSERT_EQ((Size{128, 128}.MipCount()), 7u);
711 ASSERT_EQ((Size{128, 256}.MipCount()), 8u);
712 ASSERT_EQ((Size{128, 130}.MipCount()), 8u);
713 ASSERT_EQ((Size{128, 257}.MipCount()), 9u);
714 ASSERT_EQ((Size{257, 128}.MipCount()), 9u);
715 ASSERT_EQ((Size{128, 0}.MipCount()), 1u);
716 ASSERT_EQ((Size{128, -25}.MipCount()), 1u);
717 ASSERT_EQ((Size{-128, 25}.MipCount()), 1u);
718 ASSERT_EQ((Size{1, 1}.MipCount()), 1u);
719 ASSERT_EQ((Size{0, 0}.MipCount()), 1u);
720 }

References impeller::TSize< T >::MipCount().

## ◆ TEST() [69/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CanPerformAlgebraicPointOps |
| ) |  |

Definition at line 754 of file geometry_unittests.cc.

754 {
755 {
756 IPoint p1(1, 2);
757 IPoint p2 = p1 + IPoint(1, 2);
758 ASSERT_EQ(p2.x, 2u);
759 ASSERT_EQ(p2.y, 4u);
760 }
761
762 {
763 IPoint p1(3, 6);
764 IPoint p2 = p1 - IPoint(1, 2);
765 ASSERT_EQ(p2.x, 2u);
766 ASSERT_EQ(p2.y, 4u);
767 }
768
769 {
770 IPoint p1(1, 2);
771 IPoint p2 = p1 * IPoint(2, 3);
772 ASSERT_EQ(p2.x, 2u);
773 ASSERT_EQ(p2.y, 6u);
774 }
775
776 {
777 IPoint p1(2, 6);
778 IPoint p2 = p1 / IPoint(2, 3);
779 ASSERT_EQ(p2.x, 1u);
780 ASSERT_EQ(p2.y, 2u);
781 }
782 }

References impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST() [70/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CanPerformAlgebraicPointOpsWithArithmeticTypes |
| ) |  |

Definition at line 784 of file geometry_unittests.cc.

784 {
785 // LHS
786 {
787 IPoint p1(1, 2);
788 IPoint p2 = p1 * 2.0f;
789 ASSERT_EQ(p2.x, 2u);
790 ASSERT_EQ(p2.y, 4u);
791 }
792
793 {
794 IPoint p1(2, 6);
795 IPoint p2 = p1 / 2.0f;
796 ASSERT_EQ(p2.x, 1u);
797 ASSERT_EQ(p2.y, 3u);
798 }
799
800 // RHS
801 {
802 IPoint p1(1, 2);
803 IPoint p2 = 2.0f * p1;
804 ASSERT_EQ(p2.x, 2u);
805 ASSERT_EQ(p2.y, 4u);
806 }
807
808 {
809 IPoint p1(2, 6);
810 IPoint p2 = 12.0f / p1;
811 ASSERT_EQ(p2.x, 6u);
812 ASSERT_EQ(p2.y, 2u);
813 }
814 }

References impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST() [71/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CanPerformAlgebraicVector3Ops |
| ) |  |

Definition at line 1288 of file geometry_unittests.cc.

1288 {
1289 {
1290 Vector3 p1(1, 2, 3);
1291 Vector3 p2 = p1 + Vector3(1, 2, 3);
1292 ASSERT_EQ(p2.x, 2u);
1293 ASSERT_EQ(p2.y, 4u);
1294 ASSERT_EQ(p2.z, 6u);
1295 }
1296
1297 {
1298 Vector3 p1(3, 6, 9);
1299 Vector3 p2 = p1 - Vector3(1, 2, 3);
1300 ASSERT_EQ(p2.x, 2u);
1301 ASSERT_EQ(p2.y, 4u);
1302 ASSERT_EQ(p2.z, 6u);
1303 }
1304
1305 {
1306 Vector3 p1(1, 2, 3);
1307 Vector3 p2 = p1 * Vector3(2, 3, 4);
1308 ASSERT_EQ(p2.x, 2u);
1309 ASSERT_EQ(p2.y, 6u);
1310 ASSERT_EQ(p2.z, 12u);
1311 }
1312
1313 {
1314 Vector3 p1(2, 6, 12);
1315 Vector3 p2 = p1 / Vector3(2, 3, 4);
1316 ASSERT_EQ(p2.x, 1u);
1317 ASSERT_EQ(p2.y, 2u);
1318 ASSERT_EQ(p2.z, 3u);
1319 }
1320 }

References impeller::Vector3::x, impeller::Vector3::y, and impeller::Vector3::z.

## ◆ TEST() [72/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CanPerformAlgebraicVector3OpsWithArithmeticTypes |
| ) |  |

Definition at line 1322 of file geometry_unittests.cc.

1322 {
1323 // LHS
1324 {
1325 Vector3 p1(1, 2, 3);
1326 Vector3 p2 = p1 + 2.0f;
1327 ASSERT_EQ(p2.x, 3);
1328 ASSERT_EQ(p2.y, 4);
1329 ASSERT_EQ(p2.z, 5);
1330 }
1331
1332 {
1333 Vector3 p1(1, 2, 3);
1334 Vector3 p2 = p1 - 2.0f;
1335 ASSERT_EQ(p2.x, -1);
1336 ASSERT_EQ(p2.y, 0);
1337 ASSERT_EQ(p2.z, 1);
1338 }
1339
1340 {
1341 Vector3 p1(1, 2, 3);
1342 Vector3 p2 = p1 * 2.0f;
1343 ASSERT_EQ(p2.x, 2);
1344 ASSERT_EQ(p2.y, 4);
1345 ASSERT_EQ(p2.z, 6);
1346 }
1347
1348 {
1349 Vector3 p1(2, 6, 12);
1350 Vector3 p2 = p1 / 2.0f;
1351 ASSERT_EQ(p2.x, 1);
1352 ASSERT_EQ(p2.y, 3);
1353 ASSERT_EQ(p2.z, 6);
1354 }
1355
1356 // RHS
1357 {
1358 Vector3 p1(1, 2, 3);
1359 Vector3 p2 = 2.0f + p1;
1360 ASSERT_EQ(p2.x, 3);
1361 ASSERT_EQ(p2.y, 4);
1362 ASSERT_EQ(p2.z, 5);
1363 }
1364
1365 {
1366 Vector3 p1(1, 2, 3);
1367 Vector3 p2 = 2.0f - p1;
1368 ASSERT_EQ(p2.x, 1);
1369 ASSERT_EQ(p2.y, 0);
1370 ASSERT_EQ(p2.z, -1);
1371 }
1372
1373 {
1374 Vector3 p1(1, 2, 3);
1375 Vector3 p2 = 2.0f * p1;
1376 ASSERT_EQ(p2.x, 2);
1377 ASSERT_EQ(p2.y, 4);
1378 ASSERT_EQ(p2.z, 6);
1379 }
1380
1381 {
1382 Vector3 p1(2, 6, 12);
1383 Vector3 p2 = 12.0f / p1;
1384 ASSERT_EQ(p2.x, 6);
1385 ASSERT_EQ(p2.y, 2);
1386 ASSERT_EQ(p2.z, 1);
1387 }
1388 }

References impeller::Vector3::x, impeller::Vector3::y, and impeller::Vector3::z.

## ◆ TEST() [73/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CanUsePointAssignmentOperators |
| ) |  |

Definition at line 936 of file geometry_unittests.cc.

936 {
937 // Point on RHS
938 {
939 IPoint p(1, 2);
940 p += IPoint(1, 2);
941 ASSERT_EQ(p.x, 2u);
942 ASSERT_EQ(p.y, 4u);
943 }
944
945 {
946 IPoint p(3, 6);
947 p -= IPoint(1, 2);
948 ASSERT_EQ(p.x, 2u);
949 ASSERT_EQ(p.y, 4u);
950 }
951
952 {
953 IPoint p(1, 2);
954 p *= IPoint(2, 3);
955 ASSERT_EQ(p.x, 2u);
956 ASSERT_EQ(p.y, 6u);
957 }
958
959 {
960 IPoint p(2, 6);
961 p /= IPoint(2, 3);
962 ASSERT_EQ(p.x, 1u);
963 ASSERT_EQ(p.y, 2u);
964 }
965
966 // Size on RHS
967 {
968 IPoint p(1, 2);
969 p += ISize(1, 2);
970 ASSERT_EQ(p.x, 2u);
971 ASSERT_EQ(p.y, 4u);
972 }
973
974 {
975 IPoint p(3, 6);
976 p -= ISize(1, 2);
977 ASSERT_EQ(p.x, 2u);
978 ASSERT_EQ(p.y, 4u);
979 }
980
981 {
982 IPoint p(1, 2);
983 p *= ISize(2, 3);
984 ASSERT_EQ(p.x, 2u);
985 ASSERT_EQ(p.y, 6u);
986 }
987
988 {
989 IPoint p(2, 6);
990 p /= ISize(2, 3);
991 ASSERT_EQ(p.x, 1u);
992 ASSERT_EQ(p.y, 2u);
993 }
994
995 // Arithmetic type on RHS
996 {
997 IPoint p(1, 2);
998 p *= 3;
999 ASSERT_EQ(p.x, 3u);
1000 ASSERT_EQ(p.y, 6u);
1001 }
1002
1003 {
1004 IPoint p(3, 6);
1005 p /= 3;
1006 ASSERT_EQ(p.x, 1u);
1007 ASSERT_EQ(p.y, 2u);
1008 }
1009 }

References impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST() [74/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CanUseVector3AssignmentOperators |
| ) |  |

Definition at line 1238 of file geometry_unittests.cc.

1238 {
1239 {
1240 Vector3 p(1, 2, 4);
1241 p += Vector3(1, 2, 4);
1242 ASSERT_EQ(p.x, 2u);
1243 ASSERT_EQ(p.y, 4u);
1244 ASSERT_EQ(p.z, 8u);
1245 }
1246
1247 {
1248 Vector3 p(3, 6, 8);
1249 p -= Vector3(1, 2, 3);
1250 ASSERT_EQ(p.x, 2u);
1251 ASSERT_EQ(p.y, 4u);
1252 ASSERT_EQ(p.z, 5u);
1253 }
1254
1255 {
1256 Vector3 p(1, 2, 3);
1257 p *= Vector3(2, 3, 4);
1258 ASSERT_EQ(p.x, 2u);
1259 ASSERT_EQ(p.y, 6u);
1260 ASSERT_EQ(p.z, 12u);
1261 }
1262
1263 {
1264 Vector3 p(1, 2, 3);
1265 p *= 2;
1266 ASSERT_EQ(p.x, 2u);
1267 ASSERT_EQ(p.y, 4u);
1268 ASSERT_EQ(p.z, 6u);
1269 }
1270
1271 {
1272 Vector3 p(2, 6, 12);
1273 p /= Vector3(2, 3, 4);
1274 ASSERT_EQ(p.x, 1u);
1275 ASSERT_EQ(p.y, 2u);
1276 ASSERT_EQ(p.z, 3u);
1277 }
1278
1279 {
1280 Vector3 p(2, 6, 12);
1281 p /= 2;
1282 ASSERT_EQ(p.x, 1u);
1283 ASSERT_EQ(p.y, 3u);
1284 ASSERT_EQ(p.z, 6u);
1285 }
1286 }

References impeller::Vector3::x, impeller::Vector3::y, and impeller::Vector3::z.

## ◆ TEST() [75/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorApplyColorMatrix |
| ) |  |

Definition at line 1495 of file geometry_unittests.cc.

1495 {
1496 {
1497 ColorMatrix color_matrix = {
1498 1, 1, 1, 1, 1, //
1499 1, 1, 1, 1, 1, //
1500 1, 1, 1, 1, 1, //
1501 1, 1, 1, 1, 1, //
1502 };
1503 auto result = Color::White().ApplyColorMatrix(color_matrix);
1504 auto expected = Color(1, 1, 1, 1);
1505 ASSERT_COLOR_NEAR(result, expected);
1506 }
1507
1508 {
1509 ColorMatrix color_matrix = {
1510 0.1, 0, 0, 0, 0.01, //
1511 0, 0.2, 0, 0, 0.02, //
1512 0, 0, 0.3, 0, 0.03, //
1513 0, 0, 0, 0.4, 0.04, //
1514 };
1515 auto result = Color::White().ApplyColorMatrix(color_matrix);
1516 auto expected = Color(0.11, 0.22, 0.33, 0.44);
1517 ASSERT_COLOR_NEAR(result, expected);
1518 }
1519 }

References impeller::Color::ApplyColorMatrix(), ASSERT_COLOR_NEAR, and impeller::Color::White().

## ◆ TEST() [76/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorClamp01 |
| ) |  |

Definition at line 1455 of file geometry_unittests.cc.

1455 {
1456 {
1457 Color result = Color(0.5, 0.5, 0.5, 0.5).Clamp01();
1458 Color expected = Color(0.5, 0.5, 0.5, 0.5);
1459 ASSERT_COLOR_NEAR(result, expected);
1460 }
1461
1462 {
1463 Color result = Color(-1, -1, -1, -1).Clamp01();
1464 Color expected = Color(0, 0, 0, 0);
1465 ASSERT_COLOR_NEAR(result, expected);
1466 }
1467
1468 {
1469 Color result = Color(2, 2, 2, 2).Clamp01();
1470 Color expected = Color(1, 1, 1, 1);
1471 ASSERT_COLOR_NEAR(result, expected);
1472 }
1473 }

References ASSERT_COLOR_NEAR, and impeller::Color::Clamp01().

## ◆ TEST() [77/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorLerp |
| ) |  |

Definition at line 1433 of file geometry_unittests.cc.

1433 {
1434 {
1435 Color a(0.0, 0.0, 0.0, 0.0);
1436 Color b(1.0, 1.0, 1.0, 1.0);
1437
1438 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.5), Color(0.5, 0.5, 0.5, 0.5));
1439 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.0), a);
1440 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 1.0), b);
1441 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.2), Color(0.2, 0.2, 0.2, 0.2));
1442 }
1443
1444 {
1445 Color a(0.2, 0.4, 1.0, 0.5);
1446 Color b(0.4, 1.0, 0.2, 0.3);
1447
1448 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.5), Color(0.3, 0.7, 0.6, 0.4));
1449 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.0), a);
1450 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 1.0), b);
1451 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.2), Color(0.24, 0.52, 0.84, 0.46));
1452 }
1453 }

References ASSERT_COLOR_NEAR, and impeller::Color::Lerp().

## ◆ TEST() [78/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorLinearToSRGB |
| ) |  |

Definition at line 1521 of file geometry_unittests.cc.

1521 {
1522 {
1523 auto result = Color::White().LinearToSRGB();
1524 auto expected = Color(1, 1, 1, 1);
1525 ASSERT_COLOR_NEAR(result, expected);
1526 }
1527
1528 {
1529 auto result = Color::BlackTransparent().LinearToSRGB();
1530 auto expected = Color(0, 0, 0, 0);
1531 ASSERT_COLOR_NEAR(result, expected);
1532 }
1533
1534 {
1535 auto result = Color(0.2, 0.4, 0.6, 0.8).LinearToSRGB();
1536 auto expected = Color(0.484529, 0.665185, 0.797738, 0.8);
1537 ASSERT_COLOR_NEAR(result, expected);
1538 }
1539 }

References ASSERT_COLOR_NEAR, impeller::Color::BlackTransparent(), impeller::Color::LinearToSRGB(), and impeller::Color::White().

## ◆ TEST() [79/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorMakeRGBA8 |
| ) |  |

Definition at line 1475 of file geometry_unittests.cc.

1475 {
1476 {
1477 Color a = Color::MakeRGBA8(0, 0, 0, 0);
1478 Color b = Color::BlackTransparent();
1479 ASSERT_COLOR_NEAR(a, b);
1480 }
1481
1482 {
1483 Color a = Color::MakeRGBA8(255, 255, 255, 255);
1484 Color b = Color::White();
1485 ASSERT_COLOR_NEAR(a, b);
1486 }
1487
1488 {
1489 Color a = Color::MakeRGBA8(63, 127, 191, 127);
1490 Color b(0.247059, 0.498039, 0.74902, 0.498039);
1491 ASSERT_COLOR_NEAR(a, b);
1492 }
1493 }

References ASSERT_COLOR_NEAR, impeller::Color::BlackTransparent(), impeller::Color::MakeRGBA8(), and impeller::Color::White().

## ◆ TEST() [80/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorPremultiply |
| ) |  |

Definition at line 1390 of file geometry_unittests.cc.

1390 {
1391 {
1392 Color a(1.0, 0.5, 0.2, 0.5);
1393 Color premultiplied = a.Premultiply();
1394 Color expected = Color(0.5, 0.25, 0.1, 0.5);
1395 ASSERT_COLOR_NEAR(premultiplied, expected);
1396 }
1397
1398 {
1399 Color a(0.5, 0.25, 0.1, 0.5);
1400 Color unpremultiplied = a.Unpremultiply();
1401 Color expected = Color(1.0, 0.5, 0.2, 0.5);
1402 ASSERT_COLOR_NEAR(unpremultiplied, expected);
1403 }
1404
1405 {
1406 Color a(0.5, 0.25, 0.1, 0.0);
1407 Color unpremultiplied = a.Unpremultiply();
1408 Color expected = Color(0.0, 0.0, 0.0, 0.0);
1409 ASSERT_COLOR_NEAR(unpremultiplied, expected);
1410 }
1411 }

References ASSERT_COLOR_NEAR, impeller::Color::Premultiply(), and impeller::Color::Unpremultiply().

## ◆ TEST() [81/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorPrinting |
| ) |  |

Definition at line 2263 of file geometry_unittests.cc.

2263 {
2264 {
2265 std::stringstream stream;
2266 Color m;
2267 stream << m;
2268 ASSERT_EQ(stream.str(), "(0, 0, 0, 0)");
2269 }
2270
2271 {
2272 std::stringstream stream;
2273 Color m(1, 2, 3, 4);
2274 stream << m;
2275 ASSERT_EQ(stream.str(), "(1, 2, 3, 4)");
2276 }
2277 }

## ◆ TEST() [82/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorR8G8B8A8 |
| ) |  |

Definition at line 1413 of file geometry_unittests.cc.

1413 {
1414 {
1415 Color a(1.0, 0.5, 0.2, 0.5);
1416 std::array<uint8_t, 4> expected = {255, 128, 51, 128};
1417 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1418 }
1419
1420 {
1421 Color a(0.0, 0.0, 0.0, 0.0);
1422 std::array<uint8_t, 4> expected = {0, 0, 0, 0};
1423 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1424 }
1425
1426 {
1427 Color a(1.0, 1.0, 1.0, 1.0);
1428 std::array<uint8_t, 4> expected = {255, 255, 255, 255};
1429 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1430 }
1431 }

References ASSERT_ARRAY_4_NEAR, and impeller::Color::ToR8G8B8A8().

## ◆ TEST() [83/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ColorSRGBToLinear |
| ) |  |

Definition at line 1541 of file geometry_unittests.cc.

1541 {
1542 {
1543 auto result = Color::White().SRGBToLinear();
1544 auto expected = Color(1, 1, 1, 1);
1545 ASSERT_COLOR_NEAR(result, expected);
1546 }
1547
1548 {
1549 auto result = Color::BlackTransparent().SRGBToLinear();
1550 auto expected = Color(0, 0, 0, 0);
1551 ASSERT_COLOR_NEAR(result, expected);
1552 }
1553
1554 {
1555 auto result = Color(0.2, 0.4, 0.6, 0.8).SRGBToLinear();
1556 auto expected = Color(0.0331048, 0.132868, 0.318547, 0.8);
1557 ASSERT_COLOR_NEAR(result, expected);
1558 }
1559 }

References ASSERT_COLOR_NEAR, impeller::Color::BlackTransparent(), impeller::Color::SRGBToLinear(), and impeller::Color::White().

## ◆ TEST() [84/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | CubicPathComponentPolylineDoesNotIncludePointOne |
| ) |  |

Definition at line 2013 of file geometry_unittests.cc.

2013 {
2014 CubicPathComponent component({10, 10}, {20, 35}, {35, 20}, {40, 40});
2015 auto polyline = component.CreatePolyline(1.0f);
2016 ASSERT_NE(polyline.front().x, 10);
2017 ASSERT_NE(polyline.front().y, 10);
2018 ASSERT_EQ(polyline.back().x, 40);
2019 ASSERT_EQ(polyline.back().y, 40);
2020 }

References impeller::CubicPathComponent::CreatePolyline().

## ◆ TEST() [85/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | DeterminantTest |
| ) |  |

Definition at line 118 of file geometry_unittests.cc.

118 {
119 auto matrix = Matrix{3, 4, 14, 155, 2, 1, 3, 4, 2, 3, 2, 1, 1, 2, 4, 2};
120 ASSERT_EQ(matrix.GetDeterminant(), -1889);
121 }

## ◆ TEST() [86/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | EmptyPath |
| ) |  |

Definition at line 594 of file geometry_unittests.cc.

594 {
595 auto path = PathBuilder{}.TakePath();
596 ASSERT_EQ(path.GetComponentCount(), 1u);
597
598 ContourComponent c;
599 path.GetContourComponentAtIndex(0, c);
600 ASSERT_POINT_NEAR(c.destination, Point());
601
602 Path::Polyline polyline = path.CreatePolyline(1.0f);
603 ASSERT_TRUE(polyline.points.empty());
604 ASSERT_TRUE(polyline.contours.empty());
605 }

References ASSERT_POINT_NEAR, impeller::Path::Polyline::contours, impeller::ContourComponent::destination, impeller::Path::Polyline::points, and impeller::PathBuilder::TakePath().

## ◆ TEST() [87/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ExtremaOfCubicPathComponentIsCorrect |
| ) |  |

Definition at line 688 of file geometry_unittests.cc.

688 {
689 CubicPathComponent cubic{{11.769268, 252.883148},
690 {-6.2857933, 204.356461},
691 {-4.53997231, 156.552902},
692 {17.0067291, 109.472488}};
693 auto points = cubic.Extrema();
694 ASSERT_EQ(points.size(), static_cast<size_t>(3));
695 ASSERT_POINT_NEAR(points[2], cubic.Solve(0.455916));
696 }

References ASSERT_POINT_NEAR, and impeller::CubicPathComponent::Extrema().

## ◆ TEST() [88/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Gradient |
| ) |  |

Definition at line 2285 of file geometry_unittests.cc.

2285 {
2286 {
2287 // Simple 2 color gradient produces color buffer containing exactly those
2288 // values.
2289 std::vector<Color> colors = {Color::Red(), Color::Blue()};
2290 std::vector<Scalar> stops = {0.0, 1.0};
2291
2292 auto gradient = CreateGradientBuffer(colors, stops);
2293
2294 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, colors);
2295 ASSERT_EQ(gradient.texture_size, 2u);
2296 }
2297
2298 {
2299 // Gradient with duplicate stops does not create an empty texture.
2300 std::vector<Color> colors = {Color::Red(), Color::Yellow(), Color::Black(),
2301 Color::Blue()};
2302 std::vector<Scalar> stops = {0.0, 0.25, 0.25, 1.0};
2303
2304 auto gradient = CreateGradientBuffer(colors, stops);
2305 ASSERT_EQ(gradient.texture_size, 5u);
2306 }
2307
2308 {
2309 // Simple N color gradient produces color buffer containing exactly those
2310 // values.
2311 std::vector<Color> colors = {Color::Red(), Color::Blue(), Color::Green(),
2312 Color::White()};
2313 std::vector<Scalar> stops = {0.0, 0.33, 0.66, 1.0};
2314
2315 auto gradient = CreateGradientBuffer(colors, stops);
2316
2317 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, colors);
2318 ASSERT_EQ(gradient.texture_size, 4u);
2319 }
2320
2321 {
2322 // Gradient with color stops will lerp and scale buffer.
2323 std::vector<Color> colors = {Color::Red(), Color::Blue(), Color::Green()};
2324 std::vector<Scalar> stops = {0.0, 0.25, 1.0};
2325
2326 auto gradient = CreateGradientBuffer(colors, stops);
2327
2328 std::vector<Color> lerped_colors = {
2329 Color::Red(),
2330 Color::Blue(),
2331 Color::Lerp(Color::Blue(), Color::Green(), 0.3333),
2332 Color::Lerp(Color::Blue(), Color::Green(), 0.6666),
2333 Color::Green(),
2334 };
2335 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, lerped_colors);
2336 ASSERT_EQ(gradient.texture_size, 5u);
2337 }
2338
2339 {
2340 // Gradient size is capped at 1024.
2341 std::vector<Color> colors = {};
2342 std::vector<Scalar> stops = {};
2343 for (auto i = 0u; i < 1025; i++) {
2344 colors.push_back(Color::Blue());
2345 stops.push_back(i / 1025.0);
2346 }
2347
2348 auto gradient = CreateGradientBuffer(colors, stops);
2349
2350 ASSERT_EQ(gradient.texture_size, 1024u);
2351 ASSERT_EQ(gradient.color_bytes.size(), 1024u * 4);
2352 }
2353 }

References ASSERT_COLOR_BUFFER_NEAR, impeller::Color::Black(), impeller::Color::Blue(), impeller::CreateGradientBuffer(), impeller::Color::Green(), impeller::Color::Lerp(), impeller::Color::Red(), impeller::Color::White(), and impeller::Color::Yellow().

## ◆ TEST() [89/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | HalfConversions |
| ) |  |

Definition at line 2355 of file geometry_unittests.cc.

2355 {
2356 #ifdef FML_OS_WIN
2357 GTEST_SKIP() << "Half-precision floats (IEEE 754) are not portable and "
2358 "unavailable on Windows.";
2359 #else
2360 ASSERT_EQ(ScalarToHalf(0.0), 0.0f16);
2361 ASSERT_EQ(ScalarToHalf(0.05), 0.05f16);
2362 ASSERT_EQ(ScalarToHalf(2.43), 2.43f16);
2363 ASSERT_EQ(ScalarToHalf(-1.45), -1.45f16);
2364
2365 // 65504 is the largest possible half.
2366 ASSERT_EQ(ScalarToHalf(65504.0f), 65504.0f16);
2367 ASSERT_EQ(ScalarToHalf(65504.0f + 1), 65504.0f16);
2368
2369 // Colors
2370 ASSERT_EQ(HalfVector4(Color::Red()),
2371 HalfVector4(1.0f16, 0.0f16, 0.0f16, 1.0f16));
2372 ASSERT_EQ(HalfVector4(Color::Green()),
2373 HalfVector4(0.0f16, 1.0f16, 0.0f16, 1.0f16));
2374 ASSERT_EQ(HalfVector4(Color::Blue()),
2375 HalfVector4(0.0f16, 0.0f16, 1.0f16, 1.0f16));
2376 ASSERT_EQ(HalfVector4(Color::Black().WithAlpha(0)),
2377 HalfVector4(0.0f16, 0.0f16, 0.0f16, 0.0f16));
2378
2379 ASSERT_EQ(HalfVector3(Vector3(4.0, 6.0, -1.0)),
2380 HalfVector3(4.0f16, 6.0f16, -1.0f16));
2381 ASSERT_EQ(HalfVector2(Vector2(4.0, 6.0)), HalfVector2(4.0f16, 6.0f16));
2382
2383 ASSERT_EQ(Half(0.5f), Half(0.5f16));
2384 ASSERT_EQ(Half(0.5), Half(0.5f16));
2385 ASSERT_EQ(Half(5), Half(5.0f16));
2386 #endif // FML_OS_WIN
2387 }

References impeller::Color::Black(), impeller::Color::Blue(), impeller::Color::Green(), impeller::Color::Red(), and impeller::ScalarToHalf().

## ◆ TEST() [90/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | InvertMatrix |
| ) |  |

Definition at line 123 of file geometry_unittests.cc.

123 {
124 auto inverted = Matrix{10, -9, -12, 8, //
125 7, -12, 11, 22, //
126 -10, 10, 3, 6, //
127 -2, 22, 2, 1}
128 .Invert();
129
130 auto result = Matrix{
131 438.0 / 85123.0, 1751.0 / 85123.0, -7783.0 / 85123.0, 4672.0 / 85123.0,
132 393.0 / 85123.0, -178.0 / 85123.0, -570.0 / 85123.0, 4192 / 85123.0,
133 -5230.0 / 85123.0, 2802.0 / 85123.0, -3461.0 / 85123.0, 962.0 / 85123.0,
134 2690.0 / 85123.0, 1814.0 / 85123.0, 3896.0 / 85123.0, 319.0 / 85123.0};
135
136 ASSERT_MATRIX_NEAR(inverted, result);
137 }

References ASSERT_MATRIX_NEAR, and impeller::Matrix::Invert().

## ◆ TEST() [91/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | InvertMultMatrix |
| ) |  |

Definition at line 78 of file geometry_unittests.cc.

78 {
79 {
80 auto rotation = Matrix::MakeRotationZ(Radians{kPiOver4});
81 auto invert = rotation.Invert();
82 auto expect = Matrix{0.707, -0.707, 0, 0, //
83 0.707, 0.707, 0, 0, //
84 0, 0, 1, 0, //
85 0, 0, 0, 1};
86 ASSERT_MATRIX_NEAR(invert, expect);
87 }
88 {
89 auto scale = Matrix::MakeScale(Vector2{2, 4});
90 auto invert = scale.Invert();
91 auto expect = Matrix{0.5, 0, 0, 0, //
92 0, 0.25, 0, 0, //
93 0, 0, 1, 0, //
94 0, 0, 0, 1};
95 ASSERT_MATRIX_NEAR(invert, expect);
96 }
97 }

References ASSERT_MATRIX_NEAR, impeller::Matrix::Invert(), impeller::kPiOver4, impeller::Matrix::MakeRotationZ(), and impeller::Matrix::MakeScale().

## ◆ TEST() [92/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MakeColumn |
| ) |  |

Definition at line 41 of file geometry_unittests.cc.

41 {
42 auto matrix = Matrix::MakeColumn(1, 2, 3, 4, //
43 5, 6, 7, 8, //
44 9, 10, 11, 12, //
45 13, 14, 15, 16);
46
47 auto expect = Matrix{1, 2, 3, 4, //
48 5, 6, 7, 8, //
49 9, 10, 11, 12, //
50 13, 14, 15, 16};
51
52 ASSERT_TRUE(matrix == expect);
53 }

References impeller::Matrix::MakeColumn().

## ◆ TEST() [93/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MakeRow |
| ) |  |

Definition at line 55 of file geometry_unittests.cc.

55 {
56 auto matrix = Matrix::MakeRow(1, 2, 3, 4, //
57 5, 6, 7, 8, //
58 9, 10, 11, 12, //
59 13, 14, 15, 16);
60
61 auto expect = Matrix{1, 5, 9, 13, //
62 2, 6, 10, 14, //
63 3, 7, 11, 15, //
64 4, 8, 12, 16};
65
66 ASSERT_TRUE(matrix == expect);
67 }

References impeller::Matrix::MakeRow().

## ◆ TEST() [94/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixBasis |
| ) |  |

Definition at line 99 of file geometry_unittests.cc.

99 {
100 auto matrix = Matrix{1, 2, 3, 4, //
101 5, 6, 7, 8, //
102 9, 10, 11, 12, //
103 13, 14, 15, 16};
104 auto basis = matrix.Basis();
105 auto expect = Matrix{1, 2, 3, 0, //
106 5, 6, 7, 0, //
107 9, 10, 11, 0, //
108 0, 0, 0, 1};
109 ASSERT_MATRIX_NEAR(basis, expect);
110 }

References ASSERT_MATRIX_NEAR, and impeller::Matrix::Basis().

## ◆ TEST() [95/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixGetBasisVectors |
| ) |  |

Definition at line 408 of file geometry_unittests.cc.

408 {
409 {
410 auto m = Matrix();
411 Vector3 x = m.GetBasisX();
412 Vector3 y = m.GetBasisY();
413 Vector3 z = m.GetBasisZ();
414 ASSERT_VECTOR3_NEAR(x, Vector3(1, 0, 0));
415 ASSERT_VECTOR3_NEAR(y, Vector3(0, 1, 0));
416 ASSERT_VECTOR3_NEAR(z, Vector3(0, 0, 1));
417 }
418
419 {
420 auto m = Matrix::MakeRotationZ(Radians{kPiOver2}) *
421 Matrix::MakeRotationX(Radians{kPiOver2}) *
422 Matrix::MakeScale(Vector3(2, 3, 4));
423 Vector3 x = m.GetBasisX();
424 Vector3 y = m.GetBasisY();
425 Vector3 z = m.GetBasisZ();
426 ASSERT_VECTOR3_NEAR(x, Vector3(0, 2, 0));
427 ASSERT_VECTOR3_NEAR(y, Vector3(0, 0, 3));
428 ASSERT_VECTOR3_NEAR(z, Vector3(4, 0, 0));
429 }
430 }

References ASSERT_VECTOR3_NEAR, impeller::kPiOver2, impeller::Matrix::MakeRotationX(), impeller::Matrix::MakeRotationZ(), and impeller::Matrix::MakeScale().

## ◆ TEST() [96/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixGetDirectionScale |
| ) |  |

Definition at line 432 of file geometry_unittests.cc.

432 {
433 {
434 auto m = Matrix();
435 Scalar result = m.GetDirectionScale(Vector3{1, 0, 0});
436 ASSERT_FLOAT_EQ(result, 1);
437 }
438
439 {
440 auto m = Matrix::MakeRotationX(Degrees{10}) *
441 Matrix::MakeRotationY(Degrees{83}) *
442 Matrix::MakeRotationZ(Degrees{172});
443 Scalar result = m.GetDirectionScale(Vector3{0, 1, 0});
444 ASSERT_FLOAT_EQ(result, 1);
445 }
446
447 {
448 auto m = Matrix::MakeRotationZ(Radians{kPiOver2}) *
449 Matrix::MakeScale(Vector3(3, 4, 5));
450 Scalar result = m.GetDirectionScale(Vector3{2, 0, 0});
451 ASSERT_FLOAT_EQ(result, 8);
452 }
453 }

References impeller::Matrix::GetDirectionScale(), impeller::kPiOver2, impeller::Matrix::MakeRotationX(), impeller::Matrix::MakeRotationY(), impeller::Matrix::MakeRotationZ(), and impeller::Matrix::MakeScale().

## ◆ TEST() [97/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixGetMaxBasisLength |
| ) |  |

Definition at line 330 of file geometry_unittests.cc.

330 {
331 {
332 auto m = Matrix::MakeScale({3, 1, 1});
333 ASSERT_EQ(m.GetMaxBasisLength(), 3);
334
335 m = m * Matrix::MakeSkew(0, 4);
336 ASSERT_EQ(m.GetMaxBasisLength(), 5);
337 }
338
339 {
340 auto m = Matrix::MakeScale({-3, 4, 2});
341 ASSERT_EQ(m.GetMaxBasisLength(), 4);
342 }
343 }

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

## ◆ TEST() [98/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixGetMaxBasisLengthXY |
| ) |  |

Definition at line 345 of file geometry_unittests.cc.

345 {
346 {
347 auto m = Matrix::MakeScale({3, 1, 1});
348 ASSERT_EQ(m.GetMaxBasisLengthXY(), 3);
349
350 m = m * Matrix::MakeSkew(0, 4);
351 ASSERT_EQ(m.GetMaxBasisLengthXY(), 5);
352 }
353
354 {
355 auto m = Matrix::MakeScale({-3, 4, 7});
356 ASSERT_EQ(m.GetMaxBasisLengthXY(), 4);
357 }
358 }

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

## ◆ TEST() [99/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixIsAligned |
| ) |  |

Definition at line 455 of file geometry_unittests.cc.

455 {
456 {
457 auto m = Matrix::MakeTranslation({1, 2, 3});
458 bool result = m.IsAligned();
459 ASSERT_TRUE(result);
460 }
461
462 {
463 auto m = Matrix::MakeRotationZ(Degrees{123});
464 bool result = m.IsAligned();
465 ASSERT_FALSE(result);
466 }
467 }

References impeller::Matrix::IsAligned(), impeller::Matrix::MakeRotationZ(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [100/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixLookAt |
| ) |  |

Definition at line 495 of file geometry_unittests.cc.

495 {
496 {
497 auto m = Matrix::MakeLookAt(Vector3(0, 0, -1), Vector3(0, 0, 1),
498 Vector3(0, 1, 0));
499 auto expected = Matrix{
500 1, 0, 0, 0, //
501 0, 1, 0, 0, //
502 0, 0, 1, 0, //
503 0, 0, 1, 1, //
504 };
505 ASSERT_MATRIX_NEAR(m, expected);
506 }
507
508 // Sideways tilt.
509 {
510 auto m = Matrix::MakeLookAt(Vector3(0, 0, -1), Vector3(0, 0, 1),
511 Vector3(1, 1, 0).Normalize());
512
513 // clang-format off
514 auto expected = Matrix{
515 k1OverSqrt2, k1OverSqrt2, 0, 0,
516 -k1OverSqrt2, k1OverSqrt2, 0, 0,
517 0, 0, 1, 0,
518 0, 0, 1, 1,
519 };
520 // clang-format on
521 ASSERT_MATRIX_NEAR(m, expected);
522 }
523
524 // Half way between +x and -y, yaw 90
525 {
526 auto m =
527 Matrix::MakeLookAt(Vector3(), Vector3(10, -10, 0), Vector3(0, 0, -1));
528
529 // clang-format off
530 auto expected = Matrix{
531 -k1OverSqrt2, 0, k1OverSqrt2, 0,
532 -k1OverSqrt2, 0, -k1OverSqrt2, 0,
533 0, -1, 0, 0,
534 0, 0, 0, 1,
535 };
536 // clang-format on
537 ASSERT_MATRIX_NEAR(m, expected);
538 }
539 }

References ASSERT_MATRIX_NEAR, impeller::k1OverSqrt2, and impeller::Matrix::MakeLookAt().

## ◆ TEST() [101/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixMakeOrthographic |
| ) |  |

Definition at line 360 of file geometry_unittests.cc.

360 {
361 {
362 auto m = Matrix::MakeOrthographic(Size(100, 200));
363 auto expect = Matrix{
364 0.02, 0, 0, 0, //
365 0, -0.01, 0, 0, //
366 0, 0, 0, 0, //
367 -1, 1, 0.5, 1, //
368 };
369 ASSERT_MATRIX_NEAR(m, expect);
370 }
371
372 {
373 auto m = Matrix::MakeOrthographic(Size(400, 100));
374 auto expect = Matrix{
375 0.005, 0, 0, 0, //
376 0, -0.02, 0, 0, //
377 0, 0, 0, 0, //
378 -1, 1, 0.5, 1, //
379 };
380 ASSERT_MATRIX_NEAR(m, expect);
381 }
382 }

References ASSERT_MATRIX_NEAR, and impeller::Matrix::MakeOrthographic().

## ◆ TEST() [102/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixMakePerspective |
| ) |  |

Definition at line 384 of file geometry_unittests.cc.

384 {
385 {
386 auto m = Matrix::MakePerspective(Degrees(60), Size(100, 200), 1, 10);
387 auto expect = Matrix{
388 3.4641, 0, 0, 0, //
389 0, 1.73205, 0, 0, //
390 0, 0, 1.11111, 1, //
391 0, 0, -1.11111, 0, //
392 };
393 ASSERT_MATRIX_NEAR(m, expect);
394 }
395
396 {
397 auto m = Matrix::MakePerspective(Radians(1), 2, 10, 20);
398 auto expect = Matrix{
399 0.915244, 0, 0, 0, //
400 0, 1.83049, 0, 0, //
401 0, 0, 2, 1, //
402 0, 0, -20, 0, //
403 };
404 ASSERT_MATRIX_NEAR(m, expect);
405 }
406 }

References ASSERT_MATRIX_NEAR, and impeller::Matrix::MakePerspective().

## ◆ TEST() [103/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixMakeRotationFromQuaternion |
| ) |  |

Definition at line 275 of file geometry_unittests.cc.

275 {
276 {
277 auto matrix = Matrix::MakeRotation(Quaternion({1, 0, 0}, kPiOver2));
278 auto expected = Matrix::MakeRotationX(Radians(kPiOver2));
279 ASSERT_MATRIX_NEAR(matrix, expected);
280 }
281
282 {
283 auto matrix = Matrix::MakeRotation(Quaternion({0, 1, 0}, kPiOver2));
284 auto expected = Matrix::MakeRotationY(Radians(kPiOver2));
285 ASSERT_MATRIX_NEAR(matrix, expected);
286 }
287
288 {
289 auto matrix = Matrix::MakeRotation(Quaternion({0, 0, 1}, kPiOver2));
290 auto expected = Matrix::MakeRotationZ(Radians(kPiOver2));
291 ASSERT_MATRIX_NEAR(matrix, expected);
292 }
293 }

References ASSERT_MATRIX_NEAR, impeller::kPiOver2, impeller::Matrix::MakeRotation(), impeller::Matrix::MakeRotationX(), impeller::Matrix::MakeRotationY(), and impeller::Matrix::MakeRotationZ().

## ◆ TEST() [104/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixPrinting |
| ) |  |

Definition at line 2188 of file geometry_unittests.cc.

2188 {
2189 {
2190 std::stringstream stream;
2191 Matrix m;
2192 stream << m;
2193 ASSERT_EQ(stream.str(), R"((
2194 1.000000, 0.000000, 0.000000, 0.000000,
2195 0.000000, 1.000000, 0.000000, 0.000000,
2196 0.000000, 0.000000, 1.000000, 0.000000,
2197 0.000000, 0.000000, 0.000000, 1.000000,
2198 ))");
2199 }
2200
2201 {
2202 std::stringstream stream;
2203 Matrix m = Matrix::MakeTranslation(Vector3(10, 20, 30));
2204 stream << m;
2205
2206 ASSERT_EQ(stream.str(), R"((
2207 1.000000, 0.000000, 0.000000, 10.000000,
2208 0.000000, 1.000000, 0.000000, 20.000000,
2209 0.000000, 0.000000, 1.000000, 30.000000,
2210 0.000000, 0.000000, 0.000000, 1.000000,
2211 ))");
2212 }
2213 }

References impeller::Matrix::MakeTranslation().

## ◆ TEST() [105/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixTransformDirection |
| ) |  |

Definition at line 295 of file geometry_unittests.cc.

295 {
296 {
297 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
298 Matrix::MakeRotationZ(Radians{kPiOver2}) *
299 Matrix::MakeScale({2.0, 2.0, 2.0});
300 auto vector = Vector4(10, 20, 30, 2);
301
302 Vector4 result = matrix.TransformDirection(vector);
303 auto expected = Vector4(-40, 20, 60, 2);
304 ASSERT_VECTOR4_NEAR(result, expected);
305 }
306
307 {
308 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
309 Matrix::MakeRotationZ(Radians{kPiOver2}) *
310 Matrix::MakeScale({2.0, 2.0, 2.0});
311 auto vector = Vector3(10, 20, 30);
312
313 Vector3 result = matrix.TransformDirection(vector);
314 auto expected = Vector3(-40, 20, 60);
315 ASSERT_VECTOR3_NEAR(result, expected);
316 }
317
318 {
319 auto matrix = Matrix::MakeTranslation({0, -0.4, 100}) *
320 Matrix::MakeRotationZ(Radians{kPiOver2}) *
321 Matrix::MakeScale({2.0, 2.0, 2.0});
322 auto vector = Point(10, 20);
323
324 Point result = matrix.TransformDirection(vector);
325 auto expected = Point(-40, 20);
326 ASSERT_POINT_NEAR(result, expected);
327 }
328 }

References ASSERT_POINT_NEAR, ASSERT_VECTOR3_NEAR, ASSERT_VECTOR4_NEAR, impeller::kPiOver2, impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [106/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixTranslationScaleOnly |
| ) |  |

Definition at line 469 of file geometry_unittests.cc.

469 {
470 {
471 auto m = Matrix();
472 bool result = m.IsTranslationScaleOnly();
473 ASSERT_TRUE(result);
474 }
475
476 {
477 auto m = Matrix::MakeScale(Vector3(2, 3, 4));
478 bool result = m.IsTranslationScaleOnly();
479 ASSERT_TRUE(result);
480 }
481
482 {
483 auto m = Matrix::MakeTranslation(Vector3(2, 3, 4));
484 bool result = m.IsTranslationScaleOnly();
485 ASSERT_TRUE(result);
486 }
487
488 {
489 auto m = Matrix::MakeRotationZ(Degrees(10));
490 bool result = m.IsTranslationScaleOnly();
491 ASSERT_FALSE(result);
492 }
493 }

References impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [107/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MatrixVectorMultiplication |
| ) |  |

Definition at line 210 of file geometry_unittests.cc.

210 {
211 {
212 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
213 Matrix::MakeRotationZ(Radians{kPiOver2}) *
214 Matrix::MakeScale({2.0, 2.0, 2.0});
215 auto vector = Vector4(10, 20, 30, 2);
216
217 Vector4 result = matrix * vector;
218 auto expected = Vector4(160, 220, 260, 2);
219 ASSERT_VECTOR4_NEAR(result, expected);
220 }
221
222 {
223 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
224 Matrix::MakeRotationZ(Radians{kPiOver2}) *
225 Matrix::MakeScale({2.0, 2.0, 2.0});
226 auto vector = Vector3(10, 20, 30);
227
228 Vector3 result = matrix * vector;
229 auto expected = Vector3(60, 120, 160);
230 ASSERT_VECTOR3_NEAR(result, expected);
231 }
232
233 {
234 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
235 Matrix::MakeRotationZ(Radians{kPiOver2}) *
236 Matrix::MakeScale({2.0, 2.0, 2.0});
237 auto vector = Point(10, 20);
238
239 Point result = matrix * vector;
240 auto expected = Point(60, 120);
241 ASSERT_POINT_NEAR(result, expected);
242 }
243
244 // Matrix Vector ops should respect perspective transforms.
245 {
246 auto matrix = Matrix::MakePerspective(Radians(kPiOver2), 1, 1, 100);
247 auto vector = Vector3(3, 3, -3);
248
249 Vector3 result = matrix * vector;
250 auto expected = Vector3(-1, -1, 1.3468);
251 ASSERT_VECTOR3_NEAR(result, expected);
252 }
253
254 {
255 auto matrix = Matrix::MakePerspective(Radians(kPiOver2), 1, 1, 100) *
256 Matrix::MakeTranslation(Vector3(0, 0, -3));
257 auto point = Point(3, 3);
258
259 Point result = matrix * point;
260 auto expected = Point(-1, -1);
261 ASSERT_POINT_NEAR(result, expected);
262 }
263
264 // Resolves to 0 on perspective singularity.
265 {
266 auto matrix = Matrix::MakePerspective(Radians(kPiOver2), 1, 1, 100);
267 auto point = Point(3, 3);
268
269 Point result = matrix * point;
270 auto expected = Point(0, 0);
271 ASSERT_POINT_NEAR(result, expected);
272 }
273 }

References ASSERT_POINT_NEAR, ASSERT_VECTOR3_NEAR, ASSERT_VECTOR4_NEAR, impeller::kPiOver2, impeller::Matrix::MakePerspective(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [108/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | MutliplicationMatrix |
| ) |  |

Definition at line 112 of file geometry_unittests.cc.

112 {
113 auto rotation = Matrix::MakeRotationZ(Radians{kPiOver4});
114 auto invert = rotation.Invert();
115 ASSERT_MATRIX_NEAR(rotation * invert, Matrix{});
116 }

References ASSERT_MATRIX_NEAR, impeller::Matrix::Invert(), impeller::kPiOver4, and impeller::Matrix::MakeRotationZ().

## ◆ TEST() [109/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PathAddRectPolylineHasCorrectContourData |
| ) |  |

Definition at line 2143 of file geometry_unittests.cc.

2143 {
2144 Path::Polyline polyline = PathBuilder{}
2145 .AddRect(Rect::MakeLTRB(50, 60, 70, 80))
2146 .TakePath()
2147 .CreatePolyline(1.0f);
2148 ASSERT_EQ(polyline.contours.size(), 1u);
2149 ASSERT_TRUE(polyline.contours[0].is_closed);
2150 ASSERT_EQ(polyline.contours[0].start_index, 0u);
2151 ASSERT_EQ(polyline.points.size(), 5u);
2152 ASSERT_EQ(polyline.points[0], Point(50, 60));
2153 ASSERT_EQ(polyline.points[1], Point(70, 60));
2154 ASSERT_EQ(polyline.points[2], Point(70, 80));
2155 ASSERT_EQ(polyline.points[3], Point(50, 80));
2156 ASSERT_EQ(polyline.points[4], Point(50, 60));
2157 }

References impeller::PathBuilder::AddRect(), impeller::Path::Polyline::contours, impeller::Path::CreatePolyline(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Path::Polyline::points, and impeller::PathBuilder::TakePath().

## ◆ TEST() [110/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PathBuilderSetsCorrectContourPropertiesForAddCommands |
| ) |  |

Definition at line 2041 of file geometry_unittests.cc.

2041 {
2042 // Closed shapes.
2043 {
2044 Path path = PathBuilder{}.AddCircle({100, 100}, 50).TakePath();
2045 ContourComponent contour;
2046 path.GetContourComponentAtIndex(0, contour);
2047 ASSERT_POINT_NEAR(contour.destination, Point(100, 50));
2048 ASSERT_TRUE(contour.is_closed);
2049 }
2050
2051 {
2052 Path path = PathBuilder{}.AddOval(Rect(100, 100, 100, 100)).TakePath();
2053 ContourComponent contour;
2054 path.GetContourComponentAtIndex(0, contour);
2055 ASSERT_POINT_NEAR(contour.destination, Point(150, 100));
2056 ASSERT_TRUE(contour.is_closed);
2057 }
2058
2059 {
2060 Path path = PathBuilder{}.AddRect(Rect(100, 100, 100, 100)).TakePath();
2061 ContourComponent contour;
2062 path.GetContourComponentAtIndex(0, contour);
2063 ASSERT_POINT_NEAR(contour.destination, Point(100, 100));
2064 ASSERT_TRUE(contour.is_closed);
2065 }
2066
2067 {
2068 Path path =
2069 PathBuilder{}.AddRoundedRect(Rect(100, 100, 100, 100), 10).TakePath();
2070 ContourComponent contour;
2071 path.GetContourComponentAtIndex(0, contour);
2072 ASSERT_POINT_NEAR(contour.destination, Point(110, 100));
2073 ASSERT_TRUE(contour.is_closed);
2074 }
2075
2076 // Open shapes.
2077 {
2078 Point p(100, 100);
2079 Path path = PathBuilder{}.AddLine(p, {200, 100}).TakePath();
2080 ContourComponent contour;
2081 path.GetContourComponentAtIndex(0, contour);
2082 ASSERT_POINT_NEAR(contour.destination, p);
2083 ASSERT_FALSE(contour.is_closed);
2084 }
2085
2086 {
2087 Path path =
2088 PathBuilder{}
2089 .AddCubicCurve({100, 100}, {100, 50}, {100, 150}, {200, 100})
2090 .TakePath();
2091 ContourComponent contour;
2092 path.GetContourComponentAtIndex(0, contour);
2093 ASSERT_POINT_NEAR(contour.destination, Point(100, 100));
2094 ASSERT_FALSE(contour.is_closed);
2095 }
2096
2097 {
2098 Path path = PathBuilder{}
2099 .AddQuadraticCurve({100, 100}, {100, 50}, {200, 100})
2100 .TakePath();
2101 ContourComponent contour;
2102 path.GetContourComponentAtIndex(0, contour);
2103 ASSERT_POINT_NEAR(contour.destination, Point(100, 100));
2104 ASSERT_FALSE(contour.is_closed);
2105 }
2106 }

References impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddCubicCurve(), impeller::PathBuilder::AddLine(), impeller::PathBuilder::AddOval(), impeller::PathBuilder::AddQuadraticCurve(), impeller::PathBuilder::AddRect(), impeller::PathBuilder::AddRoundedRect(), ASSERT_POINT_NEAR, impeller::ContourComponent::destination, impeller::Path::GetContourComponentAtIndex(), impeller::ContourComponent::is_closed, and impeller::PathBuilder::TakePath().

## ◆ TEST() [111/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PathBuilderWillComputeBounds |
| ) |  |

Definition at line 2425 of file geometry_unittests.cc.

2425 {
2426 PathBuilder builder;
2427 auto path_1 = builder.AddLine({0, 0}, {1, 1}).TakePath();
2428
2429 ASSERT_EQ(path_1.GetBoundingBox().value(), Rect::MakeLTRB(0, 0, 1, 1));
2430
2431 auto path_2 = builder.AddLine({-1, -1}, {1, 1}).TakePath();
2432
2433 // Verify that PathBuilder recomputes the bounds.
2434 ASSERT_EQ(path_2.GetBoundingBox().value(), Rect::MakeLTRB(-1, -1, 1, 1));
2435
2436 // PathBuilder can set the bounds to whatever it wants
2437 auto path_3 = builder.AddLine({0, 0}, {1, 1})
2438 .SetBounds(Rect::MakeLTRB(0, 0, 100, 100))
2439 .TakePath();
2440
2441 ASSERT_EQ(path_3.GetBoundingBox().value(), Rect::MakeLTRB(0, 0, 100, 100));
2442 }

References impeller::PathBuilder::AddLine(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [112/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PathCreatePolyLineDoesNotDuplicatePoints |
| ) |  |

Definition at line 2022 of file geometry_unittests.cc.

2022 {
2023 PathBuilder builder;
2024 builder.MoveTo({10, 10});
2025 builder.LineTo({20, 20});
2026 builder.LineTo({30, 30});
2027 builder.MoveTo({40, 40});
2028 builder.LineTo({50, 50});
2029
2030 auto polyline = builder.TakePath().CreatePolyline(1.0f);
2031
2032 ASSERT_EQ(polyline.contours.size(), 2u);
2033 ASSERT_EQ(polyline.points.size(), 5u);
2034 ASSERT_EQ(polyline.points[0].x, 10);
2035 ASSERT_EQ(polyline.points[1].x, 20);
2036 ASSERT_EQ(polyline.points[2].x, 30);
2037 ASSERT_EQ(polyline.points[3].x, 40);
2038 ASSERT_EQ(polyline.points[4].x, 50);
2039 }

References impeller::Path::CreatePolyline(), impeller::PathBuilder::LineTo(), impeller::PathBuilder::MoveTo(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [113/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PathCreatePolylineGeneratesCorrectContourData |
| ) |  |

Definition at line 2108 of file geometry_unittests.cc.

2108 {
2109 Path::Polyline polyline = PathBuilder{}
2110 .AddLine({100, 100}, {200, 100})
2111 .MoveTo({100, 200})
2112 .LineTo({150, 250})
2113 .LineTo({200, 200})
2114 .Close()
2115 .TakePath()
2116 .CreatePolyline(1.0f);
2117 ASSERT_EQ(polyline.points.size(), 6u);
2118 ASSERT_EQ(polyline.contours.size(), 2u);
2119 ASSERT_EQ(polyline.contours[0].is_closed, false);
2120 ASSERT_EQ(polyline.contours[0].start_index, 0u);
2121 ASSERT_EQ(polyline.contours[1].is_closed, true);
2122 ASSERT_EQ(polyline.contours[1].start_index, 2u);
2123 }

References impeller::PathBuilder::AddLine(), impeller::Close(), impeller::Path::Polyline::contours, impeller::LineTo(), impeller::MoveTo(), and impeller::Path::Polyline::points.

## ◆ TEST() [114/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PathGetBoundingBoxForCubicWithNoDerivativeRootsIsCorrect |
| ) |  |

Definition at line 698 of file geometry_unittests.cc.

698 {
699 PathBuilder builder;
700 // Straight diagonal line.
701 builder.AddCubicCurve({0, 1}, {2, 3}, {4, 5}, {6, 7});
702 auto path = builder.TakePath();
703 auto actual = path.GetBoundingBox();
704 auto expected = Rect::MakeLTRB(0, 1, 6, 7);
705 ASSERT_TRUE(actual.has_value());
706 ASSERT_RECT_NEAR(actual.value(), expected);
707 }

References impeller::PathBuilder::AddCubicCurve(), ASSERT_RECT_NEAR, impeller::Path::GetBoundingBox(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [115/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PathPolylineDuplicatesAreRemovedForSameContour |
| ) |  |

Definition at line 2159 of file geometry_unittests.cc.

2159 {
2160 Path::Polyline polyline =
2161 PathBuilder{}
2162 .MoveTo({50, 50})
2163 .LineTo({50, 50}) // Insert duplicate at beginning of contour.
2164 .LineTo({100, 50})
2165 .LineTo({100, 50}) // Insert duplicate at contour join.
2166 .LineTo({100, 100})
2167 .Close() // Implicitly insert duplicate {50, 50} across contours.
2168 .LineTo({0, 50})
2169 .LineTo({0, 100})
2170 .LineTo({0, 100}) // Insert duplicate at end of contour.
2171 .TakePath()
2172 .CreatePolyline(1.0f);
2173 ASSERT_EQ(polyline.contours.size(), 2u);
2174 ASSERT_EQ(polyline.contours[0].start_index, 0u);
2175 ASSERT_TRUE(polyline.contours[0].is_closed);
2176 ASSERT_EQ(polyline.contours[1].start_index, 4u);
2177 ASSERT_FALSE(polyline.contours[1].is_closed);
2178 ASSERT_EQ(polyline.points.size(), 7u);
2179 ASSERT_EQ(polyline.points[0], Point(50, 50));
2180 ASSERT_EQ(polyline.points[1], Point(100, 50));
2181 ASSERT_EQ(polyline.points[2], Point(100, 100));
2182 ASSERT_EQ(polyline.points[3], Point(50, 50));
2183 ASSERT_EQ(polyline.points[4], Point(50, 50));
2184 ASSERT_EQ(polyline.points[5], Point(0, 50));
2185 ASSERT_EQ(polyline.points[6], Point(0, 100));
2186 }

References impeller::Close(), impeller::Path::Polyline::contours, impeller::LineTo(), impeller::PathBuilder::MoveTo(), and impeller::Path::Polyline::points.

## ◆ TEST() [116/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PathShifting |
| ) |  |

Definition at line 2389 of file geometry_unittests.cc.

2389 {
2390 PathBuilder builder{};
2391 auto path =
2392 builder.AddLine(Point(0, 0), Point(10, 10))
2393 .AddQuadraticCurve(Point(10, 10), Point(15, 15), Point(20, 20))
2394 .AddCubicCurve(Point(20, 20), Point(25, 25), Point(-5, -5),
2395 Point(30, 30))
2396 .Close()
2397 .Shift(Point(1, 1))
2398 .TakePath();
2399
2400 ContourComponent contour;
2401 LinearPathComponent linear;
2402 QuadraticPathComponent quad;
2403 CubicPathComponent cubic;
2404
2405 ASSERT_TRUE(path.GetContourComponentAtIndex(0, contour));
2406 ASSERT_TRUE(path.GetLinearComponentAtIndex(1, linear));
2407 ASSERT_TRUE(path.GetQuadraticComponentAtIndex(3, quad));
2408 ASSERT_TRUE(path.GetCubicComponentAtIndex(5, cubic));
2409
2410 ASSERT_EQ(contour.destination, Point(1, 1));
2411
2412 ASSERT_EQ(linear.p1, Point(1, 1));
2413 ASSERT_EQ(linear.p2, Point(11, 11));
2414
2415 ASSERT_EQ(quad.cp, Point(16, 16));
2416 ASSERT_EQ(quad.p1, Point(11, 11));
2417 ASSERT_EQ(quad.p2, Point(21, 21));
2418
2419 ASSERT_EQ(cubic.cp1, Point(26, 26));
2420 ASSERT_EQ(cubic.cp2, Point(-4, -4));
2421 ASSERT_EQ(cubic.p1, Point(21, 21));
2422 ASSERT_EQ(cubic.p2, Point(31, 31));
2423 }

References impeller::PathBuilder::AddCubicCurve(), impeller::PathBuilder::AddLine(), impeller::PathBuilder::AddQuadraticCurve(), impeller::PathBuilder::Close(), impeller::QuadraticPathComponent::cp, impeller::CubicPathComponent::cp1, impeller::CubicPathComponent::cp2, impeller::ContourComponent::destination, impeller::LinearPathComponent::p1, impeller::QuadraticPathComponent::p1, impeller::CubicPathComponent::p1, impeller::LinearPathComponent::p2, impeller::QuadraticPathComponent::p2, impeller::CubicPathComponent::p2, impeller::PathBuilder::Shift(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [117/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointAbs |
| ) |  |

Definition at line 1076 of file geometry_unittests.cc.

1076 {
1077 Point a(-1, -2);
1078 auto a_abs = a.Abs();
1079 auto expected = Point(1, 2);
1080 ASSERT_POINT_NEAR(a_abs, expected);
1081 }

References impeller::TPoint< T >::Abs(), and ASSERT_POINT_NEAR.

## ◆ TEST() [118/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointAngleTo |
| ) |  |

Definition at line 1083 of file geometry_unittests.cc.

1083 {
1084 // Negative result in the CCW (with up = -Y) direction.
1085 {
1086 Point a(1, 1);
1087 Point b(1, -1);
1088 Radians actual = a.AngleTo(b);
1089 Radians expected = Radians{-kPi / 2};
1090 ASSERT_FLOAT_EQ(actual.radians, expected.radians);
1091 }
1092
1093 // Check the other direction to ensure the result is signed correctly.
1094 {
1095 Point a(1, -1);
1096 Point b(1, 1);
1097 Radians actual = a.AngleTo(b);
1098 Radians expected = Radians{kPi / 2};
1099 ASSERT_FLOAT_EQ(actual.radians, expected.radians);
1100 }
1101
1102 // Differences in magnitude should have no impact on the result.
1103 {
1104 Point a(100, -100);
1105 Point b(0.01, 0.01);
1106 Radians actual = a.AngleTo(b);
1107 Radians expected = Radians{kPi / 2};
1108 ASSERT_FLOAT_EQ(actual.radians, expected.radians);
1109 }
1110 }

References impeller::TPoint< T >::AngleTo(), impeller::kPi, and impeller::Radians::radians.

## ◆ TEST() [119/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointCeil |
| ) |  |

Definition at line 1175 of file geometry_unittests.cc.

1175 {
1176 Point p(1.5, 2.3);
1177 Point result = p.Ceil();
1178 Point expected(2, 3);
1179 ASSERT_POINT_NEAR(result, expected);
1180 }

References ASSERT_POINT_NEAR, and impeller::TPoint< T >::Ceil().

## ◆ TEST() [120/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointCrossProduct |
| ) |  |

Definition at line 1031 of file geometry_unittests.cc.

1031 {
1032 {
1033 Point p(1, 0);
1034 Scalar s = p.Cross(Point(-1, 0));
1035 ASSERT_FLOAT_EQ(s, 0);
1036 }
1037
1038 {
1039 Point p(0, -1);
1040 Scalar s = p.Cross(Point(-1, 0));
1041 ASSERT_FLOAT_EQ(s, -1);
1042 }
1043
1044 {
1045 Point p(1, 2);
1046 Scalar s = p.Cross(Point(3, -4));
1047 ASSERT_FLOAT_EQ(s, -10);
1048 }
1049 }

References impeller::TPoint< T >::Cross().

## ◆ TEST() [121/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointDotProduct |
| ) |  |

Definition at line 1011 of file geometry_unittests.cc.

1011 {
1012 {
1013 Point p(1, 0);
1014 Scalar s = p.Dot(Point(-1, 0));
1015 ASSERT_FLOAT_EQ(s, -1);
1016 }
1017
1018 {
1019 Point p(0, -1);
1020 Scalar s = p.Dot(Point(-1, 0));
1021 ASSERT_FLOAT_EQ(s, 0);
1022 }
1023
1024 {
1025 Point p(1, 2);
1026 Scalar s = p.Dot(Point(3, -4));
1027 ASSERT_FLOAT_EQ(s, -5);
1028 }
1029 }

References impeller::TPoint< T >::Dot().

## ◆ TEST() [122/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointFloor |
| ) |  |

Definition at line 1154 of file geometry_unittests.cc.

1154 {
1155 Point p(1.5, 2.3);
1156 Point result = p.Floor();
1157 Point expected(1, 2);
1158 ASSERT_POINT_NEAR(result, expected);
1159 }

References ASSERT_POINT_NEAR, and impeller::TPoint< T >::Floor().

## ◆ TEST() [123/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointIntegerCoercesToFloat |
| ) |  |

Definition at line 816 of file geometry_unittests.cc.

816 {
817 // Integer on LHS, float on RHS
818 {
819 IPoint p1(1, 2);
820 Point p2 = p1 + Point(1, 2);
821 ASSERT_FLOAT_EQ(p2.x, 2u);
822 ASSERT_FLOAT_EQ(p2.y, 4u);
823 }
824
825 {
826 IPoint p1(3, 6);
827 Point p2 = p1 - Point(1, 2);
828 ASSERT_FLOAT_EQ(p2.x, 2u);
829 ASSERT_FLOAT_EQ(p2.y, 4u);
830 }
831
832 {
833 IPoint p1(1, 2);
834 Point p2 = p1 * Point(2, 3);
835 ASSERT_FLOAT_EQ(p2.x, 2u);
836 ASSERT_FLOAT_EQ(p2.y, 6u);
837 }
838
839 {
840 IPoint p1(2, 6);
841 Point p2 = p1 / Point(2, 3);
842 ASSERT_FLOAT_EQ(p2.x, 1u);
843 ASSERT_FLOAT_EQ(p2.y, 2u);
844 }
845
846 // Float on LHS, integer on RHS
847 {
848 Point p1(1, 2);
849 Point p2 = p1 + IPoint(1, 2);
850 ASSERT_FLOAT_EQ(p2.x, 2u);
851 ASSERT_FLOAT_EQ(p2.y, 4u);
852 }
853
854 {
855 Point p1(3, 6);
856 Point p2 = p1 - IPoint(1, 2);
857 ASSERT_FLOAT_EQ(p2.x, 2u);
858 ASSERT_FLOAT_EQ(p2.y, 4u);
859 }
860
861 {
862 Point p1(1, 2);
863 Point p2 = p1 * IPoint(2, 3);
864 ASSERT_FLOAT_EQ(p2.x, 2u);
865 ASSERT_FLOAT_EQ(p2.y, 6u);
866 }
867
868 {
869 Point p1(2, 6);
870 Point p2 = p1 / IPoint(2, 3);
871 ASSERT_FLOAT_EQ(p2.x, 1u);
872 ASSERT_FLOAT_EQ(p2.y, 2u);
873 }
874 }

References impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST() [124/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointLerp |
| ) |  |

Definition at line 1217 of file geometry_unittests.cc.

1217 {
1218 Point p(1, 2);
1219 Point result = p.Lerp({5, 10}, 0.75);
1220 Point expected(4, 8);
1221 ASSERT_POINT_NEAR(result, expected);
1222 }

References ASSERT_POINT_NEAR, and impeller::TPoint< T >::Lerp().

## ◆ TEST() [125/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointMax |
| ) |  |

Definition at line 1133 of file geometry_unittests.cc.

1133 {
1134 Point p(1, 2);
1135 Point result = p.Max({0, 10});
1136 Point expected(1, 10);
1137 ASSERT_POINT_NEAR(result, expected);
1138 }

References ASSERT_POINT_NEAR, and impeller::TPoint< T >::Max().

## ◆ TEST() [126/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointMin |
| ) |  |

Definition at line 1112 of file geometry_unittests.cc.

1112 {
1113 Point p(1, 2);
1114 Point result = p.Min({0, 10});
1115 Point expected(0, 2);
1116 ASSERT_POINT_NEAR(result, expected);
1117 }

References ASSERT_POINT_NEAR, and impeller::TPoint< T >::Min().

## ◆ TEST() [127/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointPrinting |
| ) |  |

Definition at line 2215 of file geometry_unittests.cc.

2215 {
2216 {
2217 std::stringstream stream;
2218 Point m;
2219 stream << m;
2220 ASSERT_EQ(stream.str(), "(0, 0)");
2221 }
2222
2223 {
2224 std::stringstream stream;
2225 Point m(13, 37);
2226 stream << m;
2227 ASSERT_EQ(stream.str(), "(13, 37)");
2228 }
2229 }

## ◆ TEST() [128/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointReflect |
| ) |  |

Definition at line 1051 of file geometry_unittests.cc.

1051 {
1052 {
1053 Point axis = Point(0, 1);
1054 Point a(2, 3);
1055 auto reflected = a.Reflect(axis);
1056 auto expected = Point(2, -3);
1057 ASSERT_POINT_NEAR(reflected, expected);
1058 }
1059
1060 {
1061 Point axis = Point(1, 1).Normalize();
1062 Point a(1, 0);
1063 auto reflected = a.Reflect(axis);
1064 auto expected = Point(0, -1);
1065 ASSERT_POINT_NEAR(reflected, expected);
1066 }
1067
1068 {
1069 Point axis = Point(1, 1).Normalize();
1070 Point a(-1, -1);
1071 auto reflected = a.Reflect(axis);
1072 ASSERT_POINT_NEAR(reflected, -a);
1073 }
1074 }

References ASSERT_POINT_NEAR, impeller::TPoint< T >::Normalize(), and impeller::TPoint< T >::Reflect().

## ◆ TEST() [129/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PointRound |
| ) |  |

Definition at line 1196 of file geometry_unittests.cc.

1196 {
1197 Point p(1.5, 2.3);
1198 Point result = p.Round();
1199 Point expected(2, 2);
1200 ASSERT_POINT_NEAR(result, expected);
1201 }

References ASSERT_POINT_NEAR, and impeller::TPoint< T >::Round().

## ◆ TEST() [130/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | PolylineGetContourPointBoundsReturnsCorrectRanges |
| ) |  |

Definition at line 2125 of file geometry_unittests.cc.

2125 {
2126 Path::Polyline polyline = PathBuilder{}
2127 .AddLine({100, 100}, {200, 100})
2128 .MoveTo({100, 200})
2129 .LineTo({150, 250})
2130 .LineTo({200, 200})
2131 .Close()
2132 .TakePath()
2133 .CreatePolyline(1.0f);
2134 size_t a1, a2, b1, b2;
2135 std::tie(a1, a2) = polyline.GetContourPointBounds(0);
2136 std::tie(b1, b2) = polyline.GetContourPointBounds(1);
2137 ASSERT_EQ(a1, 0u);
2138 ASSERT_EQ(a2, 2u);
2139 ASSERT_EQ(b1, 2u);
2140 ASSERT_EQ(b2, 6u);
2141 }

References impeller::PathBuilder::AddLine(), impeller::Close(), impeller::Path::Polyline::GetContourPointBounds(), impeller::LineTo(), and impeller::MoveTo().

## ◆ TEST() [131/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | QuaternionLerp |
| ) |  |

Definition at line 541 of file geometry_unittests.cc.

541 {
542 auto q1 = Quaternion{{0.0, 0.0, 1.0}, 0.0};
543 auto q2 = Quaternion{{0.0, 0.0, 1.0}, kPiOver4};
544
545 auto q3 = q1.Slerp(q2, 0.5);
546
547 auto expected = Quaternion{{0.0, 0.0, 1.0}, kPiOver4 / 2.0};
548
549 ASSERT_QUATERNION_NEAR(q3, expected);
550 }

References ASSERT_QUATERNION_NEAR, and impeller::kPiOver4.

## ◆ TEST() [132/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | QuaternionVectorMultiply |
| ) |  |

Definition at line 552 of file geometry_unittests.cc.

552 {
553 {
554 Quaternion q({0, 0, 1}, 0);
555 Vector3 v(0, 1, 0);
556
557 Vector3 result = q * v;
558 Vector3 expected(0, 1, 0);
559
560 ASSERT_VECTOR3_NEAR(result, expected);
561 }
562
563 {
564 Quaternion q({0, 0, 1}, k2Pi);
565 Vector3 v(1, 0, 0);
566
567 Vector3 result = q * v;
568 Vector3 expected(1, 0, 0);
569
570 ASSERT_VECTOR3_NEAR(result, expected);
571 }
572
573 {
574 Quaternion q({0, 0, 1}, kPiOver4);
575 Vector3 v(0, 1, 0);
576
577 Vector3 result = q * v;
578 Vector3 expected(-k1OverSqrt2, k1OverSqrt2, 0);
579
580 ASSERT_VECTOR3_NEAR(result, expected);
581 }
582
583 {
584 Quaternion q(Vector3(1, 0, 1).Normalize(), kPi);
585 Vector3 v(0, 0, -1);
586
587 Vector3 result = q * v;
588 Vector3 expected(-1, 0, 0);
589
590 ASSERT_VECTOR3_NEAR(result, expected);
591 }
592 }

References ASSERT_VECTOR3_NEAR, impeller::k1OverSqrt2, impeller::k2Pi, impeller::kPi, and impeller::kPiOver4.

## ◆ TEST() [133/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | RectContainsPoint |
| ) |  |

Definition at line 1793 of file geometry_unittests.cc.

1793 {
1794 {
1795 // Origin is inclusive
1796 Rect r(100, 100, 100, 100);
1797 Point p(100, 100);
1798 ASSERT_TRUE(r.Contains(p));
1799 }
1800 {
1801 // Size is exclusive
1802 Rect r(100, 100, 100, 100);
1803 Point p(200, 200);
1804 ASSERT_FALSE(r.Contains(p));
1805 }
1806 {
1807 Rect r(100, 100, 100, 100);
1808 Point p(99, 99);
1809 ASSERT_FALSE(r.Contains(p));
1810 }
1811 {
1812 Rect r(100, 100, 100, 100);
1813 Point p(199, 199);
1814 ASSERT_TRUE(r.Contains(p));
1815 }
1816
1817 {
1818 Rect r = Rect::MakeMaximum();
1819 Point p(199, 199);
1820 ASSERT_TRUE(r.Contains(p));
1821 }
1822 }

References impeller::TRect< T >::Contains(), and impeller::TRect< Scalar >::MakeMaximum().

## ◆ TEST() [134/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | RectContainsRect |
| ) |  |

Definition at line 1824 of file geometry_unittests.cc.

1824 {
1825 {
1826 Rect a(100, 100, 100, 100);
1827 ASSERT_TRUE(a.Contains(a));
1828 }
1829 {
1830 Rect a(100, 100, 100, 100);
1831 Rect b(0, 0, 0, 0);
1832 ASSERT_FALSE(a.Contains(b));
1833 }
1834 {
1835 Rect a(100, 100, 100, 100);
1836 Rect b(150, 150, 20, 20);
1837 ASSERT_TRUE(a.Contains(b));
1838 }
1839 {
1840 Rect a(100, 100, 100, 100);
1841 Rect b(150, 150, 100, 100);
1842 ASSERT_FALSE(a.Contains(b));
1843 }
1844 {
1845 Rect a(100, 100, 100, 100);
1846 Rect b(50, 50, 100, 100);
1847 ASSERT_FALSE(a.Contains(b));
1848 }
1849 {
1850 Rect a(100, 100, 100, 100);
1851 Rect b(0, 0, 300, 300);
1852 ASSERT_FALSE(a.Contains(b));
1853 }
1854 {
1855 Rect a = Rect::MakeMaximum();
1856 Rect b(0, 0, 300, 300);
1857 ASSERT_TRUE(a.Contains(b));
1858 }
1859 }

References impeller::TRect< T >::Contains(), and impeller::TRect< Scalar >::MakeMaximum().

## ◆ TEST() [135/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | RectCutout |
| ) |  |

Definition at line 1734 of file geometry_unittests.cc.

1734 {
1735 // No cutout.
1736 {
1737 Rect a(0, 0, 100, 100);
1738 Rect b(0, 0, 50, 50);
1739 auto u = a.Cutout(b);
1740 ASSERT_TRUE(u.has_value());
1741 ASSERT_RECT_NEAR(u.value(), a);
1742 }
1743
1744 // Full cutout.
1745 {
1746 Rect a(0, 0, 100, 100);
1747 Rect b(-10, -10, 120, 120);
1748 auto u = a.Cutout(b);
1749 ASSERT_FALSE(u.has_value());
1750 }
1751
1752 // Cutout from top.
1753 {
1754 auto a = Rect::MakeLTRB(0, 0, 100, 100);
1755 auto b = Rect::MakeLTRB(-10, -10, 110, 90);
1756 auto u = a.Cutout(b);
1757 auto expected = Rect::MakeLTRB(0, 90, 100, 100);
1758 ASSERT_TRUE(u.has_value());
1759 ASSERT_RECT_NEAR(u.value(), expected);
1760 }
1761
1762 // Cutout from bottom.
1763 {
1764 auto a = Rect::MakeLTRB(0, 0, 100, 100);
1765 auto b = Rect::MakeLTRB(-10, 10, 110, 110);
1766 auto u = a.Cutout(b);
1767 auto expected = Rect::MakeLTRB(0, 0, 100, 10);
1768 ASSERT_TRUE(u.has_value());
1769 ASSERT_RECT_NEAR(u.value(), expected);
1770 }
1771
1772 // Cutout from left.
1773 {
1774 auto a = Rect::MakeLTRB(0, 0, 100, 100);
1775 auto b = Rect::MakeLTRB(-10, -10, 90, 110);
1776 auto u = a.Cutout(b);
1777 auto expected = Rect::MakeLTRB(90, 0, 100, 100);
1778 ASSERT_TRUE(u.has_value());
1779 ASSERT_RECT_NEAR(u.value(), expected);
1780 }
1781
1782 // Cutout from right.
1783 {
1784 auto a = Rect::MakeLTRB(0, 0, 100, 100);
1785 auto b = Rect::MakeLTRB(10, -10, 110, 110);
1786 auto u = a.Cutout(b);
1787 auto expected = Rect::MakeLTRB(0, 0, 10, 100);
1788 ASSERT_TRUE(u.has_value());
1789 ASSERT_RECT_NEAR(u.value(), expected);
1790 }
1791 }

References ASSERT_RECT_NEAR, impeller::TRect< T >::Cutout(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [136/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | RectDirections |
| ) |  |

Definition at line 1984 of file geometry_unittests.cc.

1984 {
1985 auto r = Rect::MakeLTRB(1, 2, 3, 4);
1986
1987 ASSERT_EQ(r.GetLeft(), 1);
1988 ASSERT_EQ(r.GetTop(), 2);
1989 ASSERT_EQ(r.GetRight(), 3);
1990 ASSERT_EQ(r.GetBottom(), 4);
1991
1992 ASSERT_POINT_NEAR(r.GetLeftTop(), Point(1, 2));
1993 ASSERT_POINT_NEAR(r.GetRightTop(), Point(3, 2));
1994 ASSERT_POINT_NEAR(r.GetLeftBottom(), Point(1, 4));
1995 ASSERT_POINT_NEAR(r.GetRightBottom(), Point(3, 4));
1996 }

References ASSERT_POINT_NEAR, and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [137/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | RectExpand |
| ) |  |

Definition at line 1915 of file geometry_unittests.cc.

1915 {
1916 {
1917 auto a = Rect::MakeLTRB(100, 100, 200, 200);
1918 auto b = a.Expand(1);
1919 auto expected = Rect::MakeLTRB(99, 99, 201, 201);
1920 ASSERT_RECT_NEAR(b, expected);
1921 }
1922 {
1923 auto a = Rect::MakeLTRB(100, 100, 200, 200);
1924 auto b = a.Expand(-1);
1925 auto expected = Rect::MakeLTRB(101, 101, 199, 199);
1926 ASSERT_RECT_NEAR(b, expected);
1927 }
1928
1929 {
1930 auto a = Rect::MakeLTRB(100, 100, 200, 200);
1931 auto b = a.Expand(1, 2, 3, 4);
1932 auto expected = Rect::MakeLTRB(99, 98, 203, 204);
1933 ASSERT_RECT_NEAR(b, expected);
1934 }
1935 {
1936 auto a = Rect::MakeLTRB(100, 100, 200, 200);
1937 auto b = a.Expand(-1, -2, -3, -4);
1938 auto expected = Rect::MakeLTRB(101, 102, 197, 196);
1939 ASSERT_RECT_NEAR(b, expected);
1940 }
1941 }

References ASSERT_RECT_NEAR, and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [138/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | RectGetPoints |
| ) |  |

Definition at line 1861 of file geometry_unittests.cc.

1861 {
1862 {
1863 Rect r(100, 200, 300, 400);
1864 auto points = r.GetPoints();
1865 ASSERT_POINT_NEAR(points[0], Point(100, 200));
1866 ASSERT_POINT_NEAR(points[1], Point(400, 200));
1867 ASSERT_POINT_NEAR(points[2], Point(100, 600));
1868 ASSERT_POINT_NEAR(points[3], Point(400, 600));
1869 }
1870
1871 {
1872 Rect r = Rect::MakeMaximum();
1873 auto points = r.GetPoints();
1874 ASSERT_EQ(points[0], Point(-std::numeric_limits<float>::infinity(),
1875 -std::numeric_limits<float>::infinity()));
1876 ASSERT_EQ(points[1], Point(std::numeric_limits<float>::infinity(),
1877 -std::numeric_limits<float>::infinity()));
1878 ASSERT_EQ(points[2], Point(-std::numeric_limits<float>::infinity(),
1879 std::numeric_limits<float>::infinity()));
1880 ASSERT_EQ(points[3], Point(std::numeric_limits<float>::infinity(),
1881 std::numeric_limits<float>::infinity()));
1882 }
1883 }

References ASSERT_POINT_NEAR, impeller::TRect< T >::GetPoints(), and impeller::TRect< Scalar >::MakeMaximum().

## ◆ TEST() [139/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | RectGetPositive |
| ) |  |

Definition at line 1943 of file geometry_unittests.cc.

1943 {
1944 {
1945 Rect r{100, 200, 300, 400};
1946 auto actual = r.GetPositive();
1947 ASSERT_RECT_NEAR(r, actual);
1948 }
1949 {
1950 Rect r{100, 200, -100, -100};
1951 auto actual = r.GetPositive();
1952 Rect expected(0, 100, 100, 100);
1953 ASSERT_RECT_NEAR(expected, actual);
1954 }
1955 }

References ASSERT_RECT_NEAR, and impeller::TRect< T >::GetPositive().

## ◆ TEST() [140/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | RectGetTransformedPoints |
| ) |  |

Definition at line 1892 of file geometry_unittests.cc.

1892 {
1893 Rect r(100, 200, 300, 400);
1894 auto points = r.GetTransformedPoints(Matrix::MakeTranslation({10, 20}));
1895 ASSERT_POINT_NEAR(points[0], Point(110, 220));
1896 ASSERT_POINT_NEAR(points[1], Point(410, 220));
1897 ASSERT_POINT_NEAR(points[2], Point(110, 620));
1898 ASSERT_POINT_NEAR(points[3], Point(410, 620));
1899 }

References ASSERT_POINT_NEAR, impeller::TRect< T >::GetTransformedPoints(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [141/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | RectIntersection |
| ) |  |

Definition at line 1647 of file geometry_unittests.cc.

1647 {
1648 {
1649 Rect a(100, 100, 100, 100);
1650 Rect b(0, 0, 0, 0);
1651
1652 auto u = a.Intersection(b);
1653 ASSERT_FALSE(u.has_value());
1654 }
1655
1656 {
1657 Rect a(100, 100, 100, 100);
1658 Rect b(10, 10, 0, 0);
1659 auto u = a.Intersection(b);
1660 ASSERT_FALSE(u.has_value());
1661 }
1662
1663 {
1664 Rect a(0, 0, 100, 100);
1665 Rect b(10, 10, 100, 100);
1666 auto u = a.Intersection(b);
1667 ASSERT_TRUE(u.has_value());
1668 auto expected = Rect(10, 10, 90, 90);
1669 ASSERT_RECT_NEAR(u.value(), expected);
1670 }
1671
1672 {
1673 Rect a(0, 0, 100, 100);
1674 Rect b(100, 100, 100, 100);
1675 auto u = a.Intersection(b);
1676 ASSERT_FALSE(u.has_value());
1677 }
1678
1679 {
1680 Rect a = Rect::MakeMaximum();
1681 Rect b(10, 10, 300, 300);
1682 auto u = a.Intersection(b);
1683 ASSERT_TRUE(u);
1684 ASSERT_RECT_NEAR(u.value(), b);
1685 }
1686
1687 {
1688 Rect a = Rect::MakeMaximum();
1689 Rect b = Rect::MakeMaximum();
1690 auto u = a.Intersection(b);
1691 ASSERT_TRUE(u);
1692 ASSERT_EQ(u, Rect::MakeMaximum());
1693 }
1694 }

References ASSERT_RECT_NEAR, impeller::TRect< T >::Intersection(), and impeller::TRect< Scalar >::MakeMaximum().

## ◆ TEST() [142/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | RectIntersectsWithRect |
| ) |  |

Definition at line 1696 of file geometry_unittests.cc.

1696 {
1697 {
1698 Rect a(100, 100, 100, 100);
1699 Rect b(0, 0, 0, 0);
1700 ASSERT_FALSE(a.IntersectsWithRect(b));
1701 }
1702
1703 {
1704 Rect a(100, 100, 100, 100);
1705 Rect b(10, 10, 0, 0);
1706 ASSERT_FALSE(a.IntersectsWithRect(b));
1707 }
1708
1709 {
1710 Rect a(0, 0, 100, 100);
1711 Rect b(10, 10, 100, 100);
1712 ASSERT_TRUE(a.IntersectsWithRect(b));
1713 }
1714
1715 {
1716 Rect a(0, 0, 100, 100);
1717 Rect b(100, 100, 100, 100);
1718 ASSERT_FALSE(a.IntersectsWithRect(b));
1719 }
1720
1721 {
1722 Rect a = Rect::MakeMaximum();
1723 Rect b(10, 10, 100, 100);
1724 ASSERT_TRUE(a.IntersectsWithRect(b));
1725 }
1726
1727 {
1728 Rect a = Rect::MakeMaximum();
1729 Rect b = Rect::MakeMaximum();
1730 ASSERT_TRUE(a.IntersectsWithRect(b));
1731 }
1732 }

References impeller::TRect< T >::IntersectsWithRect(), and impeller::TRect< Scalar >::MakeMaximum().

## ◆ TEST() [143/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | RectMakePointBounds |
| ) |  |

Definition at line 1901 of file geometry_unittests.cc.

1901 {
1902 {
1903 std::vector<Point> points{{1, 5}, {4, -1}, {0, 6}};
1904 Rect r = Rect::MakePointBounds(points.begin(), points.end()).value();
1905 auto expected = Rect(0, -1, 4, 7);
1906 ASSERT_RECT_NEAR(r, expected);
1907 }
1908 {
1909 std::vector<Point> points;
1910 std::optional<Rect> r = Rect::MakePointBounds(points.begin(), points.end());
1911 ASSERT_FALSE(r.has_value());
1912 }
1913 }

References ASSERT_RECT_NEAR, and impeller::TRect< Scalar >::MakePointBounds().

## ◆ TEST() [144/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | RectMakeSize |
| ) |  |

Definition at line 1583 of file geometry_unittests.cc.

1583 {
1584 {
1585 Size s(100, 200);
1586 Rect r = Rect::MakeSize(s);
1587 Rect expected = Rect::MakeLTRB(0, 0, 100, 200);
1588 ASSERT_RECT_NEAR(r, expected);
1589 }
1590
1591 {
1592 ISize s(100, 200);
1593 Rect r = Rect::MakeSize(s);
1594 Rect expected = Rect::MakeLTRB(0, 0, 100, 200);
1595 ASSERT_RECT_NEAR(r, expected);
1596 }
1597
1598 {
1599 Size s(100, 200);
1600 IRect r = IRect::MakeSize(s);
1601 IRect expected = IRect::MakeLTRB(0, 0, 100, 200);
1602 ASSERT_EQ(r, expected);
1603 }
1604
1605 {
1606 ISize s(100, 200);
1607 IRect r = IRect::MakeSize(s);
1608 IRect expected = IRect::MakeLTRB(0, 0, 100, 200);
1609 ASSERT_EQ(r, expected);
1610 }
1611 }

References ASSERT_RECT_NEAR, impeller::TRect< int64_t >::MakeLTRB(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< int64_t >::MakeSize(), and impeller::TRect< Scalar >::MakeSize().

## ◆ TEST() [145/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | RectProject |
| ) |  |

Definition at line 1998 of file geometry_unittests.cc.

1998 {
1999 {
2000 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
2001 auto actual = r.Project(r);
2002 auto expected = Rect::MakeLTRB(0, 0, 1, 1);
2003 ASSERT_RECT_NEAR(expected, actual);
2004 }
2005 {
2006 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
2007 auto actual = r.Project(Rect::MakeLTRB(0, 0, 100, 100));
2008 auto expected = Rect::MakeLTRB(0.5, 0.5, 1, 1);
2009 ASSERT_RECT_NEAR(expected, actual);
2010 }
2011 }

References ASSERT_RECT_NEAR, and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [146/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | RectScale |
| ) |  |

Definition at line 1957 of file geometry_unittests.cc.

1957 {
1958 {
1959 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
1960 auto actual = r.Scale(0);
1961 auto expected = Rect::MakeLTRB(0, 0, 0, 0);
1962 ASSERT_RECT_NEAR(expected, actual);
1963 }
1964 {
1965 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
1966 auto actual = r.Scale(-2);
1967 auto expected = Rect::MakeLTRB(200, 200, -200, -200);
1968 ASSERT_RECT_NEAR(expected, actual);
1969 }
1970 {
1971 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
1972 auto actual = r.Scale(Point{0, 0});
1973 auto expected = Rect::MakeLTRB(0, 0, 0, 0);
1974 ASSERT_RECT_NEAR(expected, actual);
1975 }
1976 {
1977 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
1978 auto actual = r.Scale(Size{-1, -2});
1979 auto expected = Rect::MakeLTRB(100, 200, -100, -200);
1980 ASSERT_RECT_NEAR(expected, actual);
1981 }
1982 }

References ASSERT_RECT_NEAR, and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [147/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | RectShift |
| ) |  |

Definition at line 1885 of file geometry_unittests.cc.

1885 {
1886 auto r = Rect::MakeLTRB(0, 0, 100, 100);
1887
1888 ASSERT_EQ(r.Shift(Point(10, 5)), Rect::MakeLTRB(10, 5, 110, 105));
1889 ASSERT_EQ(r.Shift(Point(-10, -5)), Rect::MakeLTRB(-10, -5, 90, 95));
1890 }

References impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [148/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | RectUnion |
| ) |  |

Definition at line 1613 of file geometry_unittests.cc.

1613 {
1614 {
1615 Rect a(100, 100, 100, 100);
1616 Rect b(0, 0, 0, 0);
1617 auto u = a.Union(b);
1618 auto expected = Rect(0, 0, 200, 200);
1619 ASSERT_RECT_NEAR(u, expected);
1620 }
1621
1622 {
1623 Rect a(100, 100, 100, 100);
1624 Rect b(10, 10, 0, 0);
1625 auto u = a.Union(b);
1626 auto expected = Rect(10, 10, 190, 190);
1627 ASSERT_RECT_NEAR(u, expected);
1628 }
1629
1630 {
1631 Rect a(0, 0, 100, 100);
1632 Rect b(10, 10, 100, 100);
1633 auto u = a.Union(b);
1634 auto expected = Rect(0, 0, 110, 110);
1635 ASSERT_RECT_NEAR(u, expected);
1636 }
1637
1638 {
1639 Rect a(0, 0, 100, 100);
1640 Rect b(100, 100, 100, 100);
1641 auto u = a.Union(b);
1642 auto expected = Rect(0, 0, 200, 200);
1643 ASSERT_RECT_NEAR(u, expected);
1644 }
1645 }

References ASSERT_RECT_NEAR, and impeller::TRect< T >::Union().

## ◆ TEST() [149/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | RotationMatrix |
| ) |  |

Definition at line 69 of file geometry_unittests.cc.

69 {
70 auto rotation = Matrix::MakeRotationZ(Radians{kPiOver4});
71 auto expect = Matrix{0.707, 0.707, 0, 0, //
72 -0.707, 0.707, 0, 0, //
73 0, 0, 1, 0, //
74 0, 0, 0, 1};
75 ASSERT_MATRIX_NEAR(rotation, expect);
76 }

References ASSERT_MATRIX_NEAR, impeller::kPiOver4, and impeller::Matrix::MakeRotationZ().

## ◆ TEST() [150/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ScalarNearlyEqual |
| ) |  |

Definition at line 32 of file geometry_unittests.cc.

32 {
33 ASSERT_FALSE(ScalarNearlyEqual(0.0021f, 0.001f));
34 ASSERT_TRUE(ScalarNearlyEqual(0.0019f, 0.001f));
35 ASSERT_TRUE(ScalarNearlyEqual(0.002f, 0.001f, 0.0011f));
36 ASSERT_FALSE(ScalarNearlyEqual(0.002f, 0.001f, 0.0009f));
37 ASSERT_TRUE(ScalarNearlyEqual(
38 1.0f, 1.0f + std::numeric_limits<float>::epsilon() * 4));
39 }

References impeller::ScalarNearlyEqual().

## ◆ TEST() [151/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | SimplePath |
| ) |  |

Definition at line 607 of file geometry_unittests.cc.

607 {
608 PathBuilder builder;
609
610 auto path = builder.AddLine({0, 0}, {100, 100})
611 .AddQuadraticCurve({100, 100}, {200, 200}, {300, 300})
612 .AddCubicCurve({300, 300}, {400, 400}, {500, 500}, {600, 600})
613 .TakePath();
614
615 ASSERT_EQ(path.GetComponentCount(), 6u);
616 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 1u);
617 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kQuadratic), 1u);
618 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kCubic), 1u);
619 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 3u);
620
621 path.EnumerateComponents(
622 [](size_t index, const LinearPathComponent& linear) {
623 Point p1(0, 0);
624 Point p2(100, 100);
625 ASSERT_EQ(index, 1u);
626 ASSERT_EQ(linear.p1, p1);
627 ASSERT_EQ(linear.p2, p2);
628 },
629 [](size_t index, const QuadraticPathComponent& quad) {
630 Point p1(100, 100);
631 Point cp(200, 200);
632 Point p2(300, 300);
633 ASSERT_EQ(index, 3u);
634 ASSERT_EQ(quad.p1, p1);
635 ASSERT_EQ(quad.cp, cp);
636 ASSERT_EQ(quad.p2, p2);
637 },
638 [](size_t index, const CubicPathComponent& cubic) {
639 Point p1(300, 300);
640 Point cp1(400, 400);
641 Point cp2(500, 500);
642 Point p2(600, 600);
643 ASSERT_EQ(index, 5u);
644 ASSERT_EQ(cubic.p1, p1);
645 ASSERT_EQ(cubic.cp1, cp1);
646 ASSERT_EQ(cubic.cp2, cp2);
647 ASSERT_EQ(cubic.p2, p2);
648 },
649 [](size_t index, const ContourComponent& contour) {
650 // There is an initial countour added for each curve.
651 if (index == 0u) {
652 Point p1(0, 0);
653 ASSERT_EQ(contour.destination, p1);
654 } else if (index == 2u) {
655 Point p1(100, 100);
656 ASSERT_EQ(contour.destination, p1);
657 } else if (index == 4u) {
658 Point p1(300, 300);
659 ASSERT_EQ(contour.destination, p1);
660 } else {
661 ASSERT_FALSE(true);
662 }
663 ASSERT_FALSE(contour.is_closed);
664 });
665 }

References impeller::PathBuilder::AddLine(), impeller::Path::kContour, impeller::Path::kCubic, impeller::Path::kLinear, impeller::Path::kQuadratic, impeller::LinearPathComponent::p1, and impeller::LinearPathComponent::p2.

## ◆ TEST() [152/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | SizeCoercesToPoint |
| ) |  |

Definition at line 876 of file geometry_unittests.cc.

876 {
877 // Point on LHS, Size on RHS
878 {
879 IPoint p1(1, 2);
880 IPoint p2 = p1 + ISize(1, 2);
881 ASSERT_EQ(p2.x, 2u);
882 ASSERT_EQ(p2.y, 4u);
883 }
884
885 {
886 IPoint p1(3, 6);
887 IPoint p2 = p1 - ISize(1, 2);
888 ASSERT_EQ(p2.x, 2u);
889 ASSERT_EQ(p2.y, 4u);
890 }
891
892 {
893 IPoint p1(1, 2);
894 IPoint p2 = p1 * ISize(2, 3);
895 ASSERT_EQ(p2.x, 2u);
896 ASSERT_EQ(p2.y, 6u);
897 }
898
899 {
900 IPoint p1(2, 6);
901 IPoint p2 = p1 / ISize(2, 3);
902 ASSERT_EQ(p2.x, 1u);
903 ASSERT_EQ(p2.y, 2u);
904 }
905
906 // Size on LHS, Point on RHS
907 {
908 ISize p1(1, 2);
909 IPoint p2 = p1 + IPoint(1, 2);
910 ASSERT_EQ(p2.x, 2u);
911 ASSERT_EQ(p2.y, 4u);
912 }
913
914 {
915 ISize p1(3, 6);
916 IPoint p2 = p1 - IPoint(1, 2);
917 ASSERT_EQ(p2.x, 2u);
918 ASSERT_EQ(p2.y, 4u);
919 }
920
921 {
922 ISize p1(1, 2);
923 IPoint p2 = p1 * IPoint(2, 3);
924 ASSERT_EQ(p2.x, 2u);
925 ASSERT_EQ(p2.y, 6u);
926 }
927
928 {
929 ISize p1(2, 6);
930 IPoint p2 = p1 / IPoint(2, 3);
931 ASSERT_EQ(p2.x, 1u);
932 ASSERT_EQ(p2.y, 2u);
933 }
934 }

References impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST() [153/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | TestDecomposition |
| ) |  |

Definition at line 139 of file geometry_unittests.cc.

139 {
140 auto rotated = Matrix::MakeRotationZ(Radians{kPiOver4});
141
142 auto result = rotated.Decompose();
143
144 ASSERT_TRUE(result.has_value());
145
146 MatrixDecomposition res = result.value();
147
148 auto quaternion = Quaternion{{0.0, 0.0, 1.0}, kPiOver4};
149 ASSERT_QUATERNION_NEAR(res.rotation, quaternion);
150 }

References ASSERT_QUATERNION_NEAR, impeller::Matrix::Decompose(), impeller::kPiOver4, impeller::Matrix::MakeRotationZ(), and impeller::MatrixDecomposition::rotation.

## ◆ TEST() [154/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | TestDecomposition2 |
| ) |  |

Definition at line 152 of file geometry_unittests.cc.

152 {
153 auto rotated = Matrix::MakeRotationZ(Radians{kPiOver4});
154 auto scaled = Matrix::MakeScale({2.0, 3.0, 1.0});
155 auto translated = Matrix::MakeTranslation({-200, 750, 20});
156
157 auto result = (translated * rotated * scaled).Decompose();
158
159 ASSERT_TRUE(result.has_value());
160
161 MatrixDecomposition res = result.value();
162
163 auto quaternion = Quaternion{{0.0, 0.0, 1.0}, kPiOver4};
164
165 ASSERT_QUATERNION_NEAR(res.rotation, quaternion);
166
167 ASSERT_FLOAT_EQ(res.translation.x, -200);
168 ASSERT_FLOAT_EQ(res.translation.y, 750);
169 ASSERT_FLOAT_EQ(res.translation.z, 20);
170
171 ASSERT_FLOAT_EQ(res.scale.x, 2);
172 ASSERT_FLOAT_EQ(res.scale.y, 3);
173 ASSERT_FLOAT_EQ(res.scale.z, 1);
174 }

References ASSERT_QUATERNION_NEAR, impeller::kPiOver4, impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::MatrixDecomposition::rotation, impeller::MatrixDecomposition::scale, impeller::MatrixDecomposition::translation, impeller::Vector3::x, impeller::Vector3::y, and impeller::Vector3::z.

## ◆ TEST() [155/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | TestRecomposition |
| ) |  |

Definition at line 176 of file geometry_unittests.cc.

176 {
177 /*
178 * Decomposition.
179 */
180 auto rotated = Matrix::MakeRotationZ(Radians{kPiOver4});
181
182 auto result = rotated.Decompose();
183
184 ASSERT_TRUE(result.has_value());
185
186 MatrixDecomposition res = result.value();
187
188 auto quaternion = Quaternion{{0.0, 0.0, 1.0}, kPiOver4};
189
190 ASSERT_QUATERNION_NEAR(res.rotation, quaternion);
191
192 /*
193 * Recomposition.
194 */
195 ASSERT_MATRIX_NEAR(rotated, Matrix{res});
196 }

References ASSERT_MATRIX_NEAR, ASSERT_QUATERNION_NEAR, impeller::Matrix::Decompose(), impeller::kPiOver4, impeller::Matrix::MakeRotationZ(), and impeller::MatrixDecomposition::rotation.

## ◆ TEST() [156/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | TestRecomposition2 |
| ) |  |

Definition at line 198 of file geometry_unittests.cc.

198 {
199 auto matrix = Matrix::MakeTranslation({100, 100, 100}) *
200 Matrix::MakeRotationZ(Radians{kPiOver4}) *
201 Matrix::MakeScale({2.0, 2.0, 2.0});
202
203 auto result = matrix.Decompose();
204
205 ASSERT_TRUE(result.has_value());
206
207 ASSERT_MATRIX_NEAR(matrix, Matrix{result.value()});
208 }

References ASSERT_MATRIX_NEAR, impeller::Matrix::Decompose(), impeller::kPiOver4, impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [157/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | ToIColor |
| ) |  |

Definition at line 2279 of file geometry_unittests.cc.

2279 {
2280 ASSERT_EQ(Color::ToIColor(Color(0, 0, 0, 0)), 0u);
2281 ASSERT_EQ(Color::ToIColor(Color(1.0, 1.0, 1.0, 1.0)), 0xFFFFFFFF);
2282 ASSERT_EQ(Color::ToIColor(Color(0.5, 0.5, 1.0, 1.0)), 0xFF8080FF);
2283 }

References impeller::Color::ToIColor().

## ◆ TEST() [158/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector3Ceil |
| ) |  |

Definition at line 1182 of file geometry_unittests.cc.

1182 {
1183 Vector3 p(1.5, 2.3, 3.9);
1184 Vector3 result = p.Ceil();
1185 Vector3 expected(2, 3, 4);
1186 ASSERT_VECTOR3_NEAR(result, expected);
1187 }

References ASSERT_VECTOR3_NEAR, and impeller::Vector3::Ceil().

## ◆ TEST() [159/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector3Floor |
| ) |  |

Definition at line 1161 of file geometry_unittests.cc.

1161 {
1162 Vector3 p(1.5, 2.3, 3.9);
1163 Vector3 result = p.Floor();
1164 Vector3 expected(1, 2, 3);
1165 ASSERT_VECTOR3_NEAR(result, expected);
1166 }

References ASSERT_VECTOR3_NEAR, and impeller::Vector3::Floor().

## ◆ TEST() [160/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector3Lerp |
| ) |  |

Definition at line 1224 of file geometry_unittests.cc.

1224 {
1225 Vector3 p(1, 2, 3);
1226 Vector3 result = p.Lerp({5, 10, 15}, 0.75);
1227 Vector3 expected(4, 8, 12);
1228 ASSERT_VECTOR3_NEAR(result, expected);
1229 }

References ASSERT_VECTOR3_NEAR, and impeller::Vector3::Lerp().

## ◆ TEST() [161/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector3Max |
| ) |  |

Definition at line 1140 of file geometry_unittests.cc.

1140 {
1141 Vector3 p(1, 2, 3);
1142 Vector3 result = p.Max({0, 10, 2});
1143 Vector3 expected(1, 10, 3);
1144 ASSERT_VECTOR3_NEAR(result, expected);
1145 }

References ASSERT_VECTOR3_NEAR, and impeller::Vector3::Max().

## ◆ TEST() [162/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector3Min |
| ) |  |

Definition at line 1119 of file geometry_unittests.cc.

1119 {
1120 Vector3 p(1, 2, 3);
1121 Vector3 result = p.Min({0, 10, 2});
1122 Vector3 expected(0, 2, 2);
1123 ASSERT_VECTOR3_NEAR(result, expected);
1124 }

References ASSERT_VECTOR3_NEAR, and impeller::Vector3::Min().

## ◆ TEST() [163/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector3Printing |
| ) |  |

Definition at line 2231 of file geometry_unittests.cc.

2231 {
2232 {
2233 std::stringstream stream;
2234 Vector3 m;
2235 stream << m;
2236 ASSERT_EQ(stream.str(), "(0, 0, 0)");
2237 }
2238
2239 {
2240 std::stringstream stream;
2241 Vector3 m(1, 2, 3);
2242 stream << m;
2243 ASSERT_EQ(stream.str(), "(1, 2, 3)");
2244 }
2245 }

## ◆ TEST() [164/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector3Round |
| ) |  |

Definition at line 1203 of file geometry_unittests.cc.

1203 {
1204 Vector3 p(1.5, 2.3, 3.9);
1205 Vector3 result = p.Round();
1206 Vector3 expected(2, 2, 4);
1207 ASSERT_VECTOR3_NEAR(result, expected);
1208 }

References ASSERT_VECTOR3_NEAR, and impeller::Vector3::Round().

## ◆ TEST() [165/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector4Ceil |
| ) |  |

Definition at line 1189 of file geometry_unittests.cc.

1189 {
1190 Vector4 p(1.5, 2.3, 3.9, 4.0);
1191 Vector4 result = p.Ceil();
1192 Vector4 expected(2, 3, 4, 4);
1193 ASSERT_VECTOR4_NEAR(result, expected);
1194 }

References ASSERT_VECTOR4_NEAR, and impeller::Vector4::Ceil().

## ◆ TEST() [166/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector4Floor |
| ) |  |

Definition at line 1168 of file geometry_unittests.cc.

1168 {
1169 Vector4 p(1.5, 2.3, 3.9, 4.0);
1170 Vector4 result = p.Floor();
1171 Vector4 expected(1, 2, 3, 4);
1172 ASSERT_VECTOR4_NEAR(result, expected);
1173 }

References ASSERT_VECTOR4_NEAR, and impeller::Vector4::Floor().

## ◆ TEST() [167/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector4Lerp |
| ) |  |

Definition at line 1231 of file geometry_unittests.cc.

1231 {
1232 Vector4 p(1, 2, 3, 4);
1233 Vector4 result = p.Lerp({5, 10, 15, 20}, 0.75);
1234 Vector4 expected(4, 8, 12, 16);
1235 ASSERT_VECTOR4_NEAR(result, expected);
1236 }

References ASSERT_VECTOR4_NEAR, and impeller::Vector4::Lerp().

## ◆ TEST() [168/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector4Max |
| ) |  |

Definition at line 1147 of file geometry_unittests.cc.

1147 {
1148 Vector4 p(1, 2, 3, 4);
1149 Vector4 result = p.Max({0, 10, 2, 1});
1150 Vector4 expected(1, 10, 3, 4);
1151 ASSERT_VECTOR4_NEAR(result, expected);
1152 }

References ASSERT_VECTOR4_NEAR, and impeller::Vector4::Max().

## ◆ TEST() [169/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector4Min |
| ) |  |

Definition at line 1126 of file geometry_unittests.cc.

1126 {
1127 Vector4 p(1, 2, 3, 4);
1128 Vector4 result = p.Min({0, 10, 2, 1});
1129 Vector4 expected(0, 2, 2, 1);
1130 ASSERT_VECTOR4_NEAR(result, expected);
1131 }

References ASSERT_VECTOR4_NEAR, and impeller::Vector4::Min().

## ◆ TEST() [170/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector4Printing |
| ) |  |

Definition at line 2247 of file geometry_unittests.cc.

2247 {
2248 {
2249 std::stringstream stream;
2250 Vector4 m;
2251 stream << m;
2252 ASSERT_EQ(stream.str(), "(0, 0, 0, 1)");
2253 }
2254
2255 {
2256 std::stringstream stream;
2257 Vector4 m(1, 2, 3, 4);
2258 stream << m;
2259 ASSERT_EQ(stream.str(), "(1, 2, 3, 4)");
2260 }
2261 }

## ◆ TEST() [171/202]

impeller::testing::TEST | ( | GeometryTest | ,
|  | Vector4Round |
| ) |  |

Definition at line 1210 of file geometry_unittests.cc.

1210 {
1211 Vector4 p(1.5, 2.3, 3.9, 4.0);
1212 Vector4 result = p.Round();
1213 Vector4 expected(2, 2, 4, 4);
1214 ASSERT_VECTOR4_NEAR(result, expected);
1215 }

References ASSERT_VECTOR4_NEAR, and impeller::Vector4::Round().

## ◆ TEST() [172/202]

impeller::testing::TEST | ( | HostBufferTest | ,
|  | CanEmplace |
| ) |  |

Definition at line 18 of file host_buffer_unittests.cc.

18 {
19 struct Length2 {
20 uint8_t pad[2];
21 };
22 static_assert(sizeof(Length2) == 2u);
23
24 auto buffer = HostBuffer::Create();
25
26 for (size_t i = 0; i < 12500; i++) {
27 auto view = buffer->Emplace(Length2{});
28 ASSERT_TRUE(view);
29 ASSERT_EQ(buffer->GetLength(), (i + 1) * sizeof(Length2));
30 ASSERT_EQ(view.range, Range(i * sizeof(Length2), 2u));
31 }
32 }

References impeller::HostBuffer::Create().

## ◆ TEST() [173/202]

impeller::testing::TEST | ( | HostBufferTest | ,
|  | CanEmplaceWithAlignment |
| ) |  |

Definition at line 34 of file host_buffer_unittests.cc.

34 {
35 struct Length2 {
36 uint8_t pad[2];
37 };
38 static_assert(sizeof(Length2) == 2);
39 struct alignas(16) Align16 {
40 uint8_t pad[2];
41 };
42 static_assert(alignof(Align16) == 16);
43 static_assert(sizeof(Align16) == 16);
44
45 auto buffer = HostBuffer::Create();
46 ASSERT_TRUE(buffer);
47
48 {
49 auto view = buffer->Emplace(Length2{});
50 ASSERT_TRUE(view);
51 ASSERT_EQ(buffer->GetLength(), 2u);
52 ASSERT_EQ(view.range, Range(0u, 2u));
53 }
54
55 {
56 auto view = buffer->Emplace(Align16{});
57 ASSERT_TRUE(view);
58 ASSERT_EQ(view.range.offset, 16u);
59 ASSERT_EQ(view.range.length, 16u);
60 ASSERT_EQ(buffer->GetLength(), 32u);
61 }
62 {
63 auto view = buffer->Emplace(Length2{});
64 ASSERT_TRUE(view);
65 ASSERT_EQ(buffer->GetLength(), 34u);
66 ASSERT_EQ(view.range, Range(32u, 2u));
67 }
68
69 {
70 auto view = buffer->Emplace(Align16{});
71 ASSERT_TRUE(view);
72 ASSERT_EQ(view.range.offset, 48u);
73 ASSERT_EQ(view.range.length, 16u);
74 ASSERT_EQ(buffer->GetLength(), 64u);
75 }
76 }

References impeller::HostBuffer::Create().

## ◆ TEST() [174/202]

impeller::testing::TEST | ( | HostBufferTest | ,
|  | TestInitialization |
| ) |  |

Definition at line 11 of file host_buffer_unittests.cc.

11 {
12 ASSERT_TRUE(HostBuffer::Create());
13 // Newly allocated buffers don't touch the heap till they have to.
14 ASSERT_EQ(HostBuffer::Create()->GetLength(), 0u);
15 ASSERT_EQ(HostBuffer::Create()->GetReservedLength(), 0u);
16 }

References impeller::HostBuffer::Create().

## ◆ TEST() [175/202]

impeller::testing::TEST | ( | PassBindingsCacheTest | ,
|  | bindPipeline |
| ) |  |

Definition at line 26 of file pass_bindings_cache_unittests.cc.

26 {
27 auto context = MockVulkanContextBuilder().Build();
28 PassBindingsCache cache;
29 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
30 auto buffer = encoder->GetCommandBuffer();
31 VkPipeline vk_pipeline = reinterpret_cast<VkPipeline>(0xfeedface);
32 vk::Pipeline pipeline(vk_pipeline);
33 cache.BindPipeline(buffer, vk::PipelineBindPoint::eGraphics, pipeline);
34 cache.BindPipeline(buffer, vk::PipelineBindPoint::eGraphics, pipeline);
35 std::shared_ptr<std::vector<std::string>> functions =
36 GetMockVulkanFunctions(context->GetDevice());
37 EXPECT_EQ(CountStringViewInstances(*functions, "vkCmdBindPipeline"), 1);
38 }

References impeller::PassBindingsCache::BindPipeline().

## ◆ TEST() [176/202]

impeller::testing::TEST | ( | PassBindingsCacheTest | ,
|  | setScissor |
| ) |  |

Definition at line 55 of file pass_bindings_cache_unittests.cc.

55 {
56 auto context = MockVulkanContextBuilder().Build();
57 PassBindingsCache cache;
58 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
59 auto buffer = encoder->GetCommandBuffer();
60 vk::Rect2D scissors;
61 cache.SetScissor(buffer, 0, 1, &scissors);
62 cache.SetScissor(buffer, 0, 1, &scissors);
63 std::shared_ptr<std::vector<std::string>> functions =
64 GetMockVulkanFunctions(context->GetDevice());
65 EXPECT_EQ(CountStringViewInstances(*functions, "vkCmdSetScissor"), 1);
66 }

References impeller::PassBindingsCache::SetScissor().

## ◆ TEST() [177/202]

impeller::testing::TEST | ( | PassBindingsCacheTest | ,
|  | setStencilReference |
| ) |  |

Definition at line 40 of file pass_bindings_cache_unittests.cc.

40 {
41 auto context = MockVulkanContextBuilder().Build();
42 PassBindingsCache cache;
43 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
44 auto buffer = encoder->GetCommandBuffer();
45 cache.SetStencilReference(
46 buffer, vk::StencilFaceFlagBits::eVkStencilFrontAndBack, 123);
47 cache.SetStencilReference(
48 buffer, vk::StencilFaceFlagBits::eVkStencilFrontAndBack, 123);
49 std::shared_ptr<std::vector<std::string>> functions =
50 GetMockVulkanFunctions(context->GetDevice());
51 EXPECT_EQ(CountStringViewInstances(*functions, "vkCmdSetStencilReference"),
52 1);
53 }

References impeller::PassBindingsCache::SetStencilReference().

## ◆ TEST() [178/202]

impeller::testing::TEST | ( | PassBindingsCacheTest | ,
|  | setViewport |
| ) |  |

Definition at line 68 of file pass_bindings_cache_unittests.cc.

68 {
69 auto context = MockVulkanContextBuilder().Build();
70 PassBindingsCache cache;
71 auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
72 auto buffer = encoder->GetCommandBuffer();
73 vk::Viewport viewports;
74 cache.SetViewport(buffer, 0, 1, &viewports);
75 cache.SetViewport(buffer, 0, 1, &viewports);
76 std::shared_ptr<std::vector<std::string>> functions =
77 GetMockVulkanFunctions(context->GetDevice());
78 EXPECT_EQ(CountStringViewInstances(*functions, "vkCmdSetViewport"), 1);
79 }

References impeller::PassBindingsCache::SetViewport().

## ◆ TEST() [179/202]

impeller::testing::TEST | ( | PipelineDescriptorTest | ,
|  | PrimitiveTypeHashEquality |
| ) |  |

Definition at line 13 of file pipeline_descriptor_unittests.cc.

13 {
14 PipelineDescriptor descA;
15 PipelineDescriptor descB;
16
17 ASSERT_TRUE(descA.IsEqual(descB));
18 ASSERT_EQ(descA.GetHash(), descB.GetHash());
19
20 descA.SetPrimitiveType(PrimitiveType::kTriangleStrip);
21
22 ASSERT_FALSE(descA.IsEqual(descB));
23 ASSERT_NE(descA.GetHash(), descB.GetHash());
24 }

References impeller::PipelineDescriptor::GetHash(), impeller::PipelineDescriptor::IsEqual(), impeller::kTriangleStrip, and impeller::PipelineDescriptor::SetPrimitiveType().

## ◆ TEST() [180/202]

impeller::testing::TEST | ( | PoolTest | ,
|  | Overload |
| ) |  |

Definition at line 47 of file pool_unittests.cc.

47 {
48 Pool<Foobar> pool(1'000);
49 {
50 std::vector<std::shared_ptr<Foobar>> values;
51 for (int i = 0; i < 20; i++) {
52 values.push_back(pool.Grab());
53 }
54 for (auto value : values) {
55 value->SetSize(100);
56 pool.Recycle(value);
57 }
58 }
59 EXPECT_EQ(pool.GetSize(), 1'000u);
60 }

## ◆ TEST() [181/202]

impeller::testing::TEST | ( | PoolTest | ,
|  | Simple |
| ) |  |

Definition at line 33 of file pool_unittests.cc.

33 {
34 Pool<Foobar> pool(1'000);
35 {
36 auto grabbed = pool.Grab();
37 grabbed->SetSize(123);
38 pool.Recycle(grabbed);
39 EXPECT_EQ(pool.GetSize(), 123u);
40 }
41 auto grabbed = pool.Grab();
42 EXPECT_EQ(grabbed->GetSize(), 123u);
43 EXPECT_TRUE(grabbed->GetIsReset());
44 EXPECT_EQ(pool.GetSize(), 0u);
45 }

## ◆ TEST() [182/202]

impeller::testing::TEST | ( | RenderTargetCacheTest | ,
|  | CachesUsedTexturesAcrossFrames |
| ) |  |

Definition at line 45 of file render_target_cache_unittests.cc.

45 {
46 auto allocator = std::make_shared<TestAllocator>();
47 auto render_target_cache = RenderTargetCache(allocator);
48 auto desc = TextureDescriptor{
49 .format = PixelFormat::kR8G8B8A8UNormInt,
50 .size = ISize(100, 100),
51 .usage = static_cast<TextureUsageMask>(TextureUsage::kRenderTarget)};
52
53 render_target_cache.Start();
54 // Create two textures of the same exact size/shape. Both should be marked
55 // as used this frame, so the cached data set will contain two.
56 render_target_cache.CreateTexture(desc);
57 render_target_cache.CreateTexture(desc);
58
59 ASSERT_EQ(render_target_cache.CachedTextureCount(), 2u);
60
61 render_target_cache.End();
62 render_target_cache.Start();
63
64 // Next frame, only create one texture. The set will still contain two,
65 // but one will be removed at the end of the frame.
66 render_target_cache.CreateTexture(desc);
67 ASSERT_EQ(render_target_cache.CachedTextureCount(), 2u);
68
69 render_target_cache.End();
70 ASSERT_EQ(render_target_cache.CachedTextureCount(), 1u);
71 }

References impeller::TextureDescriptor::format, impeller::kR8G8B8A8UNormInt, and impeller::kRenderTarget.

## ◆ TEST() [183/202]

impeller::testing::TEST | ( | RenderTargetCacheTest | ,
|  | DoesNotPersistFailedAllocations |
| ) |  |

Definition at line 73 of file render_target_cache_unittests.cc.

73 {
74 auto allocator = std::make_shared<TestAllocator>();
75 auto render_target_cache = RenderTargetCache(allocator);
76 auto desc = TextureDescriptor{
77 .format = PixelFormat::kR8G8B8A8UNormInt,
78 .size = ISize(100, 100),
79 .usage = static_cast<TextureUsageMask>(TextureUsage::kRenderTarget)};
80
81 render_target_cache.Start();
82 allocator->should_fail = true;
83
84 ASSERT_EQ(render_target_cache.CreateTexture(desc), nullptr);
85 ASSERT_EQ(render_target_cache.CachedTextureCount(), 0u);
86 }

References impeller::TextureDescriptor::format, impeller::kR8G8B8A8UNormInt, and impeller::kRenderTarget.

## ◆ TEST() [184/202]

impeller::testing::TEST | ( | ResourceManagerVKTest | ,
|  | CreatesANewInstance |
| ) |  |

Definition at line 17 of file resource_manager_vk_unittests.cc.

17 {
18 auto const a = ResourceManagerVK::Create();
19 auto const b = ResourceManagerVK::Create();
20 EXPECT_NE(a, b);
21 }

References impeller::ResourceManagerVK::Create().

## ◆ TEST() [185/202]

impeller::testing::TEST | ( | ResourceManagerVKTest | ,
|  | IsThreadSafe |
| ) |  |

Definition at line 77 of file resource_manager_vk_unittests.cc.

77 {
78 // In a typical app, there is a single ResourceManagerVK per app, shared b/w
79 // threads.
80 //
81 // This test ensures that the ResourceManagerVK is thread-safe.
82 std::weak_ptr<ResourceManagerVK> manager;
83
84 {
85 auto const manager = ResourceManagerVK::Create();
86
87 // Spawn two threads, and have them both put resources into the manager.
88 struct MockResource {};
89
90 std::thread thread1([&manager]() {
91 UniqueResourceVKT<MockResource>(manager, MockResource{});
92 });
93
94 std::thread thread2([&manager]() {
95 UniqueResourceVKT<MockResource>(manager, MockResource{});
96 });
97
98 thread1.join();
99 thread2.join();
100 }
101
102 // The thread should have terminated.
103 EXPECT_EQ(manager.lock(), nullptr);
104 }

References impeller::ResourceManagerVK::Create().

## ◆ TEST() [186/202]

impeller::testing::TEST | ( | ResourceManagerVKTest | ,
|  | ReclaimMovesAResourceAndDestroysIt |
| ) |  |

Definition at line 44 of file resource_manager_vk_unittests.cc.

44 {
45 auto const manager = ResourceManagerVK::Create();
46
47 auto waiter = fml::AutoResetWaitableEvent();
48 auto dead = false;
49 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
50
51 // Not killed immediately.
52 EXPECT_FALSE(waiter.IsSignaledForTest());
53
54 {
55 auto resource = UniqueResourceVKT<DeathRattle>(manager, std::move(rattle));
56 }
57
58 waiter.Wait();
59 }

References impeller::ResourceManagerVK::Create().

## ◆ TEST() [187/202]

impeller::testing::TEST | ( | ResourceManagerVKTest | ,
|  | TerminatesWhenOutOfScope |
| ) |  |

Definition at line 62 of file resource_manager_vk_unittests.cc.

62 {
63 // Originally, this shared_ptr was never destroyed, and the thread never
64 // terminated. This test ensures that the thread terminates when the
65 // ResourceManagerVK is out of scope.
66 std::weak_ptr<ResourceManagerVK> manager;
67
68 {
69 auto shared = ResourceManagerVK::Create();
70 manager = shared;
71 }
72
73 // The thread should have terminated.
74 EXPECT_EQ(manager.lock(), nullptr);
75 }

References impeller::ResourceManagerVK::Create().

## ◆ TEST() [188/202]

impeller::testing::TEST | ( | RuntimeStageTest | ,
|  | CanReadUniforms |
| ) |  |

Definition at line 50 of file runtime_stage_unittests.cc.

50 {
51 auto fixture =
52 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
53 ASSERT_TRUE(fixture);
54 ASSERT_GT(fixture->GetSize(), 0u);
55 RuntimeStage stage(std::move(fixture));
56 ASSERT_TRUE(stage.IsValid());
57 ASSERT_EQ(stage.GetUniforms().size(), 17u);
58 {
59 auto uni = stage.GetUniform("u_color");
60 ASSERT_NE(uni, nullptr);
61 ASSERT_EQ(uni->dimensions.rows, 4u);
62 ASSERT_EQ(uni->dimensions.cols, 1u);
63 ASSERT_EQ(uni->location, 0u);
64 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
65 }
66 {
67 auto uni = stage.GetUniform("u_alpha");
68 ASSERT_NE(uni, nullptr);
69 ASSERT_EQ(uni->dimensions.rows, 1u);
70 ASSERT_EQ(uni->dimensions.cols, 1u);
71 ASSERT_EQ(uni->location, 1u);
72 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
73 }
74 {
75 auto uni = stage.GetUniform("u_sparkle_color");
76 ASSERT_NE(uni, nullptr);
77 ASSERT_EQ(uni->dimensions.rows, 4u);
78 ASSERT_EQ(uni->dimensions.cols, 1u);
79 ASSERT_EQ(uni->location, 2u);
80 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
81 }
82 {
83 auto uni = stage.GetUniform("u_sparkle_alpha");
84 ASSERT_NE(uni, nullptr);
85 ASSERT_EQ(uni->dimensions.rows, 1u);
86 ASSERT_EQ(uni->dimensions.cols, 1u);
87 ASSERT_EQ(uni->location, 3u);
88 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
89 }
90 {
91 auto uni = stage.GetUniform("u_blur");
92 ASSERT_NE(uni, nullptr);
93 ASSERT_EQ(uni->dimensions.rows, 1u);
94 ASSERT_EQ(uni->dimensions.cols, 1u);
95 ASSERT_EQ(uni->location, 4u);
96 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
97 }
98 {
99 auto uni = stage.GetUniform("u_radius_scale");
100 ASSERT_NE(uni, nullptr);
101 ASSERT_EQ(uni->dimensions.rows, 1u);
102 ASSERT_EQ(uni->dimensions.cols, 1u);
103 ASSERT_EQ(uni->location, 6u);
104 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
105 }
106 {
107 auto uni = stage.GetUniform("u_max_radius");
108 ASSERT_NE(uni, nullptr);
109 ASSERT_EQ(uni->dimensions.rows, 1u);
110 ASSERT_EQ(uni->dimensions.cols, 1u);
111 ASSERT_EQ(uni->location, 7u);
112 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
113 }
114 {
115 auto uni = stage.GetUniform("u_resolution_scale");
116 ASSERT_NE(uni, nullptr);
117 ASSERT_EQ(uni->dimensions.rows, 2u);
118 ASSERT_EQ(uni->dimensions.cols, 1u);
119 ASSERT_EQ(uni->location, 8u);
120 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
121 }
122 {
123 auto uni = stage.GetUniform("u_noise_scale");
124 ASSERT_NE(uni, nullptr);
125 ASSERT_EQ(uni->dimensions.rows, 2u);
126 ASSERT_EQ(uni->dimensions.cols, 1u);
127 ASSERT_EQ(uni->location, 9u);
128 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
129 }
130 {
131 auto uni = stage.GetUniform("u_noise_phase");
132 ASSERT_NE(uni, nullptr);
133 ASSERT_EQ(uni->dimensions.rows, 1u);
134 ASSERT_EQ(uni->dimensions.cols, 1u);
135 ASSERT_EQ(uni->location, 10u);
136 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
137 }
138
139 {
140 auto uni = stage.GetUniform("u_circle1");
141 ASSERT_NE(uni, nullptr);
142 ASSERT_EQ(uni->dimensions.rows, 2u);
143 ASSERT_EQ(uni->dimensions.cols, 1u);
144 ASSERT_EQ(uni->location, 11u);
145 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
146 }
147 {
148 auto uni = stage.GetUniform("u_circle2");
149 ASSERT_NE(uni, nullptr);
150 ASSERT_EQ(uni->dimensions.rows, 2u);
151 ASSERT_EQ(uni->dimensions.cols, 1u);
152 ASSERT_EQ(uni->location, 12u);
153 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
154 }
155 {
156 auto uni = stage.GetUniform("u_circle3");
157 ASSERT_NE(uni, nullptr);
158 ASSERT_EQ(uni->dimensions.rows, 2u);
159 ASSERT_EQ(uni->dimensions.cols, 1u);
160 ASSERT_EQ(uni->location, 13u);
161 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
162 }
163 {
164 auto uni = stage.GetUniform("u_rotation1");
165 ASSERT_NE(uni, nullptr);
166 ASSERT_EQ(uni->dimensions.rows, 2u);
167 ASSERT_EQ(uni->dimensions.cols, 1u);
168 ASSERT_EQ(uni->location, 14u);
169 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
170 }
171 {
172 auto uni = stage.GetUniform("u_rotation2");
173 ASSERT_NE(uni, nullptr);
174 ASSERT_EQ(uni->dimensions.rows, 2u);
175 ASSERT_EQ(uni->dimensions.cols, 1u);
176 ASSERT_EQ(uni->location, 15u);
177 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
178 }
179 {
180 auto uni = stage.GetUniform("u_rotation3");
181 ASSERT_NE(uni, nullptr);
182 ASSERT_EQ(uni->dimensions.rows, 2u);
183 ASSERT_EQ(uni->dimensions.cols, 1u);
184 ASSERT_EQ(uni->location, 16u);
185 ASSERT_EQ(uni->type, RuntimeUniformType::kFloat);
186 }
187 }

References impeller::RuntimeStage::GetUniform(), impeller::RuntimeStage::GetUniforms(), impeller::RuntimeStage::IsValid(), and impeller::kFloat.

## ◆ TEST() [189/202]

impeller::testing::TEST | ( | RuntimeStageTest | ,
|  | CanReadValidBlob |
| ) |  |

Definition at line 26 of file runtime_stage_unittests.cc.

26 {
27 auto fixture =
28 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
29 ASSERT_TRUE(fixture);
30 ASSERT_GT(fixture->GetSize(), 0u);
31 RuntimeStage stage(std::move(fixture));
32 ASSERT_TRUE(stage.IsValid());
33 ASSERT_EQ(stage.GetShaderStage(), RuntimeShaderStage::kFragment);
34 }

References impeller::RuntimeStage::GetShaderStage(), impeller::RuntimeStage::IsValid(), and impeller::kFragment.

## ◆ TEST() [190/202]

impeller::testing::TEST | ( | RuntimeStageTest | ,
|  | CanRejectInvalidBlob |
| ) |  |

Definition at line 36 of file runtime_stage_unittests.cc.

36 {
37 ScopedValidationDisable disable_validation;
38 auto fixture =
39 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
40 ASSERT_TRUE(fixture);
41 auto junk_allocation = std::make_shared<Allocation>();
42 ASSERT_TRUE(junk_allocation->Truncate(fixture->GetSize(), false));
43 // Not meant to be secure. Just reject obviously bad blobs using magic
44 // numbers.
45 ::memset(junk_allocation->GetBuffer(), 127, junk_allocation->GetLength());
46 RuntimeStage stage(CreateMappingFromAllocation(junk_allocation));
47 ASSERT_FALSE(stage.IsValid());
48 }

References impeller::CreateMappingFromAllocation(), and impeller::RuntimeStage::IsValid().

## ◆ TEST() [191/202]

impeller::testing::TEST | ( | SkiaConversionsTest | ,
|  | GradientConversionNonMonotonic |
| ) |  |

Definition at line 132 of file skia_conversions_unittests.cc.

132 {
133 std::vector<flutter::DlColor> colors = {
134 flutter::DlColor::kBlue(), flutter::DlColor::kGreen(),
135 flutter::DlColor::kGreen(), flutter::DlColor::kRed()};
136 std::vector<float> stops = {0.0, 0.5, 0.4, 1.0};
137 const auto gradient =
138 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
139 SkPoint::Make(1.0, 1.0), //
140 4, //
141 colors.data(), //
142 stops.data(), //
143 flutter::DlTileMode::kClamp, //
144 nullptr //
145 );
146
147 std::vector<Color> converted_colors;
148 std::vector<Scalar> converted_stops;
149 skia_conversions::ConvertStops(gradient.get(), converted_colors,
150 converted_stops);
151
152 // Value is clamped to 0.5
153 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
154 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
155 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 0.5f));
156 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[3], 1.0f));
157 }

References impeller::skia_conversions::ConvertStops(), and impeller::ScalarNearlyEqual().

## ◆ TEST() [192/202]

impeller::testing::TEST | ( | SkiaConversionsTest | ,
|  | GradientMissing0 |
| ) |  |

Definition at line 54 of file skia_conversions_unittests.cc.

54 {
55 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
56 flutter::DlColor::kRed()};
57 std::vector<float> stops = {0.5, 1.0};
58 const auto gradient =
59 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
60 SkPoint::Make(1.0, 1.0), //
61 2, //
62 colors.data(), //
63 stops.data(), //
64 flutter::DlTileMode::kClamp, //
65 nullptr //
66 );
67
68 std::vector<Color> converted_colors;
69 std::vector<Scalar> converted_stops;
70 skia_conversions::ConvertStops(gradient.get(), converted_colors,
71 converted_stops);
72
73 // First color is inserted as blue.
74 ASSERT_TRUE(ScalarNearlyEqual(converted_colors[0].blue, 1.0f));
75 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
76 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
77 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
78 }

References impeller::skia_conversions::ConvertStops(), and impeller::ScalarNearlyEqual().

## ◆ TEST() [193/202]

impeller::testing::TEST | ( | SkiaConversionsTest | ,
|  | GradientMissingLastValue |
| ) |  |

Definition at line 80 of file skia_conversions_unittests.cc.

80 {
81 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
82 flutter::DlColor::kRed()};
83 std::vector<float> stops = {0.0, .5};
84 const auto gradient =
85 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
86 SkPoint::Make(1.0, 1.0), //
87 2, //
88 colors.data(), //
89 stops.data(), //
90 flutter::DlTileMode::kClamp, //
91 nullptr //
92 );
93
94 std::vector<Color> converted_colors;
95 std::vector<Scalar> converted_stops;
96 skia_conversions::ConvertStops(gradient.get(), converted_colors,
97 converted_stops);
98
99 // Last color is inserted as red.
100 ASSERT_TRUE(ScalarNearlyEqual(converted_colors[2].red, 1.0f));
101 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
102 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
103 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
104 }

References impeller::skia_conversions::ConvertStops(), and impeller::ScalarNearlyEqual().

## ◆ TEST() [194/202]

impeller::testing::TEST | ( | SkiaConversionsTest | ,
|  | GradientStopConversion |
| ) |  |

Definition at line 28 of file skia_conversions_unittests.cc.

28 {
29 // Typical gradient.
30 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
31 flutter::DlColor::kRed(),
32 flutter::DlColor::kGreen()};
33 std::vector<float> stops = {0.0, 0.5, 1.0};
34 const auto gradient =
35 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
36 SkPoint::Make(1.0, 1.0), //
37 3, //
38 colors.data(), //
39 stops.data(), //
40 flutter::DlTileMode::kClamp, //
41 nullptr //
42 );
43
44 std::vector<Color> converted_colors;
45 std::vector<Scalar> converted_stops;
46 skia_conversions::ConvertStops(gradient.get(), converted_colors,
47 converted_stops);
48
49 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
50 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
51 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
52 }

References impeller::skia_conversions::ConvertStops(), and impeller::ScalarNearlyEqual().

## ◆ TEST() [195/202]

impeller::testing::TEST | ( | SkiaConversionsTest | ,
|  | GradientStopGreaterThan1 |
| ) |  |

Definition at line 106 of file skia_conversions_unittests.cc.

106 {
107 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
108 flutter::DlColor::kGreen(),
109 flutter::DlColor::kRed()};
110 std::vector<float> stops = {0.0, 100, 1.0};
111 const auto gradient =
112 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
113 SkPoint::Make(1.0, 1.0), //
114 3, //
115 colors.data(), //
116 stops.data(), //
117 flutter::DlTileMode::kClamp, //
118 nullptr //
119 );
120
121 std::vector<Color> converted_colors;
122 std::vector<Scalar> converted_stops;
123 skia_conversions::ConvertStops(gradient.get(), converted_colors,
124 converted_stops);
125
126 // Value is clamped to 1.0
127 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
128 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 1.0f));
129 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
130 }

References impeller::skia_conversions::ConvertStops(), and impeller::ScalarNearlyEqual().

## ◆ TEST() [196/202]

impeller::testing::TEST | ( | SkiaConversionsTest | ,
|  | ToColor |
| ) |  |

Definition at line 14 of file skia_conversions_unittests.cc.

14 {
15 // Create a color with alpha, red, green, and blue values that are all
16 // trivially divisible by 255 so that we can test the conversion results in
17 // correct scalar values.
18 // AARRGGBB
19 const flutter::DlColor color = flutter::DlColor(0x8040C020);
20 auto converted_color = skia_conversions::ToColor(color);
21
22 ASSERT_TRUE(ScalarNearlyEqual(converted_color.alpha, 0x80 * (1.0f / 255)));
23 ASSERT_TRUE(ScalarNearlyEqual(converted_color.red, 0x40 * (1.0f / 255)));
24 ASSERT_TRUE(ScalarNearlyEqual(converted_color.green, 0xC0 * (1.0f / 255)));
25 ASSERT_TRUE(ScalarNearlyEqual(converted_color.blue, 0x20 * (1.0f / 255)));
26 }

References impeller::ScalarNearlyEqual(), and impeller::skia_conversions::ToColor().

## ◆ TEST() [197/202]

impeller::testing::TEST | ( | StringsTest | ,
|  | CanSPrintF |
| ) |  |

Definition at line 72 of file base_unittests.cc.

72 {
73 ASSERT_EQ(SPrintF("%sx%d", "Hello", 12), "Hellox12");
74 ASSERT_EQ(SPrintF(""), "");
75 ASSERT_EQ(SPrintF("Hello"), "Hello");
76 ASSERT_EQ(SPrintF("%sx%.2f", "Hello", 12.122222), "Hellox12.12");
77 }

References impeller::SPrintF().

## ◆ TEST() [198/202]

impeller::testing::TEST | ( | TessellatorTest | ,
|  | TessellatorBuilderReturnsCorrectResultStatus |
| ) |  |

Definition at line 14 of file tessellator_unittests.cc.

14 {
15 // Zero points.
16 {
17 Tessellator t;
18 auto polyline = PathBuilder{}.TakePath().CreatePolyline(1.0f);
19 Tessellator::Result result = t.Tessellate(
20 FillType::kPositive, polyline,
21 [](const float* vertices, size_t vertices_count,
22 const uint16_t* indices, size_t indices_count) { return true; });
23
24 ASSERT_EQ(polyline.points.size(), 0u);
25 ASSERT_EQ(result, Tessellator::Result::kInputError);
26 }
27
28 // One point.
29 {
30 Tessellator t;
31 auto polyline =
32 PathBuilder{}.LineTo({0, 0}).TakePath().CreatePolyline(1.0f);
33 Tessellator::Result result =
34 t.Tessellate(FillType::kPositive, polyline,
35 [](const float* vertices, size_t vertices_count,
36 const uint16_t* indices_count,
37 size_t indices_size) { return true; });
38 ASSERT_EQ(polyline.points.size(), 1u);
39 ASSERT_EQ(result, Tessellator::Result::kSuccess);
40 }
41
42 // Two points.
43 {
44 Tessellator t;
45 auto polyline =
46 PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline(1.0f);
47 Tessellator::Result result =
48 t.Tessellate(FillType::kPositive, polyline,
49 [](const float* vertices, size_t vertices_count,
50 const uint16_t* indices_count,
51 size_t indices_size) { return true; });
52
53 ASSERT_EQ(polyline.points.size(), 2u);
54 ASSERT_EQ(result, Tessellator::Result::kSuccess);
55 }
56
57 // Many points.
58 {
59 Tessellator t;
60 PathBuilder builder;
61 for (int i = 0; i < 1000; i++) {
62 auto coord = i * 1.0f;
63 builder.AddLine({coord, coord}, {coord + 1, coord + 1});
64 }
65 auto polyline = builder.TakePath().CreatePolyline(1.0f);
66 Tessellator::Result result =
67 t.Tessellate(FillType::kPositive, polyline,
68 [](const float* vertices, size_t vertices_count,
69 const uint16_t* indices_count,
70 size_t indices_size) { return true; });
71
72 ASSERT_EQ(polyline.points.size(), 2000u);
73 ASSERT_EQ(result, Tessellator::Result::kSuccess);
74 }
75
76 // Closure fails.
77 {
78 Tessellator t;
79 auto polyline =
80 PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath().CreatePolyline(1.0f);
81 Tessellator::Result result =
82 t.Tessellate(FillType::kPositive, polyline,
83 [](const float* vertices, size_t vertices_count,
84 const uint16_t* indices_count,
85 size_t indices_size) { return false; });
86
87 ASSERT_EQ(polyline.points.size(), 2u);
88 ASSERT_EQ(result, Tessellator::Result::kInputError);
89 }
90
91 // More than uint16 points, odd fill mode.
92 {
93 Tessellator t;
94 PathBuilder builder = {};
95 for (auto i = 0; i < 1000; i++) {
96 builder.AddCircle(Point(i, i), 4);
97 }
98 auto polyline = builder.TakePath(FillType::kOdd).CreatePolyline(1.0f);
99 bool no_indices = false;
100 size_t count = 0u;
101 Tessellator::Result result = t.Tessellate(
102 FillType::kOdd, polyline,
103 [&no_indices, &count](const float* vertices, size_t vertices_count,
104 const uint16_t* indices, size_t indices_count) {
105 no_indices = indices == nullptr;
106 count = vertices_count;
107 return true;
108 });
109
110 ASSERT_TRUE(no_indices);
111 ASSERT_TRUE(count >= USHRT_MAX);
112 ASSERT_EQ(result, Tessellator::Result::kSuccess);
113 }
114 }

References impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddLine(), impeller::Path::CreatePolyline(), impeller::Tessellator::kInputError, impeller::kOdd, impeller::kPositive, impeller::Tessellator::kSuccess, impeller::PathBuilder::LineTo(), impeller::PathBuilder::TakePath(), and impeller::Tessellator::Tessellate().

## ◆ TEST() [199/202]

impeller::testing::TEST | ( | ThreadTest | ,
|  | CanCreateMutex |
| ) |  |

Definition at line 22 of file base_unittests.cc.

22 {
23 Foo f = {};
24
25 // f.a = 100; <--- Static analysis error.
26 f.mtx.Lock();
27 f.a = 100;
28 f.mtx.Unlock();
29 }

References impeller::testing::Foo::mtx.

## ◆ TEST() [200/202]

impeller::testing::TEST | ( | ThreadTest | ,
|  | CanCreateMutexLock |
| ) |  |

Definition at line 31 of file base_unittests.cc.

31 {
32 Foo f = {};
33
34 // f.a = 100; <--- Static analysis error.
35 auto a = Lock(f.mtx);
36 f.a = 100;
37 }

References impeller::testing::Foo::mtx.

## ◆ TEST() [201/202]

impeller::testing::TEST | ( | ThreadTest | ,
|  | CanCreateRWMutex |
| ) |  |

Definition at line 39 of file base_unittests.cc.

39 {
40 RWFoo f = {};
41
42 // f.a = 100; <--- Static analysis error.
43 f.mtx.LockWriter();
44 f.a = 100;
45 f.mtx.UnlockWriter();
46 // int b = f.a; <--- Static analysis error.
47 f.mtx.LockReader();
48 int b = f.a; // NOLINT(clang-analyzer-deadcode.DeadStores)
49 FML_ALLOW_UNUSED_LOCAL(b);
50 f.mtx.UnlockReader();
51 }

References impeller::testing::RWFoo::mtx.

## ◆ TEST() [202/202]

impeller::testing::TEST | ( | ThreadTest | ,
|  | CanCreateRWMutexLock |
| ) |  |

Definition at line 53 of file base_unittests.cc.

53 {
54 RWFoo f = {};
55
56 // f.a = 100; <--- Static analysis error.
57 {
58 auto write_lock = WriterLock{f.mtx};
59 f.a = 100;
60 }
61
62 // int b = f.a; <--- Static analysis error.
63 {
64 auto read_lock = ReaderLock(f.mtx);
65 int b = f.a; // NOLINT(clang-analyzer-deadcode.DeadStores)
66 FML_ALLOW_UNUSED_LOCAL(b);
67 }
68
69 // f.mtx.UnlockReader(); <--- Static analysis error.
70 }

References impeller::testing::RWFoo::mtx.

## ◆ TEST_F() [1/8]

impeller::testing::TEST_F | ( | ArchiveTest | ,
|  | AddData |
| ) |  |

Definition at line 118 of file archivist_unittests.cc.

118 {
119 Archive archive(GetArchiveFileName().c_str());
120 ASSERT_TRUE(archive.IsValid());
121 Sample sample;
122 ASSERT_TRUE(archive.Write(sample));
123 }

References impeller::Archive::IsValid(), and impeller::Archive::Write().

## ◆ TEST_F() [2/8]

impeller::testing::TEST_F | ( | ArchiveTest | ,
|  | AddDataMultiple |
| ) |  |

Definition at line 125 of file archivist_unittests.cc.

125 {
126 Archive archive(GetArchiveFileName().c_str());
127 ASSERT_TRUE(archive.IsValid());
128
129 for (size_t i = 0; i < 100; i++) {
130 Sample sample(i + 1);
131 ASSERT_TRUE(archive.Write(sample));
132 }
133 }

References impeller::Archive::IsValid(), and impeller::Archive::Write().

## ◆ TEST_F() [3/8]

impeller::testing::TEST_F | ( | ArchiveTest | ,
|  | AddStorageClass |
| ) |  |

Definition at line 113 of file archivist_unittests.cc.

113 {
114 Archive archive(GetArchiveFileName().c_str());
115 ASSERT_TRUE(archive.IsValid());
116 }

References impeller::Archive::IsValid().

## ◆ TEST_F() [4/8]

impeller::testing::TEST_F | ( | ArchiveTest | ,
|  | CanReadWriteVectorOfArchivables |
| ) |  |

Definition at line 185 of file archivist_unittests.cc.

185 {
186 Archive archive(GetArchiveFileName().c_str());
187 ASSERT_TRUE(archive.IsValid());
188
189 SampleWithVector sample_with_vector;
190 ASSERT_TRUE(archive.Write(sample_with_vector));
191 bool read_success = false;
192 ASSERT_EQ(
193 archive.Read<SampleWithVector>([&](ArchiveLocation& location) -> bool {
194 SampleWithVector other_sample_with_vector;
195 read_success = other_sample_with_vector.Read(location);
196 return true; // Always keep continuing but assert that we only get one.
197 }),
198 1u);
199 ASSERT_TRUE(read_success);
200 }

References impeller::Archive::IsValid(), impeller::Archive::Read(), and impeller::Archive::Write().

## ◆ TEST_F() [5/8]

impeller::testing::TEST_F | ( | ArchiveTest | ,
|  | ReadData |
| ) |  |

Definition at line 135 of file archivist_unittests.cc.

135 {
136 Archive archive(GetArchiveFileName().c_str());
137 ASSERT_TRUE(archive.IsValid());
138
139 size_t count = 50;
140
141 std::vector<PrimaryKey::value_type> keys;
142 std::vector<uint64_t> values;
143
144 for (size_t i = 0; i < count; i++) {
145 Sample sample(i + 1);
146 keys.push_back(sample.GetPrimaryKey().value());
147 values.push_back(sample.GetSomeData());
148 ASSERT_TRUE(archive.Write(sample));
149 }
150
151 for (size_t i = 0; i < count; i++) {
152 Sample sample;
153 ASSERT_TRUE(archive.Read(keys[i], sample));
154 ASSERT_EQ(values[i], sample.GetSomeData());
155 }
156 }

References impeller::testing::Sample::GetPrimaryKey(), impeller::testing::Sample::GetSomeData(), impeller::Archive::IsValid(), impeller::Archive::Read(), and impeller::Archive::Write().

## ◆ TEST_F() [6/8]

impeller::testing::TEST_F | ( | ArchiveTest | ,
|  | ReadDataWithNames |
| ) |  |

Definition at line 158 of file archivist_unittests.cc.

158 {
159 Archive archive(GetArchiveFileName().c_str());
160 ASSERT_TRUE(archive.IsValid());
161
162 size_t count = 8;
163
164 std::vector<PrimaryKey::value_type> keys;
165 std::vector<uint64_t> values;
166
167 keys.reserve(count);
168 values.reserve(count);
169
170 for (size_t i = 0; i < count; i++) {
171 Sample sample(i + 1);
172 keys.push_back(sample.GetPrimaryKey().value());
173 values.push_back(sample.GetSomeData());
174 ASSERT_TRUE(archive.Write(sample));
175 }
176
177 for (size_t i = 0; i < count; i++) {
178 Sample sample;
179 ASSERT_TRUE(archive.Read(keys[i], sample));
180 ASSERT_EQ(values[i], sample.GetSomeData());
181 ASSERT_EQ(keys[i], sample.GetPrimaryKey());
182 }
183 }

References impeller::testing::Sample::GetPrimaryKey(), impeller::testing::Sample::GetSomeData(), impeller::Archive::IsValid(), impeller::Archive::Read(), and impeller::Archive::Write().

## ◆ TEST_F() [7/8]

impeller::testing::TEST_F | ( | ArchiveTest | ,
|  | SimpleInitialization |
| ) |  |

Definition at line 108 of file archivist_unittests.cc.

108 {
109 Archive archive(GetArchiveFileName().c_str());
110 ASSERT_TRUE(archive.IsValid());
111 }

References impeller::Archive::IsValid().

## ◆ TEST_F() [8/8]

impeller::testing::TEST_F | ( | GoldenTests | ,
|  | ConicalGradient |
| ) |  |

Definition at line 71 of file golden_tests.cc.

71 {
72 Canvas canvas;
73 Paint paint;
74
75 paint.color_source = ColorSource::MakeConicalGradient(
76 {125, 125}, 125, {Color(1.0, 0.0, 0.0, 1.0), Color(0.0, 0.0, 1.0, 1.0)},
77 {0, 1}, {180, 180}, 0, Entity::TileMode::kClamp, {});
78
79 paint.stroke_width = 0.0;
80 paint.style = Paint::Style::kFill;
81 canvas.DrawRect(Rect(10, 10, 250, 250), paint);
82 Picture picture = canvas.EndRecordingAsPicture();
83
84 auto aiks_context =
85 AiksContext(Screenshoter().GetPlayground().GetContext(), nullptr);
86 auto screenshot = Screenshoter().MakeScreenshot(aiks_context, picture);
87 ASSERT_TRUE(SaveScreenshot(std::move(screenshot)));
88 }

References impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::Paint::kFill, impeller::ColorSource::MakeConicalGradient(), impeller::Paint::stroke_width, and impeller::Paint::style.

## ◆ TEST_P() [1/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | BlendModeShouldCoverWholeScreen |
| ) |  |

Definition at line 1022 of file aiks_unittests.cc.

1022 {
1023 Canvas canvas;
1024 Paint paint;
1025
1026 paint.color = Color::Red();
1027 canvas.DrawPaint(paint);
1028
1029 paint.blend_mode = BlendMode::kSourceOver;
1030 canvas.SaveLayer(paint);
1031
1032 paint.color = Color::White();
1033 canvas.DrawRect({100, 100, 400, 400}, paint);
1034
1035 paint.blend_mode = BlendMode::kSource;
1036 canvas.SaveLayer(paint);
1037
1038 paint.color = Color::Blue();
1039 canvas.DrawRect({200, 200, 200, 200}, paint);
1040
1041 canvas.Restore();
1042 canvas.Restore();
1043
1044 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1045 }

References impeller::Paint::blend_mode, impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSource, impeller::kSourceOver, impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::White().

## ◆ TEST_P() [2/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanCanvasDrawPicture |
| ) |  |

Definition at line 3203 of file aiks_unittests.cc.

3203 {
3204 Canvas subcanvas;
3205 subcanvas.DrawRect(Rect::MakeLTRB(-100, -50, 100, 50),
3206 {.color = Color::CornflowerBlue()});
3207 auto picture = subcanvas.EndRecordingAsPicture();
3208
3209 Canvas canvas;
3210 canvas.Translate({200, 200});
3211 canvas.Rotate(Radians(kPi / 4));
3212 canvas.DrawPicture(picture);
3213
3214 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3215 }

References impeller::Canvas::DrawPicture(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kPi, impeller::Canvas::Rotate(), and impeller::Canvas::Translate().

## ◆ TEST_P() [3/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanCanvasDrawPictureWithAdvancedBlend |
| ) |  |

Definition at line 3217 of file aiks_unittests.cc.

3217 {
3218 Canvas subcanvas;
3219 subcanvas.DrawRect(
3220 Rect::MakeLTRB(-100, -50, 100, 50),
3221 {.color = Color::CornflowerBlue(), .blend_mode = BlendMode::kColorDodge});
3222 auto picture = subcanvas.EndRecordingAsPicture();
3223
3224 Canvas canvas;
3225 canvas.DrawPaint({.color = Color::Black()});
3226 canvas.DrawCircle(Point::MakeXY(150, 150), 25, {.color = Color::Red()});
3227 canvas.DrawPicture(picture);
3228
3229 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3230 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPicture(), impeller::Canvas::DrawRect(), and impeller::Canvas::EndRecordingAsPicture().

## ◆ TEST_P() [4/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanCanvasDrawPictureWithBackdropFilter |
| ) |  |

Definition at line 3232 of file aiks_unittests.cc.

3232 {
3233 Canvas subcanvas;
3234 subcanvas.SaveLayer({}, {},
3235 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
3236 FilterContents::BlurStyle::kNormal,
3237 Entity::TileMode::kDecal));
3238 auto image = std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
3239 Paint paint;
3240 paint.color = Color::Red().WithAlpha(0.5);
3241 subcanvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint);
3242
3243 auto picture = subcanvas.EndRecordingAsPicture();
3244
3245 Canvas canvas;
3246 canvas.DrawPaint({.color = Color::Black()});
3247 canvas.DrawCircle(Point::MakeXY(150, 150), 25, {.color = Color::Red()});
3248 canvas.DrawPicture(picture);
3249
3250 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3251 }

References impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawImage(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPicture(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [5/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawAnOpenPath |
| ) |  |

Definition at line 1237 of file aiks_unittests.cc.

1237 {
1238 Canvas canvas;
1239
1240 // Starting at (50, 50), draw lines from:
1241 // 1. (50, height)
1242 // 2. (width, height)
1243 // 3. (width, 50)
1244 PathBuilder builder;
1245 builder.MoveTo({50, 50});
1246 builder.LineTo({50, 100});
1247 builder.LineTo({100, 100});
1248 builder.LineTo({100, 50});
1249
1250 Paint paint;
1251 paint.color = Color::Red();
1252 paint.style = Paint::Style::kStroke;
1253 paint.stroke_width = 10;
1254
1255 canvas.DrawPath(builder.TakePath(), paint);
1256
1257 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1258 }

References impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::kStroke, impeller::PathBuilder::LineTo(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Paint::stroke_width, impeller::Paint::style, and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [6/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawAnOpenPathThatIsntARect |
| ) |  |

Definition at line 1260 of file aiks_unittests.cc.

1260 {
1261 Canvas canvas;
1262
1263 // Draw a stroked path that is explicitly closed to verify
1264 // It doesn't become a rectangle.
1265 PathBuilder builder;
1266 builder.MoveTo({50, 50});
1267 builder.LineTo({520, 120});
1268 builder.LineTo({300, 310});
1269 builder.LineTo({100, 50});
1270 builder.Close();
1271
1272 Paint paint;
1273 paint.color = Color::Red();
1274 paint.style = Paint::Style::kStroke;
1275 paint.stroke_width = 10;
1276
1277 canvas.DrawPath(builder.TakePath(), paint);
1278
1279 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1280 }

References impeller::PathBuilder::Close(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::kStroke, impeller::PathBuilder::LineTo(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Paint::stroke_width, impeller::Paint::style, and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [7/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawPaint |
| ) |  |

Definition at line 1542 of file aiks_unittests.cc.

1542 {
1543 Canvas canvas;
1544 canvas.Scale(Vector2(0.2, 0.2));
1545 canvas.DrawPaint({.color = Color::MediumTurquoise()});
1546 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1547 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), and impeller::Canvas::Scale().

## ◆ TEST_P() [8/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawPaintMultipleTimes |
| ) |  |

Definition at line 1549 of file aiks_unittests.cc.

1549 {
1550 Canvas canvas;
1551 canvas.Scale(Vector2(0.2, 0.2));
1552 canvas.DrawPaint({.color = Color::MediumTurquoise()});
1553 canvas.DrawPaint({.color = Color::Color::OrangeRed().WithAlpha(0.5)});
1554 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1555 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), and impeller::Canvas::Scale().

## ◆ TEST_P() [9/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawPaintMultipleTimesInteractive |
| ) |  |

Definition at line 1627 of file aiks_unittests.cc.

1627 {
1628 auto modes = GetBlendModeSelection();
1629
1630 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
1631 static Color background = Color::MediumTurquoise();
1632 static Color foreground = Color::Color::OrangeRed().WithAlpha(0.5);
1633 static int current_blend_index = 3;
1634
1635 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1636 {
1637 ImGui::ColorEdit4("Background", reinterpret_cast<float*>(&background));
1638 ImGui::ColorEdit4("Foreground", reinterpret_cast<float*>(&foreground));
1639 ImGui::ListBox("Blend mode", &current_blend_index,
1640 modes.blend_mode_names.data(),
1641 modes.blend_mode_names.size());
1642 }
1643 ImGui::End();
1644
1645 Canvas canvas;
1646 canvas.Scale(Vector2(0.2, 0.2));
1647 canvas.DrawPaint({.color = background});
1648 canvas.DrawPaint(
1649 {.color = foreground,
1650 .blend_mode = static_cast<BlendMode>(current_blend_index)});
1651 return canvas.EndRecordingAsPicture();
1652 };
1653 ASSERT_TRUE(OpenPlaygroundHere(callback));
1654 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), GetBlendModeSelection(), impeller::Canvas::Scale(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [10/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawPaintWithAdvancedBlend |
| ) |  |

Definition at line 1557 of file aiks_unittests.cc.

1557 {
1558 Canvas canvas;
1559 canvas.Scale(Vector2(0.2, 0.2));
1560 canvas.DrawPaint({.color = Color::MediumTurquoise()});
1561 canvas.DrawPaint({.color = Color::Color::OrangeRed().WithAlpha(0.5),
1562 .blend_mode = BlendMode::kHue});
1563 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1564 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), and impeller::Canvas::Scale().

## ◆ TEST_P() [11/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawPoints |
| ) |  |

Definition at line 3044 of file aiks_unittests.cc.

3044 {
3045 std::vector<Point> points = {
3046 {0, 0}, //
3047 {100, 100}, //
3048 {100, 0}, //
3049 {0, 100}, //
3050 {0, 0}, //
3051 {48, 48}, //
3052 {52, 52}, //
3053 };
3054 std::vector<PointStyle> caps = {
3055 PointStyle::kRound,
3056 PointStyle::kSquare,
3057 };
3058 Paint paint;
3059 paint.color = Color::Yellow().WithAlpha(0.5);
3060
3061 Paint background;
3062 background.color = Color::Black();
3063
3064 Canvas canvas;
3065 canvas.DrawPaint(background);
3066 canvas.Translate({200, 200});
3067 canvas.DrawPoints(points, 10, paint, PointStyle::kRound);
3068 canvas.Translate({150, 0});
3069 canvas.DrawPoints(points, 10, paint, PointStyle::kSquare);
3070
3071 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3072 }

References impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPoints(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Translate(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [12/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanDrawPointsWithTextureMap |
| ) |  |

Definition at line 3138 of file aiks_unittests.cc.

3138 {
3139 auto texture = CreateTextureForFixture("table_mountain_nx.png",
3140 /*enable_mipmapping=*/true);
3141
3142 std::vector<Point> points = {
3143 {0, 0}, //
3144 {100, 100}, //
3145 {100, 0}, //
3146 {0, 100}, //
3147 {0, 0}, //
3148 {48, 48}, //
3149 {52, 52}, //
3150 };
3151 std::vector<PointStyle> caps = {
3152 PointStyle::kRound,
3153 PointStyle::kSquare,
3154 };
3155 Paint paint;
3156 paint.color_source = ColorSource::MakeImage(texture, Entity::TileMode::kClamp,
3157 Entity::TileMode::kClamp, {}, {});
3158
3159 Canvas canvas;
3160 canvas.Translate({200, 200});
3161 canvas.DrawPoints(points, 100, paint, PointStyle::kRound);
3162 canvas.Translate({150, 0});
3163 canvas.DrawPoints(points, 100, paint, PointStyle::kSquare);
3164
3165 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3166 }

References impeller::Paint::color_source, and impeller::Canvas::Translate().

## ◆ TEST_P() [13/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanPerformFullScreenMSAA |
| ) |  |

Definition at line 1112 of file aiks_unittests.cc.

1112 {
1113 Canvas canvas;
1114
1115 Paint red;
1116 red.color = Color::Red();
1117
1118 canvas.DrawCircle({250, 250}, 125, red);
1119
1120 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1121 }

References impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), and impeller::Color::Red().

## ◆ TEST_P() [14/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanPerformSaveLayerWithBounds |
| ) |  |

Definition at line 1135 of file aiks_unittests.cc.

1135 {
1136 Canvas canvas;
1137
1138 Paint red;
1139 red.color = Color::Red();
1140
1141 Paint green;
1142 green.color = Color::Green();
1143
1144 Paint blue;
1145 blue.color = Color::Blue();
1146
1147 Paint save;
1148 save.color = Color::Black();
1149
1150 canvas.SaveLayer(save, Rect{0, 0, 50, 50});
1151
1152 canvas.DrawRect({0, 0, 100, 100}, red);
1153 canvas.DrawRect({10, 10, 100, 100}, green);
1154 canvas.DrawRect({20, 20, 100, 100}, blue);
1155
1156 canvas.Restore();
1157
1158 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1159 }

References impeller::Color::Black(), impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Color::Red(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [15/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanPerformSaveLayerWithBoundsAndLargerIntermediateIsNotAllocated |
| ) |  |

Definition at line 1161 of file aiks_unittests.cc.

1162 {
1163 Canvas canvas;
1164
1165 Paint red;
1166 red.color = Color::Red();
1167
1168 Paint green;
1169 green.color = Color::Green();
1170
1171 Paint blue;
1172 blue.color = Color::Blue();
1173
1174 Paint save;
1175 save.color = Color::Black().WithAlpha(0.5);
1176
1177 canvas.SaveLayer(save, Rect{0, 0, 100000, 100000});
1178
1179 canvas.DrawRect({0, 0, 100, 100}, red);
1180 canvas.DrawRect({10, 10, 100, 100}, green);
1181 canvas.DrawRect({20, 20, 100, 100}, blue);
1182
1183 canvas.Restore();
1184
1185 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1186 }

References impeller::Color::Black(), impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [16/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanPerformSkew |
| ) |  |

Definition at line 1123 of file aiks_unittests.cc.

1123 {
1124 Canvas canvas;
1125
1126 Paint red;
1127 red.color = Color::Red();
1128
1129 canvas.Skew(2, 5);
1130 canvas.DrawRect(Rect::MakeXYWH(0, 0, 100, 100), red);
1131
1132 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1133 }

References impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), and impeller::Canvas::Skew().

## ◆ TEST_P() [17/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanPictureConvertToImage |
| ) |  |

Definition at line 999 of file aiks_unittests.cc.

999 {
1000 Canvas recorder_canvas;
1001 Paint paint;
1002 paint.color = Color{0.9568, 0.2627, 0.2118, 1.0};
1003 recorder_canvas.DrawRect({100.0, 100.0, 600, 600}, paint);
1004 paint.color = Color{0.1294, 0.5882, 0.9529, 1.0};
1005 recorder_canvas.DrawRect({200.0, 200.0, 600, 600}, paint);
1006
1007 Canvas canvas;
1008 AiksContext renderer(GetContext(), nullptr);
1009 paint.color = Color::BlackTransparent();
1010 canvas.DrawPaint(paint);
1011 Picture picture = recorder_canvas.EndRecordingAsPicture();
1012 auto image = picture.ToImage(renderer, ISize{1000, 1000});
1013 if (image) {
1014 canvas.DrawImage(image, Point(), Paint());
1015 paint.color = Color{0.1, 0.1, 0.1, 0.2};
1016 canvas.DrawRect(Rect::MakeSize(ISize{1000, 1000}), paint);
1017 }
1018
1019 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1020 }

References impeller::Color::BlackTransparent(), impeller::Paint::color, impeller::Canvas::DrawImage(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeSize(), and impeller::Picture::ToImage().

## ◆ TEST_P() [18/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderBackdropBlur |
| ) |  |

Definition at line 2894 of file aiks_unittests.cc.

2894 {
2895 Canvas canvas;
2896 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
2897 canvas.DrawCircle({300, 200}, 100, {.color = Color::GreenYellow()});
2898 canvas.DrawCircle({140, 170}, 75, {.color = Color::DarkMagenta()});
2899 canvas.DrawCircle({180, 120}, 100, {.color = Color::OrangeRed()});
2900 canvas.ClipRRect(Rect::MakeLTRB(75, 50, 375, 275), 20);
2901 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
2902 ImageFilter::MakeBlur(Sigma(30.0), Sigma(30.0),
2903 FilterContents::BlurStyle::kNormal,
2904 Entity::TileMode::kClamp));
2905 canvas.Restore();
2906
2907 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2908 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [19/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderBackdropBlurHugeSigma |
| ) |  |

Definition at line 2910 of file aiks_unittests.cc.

2910 {
2911 Canvas canvas;
2912 canvas.DrawCircle({400, 400}, 300, {.color = Color::Green()});
2913 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
2914 ImageFilter::MakeBlur(Sigma(999999), Sigma(999999),
2915 FilterContents::BlurStyle::kNormal,
2916 Entity::TileMode::kClamp));
2917 canvas.Restore();
2918
2919 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2920 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [20/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderBackdropBlurInteractive |
| ) |  |

Definition at line 2871 of file aiks_unittests.cc.

2871 {
2872 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
2873 auto [a, b] = IMPELLER_PLAYGROUND_LINE(Point(50, 50), Point(300, 200), 30,
2874 Color::White(), Color::White());
2875
2876 Canvas canvas;
2877 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
2878 canvas.DrawCircle({300, 200}, 100, {.color = Color::GreenYellow()});
2879 canvas.DrawCircle({140, 170}, 75, {.color = Color::DarkMagenta()});
2880 canvas.DrawCircle({180, 120}, 100, {.color = Color::OrangeRed()});
2881 canvas.ClipRRect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), 20);
2882 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
2883 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
2884 FilterContents::BlurStyle::kNormal,
2885 Entity::TileMode::kClamp));
2886 canvas.Restore();
2887
2888 return canvas.EndRecordingAsPicture();
2889 };
2890
2891 ASSERT_TRUE(OpenPlaygroundHere(callback));
2892 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), IMPELLER_PLAYGROUND_LINE, impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [21/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderClippedBlur |
| ) |  |

Definition at line 2922 of file aiks_unittests.cc.

2922 {
2923 Canvas canvas;
2924 canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
2925 canvas.DrawCircle(
2926 {400, 400}, 200,
2927 {
2928 .color = Color::Green(),
2929 .image_filter = ImageFilter::MakeBlur(
2930 Sigma(20.0), Sigma(20.0), FilterContents::BlurStyle::kNormal,
2931 Entity::TileMode::kClamp),
2932 });
2933 canvas.Restore();
2934
2935 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2936 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), and impeller::Canvas::Restore().

## ◆ TEST_P() [22/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderClippedLayers |
| ) |  |

Definition at line 2093 of file aiks_unittests.cc.

2093 {
2094 Canvas canvas;
2095
2096 canvas.DrawPaint({.color = Color::White()});
2097
2098 // Draw a green circle on the screen.
2099 {
2100 // Increase the clip depth for the savelayer to contend with.
2101 canvas.ClipPath(PathBuilder{}.AddCircle({100, 100}, 50).TakePath());
2102
2103 canvas.SaveLayer({}, Rect::MakeXYWH(50, 50, 100, 100));
2104
2105 // Fill the layer with white.
2106 canvas.DrawRect(Rect::MakeSize(Size{400, 400}), {.color = Color::White()});
2107 // Fill the layer with green, but do so with a color blend that can't be
2108 // collapsed into the parent pass.
2109 // TODO(jonahwilliams): this blend mode was changed from color burn to
2110 // hardlight to work around https://github.com/flutter/flutter/issues/136554
2111 // .
2112 canvas.DrawRect(
2113 Rect::MakeSize(Size{400, 400}),
2114 {.color = Color::Green(), .blend_mode = BlendMode::kHardLight});
2115 }
2116
2117 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2118 }

References impeller::PathBuilder::AddCircle(), impeller::Canvas::ClipPath(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [23/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderClippedRuntimeEffects |
| ) |  |

Definition at line 2981 of file aiks_unittests.cc.

2981 {
2982 if (GetParam() != PlaygroundBackend::kMetal) {
2983 GTEST_SKIP_("This backend doesn't support runtime effects.");
2984 }
2985
2986 auto runtime_stage =
2987 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2988 ASSERT_TRUE(runtime_stage->IsDirty());
2989
2990 struct FragUniforms {
2991 Vector2 iResolution;
2992 Scalar iTime;
2993 } frag_uniforms = {.iResolution = Vector2(400, 400), .iTime = 100.0};
2994 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2995 uniform_data->resize(sizeof(FragUniforms));
2996 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2997
2998 std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
2999
3000 Paint paint;
3001 paint.color_source = ColorSource::MakeRuntimeEffect(
3002 runtime_stage, uniform_data, texture_inputs);
3003
3004 Canvas canvas;
3005 canvas.Save();
3006 canvas.ClipRRect(Rect{0, 0, 400, 400}, 10.0,
3007 Entity::ClipOperation::kIntersect);
3008 canvas.DrawRect(Rect{0, 0, 400, 400}, paint);
3009 canvas.Restore();
3010
3011 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3012 }

References impeller::Canvas::ClipRRect(), impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), and impeller::Canvas::Save().

## ◆ TEST_P() [24/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderClips |
| ) |  |

Definition at line 249 of file aiks_unittests.cc.

249 {
250 Canvas canvas;
251 Paint paint;
252 paint.color = Color::Fuchsia();
253 canvas.ClipPath(
254 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 500, 500)).TakePath());
255 canvas.DrawPath(PathBuilder{}.AddCircle({500, 500}, 250).TakePath(), paint);
256 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
257 }

References impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddRect(), impeller::Canvas::ClipPath(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Fuchsia(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [25/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderColoredRect |
| ) |  |

Definition at line 106 of file aiks_unittests.cc.

106 {
107 Canvas canvas;
108 Paint paint;
109 paint.color = Color::Blue();
110 canvas.DrawPath(PathBuilder{}
111 .AddRect(Rect::MakeXYWH(100.0, 100.0, 100.0, 100.0))
112 .TakePath(),
113 paint);
114 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
115 }

References impeller::PathBuilder::AddRect(), impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [26/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderConicalGradient |
| ) |  |

Definition at line 899 of file aiks_unittests.cc.

899 {
900 Scalar size = 256;
901 Canvas canvas;
902 Paint paint;
903 paint.color = Color::White();
904 canvas.DrawRect({0, 0, size * 3, size * 3}, paint);
905 std::vector<Color> colors = {Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF),
906 Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF),
907 Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF),
908 Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF)};
909 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
910 std::array<std::tuple<Point, float, Point, float>, 8> array{
911 std::make_tuple(Point{size / 2.f, size / 2.f}, 0.f,
912 Point{size / 2.f, size / 2.f}, size / 2.f),
913 std::make_tuple(Point{size / 2.f, size / 2.f}, size / 4.f,
914 Point{size / 2.f, size / 2.f}, size / 2.f),
915 std::make_tuple(Point{size / 4.f, size / 4.f}, 0.f,
916 Point{size / 2.f, size / 2.f}, size / 2.f),
917 std::make_tuple(Point{size / 4.f, size / 4.f}, size / 2.f,
918 Point{size / 2.f, size / 2.f}, 0),
919 std::make_tuple(Point{size / 4.f, size / 4.f}, size / 4.f,
920 Point{size / 2.f, size / 2.f}, size / 2.f),
921 std::make_tuple(Point{size / 4.f, size / 4.f}, size / 16.f,
922 Point{size / 2.f, size / 2.f}, size / 8.f),
923 std::make_tuple(Point{size / 4.f, size / 4.f}, size / 8.f,
924 Point{size / 2.f, size / 2.f}, size / 16.f),
925 std::make_tuple(Point{size / 8.f, size / 8.f}, size / 8.f,
926 Point{size / 2.f, size / 2.f}, size / 8.f),
927 };
928 for (int i = 0; i < 8; i++) {
929 canvas.Save();
930 canvas.Translate({(i % 3) * size, i / 3 * size, 0});
931 paint.color_source = ColorSource::MakeConicalGradient(
932 std::get<0>(array[i]), std::get<1>(array[i]), colors, stops,
933 std::get<2>(array[i]), std::get<3>(array[i]), Entity::TileMode::kClamp,
934 {});
935 canvas.DrawRect({0, 0, size, size}, paint);
936 canvas.Restore();
937 }
938 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
939 }

References impeller::Paint::color, impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::ColorSource::MakeConicalGradient(), impeller::Color::MakeRGBA8(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::Translate(), and impeller::Color::White().

## ◆ TEST_P() [27/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderConicalGradientWithDitheringDisabled |
| ) |  |

Definition at line 530 of file aiks_unittests.cc.

530 {
531 CanRenderConicalGradientWithDithering(this, false);
532 }

References CanRenderConicalGradientWithDithering().

## ◆ TEST_P() [28/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderConicalGradientWithDitheringEnabled |
| ) |  |

Definition at line 534 of file aiks_unittests.cc.

534 {
535 CanRenderConicalGradientWithDithering(this, true);
536 }

References CanRenderConicalGradientWithDithering().

## ◆ TEST_P() [29/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderCurvedStrokes |
| ) |  |

Definition at line 239 of file aiks_unittests.cc.

239 {
240 Canvas canvas;
241 Paint paint;
242 paint.color = Color::Red();
243 paint.stroke_width = 25.0;
244 paint.style = Paint::Style::kStroke;
245 canvas.DrawPath(PathBuilder{}.AddCircle({500, 500}, 250).TakePath(), paint);
246 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
247 }

References impeller::PathBuilder::AddCircle(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::kStroke, impeller::Color::Red(), impeller::Paint::stroke_width, and impeller::Paint::style.

## ◆ TEST_P() [30/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderDestructiveSaveLayer |
| ) |  |

Definition at line 2844 of file aiks_unittests.cc.

2844 {
2845 Canvas canvas;
2846
2847 canvas.DrawPaint({.color = Color::Red()});
2848 // Draw an empty savelayer with a destructive blend mode, which will replace
2849 // the entire red screen with fully transparent black, except for the green
2850 // circle drawn within the layer.
2851 canvas.SaveLayer({.blend_mode = BlendMode::kSource});
2852 canvas.DrawCircle({300, 300}, 100, {.color = Color::Green()});
2853 canvas.Restore();
2854
2855 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2856 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [31/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderDifferenceClips |
| ) |  |

Definition at line 272 of file aiks_unittests.cc.

272 {
273 Paint paint;
274 Canvas canvas;
275 canvas.Translate({400, 400});
276
277 // Limit drawing to face circle with a clip.
278 canvas.ClipPath(PathBuilder{}.AddCircle(Point(), 200).TakePath());
279 canvas.Save();
280
281 // Cut away eyes/mouth using difference clips.
282 canvas.ClipPath(PathBuilder{}.AddCircle({-100, -50}, 30).TakePath(),
283 Entity::ClipOperation::kDifference);
284 canvas.ClipPath(PathBuilder{}.AddCircle({100, -50}, 30).TakePath(),
285 Entity::ClipOperation::kDifference);
286 canvas.ClipPath(PathBuilder{}
287 .AddQuadraticCurve({-100, 50}, {0, 150}, {100, 50})
288 .TakePath(),
289 Entity::ClipOperation::kDifference);
290
291 // Draw a huge yellow rectangle to prove the clipping works.
292 paint.color = Color::Yellow();
293 canvas.DrawRect(Rect::MakeXYWH(-1000, -1000, 2000, 2000), paint);
294
295 // Remove the difference clips and draw hair that partially covers the eyes.
296 canvas.Restore();
297 paint.color = Color::Maroon();
298 canvas.DrawPath(PathBuilder{}
299 .MoveTo({200, -200})
300 .HorizontalLineTo(-200)
301 .VerticalLineTo(-40)
302 .CubicCurveTo({0, -40}, {0, -80}, {200, -80})
303 .TakePath(),
304 paint);
305
306 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
307 }

References impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddQuadraticCurve(), impeller::Canvas::ClipPath(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kDifference, impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Maroon(), impeller::PathBuilder::MoveTo(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::Translate(), and impeller::Color::Yellow().

## ◆ TEST_P() [32/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderDifferencePaths |
| ) |  |

Definition at line 1208 of file aiks_unittests.cc.

1208 {
1209 Canvas canvas;
1210
1211 Paint paint;
1212 paint.color = Color::Red();
1213
1214 PathBuilder builder;
1215
1216 PathBuilder::RoundingRadii radii;
1217 radii.top_left = {50, 25};
1218 radii.top_right = {25, 50};
1219 radii.bottom_right = {50, 25};
1220 radii.bottom_left = {25, 50};
1221
1222 builder.AddRoundedRect({100, 100, 200, 200}, radii);
1223 builder.AddCircle({200, 200}, 50);
1224 auto path = builder.TakePath(FillType::kOdd);
1225
1226 canvas.DrawImage(
1227 std::make_shared<Image>(CreateTextureForFixture("boston.jpg")), {10, 10},
1228 Paint{});
1229 canvas.DrawPath(path, paint);
1230
1231 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1232 }

References impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddRoundedRect(), impeller::PathBuilder::RoundingRadii::bottom_left, impeller::PathBuilder::RoundingRadii::bottom_right, impeller::Paint::color, impeller::Canvas::DrawImage(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::kOdd, impeller::Color::Red(), impeller::PathBuilder::TakePath(), impeller::PathBuilder::RoundingRadii::top_left, and impeller::PathBuilder::RoundingRadii::top_right.

## ◆ TEST_P() [33/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderDifferentShapesWithSameColorSource |
| ) |  |

Definition at line 972 of file aiks_unittests.cc.

972 {
973 Canvas canvas;
974 Paint paint;
975
976 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
977 Color{0.1294, 0.5882, 0.9529, 1.0}};
978 std::vector<Scalar> stops = {
979 0.0,
980 1.0,
981 };
982
983 paint.color_source = ColorSource::MakeLinearGradient(
984 {0, 0}, {100, 100}, std::move(colors), std::move(stops),
985 Entity::TileMode::kRepeat, {});
986
987 canvas.Save();
988 canvas.Translate({100, 100, 0});
989 canvas.DrawRect({0, 0, 200, 200}, paint);
990 canvas.Restore();
991
992 canvas.Save();
993 canvas.Translate({100, 400, 0});
994 canvas.DrawCircle({100, 100}, 100, paint);
995 canvas.Restore();
996 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
997 }

References impeller::Paint::color_source, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kRepeat, impeller::ColorSource::MakeLinearGradient(), impeller::Canvas::Restore(), impeller::Canvas::Save(), and impeller::Canvas::Translate().

## ◆ TEST_P() [34/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderEmojiTextFrame |
| ) |  |

Definition at line 1438 of file aiks_unittests.cc.

1438 {
1439 Canvas canvas;
1440 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
1441
1442 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), canvas,
1443 "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊",
1444 #if FML_OS_MACOSX
1445 "Apple Color Emoji.ttc"));
1446 #else
1447 "NotoColorEmoji.ttf"));
1448 #endif
1449 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1450 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), and RenderTextInCanvasSkia().

## ◆ TEST_P() [35/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderEmojiTextFrameWithAlpha |
| ) |  |

Definition at line 1452 of file aiks_unittests.cc.

1452 {
1453 Canvas canvas;
1454 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
1455
1456 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), canvas,
1457 "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊",
1458 #if FML_OS_MACOSX
1459 "Apple Color Emoji.ttc", { .alpha = 0.5 }
1460 #else
1461 "NotoColorEmoji.ttf", {.alpha = 0.5}
1462 #endif
1463 ));
1464 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1465 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), and RenderTextInCanvasSkia().

## ◆ TEST_P() [36/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderForegroundAdvancedBlendWithMaskBlur |
| ) |  |

Definition at line 2959 of file aiks_unittests.cc.

2959 {
2960 // This case triggers the ForegroundAdvancedBlend path. The color filter
2961 // should apply to the color only, and respect the alpha mask.
2962 Canvas canvas;
2963 canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
2964 canvas.DrawCircle({400, 400}, 200,
2965 {
2966 .color = Color::Grey(),
2967 .color_filter = ColorFilter::MakeBlend(
2968 BlendMode::kColor, Color::Green()),
2969 .mask_blur_descriptor =
2970 Paint::MaskBlurDescriptor{
2971 .style = FilterContents::BlurStyle::kNormal,
2972 .sigma = Radius(20),
2973 },
2974 });
2975 canvas.Restore();
2976
2977 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2978 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::kColor, impeller::Canvas::Restore(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [37/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderForegroundBlendWithMaskBlur |
| ) |  |

Definition at line 2938 of file aiks_unittests.cc.

2938 {
2939 // This case triggers the ForegroundPorterDuffBlend path. The color filter
2940 // should apply to the color only, and respect the alpha mask.
2941 Canvas canvas;
2942 canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
2943 canvas.DrawCircle({400, 400}, 200,
2944 {
2945 .color = Color::White(),
2946 .color_filter = ColorFilter::MakeBlend(
2947 BlendMode::kSource, Color::Green()),
2948 .mask_blur_descriptor =
2949 Paint::MaskBlurDescriptor{
2950 .style = FilterContents::BlurStyle::kNormal,
2951 .sigma = Radius(20),
2952 },
2953 });
2954 canvas.Restore();
2955
2956 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2957 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [38/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderGradientDecalWithBackground |
| ) |  |

Definition at line 941 of file aiks_unittests.cc.

941 {
942 std::vector<Color> colors = {Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF),
943 Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF),
944 Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF),
945 Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF)};
946 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
947
948 std::array<ColorSource, 3> color_sources = {
949 ColorSource::MakeLinearGradient({0, 0}, {100, 100}, colors, stops,
950 Entity::TileMode::kDecal, {}),
951 ColorSource::MakeRadialGradient({100, 100}, 100, colors, stops,
952 Entity::TileMode::kDecal, {}),
953 ColorSource::MakeSweepGradient({100, 100}, Degrees(45), Degrees(135),
954 colors, stops, Entity::TileMode::kDecal,
955 {}),
956 };
957
958 Canvas canvas;
959 Paint paint;
960 paint.color = Color::White();
961 canvas.DrawRect(Rect::MakeLTRB(0, 0, 605, 205), paint);
962 for (int i = 0; i < 3; i++) {
963 canvas.Save();
964 canvas.Translate({i * 200.0f, 0, 0});
965 paint.color_source = color_sources[i];
966 canvas.DrawRect(Rect::MakeLTRB(0, 0, 200, 200), paint);
967 canvas.Restore();
968 }
969 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
970 }

References impeller::Paint::color, impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kDecal, impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeLTRB(), impeller::ColorSource::MakeRadialGradient(), impeller::Color::MakeRGBA8(), impeller::ColorSource::MakeSweepGradient(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::Translate(), and impeller::Color::White().

## ◆ TEST_P() [39/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderGroupOpacity |
| ) |  |

Definition at line 1047 of file aiks_unittests.cc.

1047 {
1048 Canvas canvas;
1049
1050 Paint red;
1051 red.color = Color::Red();
1052 Paint green;
1053 green.color = Color::Green().WithAlpha(0.5);
1054 Paint blue;
1055 blue.color = Color::Blue();
1056
1057 Paint alpha;
1058 alpha.color = Color::Red().WithAlpha(0.5);
1059
1060 canvas.SaveLayer(alpha);
1061
1062 canvas.DrawRect({000, 000, 100, 100}, red);
1063 canvas.DrawRect({020, 020, 100, 100}, green);
1064 canvas.DrawRect({040, 040, 100, 100}, blue);
1065
1066 canvas.Restore();
1067
1068 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1069 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [40/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderImage |
| ) |  |

Definition at line 117 of file aiks_unittests.cc.

117 {
118 Canvas canvas;
119 Paint paint;
120 auto image = std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
121 paint.color = Color::Red();
122 canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint);
123 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
124 }

References impeller::Paint::color, impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::TPoint< Scalar >::MakeXY(), and impeller::Color::Red().

## ◆ TEST_P() [41/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderImageRect |
| ) |  |

Definition at line 212 of file aiks_unittests.cc.

212 {
213 Canvas canvas;
214 Paint paint;
215 auto image = std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
216 auto source_rect = Rect::MakeSize(Size(image->GetSize()));
217
218 // Render the bottom right quarter of the source image in a stretched rect.
219 source_rect.size.width /= 2;
220 source_rect.size.height /= 2;
221 source_rect.origin.x += source_rect.size.width;
222 source_rect.origin.y += source_rect.size.height;
223 canvas.DrawImageRect(image, source_rect, Rect::MakeXYWH(100, 100, 600, 600),
224 paint);
225 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
226 }

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

## ◆ TEST_P() [42/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderInvertedImage |
| ) |  |

Definition at line 126 of file aiks_unittests.cc.

126 {
127 Canvas canvas;
128 Paint paint;
129 auto image = std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
130 paint.color = Color::Red();
131 paint.invert_colors = true;
132 canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint);
133 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
134 }

References impeller::Paint::color, impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::invert_colors, impeller::TPoint< Scalar >::MakeXY(), and impeller::Color::Red().

## ◆ TEST_P() [43/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderItalicizedText |
| ) |  |

Definition at line 1428 of file aiks_unittests.cc.

1428 {
1429 Canvas canvas;
1430 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
1431
1432 ASSERT_TRUE(RenderTextInCanvasSkia(
1433 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
1434 "HomemadeApple.ttf"));
1435 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1436 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), and RenderTextInCanvasSkia().

## ◆ TEST_P() [44/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientClamp |
| ) |  |

Definition at line 388 of file aiks_unittests.cc.

388 {
389 CanRenderLinearGradient(this, Entity::TileMode::kClamp);
390 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [45/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientDecal |
| ) |  |

Definition at line 397 of file aiks_unittests.cc.

397 {
398 CanRenderLinearGradient(this, Entity::TileMode::kDecal);
399 }

References impeller::Entity::kDecal.

## ◆ TEST_P() [46/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientDecalWithColorFilter |
| ) |  |

Definition at line 401 of file aiks_unittests.cc.

401 {
402 Canvas canvas;
403 canvas.Scale(GetContentScale());
404 Paint paint;
405 canvas.Translate({100.0f, 0, 0});
406
407 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
408 Color{0.1294, 0.5882, 0.9529, 0.0}};
409 std::vector<Scalar> stops = {0.0, 1.0};
410
411 paint.color_source = ColorSource::MakeLinearGradient(
412 {0, 0}, {200, 200}, std::move(colors), std::move(stops),
413 Entity::TileMode::kDecal, {});
414 // Overlay the gradient with 25% green. This should appear as the entire
415 // rectangle being drawn with 25% green, including the border area outside the
416 // decal gradient.
417 paint.color_filter = ColorFilter::MakeBlend(BlendMode::kSourceOver,
418 Color::Green().WithAlpha(0.25));
419
420 paint.color = Color(1.0, 1.0, 1.0, 1.0);
421 canvas.DrawRect({0, 0, 600, 600}, paint);
422 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
423 }

References impeller::Paint::color, impeller::Paint::color_filter, impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Entity::kDecal, impeller::kSourceOver, impeller::ColorFilter::MakeBlend(), impeller::ColorSource::MakeLinearGradient(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [47/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientManyColorsClamp |
| ) |  |

Definition at line 600 of file aiks_unittests.cc.

600 {
601 CanRenderLinearGradientManyColors(this, Entity::TileMode::kClamp);
602 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [48/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientManyColorsDecal |
| ) |  |

Definition at line 609 of file aiks_unittests.cc.

609 {
610 CanRenderLinearGradientManyColors(this, Entity::TileMode::kDecal);
611 }

References impeller::Entity::kDecal.

## ◆ TEST_P() [49/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientManyColorsMirror |
| ) |  |

Definition at line 606 of file aiks_unittests.cc.

606 {
607 CanRenderLinearGradientManyColors(this, Entity::TileMode::kMirror);
608 }

References impeller::Entity::kMirror.

## ◆ TEST_P() [50/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientManyColorsRepeat |
| ) |  |

Definition at line 603 of file aiks_unittests.cc.

603 {
604 CanRenderLinearGradientManyColors(this, Entity::TileMode::kRepeat);
605 }

References impeller::Entity::kRepeat.

## ◆ TEST_P() [51/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientManyColorsUnevenStops |
| ) |  |

Definition at line 643 of file aiks_unittests.cc.

643 {
644 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
645 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
646 const Entity::TileMode tile_modes[] = {
647 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
648 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
649
650 static int selected_tile_mode = 0;
651 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
652 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
653 sizeof(tile_mode_names) / sizeof(char*));
654 static Matrix matrix = {
655 1, 0, 0, 0, //
656 0, 1, 0, 0, //
657 0, 0, 1, 0, //
658 0, 0, 0, 1 //
659 };
660 std::string label = "##1";
661 for (int i = 0; i < 4; i++) {
662 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float, &(matrix.vec[i]),
663 4, NULL, NULL, "%.2f", 0);
664 label[2]++;
665 }
666 ImGui::End();
667
668 Canvas canvas;
669 Paint paint;
670 canvas.Translate({100.0, 100.0, 0});
671 auto tile_mode = tile_modes[selected_tile_mode];
672
673 std::vector<Color> colors = {
674 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
675 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
676 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
677 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
678 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
679 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
680 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
681 std::vector<Scalar> stops = {
682 0.0, 2.0 / 62.0, 4.0 / 62.0, 8.0 / 62.0, 16.0 / 62.0, 32.0 / 62.0, 1.0,
683 };
684
685 paint.color_source = ColorSource::MakeLinearGradient(
686 {0, 0}, {200, 200}, std::move(colors), std::move(stops), tile_mode, {});
687
688 canvas.DrawRect({0, 0, 600, 600}, paint);
689 return canvas.EndRecordingAsPicture();
690 };
691 ASSERT_TRUE(OpenPlaygroundHere(callback));
692 }

References impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::Entity::kDecal, impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::ColorSource::MakeLinearGradient(), impeller::Canvas::Translate(), and impeller::Matrix::vec.

## ◆ TEST_P() [52/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientMaskBlur |
| ) |  |

Definition at line 694 of file aiks_unittests.cc.

694 {
695 Canvas canvas;
696
697 Paint paint = {
698 .color = Color::White(),
699 .color_source = ColorSource::MakeLinearGradient(
700 {200, 200}, {400, 400},
701 {Color::Red(), Color::White(), Color::Red(), Color::White(),
702 Color::Red(), Color::White(), Color::Red(), Color::White(),
703 Color::Red(), Color::White(), Color::Red()},
704 {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0},
705 Entity::TileMode::kClamp, {}),
706 .mask_blur_descriptor =
707 Paint::MaskBlurDescriptor{
708 .style = FilterContents::BlurStyle::kNormal,
709 .sigma = Sigma(20),
710 },
711 };
712
713 canvas.DrawCircle({300, 300}, 200, paint);
714 canvas.DrawRect(Rect::MakeLTRB(100, 300, 500, 600), paint);
715
716 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
717 }

References impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Color::Red(), impeller::Paint::MaskBlurDescriptor::style, and impeller::Color::White().

## ◆ TEST_P() [53/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientMirror |
| ) |  |

Definition at line 394 of file aiks_unittests.cc.

394 {
395 CanRenderLinearGradient(this, Entity::TileMode::kMirror);
396 }

References impeller::Entity::kMirror.

## ◆ TEST_P() [54/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientRepeat |
| ) |  |

Definition at line 391 of file aiks_unittests.cc.

391 {
392 CanRenderLinearGradient(this, Entity::TileMode::kRepeat);
393 }

References impeller::Entity::kRepeat.

## ◆ TEST_P() [55/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientWayManyColorsClamp |
| ) |  |

Definition at line 639 of file aiks_unittests.cc.

639 {
640 CanRenderLinearGradientWayManyColors(this, Entity::TileMode::kClamp);
641 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [56/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientWithDitheringDisabled |
| ) |  |

Definition at line 445 of file aiks_unittests.cc.

445 {
446 CanRenderLinearGradientWithDithering(this, false);
447 }

References CanRenderLinearGradientWithDithering().

## ◆ TEST_P() [57/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientWithDitheringEnabled |
| ) |  |

Definition at line 449 of file aiks_unittests.cc.

449 {
450 CanRenderLinearGradientWithDithering(this, true);
451 } // namespace

References CanRenderLinearGradientWithDithering().

## ◆ TEST_P() [58/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderLinearGradientWithOverlappingStopsClamp |
| ) |  |

Definition at line 560 of file aiks_unittests.cc.

560 {
561 CanRenderLinearGradientWithOverlappingStops(this, Entity::TileMode::kClamp);
562 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [59/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderMaskBlurHugeSigma |
| ) |  |

Definition at line 2858 of file aiks_unittests.cc.

2858 {
2859 Canvas canvas;
2860 canvas.DrawCircle({400, 400}, 300,
2861 {.color = Color::Green(),
2862 .mask_blur_descriptor = Paint::MaskBlurDescriptor{
2863 .style = FilterContents::BlurStyle::kNormal,
2864 .sigma = Sigma(99999),
2865 }});
2866 canvas.Restore();
2867
2868 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2869 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [60/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderNestedClips |
| ) |  |

Definition at line 259 of file aiks_unittests.cc.

259 {
260 Canvas canvas;
261 Paint paint;
262 paint.color = Color::Fuchsia();
263 canvas.Save();
264 canvas.ClipPath(PathBuilder{}.AddCircle({200, 400}, 300).TakePath());
265 canvas.Restore();
266 canvas.ClipPath(PathBuilder{}.AddCircle({600, 400}, 300).TakePath());
267 canvas.ClipPath(PathBuilder{}.AddCircle({400, 600}, 300).TakePath());
268 canvas.DrawRect(Rect::MakeXYWH(200, 200, 400, 400), paint);
269 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
270 }

References impeller::PathBuilder::AddCircle(), impeller::Canvas::ClipPath(), impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Fuchsia(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), and impeller::Canvas::Save().

## ◆ TEST_P() [61/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderOffscreenCheckerboard |
| ) |  |

Tests that the debug checkerboard displays for offscreen textures when enabled. Most of the complexity here is just to future proof by making pass collapsing hard.

Definition at line 2796 of file aiks_unittests.cc.

2796 {
2797 Canvas canvas;
2798 canvas.debug_options.offscreen_texture_checkerboard = true;
2799
2800 canvas.DrawPaint({.color = Color::AntiqueWhite()});
2801 canvas.DrawCircle({400, 300}, 200,
2802 {.color = Color::CornflowerBlue().WithAlpha(0.75)});
2803
2804 canvas.SaveLayer({.blend_mode = BlendMode::kMultiply});
2805 {
2806 canvas.DrawCircle({500, 400}, 200,
2807 {.color = Color::DarkBlue().WithAlpha(0.75)});
2808 canvas.DrawCircle({550, 450}, 200,
2809 {.color = Color::LightCoral().WithAlpha(0.75),
2810 .blend_mode = BlendMode::kLuminosity});
2811 }
2812 canvas.Restore();
2813
2814 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2815 }

References impeller::Canvas::debug_options, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::DebugOptions::offscreen_texture_checkerboard, impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [62/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderRadialGradient |
| ) |  |

Definition at line 719 of file aiks_unittests.cc.

719 {
720 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
721 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
722 const Entity::TileMode tile_modes[] = {
723 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
724 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
725
726 static int selected_tile_mode = 0;
727 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
728 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
729 sizeof(tile_mode_names) / sizeof(char*));
730 static Matrix matrix = {
731 1, 0, 0, 0, //
732 0, 1, 0, 0, //
733 0, 0, 1, 0, //
734 0, 0, 0, 1 //
735 };
736 std::string label = "##1";
737 for (int i = 0; i < 4; i++) {
738 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float, &(matrix.vec[i]),
739 4, NULL, NULL, "%.2f", 0);
740 label[2]++;
741 }
742 ImGui::End();
743
744 Canvas canvas;
745 Paint paint;
746 canvas.Translate({100.0, 100.0, 0});
747 auto tile_mode = tile_modes[selected_tile_mode];
748
749 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
750 Color{0.1294, 0.5882, 0.9529, 1.0}};
751 std::vector<Scalar> stops = {0.0, 1.0};
752
753 paint.color_source = ColorSource::MakeRadialGradient(
754 {100, 100}, 100, std::move(colors), std::move(stops), tile_mode, {});
755
756 canvas.DrawRect({0, 0, 600, 600}, paint);
757 return canvas.EndRecordingAsPicture();
758 };
759 ASSERT_TRUE(OpenPlaygroundHere(callback));
760 }

References impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::Entity::kDecal, impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::ColorSource::MakeRadialGradient(), impeller::Canvas::Translate(), and impeller::Matrix::vec.

## ◆ TEST_P() [63/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderRadialGradientManyColors |
| ) |  |

Definition at line 762 of file aiks_unittests.cc.

762 {
763 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
764 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
765 const Entity::TileMode tile_modes[] = {
766 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
767 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
768
769 static int selected_tile_mode = 0;
770 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
771 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
772 sizeof(tile_mode_names) / sizeof(char*));
773 static Matrix matrix = {
774 1, 0, 0, 0, //
775 0, 1, 0, 0, //
776 0, 0, 1, 0, //
777 0, 0, 0, 1 //
778 };
779 std::string label = "##1";
780 for (int i = 0; i < 4; i++) {
781 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float, &(matrix.vec[i]),
782 4, NULL, NULL, "%.2f", 0);
783 label[2]++;
784 }
785 ImGui::End();
786
787 Canvas canvas;
788 Paint paint;
789 canvas.Translate({100.0, 100.0, 0});
790 auto tile_mode = tile_modes[selected_tile_mode];
791
792 std::vector<Color> colors = {
793 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
794 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
795 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
796 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
797 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
798 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
799 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
800 std::vector<Scalar> stops = {
801 0.0,
802 (1.0 / 6.0) * 1,
803 (1.0 / 6.0) * 2,
804 (1.0 / 6.0) * 3,
805 (1.0 / 6.0) * 4,
806 (1.0 / 6.0) * 5,
807 1.0,
808 };
809
810 paint.color_source = ColorSource::MakeRadialGradient(
811 {100, 100}, 100, std::move(colors), std::move(stops), tile_mode, {});
812
813 canvas.DrawRect({0, 0, 600, 600}, paint);
814 return canvas.EndRecordingAsPicture();
815 };
816 ASSERT_TRUE(OpenPlaygroundHere(callback));
817 }

References impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::Entity::kDecal, impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::ColorSource::MakeRadialGradient(), impeller::Canvas::Translate(), and impeller::Matrix::vec.

## ◆ TEST_P() [64/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderRadialGradientWithDitheringDisabled |
| ) |  |

Definition at line 472 of file aiks_unittests.cc.

472 {
473 CanRenderRadialGradientWithDithering(this, false);
474 }

References CanRenderRadialGradientWithDithering().

## ◆ TEST_P() [65/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderRadialGradientWithDitheringEnabled |
| ) |  |

Definition at line 476 of file aiks_unittests.cc.

476 {
477 CanRenderRadialGradientWithDithering(this, true);
478 }

References CanRenderRadialGradientWithDithering().

## ◆ TEST_P() [66/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderRoundedRectWithNonUniformRadii |
| ) |  |

Definition at line 1188 of file aiks_unittests.cc.

1188 {
1189 Canvas canvas;
1190
1191 Paint paint;
1192 paint.color = Color::Red();
1193
1194 PathBuilder::RoundingRadii radii;
1195 radii.top_left = {50, 25};
1196 radii.top_right = {25, 50};
1197 radii.bottom_right = {50, 25};
1198 radii.bottom_left = {25, 50};
1199
1200 auto path =
1201 PathBuilder{}.AddRoundedRect(Rect{100, 100, 500, 500}, radii).TakePath();
1202
1203 canvas.DrawPath(path, paint);
1204
1205 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1206 }

References impeller::PathBuilder::AddRoundedRect(), impeller::PathBuilder::RoundingRadii::bottom_left, impeller::PathBuilder::RoundingRadii::bottom_right, impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Red(), impeller::PathBuilder::RoundingRadii::top_left, and impeller::PathBuilder::RoundingRadii::top_right.

## ◆ TEST_P() [67/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderStrokes |
| ) |  |

Definition at line 228 of file aiks_unittests.cc.

228 {
229 Canvas canvas;
230 Paint paint;
231 paint.color = Color::Red();
232 paint.stroke_width = 20.0;
233 paint.style = Paint::Style::kStroke;
234 canvas.DrawPath(PathBuilder{}.AddLine({200, 100}, {800, 100}).TakePath(),
235 paint);
236 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
237 }

References impeller::PathBuilder::AddLine(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::kStroke, impeller::Color::Red(), impeller::Paint::stroke_width, and impeller::Paint::style.

## ◆ TEST_P() [68/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientClamp |
| ) |  |

Definition at line 839 of file aiks_unittests.cc.

839 {
840 CanRenderSweepGradient(this, Entity::TileMode::kClamp);
841 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [69/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientDecal |
| ) |  |

Definition at line 848 of file aiks_unittests.cc.

848 {
849 CanRenderSweepGradient(this, Entity::TileMode::kDecal);
850 }

References impeller::Entity::kDecal.

## ◆ TEST_P() [70/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientManyColorsClamp |
| ) |  |

Definition at line 886 of file aiks_unittests.cc.

886 {
887 CanRenderSweepGradientManyColors(this, Entity::TileMode::kClamp);
888 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [71/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientManyColorsDecal |
| ) |  |

Definition at line 895 of file aiks_unittests.cc.

895 {
896 CanRenderSweepGradientManyColors(this, Entity::TileMode::kDecal);
897 }

References impeller::Entity::kDecal.

## ◆ TEST_P() [72/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientManyColorsMirror |
| ) |  |

Definition at line 892 of file aiks_unittests.cc.

892 {
893 CanRenderSweepGradientManyColors(this, Entity::TileMode::kMirror);
894 }

References impeller::Entity::kMirror.

## ◆ TEST_P() [73/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientManyColorsRepeat |
| ) |  |

Definition at line 889 of file aiks_unittests.cc.

889 {
890 CanRenderSweepGradientManyColors(this, Entity::TileMode::kRepeat);
891 }

References impeller::Entity::kRepeat.

## ◆ TEST_P() [74/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientMirror |
| ) |  |

Definition at line 845 of file aiks_unittests.cc.

845 {
846 CanRenderSweepGradient(this, Entity::TileMode::kMirror);
847 }

References impeller::Entity::kMirror.

## ◆ TEST_P() [75/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientRepeat |
| ) |  |

Definition at line 842 of file aiks_unittests.cc.

842 {
843 CanRenderSweepGradient(this, Entity::TileMode::kRepeat);
844 }

References impeller::Entity::kRepeat.

## ◆ TEST_P() [76/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientWithDitheringDisabled |
| ) |  |

Definition at line 501 of file aiks_unittests.cc.

501 {
502 CanRenderSweepGradientWithDithering(this, false);
503 }

References CanRenderSweepGradientWithDithering().

## ◆ TEST_P() [77/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderSweepGradientWithDitheringEnabled |
| ) |  |

Definition at line 505 of file aiks_unittests.cc.

505 {
506 CanRenderSweepGradientWithDithering(this, true);
507 }

References CanRenderSweepGradientWithDithering().

## ◆ TEST_P() [78/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextFrame |
| ) |  |

Definition at line 1365 of file aiks_unittests.cc.

1365 {
1366 Canvas canvas;
1367 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
1368 ASSERT_TRUE(RenderTextInCanvasSkia(
1369 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
1370 "Roboto-Regular.ttf"));
1371 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1372 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), and RenderTextInCanvasSkia().

## ◆ TEST_P() [79/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextFrameSTB |
| ) |  |

Definition at line 1374 of file aiks_unittests.cc.

1374 {
1375 Canvas canvas;
1376 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
1377 ASSERT_TRUE(RenderTextInCanvasSTB(
1378 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
1379 "Roboto-Regular.ttf"));
1380
1381 SetTypographerContext(TypographerContextSTB::Make());
1382 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1383 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), and RenderTextInCanvasSTB().

## ◆ TEST_P() [80/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextInSaveLayer |
| ) |  |

Definition at line 1467 of file aiks_unittests.cc.

1467 {
1468 Canvas canvas;
1469 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
1470
1471 canvas.Translate({100, 100});
1472 canvas.Scale(Vector2{0.5, 0.5});
1473
1474 // Blend the layer with the parent pass using kClear to expose the coverage.
1475 canvas.SaveLayer({.blend_mode = BlendMode::kClear});
1476 ASSERT_TRUE(RenderTextInCanvasSkia(
1477 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
1478 "Roboto-Regular.ttf"));
1479 canvas.Restore();
1480
1481 // Render the text again over the cleared coverage rect.
1482 ASSERT_TRUE(RenderTextInCanvasSkia(
1483 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
1484 "Roboto-Regular.ttf"));
1485
1486 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1487 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), RenderTextInCanvasSkia(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [81/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTextOutsideBoundaries |
| ) |  |

Definition at line 1489 of file aiks_unittests.cc.

1489 {
1490 Canvas canvas;
1491 canvas.Translate({200, 150});
1492
1493 // Construct the text blob.
1494 auto mapping = OpenFixtureAsSkData("wtf.otf");
1495 ASSERT_NE(mapping, nullptr);
1496
1497 Scalar font_size = 80;
1498 SkFont sk_font(SkTypeface::MakeFromData(mapping), font_size);
1499
1500 Paint text_paint;
1501 text_paint.color = Color::Blue().WithAlpha(0.8);
1502
1503 struct {
1504 Point position;
1505 const char* text;
1506 } text[] = {{Point(0, 0), "0F0F0F0"},
1507 {Point(1, 2), "789"},
1508 {Point(1, 3), "456"},
1509 {Point(1, 4), "123"},
1510 {Point(0, 6), "0F0F0F0"}};
1511 for (auto& t : text) {
1512 canvas.Save();
1513 canvas.Translate(t.position * Point(font_size * 2, font_size * 1.1));
1514 {
1515 auto blob = SkTextBlob::MakeFromString(t.text, sk_font);
1516 ASSERT_NE(blob, nullptr);
1517 auto frame = MakeTextFrameFromTextBlobSkia(blob);
1518 canvas.DrawTextFrame(frame, Point(), text_paint);
1519 }
1520 canvas.Restore();
1521 }
1522
1523 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1524 }

References impeller::Paint::color, impeller::Canvas::DrawTextFrame(), impeller::Canvas::EndRecordingAsPicture(), impeller::MakeTextFrameFromTextBlobSkia(), OpenFixtureAsSkData(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::Translate(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [82/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTiledTextureClamp |
| ) |  |

Definition at line 191 of file aiks_unittests.cc.

191 {
192 CanRenderTiledTexture(this, Entity::TileMode::kClamp);
193 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [83/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTiledTextureClampWithTranslate |
| ) |  |

Definition at line 207 of file aiks_unittests.cc.

207 {
208 CanRenderTiledTexture(this, Entity::TileMode::kClamp,
209 Matrix::MakeTranslation({172.f, 172.f, 0.f}));
210 }

References impeller::Entity::kClamp, and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [84/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTiledTextureDecal |
| ) |  |

Definition at line 203 of file aiks_unittests.cc.

203 {
204 CanRenderTiledTexture(this, Entity::TileMode::kDecal);
205 }

References impeller::Entity::kDecal.

## ◆ TEST_P() [85/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTiledTextureMirror |
| ) |  |

Definition at line 199 of file aiks_unittests.cc.

199 {
200 CanRenderTiledTexture(this, Entity::TileMode::kMirror);
201 }

References impeller::Entity::kMirror.

## ◆ TEST_P() [86/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTiledTextureRepeat |
| ) |  |

Definition at line 195 of file aiks_unittests.cc.

195 {
196 CanRenderTiledTexture(this, Entity::TileMode::kRepeat);
197 }

References impeller::Entity::kRepeat.

## ◆ TEST_P() [87/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderTinyOverlappingSubpasses |
| ) |  |

This is a regression check for https://github.com/flutter/engine/pull/41129 The entire screen is green if successful. If failing, no frames will render, or the entire screen will be transparent black.

Definition at line 2776 of file aiks_unittests.cc.

2776 {
2777 Canvas canvas;
2778 canvas.DrawPaint({.color = Color::Red()});
2779
2780 // Draw two overlapping subpixel circles.
2781 canvas.SaveLayer({});
2782 canvas.DrawCircle({100, 100}, 0.1, {.color = Color::Yellow()});
2783 canvas.Restore();
2784 canvas.SaveLayer({});
2785 canvas.DrawCircle({100, 100}, 0.1, {.color = Color::Yellow()});
2786 canvas.Restore();
2787
2788 canvas.DrawPaint({.color = Color::Green()});
2789
2790 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2791 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [88/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanRenderWithContiguousClipRestores |
| ) |  |

Definition at line 309 of file aiks_unittests.cc.

309 {
310 Canvas canvas;
311
312 // Cover the whole canvas with red.
313 canvas.DrawPaint({.color = Color::Red()});
314
315 canvas.Save();
316
317 // Append two clips, the second resulting in empty coverage.
318 canvas.ClipPath(
319 PathBuilder{}.AddRect(Rect::MakeXYWH(100, 100, 100, 100)).TakePath());
320 canvas.ClipPath(
321 PathBuilder{}.AddRect(Rect::MakeXYWH(300, 300, 100, 100)).TakePath());
322
323 // Restore to no clips.
324 canvas.Restore();
325
326 // Replace the whole canvas with green.
327 canvas.DrawPaint({.color = Color::Green()});
328
329 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
330 }

References impeller::PathBuilder::AddRect(), impeller::Canvas::ClipPath(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::Save(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [89/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanSaveLayerStandalone |
| ) |  |

Definition at line 350 of file aiks_unittests.cc.

350 {
351 Canvas canvas;
352
353 Paint red;
354 red.color = Color::Red();
355
356 Paint alpha;
357 alpha.color = Color::Red().WithAlpha(0.5);
358
359 canvas.SaveLayer(alpha);
360
361 canvas.DrawCircle({125, 125}, 125, red);
362
363 canvas.Restore();
364
365 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
366 }

References impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [90/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanvasCanPushPopCTM |
| ) |  |

Definition at line 90 of file aiks_unittests.cc.

90 {
91 Canvas canvas;
92 ASSERT_EQ(canvas.GetSaveCount(), 1u);
93 ASSERT_EQ(canvas.Restore(), false);
94
95 canvas.Translate(Size{100, 100});
96 canvas.Save();
97 ASSERT_EQ(canvas.GetSaveCount(), 2u);
98 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransformation(),
99 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
100 ASSERT_TRUE(canvas.Restore());
101 ASSERT_EQ(canvas.GetSaveCount(), 1u);
102 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransformation(),
103 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
104 }

References ASSERT_MATRIX_NEAR, impeller::Canvas::GetCurrentTransformation(), impeller::Canvas::GetSaveCount(), impeller::Matrix::MakeTranslation(), impeller::Canvas::Restore(), impeller::Canvas::Save(), and impeller::Canvas::Translate().

## ◆ TEST_P() [91/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CanvasCTMCanBeUpdated |
| ) |  |

Definition at line 81 of file aiks_unittests.cc.

81 {
82 Canvas canvas;
83 Matrix identity;
84 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransformation(), identity);
85 canvas.Translate(Size{100, 100});
86 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransformation(),
87 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
88 }

References ASSERT_MATRIX_NEAR, impeller::Canvas::GetCurrentTransformation(), impeller::Matrix::MakeTranslation(), and impeller::Canvas::Translate().

## ◆ TEST_P() [92/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CaptureContext |
| ) |  |

Definition at line 3475 of file aiks_unittests.cc.

3475 {
3476 auto capture_context = CaptureContext::MakeAllowlist({"TestDocument"});
3477
3478 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
3479 Canvas canvas;
3480
3481 capture_context.Rewind();
3482 auto document = capture_context.GetDocument("TestDocument");
3483
3484 auto color = document.AddColor("Background color", Color::CornflowerBlue());
3485 canvas.DrawPaint({.color = color});
3486
3487 ImGui::Begin("TestDocument", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
3488 document.GetElement()->properties.Iterate([](CaptureProperty& property) {
3489 property.Invoke({.color = [](CaptureColorProperty& p) {
3490 ImGui::ColorEdit4(p.label.c_str(), reinterpret_cast<float*>(&p.value));
3491 }});
3492 });
3493 ImGui::End();
3494
3495 return canvas.EndRecordingAsPicture();
3496 };
3497 OpenPlaygroundHere(callback);
3498 }

References impeller::Canvas::DrawPaint(), and impeller::Canvas::EndRecordingAsPicture().

## ◆ TEST_P() [93/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CaptureInactivatedByDefault |
| ) |  |

Definition at line 3500 of file aiks_unittests.cc.

3500 {
3501 ASSERT_FALSE(GetContext()->capture.IsActive());
3502 }

## ◆ TEST_P() [94/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClearBlend |
| ) |  |

Definition at line 3577 of file aiks_unittests.cc.

3577 {
3578 Canvas canvas;
3579 Paint white;
3580 white.color = Color::Blue();
3581 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600.0, 600.0), white);
3582
3583 Paint clear;
3584 clear.blend_mode = BlendMode::kClear;
3585
3586 canvas.DrawCircle(Point::MakeXY(300.0, 300.0), 200.0, clear);
3587 }

References impeller::Paint::blend_mode, impeller::Paint::color, impeller::Canvas::DrawCircle(), and impeller::Canvas::DrawRect().

## ◆ TEST_P() [95/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClearBlendWithBlur |
| ) |  |

Definition at line 3559 of file aiks_unittests.cc.

3559 {
3560 Canvas canvas;
3561 Paint white;
3562 white.color = Color::Blue();
3563 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600.0, 600.0), white);
3564
3565 Paint clear;
3566 clear.blend_mode = BlendMode::kClear;
3567 clear.mask_blur_descriptor = Paint::MaskBlurDescriptor{
3568 .style = FilterContents::BlurStyle::kNormal,
3569 .sigma = Sigma(20),
3570 };
3571
3572 canvas.DrawCircle(Point::MakeXY(300.0, 300.0), 200.0, clear);
3573
3574 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3575 }

References impeller::Paint::blend_mode, impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::mask_blur_descriptor, and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [96/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClearColorOptimizationDoesNotApplyForBackdropFilters |
| ) |  |

Definition at line 2405 of file aiks_unittests.cc.

2405 {
2406 Canvas canvas;
2407 canvas.SaveLayer({}, std::nullopt,
2408 ImageFilter::MakeBlur(Sigma(3), Sigma(3),
2409 FilterContents::BlurStyle::kNormal,
2410 Entity::TileMode::kClamp));
2411 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
2412 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
2413 .blend_mode = BlendMode::kSourceOver});
2414 canvas.Restore();
2415
2416 Picture picture = canvas.EndRecordingAsPicture();
2417
2418 std::optional<Color> actual_color;
2419 bool found_subpass = false;
2420 picture.pass->IterateAllElements([&](EntityPass::Element& element) -> bool {
2421 if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
2422 actual_color = subpass->get()->GetClearColor();
2423 found_subpass = true;
2424 }
2425 // Fail if the first element isn't a subpass.
2426 return true;
2427 });
2428
2429 EXPECT_TRUE(found_subpass);
2430 EXPECT_FALSE(actual_color.has_value());
2431 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Picture::pass, impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [97/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClearColorOptimizationWhenSubpassIsBiggerThanParentPass |
| ) |  |

Definition at line 3611 of file aiks_unittests.cc.

3611 {
3612 Canvas canvas;
3613 canvas.Scale(GetContentScale());
3614 canvas.DrawRect(Rect::MakeLTRB(200, 200, 300, 300), {.color = Color::Red()});
3615 canvas.SaveLayer({
3616 .image_filter = std::make_shared<MatrixImageFilter>(
3617 Matrix::MakeScale({2, 2, 1}), SamplerDescriptor{}),
3618 });
3619 // Draw a rectangle that would fully cover the parent pass size, but not
3620 // the subpass that it is rendered in.
3621 canvas.DrawRect(Rect::MakeLTRB(0, 0, 400, 400), {.color = Color::Green()});
3622 // Draw a bigger rectangle to force the subpass to be bigger.
3623 canvas.DrawRect(Rect::MakeLTRB(0, 0, 800, 800), {.color = Color::Red()});
3624 canvas.Restore();
3625
3626 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3627 }

References impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Scale().

## ◆ TEST_P() [98/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClippedBlurFilterRendersCorrectly |
| ) |  |

Definition at line 3460 of file aiks_unittests.cc.

3460 {
3461 Canvas canvas;
3462 canvas.Translate(Point(0, -400));
3463 Paint paint;
3464 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
3465 .style = FilterContents::BlurStyle::kNormal,
3466 .sigma = Radius{120 * 3},
3467 };
3468 paint.color = Color::Red();
3469 PathBuilder builder{};
3470 builder.AddRect(Rect::MakeLTRB(0, 0, 800, 800));
3471 canvas.DrawPath(builder.TakePath(), paint);
3472 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3473 }

References impeller::PathBuilder::AddRect(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::mask_blur_descriptor, impeller::Paint::MaskBlurDescriptor::style, and impeller::Canvas::Translate().

## ◆ TEST_P() [99/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClippedBlurFilterRendersCorrectlyInteractive |
| ) |  |

Definition at line 3440 of file aiks_unittests.cc.

3440 {
3441 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
3442 auto point = IMPELLER_PLAYGROUND_POINT(Point(400, 400), 20, Color::Green());
3443
3444 Canvas canvas;
3445 canvas.Translate(point - Point(400, 400));
3446 Paint paint;
3447 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
3448 .style = FilterContents::BlurStyle::kNormal,
3449 .sigma = Radius{120 * 3},
3450 };
3451 paint.color = Color::Red();
3452 PathBuilder builder{};
3453 builder.AddRect(Rect::MakeLTRB(0, 0, 800, 800));
3454 canvas.DrawPath(builder.TakePath(), paint);
3455 return canvas.EndRecordingAsPicture();
3456 };
3457 ASSERT_TRUE(OpenPlaygroundHere(callback));
3458 }

References impeller::PathBuilder::AddRect(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), IMPELLER_PLAYGROUND_POINT, impeller::Paint::mask_blur_descriptor, impeller::Paint::MaskBlurDescriptor::style, and impeller::Canvas::Translate().

## ◆ TEST_P() [100/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClipRectElidesNoOpClips |
| ) |  |

Definition at line 2381 of file aiks_unittests.cc.

2381 {
2382 Canvas canvas(Rect(0, 0, 100, 100));
2383 canvas.ClipRect(Rect(0, 0, 100, 100));
2384 canvas.ClipRect(Rect(-100, -100, 300, 300));
2385 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
2386 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
2387 .blend_mode = BlendMode::kSourceOver});
2388
2389 Picture picture = canvas.EndRecordingAsPicture();
2390 auto expected = Color::Red().Blend(Color::CornflowerBlue().WithAlpha(0.75),
2391 BlendMode::kSourceOver);
2392 ASSERT_EQ(picture.pass->GetClearColor(), expected);
2393
2394 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
2395 std::shared_ptr<Context> real_context = GetContext();
2396 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
2397 AiksContext renderer(mock_context, nullptr);
2398 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
2399
2400 ASSERT_EQ(spy->render_passes_.size(), 1llu);
2401 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
2402 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
2403 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Picture::pass, and impeller::Picture::ToImage().

## ◆ TEST_P() [101/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ClipsUseCurrentTransform |
| ) |  |

Definition at line 332 of file aiks_unittests.cc.

332 {
333 std::array<Color, 5> colors = {Color::White(), Color::Black(),
334 Color::SkyBlue(), Color::Red(),
335 Color::Yellow()};
336 Canvas canvas;
337 Paint paint;
338
339 canvas.Translate(Vector3(300, 300));
340 for (int i = 0; i < 15; i++) {
341 canvas.Scale(Vector3(0.8, 0.8));
342
343 paint.color = colors[i % colors.size()];
344 canvas.ClipPath(PathBuilder{}.AddCircle({0, 0}, 300).TakePath());
345 canvas.DrawRect(Rect(-300, -300, 600, 600), paint);
346 }
347 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
348 }

References impeller::PathBuilder::AddCircle(), impeller::Color::Black(), impeller::Canvas::ClipPath(), impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Red(), impeller::Canvas::Scale(), impeller::Color::SkyBlue(), impeller::Canvas::Translate(), impeller::Color::White(), and impeller::Color::Yellow().

## ◆ TEST_P() [102/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CollapsedDrawPaintInSubpass |
| ) |  |

Definition at line 2433 of file aiks_unittests.cc.

2433 {
2434 Canvas canvas;
2435 canvas.DrawPaint(
2436 {.color = Color::Yellow(), .blend_mode = BlendMode::kSource});
2437 canvas.SaveLayer({.blend_mode = BlendMode::kMultiply});
2438 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
2439 .blend_mode = BlendMode::kSourceOver});
2440
2441 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2442 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [103/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CollapsedDrawPaintInSubpassBackdropFilter |
| ) |  |

Definition at line 2444 of file aiks_unittests.cc.

2444 {
2445 // Bug: https://github.com/flutter/flutter/issues/131576
2446 Canvas canvas;
2447 canvas.DrawPaint(
2448 {.color = Color::Yellow(), .blend_mode = BlendMode::kSource});
2449 canvas.SaveLayer({}, {},
2450 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
2451 FilterContents::BlurStyle::kNormal,
2452 Entity::TileMode::kDecal));
2453 canvas.DrawPaint(
2454 {.color = Color::CornflowerBlue(), .blend_mode = BlendMode::kSourceOver});
2455
2456 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2457 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [104/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ColorMatrixFilterSubpassCollapseOptimization |
| ) |  |

Definition at line 2474 of file aiks_unittests.cc.

2474 {
2475 Canvas canvas;
2476
2477 canvas.SaveLayer({
2478 .color_filter =
2479 ColorFilter::MakeMatrix({.array =
2480 {
2481 -1.0, 0, 0, 1.0, 0, //
2482 0, -1.0, 0, 1.0, 0, //
2483 0, 0, -1.0, 1.0, 0, //
2484 1.0, 1.0, 1.0, 1.0, 0 //
2485 }}),
2486 });
2487
2488 canvas.Translate({500, 300, 0});
2489 canvas.Rotate(Radians(2 * kPi / 3));
2490 canvas.DrawRect({100, 100, 200, 200}, {.color = Color::Blue()});
2491
2492 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2493 }

References impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kPi, impeller::Canvas::Rotate(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Translate().

## ◆ TEST_P() [105/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ColorWheel |
| ) |  |

color_wheel_sampler: r=0 -> fuchsia, r=2pi/3 -> yellow, r=4pi/3 -> cyan domain: r >= 0 (because modulo used is non euclidean)

Definition at line 1675 of file aiks_unittests.cc.

1675 {
1676 // Compare with https://fiddle.skia.org/c/@BlendModes
1677
1678 BlendModeSelection blend_modes = GetBlendModeSelection();
1679
1680 auto draw_color_wheel = [](Canvas& canvas) {
1681 /// color_wheel_sampler: r=0 -> fuchsia, r=2pi/3 -> yellow, r=4pi/3 ->
1682 /// cyan domain: r >= 0 (because modulo used is non euclidean)
1683 auto color_wheel_sampler = [](Radians r) {
1684 Scalar x = r.radians / k2Pi + 1;
1685
1686 // https://www.desmos.com/calculator/6nhjelyoaj
1687 auto color_cycle = [](Scalar x) {
1688 Scalar cycle = std::fmod(x, 6.0f);
1689 return std::max(0.0f, std::min(1.0f, 2 - std::abs(2 - cycle)));
1690 };
1691 return Color(color_cycle(6 * x + 1), //
1692 color_cycle(6 * x - 1), //
1693 color_cycle(6 * x - 3), //
1694 1);
1695 };
1696
1697 Paint paint;
1698 paint.blend_mode = BlendMode::kSourceOver;
1699
1700 // Draw a fancy color wheel for the backdrop.
1701 // https://www.desmos.com/calculator/xw7kafthwd
1702 const int max_dist = 900;
1703 for (int i = 0; i <= 900; i++) {
1704 Radians r(kPhi / k2Pi * i);
1705 Scalar distance = r.radians / std::powf(4.12, 0.0026 * r.radians);
1706 Scalar normalized_distance = static_cast<Scalar>(i) / max_dist;
1707
1708 paint.color =
1709 color_wheel_sampler(r).WithAlpha(1.0f - normalized_distance);
1710 Point position(distance * std::sin(r.radians),
1711 -distance * std::cos(r.radians));
1712
1713 canvas.DrawCircle(position, 9 + normalized_distance * 3, paint);
1714 }
1715 };
1716
1717 std::shared_ptr<Image> color_wheel_image;
1718 Matrix color_wheel_transform;
1719
1720 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
1721 // UI state.
1722 static bool cache_the_wheel = true;
1723 static int current_blend_index = 3;
1724 static float dst_alpha = 1;
1725 static float src_alpha = 1;
1726 static Color color0 = Color::Red();
1727 static Color color1 = Color::Green();
1728 static Color color2 = Color::Blue();
1729
1730 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1731 {
1732 ImGui::Checkbox("Cache the wheel", &cache_the_wheel);
1733 ImGui::ListBox("Blending mode", &current_blend_index,
1734 blend_modes.blend_mode_names.data(),
1735 blend_modes.blend_mode_names.size());
1736 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
1737 ImGui::ColorEdit4("Color A", reinterpret_cast<float*>(&color0));
1738 ImGui::ColorEdit4("Color B", reinterpret_cast<float*>(&color1));
1739 ImGui::ColorEdit4("Color C", reinterpret_cast<float*>(&color2));
1740 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
1741 }
1742 ImGui::End();
1743
1744 static Point content_scale;
1745 Point new_content_scale = GetContentScale();
1746
1747 if (!cache_the_wheel || new_content_scale != content_scale) {
1748 content_scale = new_content_scale;
1749
1750 // Render the color wheel to an image.
1751
1752 Canvas canvas;
1753 canvas.Scale(content_scale);
1754
1755 canvas.Translate(Vector2(500, 400));
1756 canvas.Scale(Vector2(3, 3));
1757
1758 draw_color_wheel(canvas);
1759 auto color_wheel_picture = canvas.EndRecordingAsPicture();
1760 auto snapshot = color_wheel_picture.Snapshot(renderer);
1761 if (!snapshot.has_value() || !snapshot->texture) {
1762 return std::nullopt;
1763 }
1764 color_wheel_image = std::make_shared<Image>(snapshot->texture);
1765 color_wheel_transform = snapshot->transform;
1766 }
1767
1768 Canvas canvas;
1769
1770 // Blit the color wheel backdrop to the screen with managed alpha.
1771 canvas.SaveLayer({.color = Color::White().WithAlpha(dst_alpha),
1772 .blend_mode = BlendMode::kSource});
1773 {
1774 canvas.DrawPaint({.color = Color::White()});
1775
1776 canvas.Save();
1777 canvas.Transform(color_wheel_transform);
1778 canvas.DrawImage(color_wheel_image, Point(), Paint());
1779 canvas.Restore();
1780 }
1781 canvas.Restore();
1782
1783 canvas.Scale(content_scale);
1784 canvas.Translate(Vector2(500, 400));
1785 canvas.Scale(Vector2(3, 3));
1786
1787 // Draw 3 circles to a subpass and blend it in.
1788 canvas.SaveLayer(
1789 {.color = Color::White().WithAlpha(src_alpha),
1790 .blend_mode = blend_modes.blend_mode_values[current_blend_index]});
1791 {
1792 Paint paint;
1793 paint.blend_mode = BlendMode::kPlus;
1794 const Scalar x = std::sin(k2Pi / 3);
1795 const Scalar y = -std::cos(k2Pi / 3);
1796 paint.color = color0;
1797 canvas.DrawCircle(Point(-x, y) * 45, 65, paint);
1798 paint.color = color1;
1799 canvas.DrawCircle(Point(0, -1) * 45, 65, paint);
1800 paint.color = color2;
1801 canvas.DrawCircle(Point(x, y) * 45, 65, paint);
1802 }
1803 canvas.Restore();
1804
1805 return canvas.EndRecordingAsPicture();
1806 };
1807
1808 ASSERT_TRUE(OpenPlaygroundHere(callback));
1809 }

References impeller::Paint::blend_mode, impeller::testing::BlendModeSelection::blend_mode_names, impeller::testing::BlendModeSelection::blend_mode_values, impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawImage(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), GetBlendModeSelection(), impeller::k2Pi, impeller::kPhi, impeller::Radians::radians, impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), impeller::Picture::Snapshot(), impeller::Canvas::Transform(), impeller::Canvas::Translate(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [106/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CoordinateConversionsAreCorrect |
| ) |  |

Definition at line 1071 of file aiks_unittests.cc.

1071 {
1072 Canvas canvas;
1073
1074 // Render a texture directly.
1075 {
1076 Paint paint;
1077 auto image =
1078 std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
1079 paint.color = Color::Red();
1080
1081 canvas.Save();
1082 canvas.Translate({100, 200, 0});
1083 canvas.Scale(Vector2{0.5, 0.5});
1084 canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint);
1085 canvas.Restore();
1086 }
1087
1088 // Render an offscreen rendered texture.
1089 {
1090 Paint red;
1091 red.color = Color::Red();
1092 Paint green;
1093 green.color = Color::Green();
1094 Paint blue;
1095 blue.color = Color::Blue();
1096
1097 Paint alpha;
1098 alpha.color = Color::Red().WithAlpha(0.5);
1099
1100 canvas.SaveLayer(alpha);
1101
1102 canvas.DrawRect({000, 000, 100, 100}, red);
1103 canvas.DrawRect({020, 020, 100, 100}, green);
1104 canvas.DrawRect({040, 040, 100, 100}, blue);
1105
1106 canvas.Restore();
1107 }
1108
1109 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1110 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawImage(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::TPoint< Scalar >::MakeXY(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), impeller::Canvas::Translate(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [107/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | CoverageOriginShouldBeAccountedForInSubpasses |
| ) |  |

Definition at line 1990 of file aiks_unittests.cc.

1990 {
1991 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
1992 Canvas canvas;
1993 canvas.Scale(GetContentScale());
1994
1995 Paint alpha;
1996 alpha.color = Color::Red().WithAlpha(0.5);
1997
1998 auto current = Point{25, 25};
1999 const auto offset = Point{25, 25};
2000 const auto size = Size(100, 100);
2001
2002 auto [b0, b1] = IMPELLER_PLAYGROUND_LINE(Point(40, 40), Point(160, 160), 10,
2003 Color::White(), Color::White());
2004 auto bounds = Rect::MakeLTRB(b0.x, b0.y, b1.x, b1.y);
2005
2006 canvas.DrawRect(bounds, Paint{.color = Color::Yellow(),
2007 .stroke_width = 5.0f,
2008 .style = Paint::Style::kStroke});
2009
2010 canvas.SaveLayer(alpha, bounds);
2011
2012 canvas.DrawRect({current, size}, Paint{.color = Color::Red()});
2013 canvas.DrawRect({current += offset, size}, Paint{.color = Color::Green()});
2014 canvas.DrawRect({current += offset, size}, Paint{.color = Color::Blue()});
2015
2016 canvas.Restore();
2017
2018 return canvas.EndRecordingAsPicture();
2019 };
2020
2021 ASSERT_TRUE(OpenPlaygroundHere(callback));
2022 }

References impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), IMPELLER_PLAYGROUND_LINE, impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [108/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawAdvancedBlendPartlyOffscreen |
| ) |  |

Definition at line 1583 of file aiks_unittests.cc.

1583 {
1584 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
1585 Color{0.1294, 0.5882, 0.9529, 1.0}};
1586 std::vector<Scalar> stops = {0.0, 1.0};
1587
1588 Paint paint = {
1589 .color_source = ColorSource::MakeLinearGradient(
1590 {0, 0}, {100, 100}, std::move(colors), std::move(stops),
1591 Entity::TileMode::kRepeat, Matrix::MakeScale(Vector3(0.3, 0.3, 0.3))),
1592 .blend_mode = BlendMode::kLighten,
1593 };
1594
1595 Canvas canvas;
1596 canvas.DrawPaint({.color = Color::Blue()});
1597 canvas.Scale(Vector2(2, 2));
1598 canvas.ClipRect(Rect::MakeLTRB(0, 0, 200, 200));
1599 canvas.DrawCircle({100, 100}, 100, paint);
1600 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1601 }

References impeller::Canvas::ClipRect(), impeller::Paint::color_source, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), and impeller::Canvas::Scale().

## ◆ TEST_P() [109/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawAtlasAdvancedAndTransform |
| ) |  |

Definition at line 3108 of file aiks_unittests.cc.

3108 {
3109 // Draws the image as four squares stiched together.
3110 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
3111 auto size = atlas->GetSize();
3112 auto image = std::make_shared<Image>(atlas);
3113 // Divide image into four quadrants.
3114 Scalar half_width = size.width / 2;
3115 Scalar half_height = size.height / 2;
3116 std::vector<Rect> texture_coordinates = {
3117 Rect::MakeLTRB(0, 0, half_width, half_height),
3118 Rect::MakeLTRB(half_width, 0, size.width, half_height),
3119 Rect::MakeLTRB(0, half_height, half_width, size.height),
3120 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
3121 // Position quadrants adjacent to eachother.
3122 std::vector<Matrix> transforms = {
3123 Matrix::MakeTranslation({0, 0, 0}),
3124 Matrix::MakeTranslation({half_width, 0, 0}),
3125 Matrix::MakeTranslation({0, half_height, 0}),
3126 Matrix::MakeTranslation({half_width, half_height, 0})};
3127
3128 Paint paint;
3129
3130 Canvas canvas;
3131 canvas.Scale({0.25, 0.25, 1.0});
3132 canvas.DrawAtlas(image, transforms, texture_coordinates, {},
3133 BlendMode::kModulate, {}, std::nullopt, paint);
3134
3135 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3136 }

References impeller::Canvas::DrawAtlas(), impeller::Canvas::EndRecordingAsPicture(), and impeller::Canvas::Scale().

## ◆ TEST_P() [110/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawAtlasWithColorAdvancedAndTransform |
| ) |  |

Definition at line 3075 of file aiks_unittests.cc.

3075 {
3076 // Draws the image as four squares stiched together.
3077 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
3078 auto size = atlas->GetSize();
3079 auto image = std::make_shared<Image>(atlas);
3080 // Divide image into four quadrants.
3081 Scalar half_width = size.width / 2;
3082 Scalar half_height = size.height / 2;
3083 std::vector<Rect> texture_coordinates = {
3084 Rect::MakeLTRB(0, 0, half_width, half_height),
3085 Rect::MakeLTRB(half_width, 0, size.width, half_height),
3086 Rect::MakeLTRB(0, half_height, half_width, size.height),
3087 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
3088 // Position quadrants adjacent to eachother.
3089 std::vector<Matrix> transforms = {
3090 Matrix::MakeTranslation({0, 0, 0}),
3091 Matrix::MakeTranslation({half_width, 0, 0}),
3092 Matrix::MakeTranslation({0, half_height, 0}),
3093 Matrix::MakeTranslation({half_width, half_height, 0})};
3094 std::vector<Color> colors = {Color::Red(), Color::Green(), Color::Blue(),
3095 Color::Yellow()};
3096
3097 Paint paint;
3098
3099 Canvas canvas;
3100 canvas.Scale({0.25, 0.25, 1.0});
3101 canvas.DrawAtlas(image, transforms, texture_coordinates, colors,
3102 BlendMode::kModulate, {}, std::nullopt, paint);
3103
3104 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3105 }

References impeller::Canvas::DrawAtlas(), impeller::Canvas::EndRecordingAsPicture(), and impeller::Canvas::Scale().

## ◆ TEST_P() [111/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawPaintAbsorbsClears |
| ) |  |

Definition at line 2255 of file aiks_unittests.cc.

2255 {
2256 Canvas canvas;
2257 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
2258 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
2259 .blend_mode = BlendMode::kSourceOver});
2260
2261 Picture picture = canvas.EndRecordingAsPicture();
2262 auto expected = Color::Red().Blend(Color::CornflowerBlue().WithAlpha(0.75),
2263 BlendMode::kSourceOver);
2264 ASSERT_EQ(picture.pass->GetClearColor(), expected);
2265
2266 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
2267 std::shared_ptr<Context> real_context = GetContext();
2268 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
2269 AiksContext renderer(mock_context, nullptr);
2270 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
2271
2272 ASSERT_EQ(spy->render_passes_.size(), 1llu);
2273 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
2274 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
2275 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Picture::pass, and impeller::Picture::ToImage().

## ◆ TEST_P() [112/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawPaintTransformsBounds |
| ) |  |

Definition at line 3014 of file aiks_unittests.cc.

3014 {
3015 if (GetParam() != PlaygroundBackend::kMetal) {
3016 GTEST_SKIP_("This backend doesn't support runtime effects.");
3017 }
3018
3019 auto runtime_stage = OpenAssetAsRuntimeStage("gradient.frag.iplr");
3020 ASSERT_TRUE(runtime_stage->IsDirty());
3021
3022 struct FragUniforms {
3023 Size size;
3024 } frag_uniforms = {.size = Size::MakeWH(400, 400)};
3025 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
3026 uniform_data->resize(sizeof(FragUniforms));
3027 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
3028
3029 std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
3030
3031 Paint paint;
3032 paint.color_source = ColorSource::MakeRuntimeEffect(
3033 runtime_stage, uniform_data, texture_inputs);
3034
3035 Canvas canvas;
3036 canvas.Save();
3037 canvas.Scale(GetContentScale());
3038 canvas.DrawPaint(paint);
3039 canvas.Restore();
3040
3041 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3042 }

References impeller::Paint::color_source, impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), impeller::Canvas::Save(), and impeller::Canvas::Scale().

## ◆ TEST_P() [113/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawPaintWithAdvancedBlendOverFilter |
| ) |  |

Definition at line 1566 of file aiks_unittests.cc.

1566 {
1567 Paint filtered = {
1568 .color = Color::Black(),
1569 .mask_blur_descriptor =
1570 Paint::MaskBlurDescriptor{
1571 .style = FilterContents::BlurStyle::kNormal,
1572 .sigma = Sigma(60),
1573 },
1574 };
1575
1576 Canvas canvas;
1577 canvas.DrawPaint({.color = Color::White()});
1578 canvas.DrawCircle({300, 300}, 200, filtered);
1579 canvas.DrawPaint({.color = Color::Green(), .blend_mode = BlendMode::kScreen});
1580 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1581 }

References impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [114/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawPictureClipped |
| ) |  |

Definition at line 3282 of file aiks_unittests.cc.

3282 {
3283 Canvas subcanvas;
3284 subcanvas.ClipRRect(Rect::MakeLTRB(100, 100, 400, 400), 15);
3285 subcanvas.DrawPaint({.color = Color::Red()});
3286 auto picture = subcanvas.EndRecordingAsPicture();
3287
3288 Canvas canvas;
3289 canvas.DrawPaint({.color = Color::CornflowerBlue()});
3290
3291 // Draw a red RRect via DrawPicture.
3292 canvas.DrawPicture(picture);
3293
3294 // Draw over the picture with a larger green rectangle, completely covering it
3295 // up.
3296 canvas.ClipRRect(Rect::MakeLTRB(100, 100, 400, 400).Expand(20), 15);
3297 canvas.DrawPaint({.color = Color::Green()});
3298
3299 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3300 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPicture(), and impeller::Canvas::EndRecordingAsPicture().

## ◆ TEST_P() [115/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawPictureWithText |
| ) |  |

Definition at line 3253 of file aiks_unittests.cc.

3253 {
3254 Canvas subcanvas;
3255 ASSERT_TRUE(RenderTextInCanvasSkia(
3256 GetContext(), subcanvas,
3257 "the quick brown fox jumped over the lazy dog!.?", "Roboto-Regular.ttf"));
3258 subcanvas.Translate({0, 10});
3259 subcanvas.Scale(Vector2(3, 3));
3260 ASSERT_TRUE(RenderTextInCanvasSkia(
3261 GetContext(), subcanvas,
3262 "the quick brown fox jumped over the very big lazy dog!.?",
3263 "Roboto-Regular.ttf"));
3264 auto picture = subcanvas.EndRecordingAsPicture();
3265
3266 Canvas canvas;
3267 canvas.Scale(Vector2(.2, .2));
3268 canvas.Save();
3269 canvas.Translate({200, 200});
3270 canvas.Scale(Vector2(3.5, 3.5)); // The text must not be blurry after this.
3271 canvas.DrawPicture(picture);
3272 canvas.Restore();
3273
3274 canvas.Scale(Vector2(1.5, 1.5));
3275 ASSERT_TRUE(RenderTextInCanvasSkia(
3276 GetContext(), canvas,
3277 "the quick brown fox jumped over the smaller lazy dog!.?",
3278 "Roboto-Regular.ttf"));
3279 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3280 }

References impeller::Canvas::DrawPicture(), impeller::Canvas::EndRecordingAsPicture(), RenderTextInCanvasSkia(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [116/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawRectAbsorbsClears |
| ) |  |

Definition at line 2301 of file aiks_unittests.cc.

2301 {
2302 Canvas canvas;
2303 canvas.DrawRect({0, 0, 300, 300},
2304 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
2305 canvas.DrawRect({0, 0, 300, 300},
2306 {.color = Color::CornflowerBlue().WithAlpha(0.75),
2307 .blend_mode = BlendMode::kSourceOver});
2308
2309 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
2310 Picture picture = canvas.EndRecordingAsPicture();
2311 std::shared_ptr<Context> real_context = GetContext();
2312 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
2313 AiksContext renderer(mock_context, nullptr);
2314 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
2315
2316 ASSERT_EQ(spy->render_passes_.size(), 1llu);
2317 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
2318 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
2319 }

References impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), and impeller::Picture::ToImage().

## ◆ TEST_P() [117/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawRectAbsorbsClearsNegative |
| ) |  |

Definition at line 2361 of file aiks_unittests.cc.

2361 {
2362 Canvas canvas;
2363 canvas.DrawRect({0, 0, 300, 300},
2364 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
2365 canvas.DrawRect({0, 0, 300, 300},
2366 {.color = Color::CornflowerBlue().WithAlpha(0.75),
2367 .blend_mode = BlendMode::kSourceOver});
2368
2369 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
2370 Picture picture = canvas.EndRecordingAsPicture();
2371 std::shared_ptr<Context> real_context = GetContext();
2372 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
2373 AiksContext renderer(mock_context, nullptr);
2374 std::shared_ptr<Image> image = picture.ToImage(renderer, {301, 301});
2375
2376 ASSERT_EQ(spy->render_passes_.size(), 1llu);
2377 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
2378 ASSERT_EQ(render_pass->GetCommands().size(), 2llu);
2379 }

References impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), and impeller::Picture::ToImage().

## ◆ TEST_P() [118/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawRectAbsorbsClearsNegativeRotation |
| ) |  |

Definition at line 2341 of file aiks_unittests.cc.

2341 {
2342 Canvas canvas;
2343 canvas.Translate(Vector3(150.0, 150.0, 0.0));
2344 canvas.Rotate(Degrees(45.0));
2345 canvas.Translate(Vector3(-150.0, -150.0, 0.0));
2346 canvas.DrawRect({0, 0, 300, 300},
2347 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
2348
2349 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
2350 Picture picture = canvas.EndRecordingAsPicture();
2351 std::shared_ptr<Context> real_context = GetContext();
2352 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
2353 AiksContext renderer(mock_context, nullptr);
2354 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
2355
2356 ASSERT_EQ(spy->render_passes_.size(), 1llu);
2357 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
2358 ASSERT_EQ(render_pass->GetCommands().size(), 1llu);
2359 }

References impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Rotate(), impeller::Picture::ToImage(), and impeller::Canvas::Translate().

## ◆ TEST_P() [119/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawRectAbsorbsClearsNegativeRRect |
| ) |  |

Definition at line 2321 of file aiks_unittests.cc.

2321 {
2322 Canvas canvas;
2323 canvas.DrawRRect({0, 0, 300, 300}, 5.0,
2324 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
2325 canvas.DrawRRect({0, 0, 300, 300}, 5.0,
2326 {.color = Color::CornflowerBlue().WithAlpha(0.75),
2327 .blend_mode = BlendMode::kSourceOver});
2328
2329 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
2330 Picture picture = canvas.EndRecordingAsPicture();
2331 std::shared_ptr<Context> real_context = GetContext();
2332 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
2333 AiksContext renderer(mock_context, nullptr);
2334 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
2335
2336 ASSERT_EQ(spy->render_passes_.size(), 1llu);
2337 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
2338 ASSERT_EQ(render_pass->GetCommands().size(), 2llu);
2339 }

References impeller::Canvas::DrawRRect(), impeller::Canvas::EndRecordingAsPicture(), and impeller::Picture::ToImage().

## ◆ TEST_P() [120/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawRectStrokesRenderCorrectly |
| ) |  |

Definition at line 2024 of file aiks_unittests.cc.

2024 {
2025 Canvas canvas;
2026 Paint paint;
2027 paint.color = Color::Red();
2028 paint.style = Paint::Style::kStroke;
2029 paint.stroke_width = 10;
2030
2031 canvas.Translate({100, 100});
2032 canvas.DrawPath(
2033 PathBuilder{}.AddRect(Rect::MakeSize(Size{100, 100})).TakePath(),
2034 {paint});
2035
2036 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2037 }

References impeller::PathBuilder::AddRect(), impeller::Paint::color, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::stroke_width, impeller::Paint::style, and impeller::Canvas::Translate().

## ◆ TEST_P() [121/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawScaledTextWithPerspectiveNoSaveLayer |
| ) |  |

Definition at line 3383 of file aiks_unittests.cc.

3383 {
3384 Canvas canvas;
3385 // clang-format off
3386 canvas.Transform(Matrix(
3387 2.000000, 0.000000, 0.000000, 0.000000,
3388 1.445767, 2.637070, -0.507928, 0.001524,
3389 -2.451887, -0.534662, 0.861399, -0.002584,
3390 1063.481934, 1025.951416, -48.300270, 1.144901
3391 ));
3392 // clang-format on
3393
3394 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), canvas, "Hello world",
3395 "Roboto-Regular.ttf"));
3396
3397 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3398 }

References impeller::Canvas::EndRecordingAsPicture(), RenderTextInCanvasSkia(), and impeller::Canvas::Transform().

## ◆ TEST_P() [122/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | DrawScaledTextWithPerspectiveSaveLayer |
| ) |  |

Definition at line 3400 of file aiks_unittests.cc.

3400 {
3401 Canvas canvas;
3402 Paint save_paint;
3403 canvas.SaveLayer(save_paint);
3404 // clang-format off
3405 canvas.Transform(Matrix(
3406 2.000000, 0.000000, 0.000000, 0.000000,
3407 1.445767, 2.637070, -0.507928, 0.001524,
3408 -2.451887, -0.534662, 0.861399, -0.002584,
3409 1063.481934, 1025.951416, -48.300270, 1.144901
3410 ));
3411 // clang-format on
3412
3413 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), canvas, "Hello world",
3414 "Roboto-Regular.ttf"));
3415 }

References RenderTextInCanvasSkia(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Transform().

## ◆ TEST_P() [123/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ForegroundBlendSubpassCollapseOptimization |
| ) |  |

Definition at line 2459 of file aiks_unittests.cc.

2459 {
2460 Canvas canvas;
2461
2462 canvas.SaveLayer({
2463 .color_filter =
2464 ColorFilter::MakeBlend(BlendMode::kColorDodge, Color::Red()),
2465 });
2466
2467 canvas.Translate({500, 300, 0});
2468 canvas.Rotate(Radians(2 * kPi / 3));
2469 canvas.DrawRect({100, 100, 200, 200}, {.color = Color::Blue()});
2470
2471 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2472 }

References impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kPi, impeller::Canvas::Rotate(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Translate().

## ◆ TEST_P() [124/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | GradientStrokesRenderCorrectly |
| ) |  |

Definition at line 1913 of file aiks_unittests.cc.

1913 {
1914 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
1915 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
1916 static float scale = 3;
1917 static bool add_circle_clip = true;
1918 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1919 const Entity::TileMode tile_modes[] = {
1920 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
1921 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
1922 static int selected_tile_mode = 0;
1923 static float alpha = 1;
1924
1925 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1926 ImGui::SliderFloat("Scale", &scale, 0, 6);
1927 ImGui::Checkbox("Circle clip", &add_circle_clip);
1928 ImGui::SliderFloat("Alpha", &alpha, 0, 1);
1929 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1930 sizeof(tile_mode_names) / sizeof(char*));
1931 ImGui::End();
1932
1933 Canvas canvas;
1934 canvas.Scale(GetContentScale());
1935 Paint paint;
1936 paint.color = Color::White();
1937 canvas.DrawPaint(paint);
1938
1939 paint.style = Paint::Style::kStroke;
1940 paint.color = Color(1.0, 1.0, 1.0, alpha);
1941 paint.stroke_width = 10;
1942 auto tile_mode = tile_modes[selected_tile_mode];
1943
1944 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
1945 Color{0.1294, 0.5882, 0.9529, 1.0}};
1946 std::vector<Scalar> stops = {0.0, 1.0};
1947
1948 paint.color_source = ColorSource::MakeLinearGradient(
1949 {0, 0}, {50, 50}, std::move(colors), std::move(stops), tile_mode, {});
1950
1951 Path path = PathBuilder{}
1952 .MoveTo({20, 20})
1953 .QuadraticCurveTo({60, 20}, {60, 60})
1954 .Close()
1955 .MoveTo({60, 20})
1956 .QuadraticCurveTo({60, 60}, {20, 60})
1957 .TakePath();
1958
1959 canvas.Scale(Vector2(scale, scale));
1960
1961 if (add_circle_clip) {
1962 auto [handle_a, handle_b] = IMPELLER_PLAYGROUND_LINE(
1963 Point(60, 300), Point(600, 300), 20, Color::Red(), Color::Red());
1964
1965 auto screen_to_canvas = canvas.GetCurrentTransformation().Invert();
1966 Point point_a = screen_to_canvas * handle_a * GetContentScale();
1967 Point point_b = screen_to_canvas * handle_b * GetContentScale();
1968
1969 Point middle = (point_a + point_b) / 2;
1970 auto radius = point_a.GetDistance(middle);
1971 canvas.ClipPath(PathBuilder{}.AddCircle(middle, radius).TakePath());
1972 }
1973
1974 for (auto join : {Join::kBevel, Join::kRound, Join::kMiter}) {
1975 paint.stroke_join = join;
1976 for (auto cap : {Cap::kButt, Cap::kSquare, Cap::kRound}) {
1977 paint.stroke_cap = cap;
1978 canvas.DrawPath(path, paint);
1979 canvas.Translate({80, 0});
1980 }
1981 canvas.Translate({-240, 60});
1982 }
1983
1984 return canvas.EndRecordingAsPicture();
1985 };
1986
1987 ASSERT_TRUE(OpenPlaygroundHere(callback));
1988 }

References impeller::PathBuilder::AddCircle(), impeller::Canvas::ClipPath(), impeller::Close(), impeller::Paint::color, impeller::Paint::color_source, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::GetCurrentTransformation(), impeller::TPoint< T >::GetDistance(), IMPELLER_PLAYGROUND_LINE, impeller::Matrix::Invert(), impeller::PathBuilder::MoveTo(), impeller::Canvas::Scale(), impeller::Paint::stroke_cap, impeller::Paint::stroke_join, impeller::Paint::stroke_width, impeller::Paint::style, impeller::PathBuilder::TakePath(), and impeller::Canvas::Translate().

## ◆ TEST_P() [125/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | LinearToSrgbFilterSubpassCollapseOptimization |
| ) |  |

Definition at line 2495 of file aiks_unittests.cc.

2495 {
2496 Canvas canvas;
2497
2498 canvas.SaveLayer({
2499 .color_filter = ColorFilter::MakeLinearToSrgb(),
2500 });
2501
2502 canvas.Translate({500, 300, 0});
2503 canvas.Rotate(Radians(2 * kPi / 3));
2504 canvas.DrawRect({100, 100, 200, 200}, {.color = Color::Blue()});
2505
2506 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2507 }

References impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kPi, impeller::Canvas::Rotate(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Translate().

## ◆ TEST_P() [126/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MaskBlurWithZeroSigmaIsSkipped |
| ) |  |

Definition at line 3629 of file aiks_unittests.cc.

3629 {
3630 Canvas canvas;
3631
3632 Paint paint = {
3633 .color = Color::White(),
3634 .mask_blur_descriptor =
3635 Paint::MaskBlurDescriptor{
3636 .style = FilterContents::BlurStyle::kNormal,
3637 .sigma = Sigma(0),
3638 },
3639 };
3640
3641 canvas.DrawCircle({300, 300}, 200, paint);
3642 canvas.DrawRect(Rect::MakeLTRB(100, 300, 500, 600), paint);
3643
3644 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3645 }

References impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [127/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MatrixBackdropFilter |
| ) |  |

Definition at line 3329 of file aiks_unittests.cc.

3329 {
3330 Canvas canvas;
3331 canvas.DrawPaint({.color = Color::Black()});
3332 canvas.SaveLayer({}, std::nullopt);
3333 {
3334 canvas.DrawCircle(Point(200, 200), 100,
3335 {.color = Color::Green().WithAlpha(0.5),
3336 .blend_mode = BlendMode::kPlus});
3337 // Should render a second circle, centered on the bottom-right-most edge of
3338 // the circle.
3339 canvas.SaveLayer(
3340 {}, std::nullopt,
3341 ImageFilter::MakeMatrix(
3342 Matrix::MakeTranslation(Vector2(1, 1) * (100 + 100 * k1OverSqrt2)) *
3343 Matrix::MakeScale(Vector2(1, 1) * 0.5) *
3344 Matrix::MakeTranslation(Vector2(-100, -100)),
3345 SamplerDescriptor{}));
3346 canvas.Restore();
3347 }
3348 canvas.Restore();
3349
3350 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3351 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::k1OverSqrt2, impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [128/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MatrixImageFilterMagnify |
| ) |  |

Definition at line 3589 of file aiks_unittests.cc.

3589 {
3590 Canvas canvas;
3591 canvas.Scale(GetContentScale());
3592 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
3593 canvas.Translate({600, -200});
3594 canvas.SaveLayer({
3595 .image_filter = std::make_shared<MatrixImageFilter>(
3596 Matrix{
3597 2, 0, 0, 0, //
3598 0, 2, 0, 0, //
3599 0, 0, 2, 0, //
3600 0, 0, 0, 1 //
3601 },
3602 SamplerDescriptor{}),
3603 });
3604 canvas.DrawImage(image, {0, 0}, Paint{.color = Color(1.0, 1.0, 1.0, 0.5)});
3605 canvas.Restore();
3606
3607 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3608 }

References impeller::Paint::color, impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [129/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | MatrixSaveLayerFilter |
| ) |  |

Definition at line 3302 of file aiks_unittests.cc.

3302 {
3303 Canvas canvas;
3304 canvas.DrawPaint({.color = Color::Black()});
3305 canvas.SaveLayer({}, std::nullopt);
3306 {
3307 canvas.DrawCircle(Point(200, 200), 100,
3308 {.color = Color::Green().WithAlpha(0.5),
3309 .blend_mode = BlendMode::kPlus});
3310 // Should render a second circle, centered on the bottom-right-most edge of
3311 // the circle.
3312 canvas.SaveLayer({.image_filter = ImageFilter::MakeMatrix(
3313 Matrix::MakeTranslation(Vector2(1, 1) *
3314 (200 + 100 * k1OverSqrt2)) *
3315 Matrix::MakeScale(Vector2(1, 1) * 0.5) *
3316 Matrix::MakeTranslation(Vector2(-200, -200)),
3317 SamplerDescriptor{})},
3318 std::nullopt);
3319 canvas.DrawCircle(Point(200, 200), 100,
3320 {.color = Color::Green().WithAlpha(0.5),
3321 .blend_mode = BlendMode::kPlus});
3322 canvas.Restore();
3323 }
3324 canvas.Restore();
3325
3326 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3327 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::k1OverSqrt2, impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [130/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | OpacityPeepHoleApplicationTest |
| ) |  |

Definition at line 2216 of file aiks_unittests.cc.

2216 {
2217 auto entity_pass = std::make_shared<EntityPass>();
2218 auto rect = Rect::MakeLTRB(0, 0, 100, 100);
2219 Paint paint;
2220 paint.color = Color::White().WithAlpha(0.5);
2221 paint.color_filter =
2222 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Blue());
2223
2224 // Paint has color filter, can't elide.
2225 auto delegate = std::make_shared<OpacityPeepholePassDelegate>(paint);
2226 ASSERT_FALSE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
2227
2228 paint.color_filter = nullptr;
2229 paint.image_filter = ImageFilter::MakeBlur(Sigma(1.0), Sigma(1.0),
2230 FilterContents::BlurStyle::kNormal,
2231 Entity::TileMode::kClamp);
2232
2233 // Paint has image filter, can't elide.
2234 delegate = std::make_shared<OpacityPeepholePassDelegate>(paint);
2235 ASSERT_FALSE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
2236
2237 paint.image_filter = nullptr;
2238 paint.color = Color::Red();
2239
2240 // Paint has no alpha, can't elide;
2241 delegate = std::make_shared<OpacityPeepholePassDelegate>(paint);
2242 ASSERT_FALSE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
2243
2244 // Positive test.
2245 Entity entity;
2246 entity.SetContents(SolidColorContents::Make(
2247 PathBuilder{}.AddRect(rect).TakePath(), Color::Red()));
2248 entity_pass->AddEntity(entity);
2249 paint.color = Color::Red().WithAlpha(0.5);
2250
2251 delegate = std::make_shared<OpacityPeepholePassDelegate>(paint);
2252 ASSERT_TRUE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
2253 }

References impeller::PathBuilder::AddRect(), impeller::Paint::color, impeller::Paint::color_filter, impeller::Paint::image_filter, impeller::Entity::SetContents(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [131/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | OpaqueEntitiesGetCoercedToSource |
| ) |  |

Definition at line 2817 of file aiks_unittests.cc.

2817 {
2818 Canvas canvas;
2819 canvas.Scale(Vector2(1.618, 1.618));
2820 canvas.DrawCircle(Point(), 10,
2821 {
2822 .color = Color::CornflowerBlue(),
2823 .blend_mode = BlendMode::kSourceOver,
2824 });
2825 Picture picture = canvas.EndRecordingAsPicture();
2826
2827 // Extract the SolidColorSource.
2828 Entity entity;
2829 std::shared_ptr<SolidColorContents> contents;
2830 picture.pass->IterateAllEntities([&e = entity, &contents](Entity& entity) {
2831 if (ScalarNearlyEqual(entity.GetTransformation().GetScale().x, 1.618f)) {
2832 e = entity;
2833 contents =
2834 std::static_pointer_cast<SolidColorContents>(entity.GetContents());
2835 return false;
2836 }
2837 return true;
2838 });
2839
2840 ASSERT_TRUE(contents->IsOpaque());
2841 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kSource);
2842 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::GetBlendMode(), impeller::Entity::GetContents(), impeller::Matrix::GetScale(), impeller::Entity::GetTransformation(), impeller::Picture::pass, impeller::ScalarNearlyEqual(), impeller::Canvas::Scale(), and impeller::Vector3::x.

## ◆ TEST_P() [132/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | PaintBlendModeIsRespected |
| ) |  |

Definition at line 1656 of file aiks_unittests.cc.

1656 {
1657 Paint paint;
1658 Canvas canvas;
1659 // Default is kSourceOver.
1660 paint.color = Color(1, 0, 0, 0.5);
1661 canvas.DrawCircle(Point(150, 200), 100, paint);
1662 paint.color = Color(0, 1, 0, 0.5);
1663 canvas.DrawCircle(Point(250, 200), 100, paint);
1664
1665 paint.blend_mode = BlendMode::kPlus;
1666 paint.color = Color::Red();
1667 canvas.DrawCircle(Point(450, 250), 100, paint);
1668 paint.color = Color::Green();
1669 canvas.DrawCircle(Point(550, 250), 100, paint);
1670 paint.color = Color::Blue();
1671 canvas.DrawCircle(Point(500, 150), 100, paint);
1672 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1673 }

References impeller::Paint::blend_mode, impeller::Paint::color, impeller::Canvas::DrawCircle(), and impeller::Canvas::EndRecordingAsPicture().

## ◆ TEST_P() [133/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | PaintWithFilters |
| ) |  |

Definition at line 2189 of file aiks_unittests.cc.

2189 {
2190 // validate that a paint with a color filter "HasFilters", no other filters
2191 // impact this setting.
2192 Paint paint;
2193
2194 ASSERT_FALSE(paint.HasColorFilter());
2195
2196 paint.color_filter =
2197 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Blue());
2198
2199 ASSERT_TRUE(paint.HasColorFilter());
2200
2201 paint.image_filter = ImageFilter::MakeBlur(Sigma(1.0), Sigma(1.0),
2202 FilterContents::BlurStyle::kNormal,
2203 Entity::TileMode::kClamp);
2204
2205 ASSERT_TRUE(paint.HasColorFilter());
2206
2207 paint.mask_blur_descriptor = {};
2208
2209 ASSERT_TRUE(paint.HasColorFilter());
2210
2211 paint.color_filter = nullptr;
2212
2213 ASSERT_FALSE(paint.HasColorFilter());
2214 }

References impeller::Paint::color_filter, impeller::Paint::HasColorFilter(), impeller::Paint::image_filter, and impeller::Paint::mask_blur_descriptor.

## ◆ TEST_P() [134/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ParentSaveLayerCreatesRenderPassWhenChildBackdropFilterIsPresent |
| ) |  |

Definition at line 2279 of file aiks_unittests.cc.

2280 {
2281 Canvas canvas;
2282 canvas.SaveLayer({}, std::nullopt, ImageFilter::MakeMatrix(Matrix(), {}));
2283 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
2284 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
2285 .blend_mode = BlendMode::kSourceOver});
2286 canvas.Restore();
2287
2288 Picture picture = canvas.EndRecordingAsPicture();
2289
2290 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
2291 std::shared_ptr<Context> real_context = GetContext();
2292 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
2293 AiksContext renderer(mock_context, nullptr);
2294 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
2295
2296 ASSERT_EQ(spy->render_passes_.size(), 3llu);
2297 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
2298 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
2299 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Picture::ToImage().

## ◆ TEST_P() [135/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | PipelineBlendSingleParameter |
| ) |  |

Definition at line 3417 of file aiks_unittests.cc.

3417 {
3418 Canvas canvas;
3419
3420 // Should render a green square in the middle of a blue circle.
3421 canvas.SaveLayer({});
3422 {
3423 canvas.Translate(Point(100, 100));
3424 canvas.DrawCircle(Point(200, 200), 200, {.color = Color::Blue()});
3425 canvas.ClipRect(Rect(100, 100, 200, 200));
3426 canvas.DrawCircle(Point(200, 200), 200,
3427 {
3428 .color = Color::Green(),
3429 .blend_mode = BlendMode::kSourceOver,
3430 .image_filter = ImageFilter::MakeFromColorFilter(
3431 *ColorFilter::MakeBlend(BlendMode::kDestination,
3432 Color::White())),
3433 });
3434 canvas.Restore();
3435 }
3436
3437 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3438 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Translate().

## ◆ TEST_P() [136/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | ReleasesTextureOnTeardown |
| ) |  |

Definition at line 3505 of file aiks_unittests.cc.

3505 {
3506 auto context = GetContext();
3507 std::weak_ptr<Texture> weak_texture;
3508
3509 {
3510 auto texture = CreateTextureForFixture("table_mountain_nx.png");
3511
3512 Canvas canvas;
3513 canvas.Scale(GetContentScale());
3514 canvas.Translate({100.0f, 100.0f, 0});
3515
3516 Paint paint;
3517 paint.color_source = ColorSource::MakeImage(
3518 texture, Entity::TileMode::kClamp, Entity::TileMode::kClamp, {}, {});
3519 canvas.DrawRect({0, 0, 600, 600}, paint);
3520
3521 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3522 }
3523
3524 // See https://github.com/flutter/flutter/issues/134751.
3525 //
3526 // If the fence waiter was working this may not be released by the end of the
3527 // scope above. Adding a manual shutdown so that future changes to the fence
3528 // waiter will not flake this test.
3529 context->Shutdown();
3530
3531 // The texture should be released by now.
3532 ASSERT_TRUE(weak_texture.expired()) << "When the texture is no longer in use "
3533 "by the backend, it should be "
3534 "released.";
3535 }

References impeller::Paint::color_source, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [137/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | RotateColorFilteredPath |
| ) |  |

Definition at line 56 of file aiks_unittests.cc.

56 {
57 Canvas canvas;
58 canvas.Concat(Matrix::MakeTranslation({300, 300}));
59 canvas.Concat(Matrix::MakeRotationZ(Radians(kPiOver2)));
60 auto arrow_stem =
61 PathBuilder{}.MoveTo({120, 190}).LineTo({120, 50}).TakePath();
62 auto arrow_head = PathBuilder{}
63 .MoveTo({50, 120})
64 .LineTo({120, 190})
65 .LineTo({190, 120})
66 .TakePath();
67 auto paint = Paint{
68 .stroke_width = 15.0,
69 .stroke_cap = Cap::kRound,
70 .stroke_join = Join::kRound,
71 .style = Paint::Style::kStroke,
72 .color_filter =
73 ColorFilter::MakeBlend(BlendMode::kSourceIn, Color::AliceBlue()),
74 };
75
76 canvas.DrawPath(arrow_stem, paint);
77 canvas.DrawPath(arrow_head, paint);
78 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
79 }

References impeller::Color::AliceBlue(), impeller::Canvas::Concat(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::kPiOver2, impeller::kRound, impeller::kSourceIn, impeller::Paint::kStroke, impeller::LineTo(), impeller::ColorFilter::MakeBlend(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeTranslation(), impeller::PathBuilder::MoveTo(), and impeller::Paint::stroke_width.

## ◆ TEST_P() [138/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SaveLayerDrawsBehindSubsequentEntities |
| ) |  |

Definition at line 2039 of file aiks_unittests.cc.

2039 {
2040 // Compare with https://fiddle.skia.org/c/9e03de8567ffb49e7e83f53b64bcf636
2041 Canvas canvas;
2042 Paint paint;
2043
2044 paint.color = Color::Black();
2045 Rect rect(25, 25, 25, 25);
2046 canvas.DrawRect(rect, paint);
2047
2048 canvas.Translate({10, 10});
2049 canvas.SaveLayer({});
2050
2051 paint.color = Color::Green();
2052 canvas.DrawRect(rect, paint);
2053
2054 canvas.Restore();
2055
2056 canvas.Translate({10, 10});
2057 paint.color = Color::Red();
2058 canvas.DrawRect(rect, paint);
2059
2060 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2061 }

References impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Translate().

## ◆ TEST_P() [139/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SaveLayerFiltersScaleWithTransform |
| ) |  |

Definition at line 2120 of file aiks_unittests.cc.

2120 {
2121 Canvas canvas;
2122 canvas.Scale(GetContentScale());
2123 canvas.Translate(Vector2(100, 100));
2124
2125 auto texture = std::make_shared<Image>(CreateTextureForFixture("boston.jpg"));
2126 auto draw_image_layer = [&canvas, &texture](const Paint& paint) {
2127 canvas.SaveLayer(paint);
2128 canvas.DrawImage(texture, {}, Paint{});
2129 canvas.Restore();
2130 };
2131
2132 Paint effect_paint;
2133 effect_paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
2134 .style = FilterContents::BlurStyle::kNormal,
2135 .sigma = Sigma{6},
2136 };
2137 draw_image_layer(effect_paint);
2138
2139 canvas.Translate(Vector2(300, 300));
2140 canvas.Scale(Vector2(3, 3));
2141 draw_image_layer(effect_paint);
2142
2143 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2144 }

References impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::mask_blur_descriptor, impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), impeller::Paint::MaskBlurDescriptor::style, and impeller::Canvas::Translate().

## ◆ TEST_P() [140/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SiblingSaveLayerBoundsAreRespected |
| ) |  |

Definition at line 2063 of file aiks_unittests.cc.

2063 {
2064 Canvas canvas;
2065 Paint paint;
2066 Rect rect(0, 0, 1000, 1000);
2067
2068 // Black, green, and red squares offset by [10, 10].
2069 {
2070 canvas.SaveLayer({}, Rect::MakeXYWH(25, 25, 25, 25));
2071 paint.color = Color::Black();
2072 canvas.DrawRect(rect, paint);
2073 canvas.Restore();
2074 }
2075
2076 {
2077 canvas.SaveLayer({}, Rect::MakeXYWH(35, 35, 25, 25));
2078 paint.color = Color::Green();
2079 canvas.DrawRect(rect, paint);
2080 canvas.Restore();
2081 }
2082
2083 {
2084 canvas.SaveLayer({}, Rect::MakeXYWH(45, 45, 25, 25));
2085 paint.color = Color::Red();
2086 canvas.DrawRect(rect, paint);
2087 canvas.Restore();
2088 }
2089
2090 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2091 }

References impeller::Paint::color, impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [141/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SolidColorApplyColorFilter |
| ) |  |

Definition at line 3353 of file aiks_unittests.cc.

3353 {
3354 auto contents = SolidColorContents();
3355 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.75));
3356 auto result = contents.ApplyColorFilter([](const Color& color) {
3357 return color.Blend(Color::LimeGreen().WithAlpha(0.75), BlendMode::kScreen);
3358 });
3359 ASSERT_TRUE(result);
3360 ASSERT_COLOR_NEAR(contents.GetColor(),
3361 Color(0.433247, 0.879523, 0.825324, 0.75));
3362 }

References ASSERT_COLOR_NEAR, and impeller::Color::Blend().

## ◆ TEST_P() [142/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SolidStrokesRenderCorrectly |
| ) |  |

Definition at line 1850 of file aiks_unittests.cc.

1850 {
1851 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
1852 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
1853 static Color color = Color::Black().WithAlpha(0.5);
1854 static float scale = 3;
1855 static bool add_circle_clip = true;
1856
1857 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1858 ImGui::ColorEdit4("Color", reinterpret_cast<float*>(&color));
1859 ImGui::SliderFloat("Scale", &scale, 0, 6);
1860 ImGui::Checkbox("Circle clip", &add_circle_clip);
1861 ImGui::End();
1862
1863 Canvas canvas;
1864 canvas.Scale(GetContentScale());
1865 Paint paint;
1866
1867 paint.color = Color::White();
1868 canvas.DrawPaint(paint);
1869
1870 paint.color = color;
1871 paint.style = Paint::Style::kStroke;
1872 paint.stroke_width = 10;
1873
1874 Path path = PathBuilder{}
1875 .MoveTo({20, 20})
1876 .QuadraticCurveTo({60, 20}, {60, 60})
1877 .Close()
1878 .MoveTo({60, 20})
1879 .QuadraticCurveTo({60, 60}, {20, 60})
1880 .TakePath();
1881
1882 canvas.Scale(Vector2(scale, scale));
1883
1884 if (add_circle_clip) {
1885 auto [handle_a, handle_b] = IMPELLER_PLAYGROUND_LINE(
1886 Point(60, 300), Point(600, 300), 20, Color::Red(), Color::Red());
1887
1888 auto screen_to_canvas = canvas.GetCurrentTransformation().Invert();
1889 Point point_a = screen_to_canvas * handle_a * GetContentScale();
1890 Point point_b = screen_to_canvas * handle_b * GetContentScale();
1891
1892 Point middle = (point_a + point_b) / 2;
1893 auto radius = point_a.GetDistance(middle);
1894 canvas.ClipPath(PathBuilder{}.AddCircle(middle, radius).TakePath());
1895 }
1896
1897 for (auto join : {Join::kBevel, Join::kRound, Join::kMiter}) {
1898 paint.stroke_join = join;
1899 for (auto cap : {Cap::kButt, Cap::kSquare, Cap::kRound}) {
1900 paint.stroke_cap = cap;
1901 canvas.DrawPath(path, paint);
1902 canvas.Translate({80, 0});
1903 }
1904 canvas.Translate({-240, 60});
1905 }
1906
1907 return canvas.EndRecordingAsPicture();
1908 };
1909
1910 ASSERT_TRUE(OpenPlaygroundHere(callback));
1911 }

References impeller::PathBuilder::AddCircle(), impeller::Canvas::ClipPath(), impeller::Close(), impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::GetCurrentTransformation(), impeller::TPoint< T >::GetDistance(), IMPELLER_PLAYGROUND_LINE, impeller::Matrix::Invert(), impeller::PathBuilder::MoveTo(), impeller::Canvas::Scale(), impeller::Paint::stroke_cap, impeller::Paint::stroke_join, impeller::Paint::stroke_width, impeller::Paint::style, impeller::PathBuilder::TakePath(), impeller::Canvas::Translate(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [143/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SrgbToLinearFilterSubpassCollapseOptimization |
| ) |  |

Definition at line 2509 of file aiks_unittests.cc.

2509 {
2510 Canvas canvas;
2511
2512 canvas.SaveLayer({
2513 .color_filter = ColorFilter::MakeSrgbToLinear(),
2514 });
2515
2516 canvas.Translate({500, 300, 0});
2517 canvas.Rotate(Radians(2 * kPi / 3));
2518 canvas.DrawRect({100, 100, 200, 200}, {.color = Color::Blue()});
2519
2520 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2521 }

References impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kPi, impeller::Canvas::Rotate(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Translate().

## ◆ TEST_P() [144/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | SubpassWithClearColorOptimization |
| ) |  |

Definition at line 3647 of file aiks_unittests.cc.

3647 {
3648 Canvas canvas;
3649
3650 // Use a non-srcOver blend mode to ensure that we don't detect this as an
3651 // opacity peephole optimization.
3652 canvas.SaveLayer(
3653 {.color = Color::Blue().WithAlpha(0.5), .blend_mode = BlendMode::kSource},
3654 Rect::MakeLTRB(0, 0, 200, 200));
3655 canvas.DrawPaint(
3656 {.color = Color::BlackTransparent(), .blend_mode = BlendMode::kSource});
3657 canvas.Restore();
3658
3659 canvas.SaveLayer(
3660 {.color = Color::Blue(), .blend_mode = BlendMode::kDestinationOver});
3661 canvas.Restore();
3662
3663 // This playground should appear blank on CI since we are only drawing
3664 // transparent black. If the clear color optimization is broken, the texture
3665 // will be filled with NaNs and may produce a magenta texture on macOS or iOS.
3666 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3667 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [145/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextForegroundShaderWithTransform |
| ) |  |

Definition at line 3171 of file aiks_unittests.cc.

3171 {
3172 auto mapping = OpenFixtureAsSkData("Roboto-Regular.ttf");
3173 ASSERT_NE(mapping, nullptr);
3174
3175 Scalar font_size = 100;
3176 SkFont sk_font(SkTypeface::MakeFromData(mapping), font_size);
3177
3178 Paint text_paint;
3179 text_paint.color = Color::Blue();
3180
3181 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
3182 Color{0.1294, 0.5882, 0.9529, 1.0}};
3183 std::vector<Scalar> stops = {
3184 0.0,
3185 1.0,
3186 };
3187 text_paint.color_source = ColorSource::MakeLinearGradient(
3188 {0, 0}, {100, 100}, std::move(colors), std::move(stops),
3189 Entity::TileMode::kRepeat, {});
3190
3191 Canvas canvas;
3192 canvas.Translate({100, 100});
3193 canvas.Rotate(Radians(kPi / 4));
3194
3195 auto blob = SkTextBlob::MakeFromString("Hello", sk_font);
3196 ASSERT_NE(blob, nullptr);
3197 auto frame = MakeTextFrameFromTextBlobSkia(blob);
3198 canvas.DrawTextFrame(frame, Point(), text_paint);
3199
3200 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3201 }

References impeller::Paint::color, impeller::Paint::color_source, impeller::kPi, impeller::MakeTextFrameFromTextBlobSkia(), OpenFixtureAsSkData(), and impeller::Canvas::Translate().

## ◆ TEST_P() [146/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextFrameSubpixelAlignment |
| ) |  |

Definition at line 1385 of file aiks_unittests.cc.

1385 {
1386 std::array<Scalar, 20> phase_offsets;
1387 for (Scalar& offset : phase_offsets) {
1388 auto rand = std::rand(); // NOLINT
1389 offset = (static_cast<float>(rand) / static_cast<float>(RAND_MAX)) * k2Pi;
1390 }
1391
1392 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
1393 static float font_size = 20;
1394 static float phase_variation = 0.2;
1395 static float speed = 0.5;
1396 static float magnitude = 100;
1397 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1398 ImGui::SliderFloat("Font size", &font_size, 5, 50);
1399 ImGui::SliderFloat("Phase variation", &phase_variation, 0, 1);
1400 ImGui::SliderFloat("Oscillation speed", &speed, 0, 2);
1401 ImGui::SliderFloat("Oscillation magnitude", &magnitude, 0, 300);
1402 ImGui::End();
1403
1404 Canvas canvas;
1405 canvas.Scale(GetContentScale());
1406
1407 for (size_t i = 0; i < phase_offsets.size(); i++) {
1408 auto position = Point(
1409 200 + magnitude * std::sin((-phase_offsets[i] * phase_variation +
1410 GetSecondsElapsed() * speed)), //
1411 200 + i * font_size * 1.1 //
1412 );
1413 if (!RenderTextInCanvasSkia(
1414 GetContext(), canvas,
1415 "the quick brown fox jumped over "
1416 "the lazy dog!.?",
1417 "Roboto-Regular.ttf",
1418 {.font_size = font_size, .position = position})) {
1419 return std::nullopt;
1420 }
1421 }
1422 return canvas.EndRecordingAsPicture();
1423 };
1424
1425 ASSERT_TRUE(OpenPlaygroundHere(callback));
1426 }

References impeller::Canvas::EndRecordingAsPicture(), impeller::k2Pi, RenderTextInCanvasSkia(), and impeller::Canvas::Scale().

## ◆ TEST_P() [147/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TextRotated |
| ) |  |

Definition at line 1526 of file aiks_unittests.cc.

1526 {
1527 Canvas canvas;
1528 canvas.Scale(GetContentScale());
1529 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
1530
1531 canvas.Transform(Matrix(0.25, -0.3, 0, -0.002, //
1532 0, 0.5, 0, 0, //
1533 0, 0, 0.3, 0, //
1534 100, 100, 0, 1.3));
1535 ASSERT_TRUE(RenderTextInCanvasSkia(
1536 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
1537 "Roboto-Regular.ttf"));
1538
1539 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1540 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), RenderTextInCanvasSkia(), impeller::Canvas::Scale(), and impeller::Canvas::Transform().

## ◆ TEST_P() [148/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TransformMultipliesCorrectly |
| ) |  |

Definition at line 1811 of file aiks_unittests.cc.

1811 {
1812 Canvas canvas;
1813 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransformation(), Matrix());
1814
1815 // clang-format off
1816 canvas.Translate(Vector3(100, 200));
1817 ASSERT_MATRIX_NEAR(
1818 canvas.GetCurrentTransformation(),
1819 Matrix( 1, 0, 0, 0,
1820 0, 1, 0, 0,
1821 0, 0, 1, 0,
1822 100, 200, 0, 1));
1823
1824 canvas.Rotate(Radians(kPiOver2));
1825 ASSERT_MATRIX_NEAR(
1826 canvas.GetCurrentTransformation(),
1827 Matrix( 0, 1, 0, 0,
1828 -1, 0, 0, 0,
1829 0, 0, 1, 0,
1830 100, 200, 0, 1));
1831
1832 canvas.Scale(Vector3(2, 3));
1833 ASSERT_MATRIX_NEAR(
1834 canvas.GetCurrentTransformation(),
1835 Matrix( 0, 2, 0, 0,
1836 -3, 0, 0, 0,
1837 0, 0, 0, 0,
1838 100, 200, 0, 1));
1839
1840 canvas.Translate(Vector3(100, 200));
1841 ASSERT_MATRIX_NEAR(
1842 canvas.GetCurrentTransformation(),
1843 Matrix( 0, 2, 0, 0,
1844 -3, 0, 0, 0,
1845 0, 0, 0, 0,
1846 -500, 400, 0, 1));
1847 // clang-format on
1848 }

References ASSERT_MATRIX_NEAR, impeller::Canvas::GetCurrentTransformation(), impeller::kPiOver2, impeller::Canvas::Rotate(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [149/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentSaveLayerDrawsCorrectly |
| ) |  |

Definition at line 2615 of file aiks_unittests.cc.

2615 {
2616 Canvas canvas;
2617
2618 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
2619
2620 canvas.SaveLayer({.color = Color::Black().WithAlpha(0.5)});
2621 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
2622 canvas.Restore();
2623
2624 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2625 }

References impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [150/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentSaveLayerImageDrawsCorrectly |
| ) |  |

Definition at line 2677 of file aiks_unittests.cc.

2677 {
2678 Canvas canvas;
2679
2680 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2681 canvas.DrawImage(image, {100, 100}, {});
2682
2683 canvas.SaveLayer({.color = Color::Black().WithAlpha(0.5)});
2684 canvas.DrawImage(image, {100, 500}, {});
2685 canvas.Restore();
2686
2687 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2688 }

References impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [151/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentSaveLayerWithAdvancedBlendModeDrawsCorrectly |
| ) |  |

Definition at line 2761 of file aiks_unittests.cc.

2761 {
2762 Canvas canvas;
2763 canvas.DrawRect({0, 0, 400, 400}, {.color = Color::Red()});
2764 canvas.SaveLayer({
2765 .color = Color::Black().WithAlpha(0.5),
2766 .blend_mode = BlendMode::kLighten,
2767 });
2768 canvas.DrawCircle({200, 200}, 100, {.color = Color::Green()});
2769 canvas.Restore();
2770 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2771 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [152/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentSaveLayerWithBlendColorFilterDrawsCorrectly |
| ) |  |

Definition at line 2627 of file aiks_unittests.cc.

2627 {
2628 Canvas canvas;
2629
2630 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
2631
2632 canvas.SaveLayer({
2633 .color = Color::Black().WithAlpha(0.5),
2634 .color_filter =
2635 ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red()),
2636 });
2637 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
2638 canvas.Restore();
2639
2640 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2641 }

References impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [153/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentSaveLayerWithBlendImageFilterDrawsCorrectly |
| ) |  |

Definition at line 2643 of file aiks_unittests.cc.

2643 {
2644 Canvas canvas;
2645
2646 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
2647
2648 canvas.SaveLayer({
2649 .color = Color::Black().WithAlpha(0.5),
2650 .image_filter = ImageFilter::MakeFromColorFilter(
2651 *ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red())),
2652 });
2653
2654 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
2655 canvas.Restore();
2656
2657 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2658 }

References impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [154/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentSaveLayerWithColorAndImageFilterDrawsCorrectly |
| ) |  |

Definition at line 2660 of file aiks_unittests.cc.

2660 {
2661 Canvas canvas;
2662
2663 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
2664
2665 canvas.SaveLayer({
2666 .color = Color::Black().WithAlpha(0.5),
2667 .color_filter =
2668 ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red()),
2669 });
2670
2671 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
2672 canvas.Restore();
2673
2674 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2675 }

References impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [155/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentSaveLayerWithColorFilterAndImageFilterDrawsCorrectly |
| ) |  |

Definition at line 2735 of file aiks_unittests.cc.

2736 {
2737 Canvas canvas;
2738
2739 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2740 canvas.DrawImage(image, {100, 100}, {});
2741
2742 canvas.SaveLayer({
2743 .color = Color::Black().WithAlpha(0.5),
2744 .image_filter = ImageFilter::MakeFromColorFilter(
2745 *ColorFilter::MakeMatrix({.array =
2746 {
2747 1, 0, 0, 0, 0, //
2748 0, 1, 0, 0, 0, //
2749 0, 0.2, 1, 0, 0, //
2750 0, 0, 0, 0.5, 0 //
2751 }})),
2752 .color_filter =
2753 ColorFilter::MakeBlend(BlendMode::kModulate, Color::Green()),
2754 });
2755 canvas.DrawImage(image, {100, 500}, {});
2756 canvas.Restore();
2757
2758 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2759 }

References impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [156/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentSaveLayerWithColorMatrixColorFilterDrawsCorrectly |
| ) |  |

Definition at line 2690 of file aiks_unittests.cc.

2690 {
2691 Canvas canvas;
2692
2693 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2694 canvas.DrawImage(image, {100, 100}, {});
2695
2696 canvas.SaveLayer({
2697 .color = Color::Black().WithAlpha(0.5),
2698 .color_filter = ColorFilter::MakeMatrix({.array =
2699 {
2700 1, 0, 0, 0, 0, //
2701 0, 1, 0, 0, 0, //
2702 0, 0, 1, 0, 0, //
2703 0, 0, 0, 2, 0 //
2704 }}),
2705 });
2706 canvas.DrawImage(image, {100, 500}, {});
2707 canvas.Restore();
2708
2709 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2710 }

References impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [157/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | TranslucentSaveLayerWithColorMatrixImageFilterDrawsCorrectly |
| ) |  |

Definition at line 2712 of file aiks_unittests.cc.

2712 {
2713 Canvas canvas;
2714
2715 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2716 canvas.DrawImage(image, {100, 100}, {});
2717
2718 canvas.SaveLayer({
2719 .color = Color::Black().WithAlpha(0.5),
2720 .image_filter = ImageFilter::MakeFromColorFilter(
2721 *ColorFilter::MakeMatrix({.array =
2722 {
2723 1, 0, 0, 0, 0, //
2724 0, 1, 0, 0, 0, //
2725 0, 0, 1, 0, 0, //
2726 0, 0, 0, 2, 0 //
2727 }})),
2728 });
2729 canvas.DrawImage(image, {100, 500}, {});
2730 canvas.Restore();
2731
2732 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2733 }

References impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [158/317]

impeller::testing::TEST_P | ( | AiksTest | ,
|  | VerticesGeometryUVPositionData |
| ) |  |

Definition at line 3538 of file aiks_unittests.cc.

3538 {
3539 Canvas canvas;
3540 Paint paint;
3541 auto texture = CreateTextureForFixture("table_mountain_nx.png");
3542
3543 paint.color_source = ColorSource::MakeImage(texture, Entity::TileMode::kClamp,
3544 Entity::TileMode::kClamp, {}, {});
3545
3546 auto vertices = {Point(0, 0), Point(texture->GetSize().width, 0),
3547 Point(0, texture->GetSize().height)};
3548 std::vector<uint16_t> indices = {0u, 1u, 2u};
3549 std::vector<Point> texture_coordinates = {};
3550 std::vector<Color> vertex_colors = {};
3551 auto geometry = std::make_shared<VerticesGeometry>(
3552 vertices, indices, texture_coordinates, vertex_colors,
3553 Rect::MakeLTRB(0, 0, 1, 1), VerticesGeometry::VertexMode::kTriangleStrip);
3554
3555 canvas.DrawVertices(geometry, BlendMode::kSourceOver, paint);
3556 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
3557 }

References impeller::Paint::color_source, impeller::Canvas::DrawVertices(), and impeller::Canvas::EndRecordingAsPicture().

## ◆ TEST_P() [159/317]

impeller::testing::TEST_P | ( | ComputeSubgroupTest | ,
|  | CapabilitiesSuportSubgroups |
| ) |  |

Definition at line 42 of file compute_subgroup_unittests.cc.

42 {
43 auto context = GetContext();
44 ASSERT_TRUE(context);
45 ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups());
46 }

## ◆ TEST_P() [160/317]

impeller::testing::TEST_P | ( | ComputeSubgroupTest | ,
|  | LargePath |
| ) |  |

Definition at line 179 of file compute_subgroup_unittests.cc.

179 {
180 // The path in here is large enough to highlight issues around exceeding
181 // subgroup size.
182 using SS = StrokeComputeShader;
183
184 auto context = GetContext();
185 ASSERT_TRUE(context);
186 ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups());
187 size_t vertex_count = 0;
188 Scalar stroke_width = 1.0;
189
190 auto vertex_buffer = CreateHostVisibleDeviceBuffer<SS::VertexBuffer<2048>>(
191 context, "VertexBuffer");
192 auto vertex_buffer_count =
193 CreateHostVisibleDeviceBuffer<SS::VertexBufferCount>(context,
194 "VertexCount");
195
196 auto complex_path =
197 PathBuilder{}
198 .MoveTo({359.934, 96.6335})
199 .CubicCurveTo({358.189, 96.7055}, {356.436, 96.7908},
200 {354.673, 96.8895})
201 .CubicCurveTo({354.571, 96.8953}, {354.469, 96.9016},
202 {354.367, 96.9075})
203 .CubicCurveTo({352.672, 97.0038}, {350.969, 97.113},
204 {349.259, 97.2355})
205 .CubicCurveTo({349.048, 97.2506}, {348.836, 97.2678},
206 {348.625, 97.2834})
207 .CubicCurveTo({347.019, 97.4014}, {345.407, 97.5299},
208 {343.789, 97.6722})
209 .CubicCurveTo({343.428, 97.704}, {343.065, 97.7402},
210 {342.703, 97.7734})
211 .CubicCurveTo({341.221, 97.9086}, {339.736, 98.0505},
212 {338.246, 98.207})
213 .CubicCurveTo({337.702, 98.2642}, {337.156, 98.3292},
214 {336.612, 98.3894})
215 .CubicCurveTo({335.284, 98.5356}, {333.956, 98.6837},
216 {332.623, 98.8476})
217 .CubicCurveTo({332.495, 98.8635}, {332.366, 98.8818},
218 {332.237, 98.8982})
219 .LineTo({332.237, 102.601})
220 .LineTo({321.778, 102.601})
221 .LineTo({321.778, 100.382})
222 .CubicCurveTo({321.572, 100.413}, {321.367, 100.442},
223 {321.161, 100.476})
224 .CubicCurveTo({319.22, 100.79}, {317.277, 101.123},
225 {315.332, 101.479})
226 .CubicCurveTo({315.322, 101.481}, {315.311, 101.482},
227 {315.301, 101.484})
228 .LineTo({310.017, 105.94})
229 .LineTo({309.779, 105.427})
230 .LineTo({314.403, 101.651})
231 .CubicCurveTo({314.391, 101.653}, {314.379, 101.656},
232 {314.368, 101.658})
233 .CubicCurveTo({312.528, 102.001}, {310.687, 102.366},
234 {308.846, 102.748})
235 .CubicCurveTo({307.85, 102.955}, {306.855, 103.182}, {305.859, 103.4})
236 .CubicCurveTo({305.048, 103.579}, {304.236, 103.75},
237 {303.425, 103.936})
238 .LineTo({299.105, 107.578})
239 .LineTo({298.867, 107.065})
240 .LineTo({302.394, 104.185})
241 .LineTo({302.412, 104.171})
242 .CubicCurveTo({301.388, 104.409}, {300.366, 104.67},
243 {299.344, 104.921})
244 .CubicCurveTo({298.618, 105.1}, {297.89, 105.269}, {297.165, 105.455})
245 .CubicCurveTo({295.262, 105.94}, {293.36, 106.445},
246 {291.462, 106.979})
247 .CubicCurveTo({291.132, 107.072}, {290.802, 107.163},
248 {290.471, 107.257})
249 .CubicCurveTo({289.463, 107.544}, {288.455, 107.839},
250 {287.449, 108.139})
251 .CubicCurveTo({286.476, 108.431}, {285.506, 108.73},
252 {284.536, 109.035})
253 .CubicCurveTo({283.674, 109.304}, {282.812, 109.579},
254 {281.952, 109.859})
255 .CubicCurveTo({281.177, 110.112}, {280.406, 110.377},
256 {279.633, 110.638})
257 .CubicCurveTo({278.458, 111.037}, {277.256, 111.449},
258 {276.803, 111.607})
259 .CubicCurveTo({276.76, 111.622}, {276.716, 111.637},
260 {276.672, 111.653})
261 .CubicCurveTo({275.017, 112.239}, {273.365, 112.836},
262 {271.721, 113.463})
263 .LineTo({271.717, 113.449})
264 .CubicCurveTo({271.496, 113.496}, {271.238, 113.559},
265 {270.963, 113.628})
266 .CubicCurveTo({270.893, 113.645}, {270.822, 113.663},
267 {270.748, 113.682})
268 .CubicCurveTo({270.468, 113.755}, {270.169, 113.834},
269 {269.839, 113.926})
270 .CubicCurveTo({269.789, 113.94}, {269.732, 113.957},
271 {269.681, 113.972})
272 .CubicCurveTo({269.391, 114.053}, {269.081, 114.143},
273 {268.756, 114.239})
274 .CubicCurveTo({268.628, 114.276}, {268.5, 114.314},
275 {268.367, 114.354})
276 .CubicCurveTo({268.172, 114.412}, {267.959, 114.478},
277 {267.752, 114.54})
278 .CubicCurveTo({263.349, 115.964}, {258.058, 117.695},
279 {253.564, 119.252})
280 .CubicCurveTo({253.556, 119.255}, {253.547, 119.258},
281 {253.538, 119.261})
282 .CubicCurveTo({251.844, 119.849}, {250.056, 120.474},
283 {248.189, 121.131})
284 .CubicCurveTo({248, 121.197}, {247.812, 121.264}, {247.621, 121.331})
285 .CubicCurveTo({247.079, 121.522}, {246.531, 121.715},
286 {245.975, 121.912})
287 .CubicCurveTo({245.554, 122.06}, {245.126, 122.212},
288 {244.698, 122.364})
289 .CubicCurveTo({244.071, 122.586}, {243.437, 122.811},
290 {242.794, 123.04})
291 .CubicCurveTo({242.189, 123.255}, {241.58, 123.472},
292 {240.961, 123.693})
293 .CubicCurveTo({240.659, 123.801}, {240.357, 123.909},
294 {240.052, 124.018})
295 .CubicCurveTo({239.12, 124.351}, {238.18, 124.687}, {237.22, 125.032})
296 .LineTo({237.164, 125.003})
297 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
298 {235.81, 125.538})
299 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
300 {234.592, 125.977})
301 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
302 {234.59, 125.977})
303 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
304 {192.381, 141.429})
305 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
306 .LineTo({360, 160})
307 .LineTo({360, 119.256})
308 .LineTo({360, 106.332})
309 .LineTo({360, 96.6307})
310 .CubicCurveTo({359.978, 96.6317}, {359.956, 96.6326},
311 {359.934, 96.6335})
312 .Close()
313 .TakePath();
314
315 auto callback = [&](RenderPass& pass) -> bool {
316 ::memset(vertex_buffer_count->AsBufferView().contents, 0,
317 sizeof(SS::VertexBufferCount));
318 ::memset(vertex_buffer->AsBufferView().contents, 0,
319 sizeof(SS::VertexBuffer<2048>));
320
321 ComputeTessellator{}
322 .SetStrokeWidth(stroke_width)
323 .Tessellate(
324 complex_path, context, vertex_buffer->AsBufferView(),
325 vertex_buffer_count->AsBufferView(),
326 [vertex_buffer_count, &vertex_count](CommandBuffer::Status status) {
327 vertex_count = reinterpret_cast<SS::VertexBufferCount*>(
328 vertex_buffer_count->AsBufferView().contents)
329 ->count;
330 });
331
332 ContentContext renderer(context, nullptr);
333 if (!renderer.IsValid()) {
334 return false;
335 }
336
337 using VS = SolidFillPipeline::VertexShader;
338
339 Command cmd;
340 DEBUG_COMMAND_INFO(cmd, "Draw Stroke");
341 cmd.stencil_reference = 0;
342
343 ContentContextOptions options;
344 options.sample_count = pass.GetRenderTarget().GetSampleCount();
345 options.color_attachment_pixel_format =
346 pass.GetRenderTarget().GetRenderTargetPixelFormat();
347 options.has_stencil_attachment =
348 pass.GetRenderTarget().GetStencilAttachment().has_value();
349 options.blend_mode = BlendMode::kSourceIn;
350 options.primitive_type = PrimitiveType::kTriangleStrip;
351 options.stencil_compare = CompareFunction::kEqual;
352 options.stencil_operation = StencilOperation::kIncrementClamp;
353
354 cmd.pipeline = renderer.GetSolidFillPipeline(options);
355
356 auto count = reinterpret_cast<SS::VertexBufferCount*>(
357 vertex_buffer_count->AsBufferView().contents)
358 ->count;
359
360 VertexBuffer render_vertex_buffer{
361 .vertex_buffer = vertex_buffer->AsBufferView(),
362 .vertex_count = count,
363 .index_type = IndexType::kNone};
364 cmd.BindVertices(render_vertex_buffer);
365
366 VS::FrameInfo frame_info;
367 auto world_matrix = Matrix::MakeScale(GetContentScale());
368 frame_info.mvp =
369 Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * world_matrix;
370 frame_info.color = Color::Red().Premultiply();
371 VS::BindFrameInfo(cmd,
372 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
373
374 if (!pass.AddCommand(std::move(cmd))) {
375 return false;
376 }
377
378 return true;
379 };
380 ASSERT_TRUE(OpenPlaygroundHere(callback));
381 }

References impeller::Command::BindVertices(), impeller::ContentContextOptions::blend_mode, impeller::Close(), impeller::ContentContextOptions::color_attachment_pixel_format, DEBUG_COMMAND_INFO, impeller::ContentContext::GetSolidFillPipeline(), impeller::ContentContextOptions::has_stencil_attachment, impeller::ContentContext::IsValid(), impeller::kEqual, impeller::kIncrementClamp, impeller::kNone, impeller::kSourceIn, impeller::kTriangleStrip, impeller::LineTo(), impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Command::pipeline, impeller::Color::Premultiply(), impeller::ContentContextOptions::primitive_type, impeller::Color::Red(), impeller::ContentContextOptions::sample_count, impeller::ComputeTessellator::SetStrokeWidth(), impeller::ContentContextOptions::stencil_compare, impeller::ContentContextOptions::stencil_operation, impeller::Command::stencil_reference, impeller::ComputeTessellator::Tessellate(), and impeller::VertexBuffer::vertex_buffer.

## ◆ TEST_P() [161/317]

impeller::testing::TEST_P | ( | ComputeSubgroupTest | ,
|  | PathPlayground |
| ) |  |

Definition at line 48 of file compute_subgroup_unittests.cc.

48 {
49 // Renders stroked SVG paths in an interactive playground.
50 using SS = StrokeComputeShader;
51
52 auto context = GetContext();
53 ASSERT_TRUE(context);
54 ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups());
55 char svg_path_data[16384] =
56 "M140 20 "
57 "C73 20 20 74 20 140 "
58 "c0 135 136 170 228 303 "
59 "88-132 229-173 229-303 "
60 "0-66-54-120-120-120 "
61 "-48 0-90 28-109 69 "
62 "-19-41-60-69-108-69z";
63 size_t vertex_count = 0;
64 Scalar stroke_width = 1.0;
65
66 auto vertex_buffer = CreateHostVisibleDeviceBuffer<SS::VertexBuffer<2048>>(
67 context, "VertexBuffer");
68 auto vertex_buffer_count =
69 CreateHostVisibleDeviceBuffer<SS::VertexBufferCount>(context,
70 "VertexCount");
71
72 auto callback = [&](RenderPass& pass) -> bool {
73 ::memset(vertex_buffer_count->AsBufferView().contents, 0,
74 sizeof(SS::VertexBufferCount));
75 ::memset(vertex_buffer->AsBufferView().contents, 0,
76 sizeof(SS::VertexBuffer<2048>));
77 const auto* main_viewport = ImGui::GetMainViewport();
78 ImGui::SetNextWindowPos(
79 ImVec2(main_viewport->WorkPos.x + 650, main_viewport->WorkPos.y + 20));
80 ImGui::Begin("Path data", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
81 ImGui::InputTextMultiline("Path", svg_path_data,
82 IM_ARRAYSIZE(svg_path_data));
83 ImGui::DragFloat("Stroke width", &stroke_width, .1, 0.0, 25.0);
84
85 SkPath sk_path;
86 if (SkParsePath::FromSVGString(svg_path_data, &sk_path)) {
87 std::promise<bool> promise;
88 auto future = promise.get_future();
89
90 auto path = skia_conversions::ToPath(sk_path);
91 auto status =
92 ComputeTessellator{}
93 .SetStrokeWidth(stroke_width)
94 .Tessellate(
95 path, context, vertex_buffer->AsBufferView(),
96 vertex_buffer_count->AsBufferView(),
97 [vertex_buffer_count, &vertex_count,
98 &promise](CommandBuffer::Status status) {
99 vertex_count =
100 reinterpret_cast<SS::VertexBufferCount*>(
101 vertex_buffer_count->AsBufferView().contents)
102 ->count;
103 promise.set_value(status ==
104 CommandBuffer::Status::kCompleted);
105 });
106 switch (status) {
107 case ComputeTessellator::Status::kCommandInvalid:
108 ImGui::Text("Failed to submit compute job (invalid command)");
109 break;
110 case ComputeTessellator::Status::kTooManyComponents:
111 ImGui::Text("Failed to submit compute job (too many components) ");
112 break;
113 case ComputeTessellator::Status::kOk:
114 break;
115 }
116 if (!future.get()) {
117 ImGui::Text("Failed to submit compute job.");
118 return false;
119 }
120 if (vertex_count > 0) {
121 ImGui::Text("Vertex count: %zu", vertex_count);
122 }
123 } else {
124 ImGui::Text("Failed to parse path data");
125 }
126 ImGui::End();
127
128 ContentContext renderer(context, nullptr);
129 if (!renderer.IsValid()) {
130 return false;
131 }
132
133 using VS = SolidFillPipeline::VertexShader;
134
135 Command cmd;
136 DEBUG_COMMAND_INFO(cmd, "Draw Stroke");
137 cmd.stencil_reference = 0;
138
139 ContentContextOptions options;
140 options.sample_count = pass.GetRenderTarget().GetSampleCount();
141 options.color_attachment_pixel_format =
142 pass.GetRenderTarget().GetRenderTargetPixelFormat();
143 options.has_stencil_attachment =
144 pass.GetRenderTarget().GetStencilAttachment().has_value();
145 options.blend_mode = BlendMode::kSourceIn;
146 options.primitive_type = PrimitiveType::kTriangleStrip;
147 options.stencil_compare = CompareFunction::kEqual;
148 options.stencil_operation = StencilOperation::kIncrementClamp;
149
150 cmd.pipeline = renderer.GetSolidFillPipeline(options);
151
152 auto count = reinterpret_cast<SS::VertexBufferCount*>(
153 vertex_buffer_count->AsBufferView().contents)
154 ->count;
155
156 VertexBuffer render_vertex_buffer{
157 .vertex_buffer = vertex_buffer->AsBufferView(),
158 .vertex_count = count,
159 .index_type = IndexType::kNone};
160 cmd.BindVertices(render_vertex_buffer);
161
162 VS::FrameInfo frame_info;
163 auto world_matrix = Matrix::MakeScale(GetContentScale());
164 frame_info.mvp =
165 Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * world_matrix;
166 frame_info.color = Color::Red().Premultiply();
167 VS::BindFrameInfo(cmd,
168 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
169
170 if (!pass.AddCommand(std::move(cmd))) {
171 return false;
172 }
173
174 return true;
175 };
176 ASSERT_TRUE(OpenPlaygroundHere(callback));
177 }

References impeller::Command::BindVertices(), impeller::ContentContextOptions::blend_mode, impeller::ContentContextOptions::color_attachment_pixel_format, DEBUG_COMMAND_INFO, impeller::ContentContext::GetSolidFillPipeline(), impeller::ContentContextOptions::has_stencil_attachment, impeller::ContentContext::IsValid(), impeller::ComputeTessellator::kCommandInvalid, impeller::kEqual, impeller::kIncrementClamp, impeller::kNone, impeller::ComputeTessellator::kOk, impeller::kSourceIn, impeller::ComputeTessellator::kTooManyComponents, impeller::kTriangleStrip, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::Command::pipeline, impeller::Color::Premultiply(), impeller::ContentContextOptions::primitive_type, impeller::Color::Red(), impeller::ContentContextOptions::sample_count, impeller::ComputeTessellator::SetStrokeWidth(), impeller::ContentContextOptions::stencil_compare, impeller::ContentContextOptions::stencil_operation, impeller::Command::stencil_reference, impeller::ComputeTessellator::Tessellate(), impeller::skia_conversions::ToPath(), and impeller::VertexBuffer::vertex_buffer.

## ◆ TEST_P() [162/317]

impeller::testing::TEST_P | ( | ComputeSubgroupTest | ,
|  | QuadAndCubicInOnePath |
| ) |  |

Definition at line 383 of file compute_subgroup_unittests.cc.

383 {
384 using SS = StrokeComputeShader;
385
386 auto context = GetContext();
387 ASSERT_TRUE(context);
388 ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups());
389
390 auto vertex_buffer = CreateHostVisibleDeviceBuffer<SS::VertexBuffer<2048>>(
391 context, "VertexBuffer");
392 auto vertex_buffer_count =
393 CreateHostVisibleDeviceBuffer<SS::VertexBufferCount>(context,
394 "VertexBufferCount");
395
396 auto path = PathBuilder{}
397 .AddCubicCurve({140, 20}, {73, 20}, {20, 74}, {20, 140})
398 .AddQuadraticCurve({20, 140}, {93, 90}, {100, 42})
399 .TakePath();
400
401 auto tessellator = ComputeTessellator{};
402
403 fml::AutoResetWaitableEvent latch;
404
405 auto status = tessellator.Tessellate(
406 path, context, vertex_buffer->AsBufferView(),
407 vertex_buffer_count->AsBufferView(),
408 [&latch](CommandBuffer::Status status) {
409 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
410 latch.Signal();
411 });
412
413 ASSERT_EQ(status, ComputeTessellator::Status::kOk);
414
415 auto callback = [&](RenderPass& pass) -> bool {
416 ContentContext renderer(context, nullptr);
417 if (!renderer.IsValid()) {
418 return false;
419 }
420
421 using VS = SolidFillPipeline::VertexShader;
422
423 Command cmd;
424 DEBUG_COMMAND_INFO(cmd, "Draw Stroke");
425 cmd.stencil_reference = 0;
426
427 ContentContextOptions options;
428 options.sample_count = pass.GetRenderTarget().GetSampleCount();
429 options.color_attachment_pixel_format =
430 pass.GetRenderTarget().GetRenderTargetPixelFormat();
431 options.has_stencil_attachment =
432 pass.GetRenderTarget().GetStencilAttachment().has_value();
433 options.blend_mode = BlendMode::kSourceIn;
434 options.primitive_type = PrimitiveType::kTriangleStrip;
435 options.stencil_compare = CompareFunction::kEqual;
436 options.stencil_operation = StencilOperation::kIncrementClamp;
437
438 cmd.pipeline = renderer.GetSolidFillPipeline(options);
439
440 auto count = reinterpret_cast<SS::VertexBufferCount*>(
441 vertex_buffer_count->AsBufferView().contents)
442 ->count;
443
444 VertexBuffer render_vertex_buffer{
445 .vertex_buffer = vertex_buffer->AsBufferView(),
446 .vertex_count = count,
447 .index_type = IndexType::kNone};
448 cmd.BindVertices(render_vertex_buffer);
449
450 VS::FrameInfo frame_info;
451 auto world_matrix = Matrix::MakeScale(GetContentScale());
452 frame_info.mvp =
453 Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * world_matrix;
454 frame_info.color = Color::Red().Premultiply();
455 VS::BindFrameInfo(cmd,
456 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
457
458 if (!pass.AddCommand(std::move(cmd))) {
459 return false;
460 }
461
462 return true;
463 };
464 ASSERT_TRUE(OpenPlaygroundHere(callback));
465
466 // The latch is down here because it's expected that on Metal the backend
467 // will take care of synchronizing the buffer between the compute and render
468 // pass usages, since it's not MTLHeap allocated. However, if playgrounds
469 // are disabled, no render pass actually gets submitted and we need to do a
470 // CPU latch here.
471 latch.Wait();
472
473 auto vertex_count = reinterpret_cast<SS::VertexBufferCount*>(
474 vertex_buffer_count->AsBufferView().contents)
475 ->count;
476 EXPECT_EQ(vertex_count, golden_cubic_and_quad_points.size());
477 auto vertex_buffer_data = reinterpret_cast<SS::VertexBuffer<2048>*>(
478 vertex_buffer->AsBufferView().contents);
479 for (size_t i = 0; i < vertex_count; i++) {
480 EXPECT_LT(std::abs(golden_cubic_and_quad_points[i].x -
481 vertex_buffer_data->position[i].x),
482 1e-3);
483 EXPECT_LT(std::abs(golden_cubic_and_quad_points[i].y -
484 vertex_buffer_data->position[i].y),
485 1e-3);
486 }
487 }

References impeller::PathBuilder::AddCubicCurve(), impeller::Command::BindVertices(), impeller::ContentContextOptions::blend_mode, impeller::ContentContextOptions::color_attachment_pixel_format, DEBUG_COMMAND_INFO, impeller::ContentContext::GetSolidFillPipeline(), golden_cubic_and_quad_points, impeller::ContentContextOptions::has_stencil_attachment, impeller::ContentContext::IsValid(), impeller::kEqual, impeller::kIncrementClamp, impeller::kNone, impeller::ComputeTessellator::kOk, impeller::kSourceIn, impeller::kTriangleStrip, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::Command::pipeline, impeller::Color::Premultiply(), impeller::ContentContextOptions::primitive_type, impeller::Color::Red(), impeller::ContentContextOptions::sample_count, impeller::ContentContextOptions::stencil_compare, impeller::ContentContextOptions::stencil_operation, impeller::Command::stencil_reference, impeller::ComputeTessellator::Tessellate(), and impeller::VertexBuffer::vertex_buffer.

## ◆ TEST_P() [163/317]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | 1DThreadgroupSizingIsCorrect |
| ) |  |

Definition at line 178 of file compute_unittests.cc.

178 {
179 using CS = ThreadgroupSizingTestComputeShader;
180 auto context = GetContext();
181 ASSERT_TRUE(context);
182 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
183
184 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
185 auto pipeline_desc =
186 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
187 ASSERT_TRUE(pipeline_desc.has_value());
188 auto compute_pipeline =
189 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
190 ASSERT_TRUE(compute_pipeline);
191
192 auto cmd_buffer = context->CreateCommandBuffer();
193 auto pass = cmd_buffer->CreateComputePass();
194 ASSERT_TRUE(pass && pass->IsValid());
195
196 static constexpr size_t kCount = 2048;
197
198 pass->SetGridSize(ISize(kCount, 1));
199 pass->SetThreadGroupSize(ISize(kCount, 1));
200
201 ComputeCommand cmd;
202 cmd.pipeline = compute_pipeline;
203
204 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
205 context, "Output Buffer");
206
207 CS::BindOutputData(cmd, output_buffer->AsBufferView());
208
209 ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
210 ASSERT_TRUE(pass->EncodeCommands());
211
212 fml::AutoResetWaitableEvent latch;
213 ASSERT_TRUE(cmd_buffer->SubmitCommands(
214 [&latch, output_buffer](CommandBuffer::Status status) {
215 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
216
217 auto view = output_buffer->AsBufferView();
218 EXPECT_EQ(view.range.length, sizeof(CS::OutputData<kCount>));
219
220 CS::OutputData<kCount>* output =
221 reinterpret_cast<CS::OutputData<kCount>*>(view.contents);
222 EXPECT_TRUE(output);
223 EXPECT_EQ(output->data[kCount - 1], kCount - 1);
224 latch.Signal();
225 }));
226
227 latch.Wait();
228 }

References impeller::ComputeCommand::pipeline.

## ◆ TEST_P() [164/317]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanCompute1DimensionalData |
| ) |  |

Definition at line 373 of file compute_unittests.cc.

373 {
374 using CS = SampleComputeShader;
375 auto context = GetContext();
376 ASSERT_TRUE(context);
377 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
378
379 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
380 auto pipeline_desc =
381 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
382 ASSERT_TRUE(pipeline_desc.has_value());
383 auto compute_pipeline =
384 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
385 ASSERT_TRUE(compute_pipeline);
386
387 auto cmd_buffer = context->CreateCommandBuffer();
388 auto pass = cmd_buffer->CreateComputePass();
389 ASSERT_TRUE(pass && pass->IsValid());
390
391 static constexpr size_t kCount = 5;
392
393 pass->SetGridSize(ISize(kCount, 1));
394
395 ComputeCommand cmd;
396 cmd.pipeline = compute_pipeline;
397
398 CS::Info info{.count = kCount};
399 CS::Input0<kCount> input_0;
400 CS::Input1<kCount> input_1;
401 for (size_t i = 0; i < kCount; i++) {
402 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
403 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
404 }
405
406 input_0.fixed_array[1] = IPoint32(2, 2);
407 input_1.fixed_array[0] = UintPoint32(3, 3);
408 input_0.some_int = 5;
409 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
410
411 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
412 context, "Output Buffer");
413
414 CS::BindInfo(cmd, pass->GetTransientsBuffer().EmplaceUniform(info));
415 CS::BindInput0(cmd,
416 pass->GetTransientsBuffer().EmplaceStorageBuffer(input_0));
417 CS::BindInput1(cmd,
418 pass->GetTransientsBuffer().EmplaceStorageBuffer(input_1));
419 CS::BindOutput(cmd, output_buffer->AsBufferView());
420
421 ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
422 ASSERT_TRUE(pass->EncodeCommands());
423
424 fml::AutoResetWaitableEvent latch;
425 ASSERT_TRUE(
426 cmd_buffer->SubmitCommands([&latch, output_buffer, &input_0,
427 &input_1](CommandBuffer::Status status) {
428 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
429
430 auto view = output_buffer->AsBufferView();
431 EXPECT_EQ(view.range.length, sizeof(CS::Output<kCount>));
432
433 CS::Output<kCount>* output =
434 reinterpret_cast<CS::Output<kCount>*>(view.contents);
435 EXPECT_TRUE(output);
436 for (size_t i = 0; i < kCount; i++) {
437 Vector4 vector = output->elements[i];
438 Vector4 computed = input_0.elements[i] * input_1.elements[i];
439 EXPECT_EQ(vector, Vector4(computed.x + 2 + input_1.some_struct.i,
440 computed.y + 3 + input_1.some_struct.vf.x,
441 computed.z + 5 + input_1.some_struct.vf.y,
442 computed.w));
443 }
444 latch.Signal();
445 }));
446
447 latch.Wait();
448 }

References impeller::ComputeCommand::pipeline.

## ◆ TEST_P() [165/317]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanComputePrefixSum |
| ) |  |

Definition at line 113 of file compute_unittests.cc.

113 {
114 using CS = PrefixSumTestComputeShader;
115 auto context = GetContext();
116 ASSERT_TRUE(context);
117 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
118
119 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
120 auto pipeline_desc =
121 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
122 ASSERT_TRUE(pipeline_desc.has_value());
123 auto compute_pipeline =
124 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
125 ASSERT_TRUE(compute_pipeline);
126
127 auto cmd_buffer = context->CreateCommandBuffer();
128 auto pass = cmd_buffer->CreateComputePass();
129 ASSERT_TRUE(pass && pass->IsValid());
130
131 static constexpr size_t kCount = 5;
132
133 pass->SetGridSize(ISize(kCount, 1));
134 pass->SetThreadGroupSize(ISize(kCount, 1));
135
136 ComputeCommand cmd;
137 cmd.pipeline = compute_pipeline;
138
139 CS::InputData<kCount> input_data;
140 input_data.count = kCount;
141 for (size_t i = 0; i < kCount; i++) {
142 input_data.data[i] = 1 + i;
143 }
144
145 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
146 context, "Output Buffer");
147
148 CS::BindInputData(
149 cmd, pass->GetTransientsBuffer().EmplaceStorageBuffer(input_data));
150 CS::BindOutputData(cmd, output_buffer->AsBufferView());
151
152 ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
153 ASSERT_TRUE(pass->EncodeCommands());
154
155 fml::AutoResetWaitableEvent latch;
156 ASSERT_TRUE(cmd_buffer->SubmitCommands(
157 [&latch, output_buffer](CommandBuffer::Status status) {
158 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
159
160 auto view = output_buffer->AsBufferView();
161 EXPECT_EQ(view.range.length, sizeof(CS::OutputData<kCount>));
162
163 CS::OutputData<kCount>* output =
164 reinterpret_cast<CS::OutputData<kCount>*>(view.contents);
165 EXPECT_TRUE(output);
166
167 constexpr uint32_t expected[kCount] = {1, 3, 6, 10, 15};
168 for (size_t i = 0; i < kCount; i++) {
169 auto computed_sum = output->data[i];
170 EXPECT_EQ(computed_sum, expected[i]);
171 }
172 latch.Signal();
173 }));
174
175 latch.Wait();
176 }

References impeller::ComputeCommand::pipeline.

## ◆ TEST_P() [166/317]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanComputePrefixSumLargeInteractive |
| ) |  |

Definition at line 230 of file compute_unittests.cc.

230 {
231 using CS = PrefixSumTestComputeShader;
232
233 auto context = GetContext();
234 ASSERT_TRUE(context);
235 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
236
237 auto callback = [&](RenderPass& render_pass) -> bool {
238 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
239 auto pipeline_desc =
240 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
241 auto compute_pipeline =
242 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
243
244 auto cmd_buffer = context->CreateCommandBuffer();
245 auto pass = cmd_buffer->CreateComputePass();
246
247 static constexpr size_t kCount = 1023;
248
249 pass->SetGridSize(ISize(kCount, 1));
250
251 ComputeCommand cmd;
252 cmd.pipeline = compute_pipeline;
253
254 CS::InputData<kCount> input_data;
255 input_data.count = kCount;
256 for (size_t i = 0; i < kCount; i++) {
257 input_data.data[i] = 1 + i;
258 }
259
260 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
261 context, "Output Buffer");
262
263 CS::BindInputData(
264 cmd, pass->GetTransientsBuffer().EmplaceStorageBuffer(input_data));
265 CS::BindOutputData(cmd, output_buffer->AsBufferView());
266
267 pass->AddCommand(std::move(cmd));
268 pass->EncodeCommands();
269 return cmd_buffer->SubmitCommands();
270 };
271 ASSERT_TRUE(OpenPlaygroundHere(callback));
272 }

References impeller::ComputeCommand::pipeline.

## ◆ TEST_P() [167/317]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanCreateComputePass |
| ) |  |

Definition at line 35 of file compute_unittests.cc.

35 {
36 using CS = SampleComputeShader;
37 auto context = GetContext();
38 ASSERT_TRUE(context);
39 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
40
41 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
42 auto pipeline_desc =
43 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
44 ASSERT_TRUE(pipeline_desc.has_value());
45 auto compute_pipeline =
46 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
47 ASSERT_TRUE(compute_pipeline);
48
49 auto cmd_buffer = context->CreateCommandBuffer();
50 auto pass = cmd_buffer->CreateComputePass();
51 ASSERT_TRUE(pass && pass->IsValid());
52
53 static constexpr size_t kCount = 5;
54
55 pass->SetGridSize(ISize(kCount, 1));
56 pass->SetThreadGroupSize(ISize(kCount, 1));
57
58 ComputeCommand cmd;
59 cmd.pipeline = compute_pipeline;
60
61 CS::Info info{.count = kCount};
62 CS::Input0<kCount> input_0;
63 CS::Input1<kCount> input_1;
64 for (size_t i = 0; i < kCount; i++) {
65 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
66 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
67 }
68
69 input_0.fixed_array[1] = IPoint32(2, 2);
70 input_1.fixed_array[0] = UintPoint32(3, 3);
71 input_0.some_int = 5;
72 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
73
74 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
75 context, "Output Buffer");
76
77 CS::BindInfo(cmd, pass->GetTransientsBuffer().EmplaceUniform(info));
78 CS::BindInput0(cmd,
79 pass->GetTransientsBuffer().EmplaceStorageBuffer(input_0));
80 CS::BindInput1(cmd,
81 pass->GetTransientsBuffer().EmplaceStorageBuffer(input_1));
82 CS::BindOutput(cmd, output_buffer->AsBufferView());
83
84 ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
85 ASSERT_TRUE(pass->EncodeCommands());
86
87 fml::AutoResetWaitableEvent latch;
88 ASSERT_TRUE(
89 cmd_buffer->SubmitCommands([&latch, output_buffer, &input_0,
90 &input_1](CommandBuffer::Status status) {
91 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
92
93 auto view = output_buffer->AsBufferView();
94 EXPECT_EQ(view.range.length, sizeof(CS::Output<kCount>));
95
96 CS::Output<kCount>* output =
97 reinterpret_cast<CS::Output<kCount>*>(view.contents);
98 EXPECT_TRUE(output);
99 for (size_t i = 0; i < kCount; i++) {
100 Vector4 vector = output->elements[i];
101 Vector4 computed = input_0.elements[i] * input_1.elements[i];
102 EXPECT_EQ(vector, Vector4(computed.x + 2 + input_1.some_struct.i,
103 computed.y + 3 + input_1.some_struct.vf.x,
104 computed.z + 5 + input_1.some_struct.vf.y,
105 computed.w));
106 }
107 latch.Signal();
108 }));
109
110 latch.Wait();
111 }

References impeller::ComputeCommand::pipeline.

## ◆ TEST_P() [168/317]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CapabilitiesReportSupport |
| ) |  |

Definition at line 29 of file compute_unittests.cc.

29 {
30 auto context = GetContext();
31 ASSERT_TRUE(context);
32 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
33 }

## ◆ TEST_P() [169/317]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | MultiStageInputAndOutput |
| ) |  |

Definition at line 274 of file compute_unittests.cc.

274 {
275 using CS1 = Stage1ComputeShader;
276 using Stage1PipelineBuilder = ComputePipelineBuilder<CS1>;
277 using CS2 = Stage2ComputeShader;
278 using Stage2PipelineBuilder = ComputePipelineBuilder<CS2>;
279
280 auto context = GetContext();
281 ASSERT_TRUE(context);
282 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
283
284 auto pipeline_desc_1 =
285 Stage1PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
286 ASSERT_TRUE(pipeline_desc_1.has_value());
287 auto compute_pipeline_1 =
288 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_1).Get();
289 ASSERT_TRUE(compute_pipeline_1);
290
291 auto pipeline_desc_2 =
292 Stage2PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
293 ASSERT_TRUE(pipeline_desc_2.has_value());
294 auto compute_pipeline_2 =
295 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_2).Get();
296 ASSERT_TRUE(compute_pipeline_2);
297
298 auto cmd_buffer = context->CreateCommandBuffer();
299 auto pass = cmd_buffer->CreateComputePass();
300 ASSERT_TRUE(pass && pass->IsValid());
301
302 static constexpr size_t kCount1 = 5;
303 static constexpr size_t kCount2 = kCount1 * 2;
304
305 pass->SetGridSize(ISize(512, 1));
306 pass->SetThreadGroupSize(ISize(512, 1));
307
308 CS1::Input<kCount1> input_1;
309 input_1.count = kCount1;
310 for (size_t i = 0; i < kCount1; i++) {
311 input_1.elements[i] = i;
312 }
313
314 CS2::Input<kCount2> input_2;
315 input_2.count = kCount2;
316 for (size_t i = 0; i < kCount2; i++) {
317 input_2.elements[i] = i;
318 }
319
320 auto output_buffer_1 = CreateHostVisibleDeviceBuffer<CS1::Output<kCount2>>(
321 context, "Output Buffer Stage 1");
322 auto output_buffer_2 = CreateHostVisibleDeviceBuffer<CS2::Output<kCount2>>(
323 context, "Output Buffer Stage 2");
324
325 {
326 ComputeCommand cmd;
327 cmd.pipeline = compute_pipeline_1;
328
329 CS1::BindInput(cmd,
330 pass->GetTransientsBuffer().EmplaceStorageBuffer(input_1));
331 CS1::BindOutput(cmd, output_buffer_1->AsBufferView());
332
333 ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
334 }
335
336 {
337 ComputeCommand cmd;
338 cmd.pipeline = compute_pipeline_2;
339
340 CS1::BindInput(cmd, output_buffer_1->AsBufferView());
341 CS2::BindOutput(cmd, output_buffer_2->AsBufferView());
342 ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
343 }
344
345 ASSERT_TRUE(pass->EncodeCommands());
346
347 fml::AutoResetWaitableEvent latch;
348 ASSERT_TRUE(cmd_buffer->SubmitCommands([&latch, &output_buffer_1,
349 &output_buffer_2](
350 CommandBuffer::Status status) {
351 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
352
353 CS1::Output<kCount2>* output_1 = reinterpret_cast<CS1::Output<kCount2>*>(
354 output_buffer_1->AsBufferView().contents);
355 EXPECT_TRUE(output_1);
356 EXPECT_EQ(output_1->count, 10u);
357 EXPECT_THAT(output_1->elements,
358 ::testing::ElementsAre(0, 0, 2, 3, 4, 6, 6, 9, 8, 12));
359
360 CS2::Output<kCount2>* output_2 = reinterpret_cast<CS2::Output<kCount2>*>(
361 output_buffer_2->AsBufferView().contents);
362 EXPECT_TRUE(output_2);
363 EXPECT_EQ(output_2->count, 10u);
364 EXPECT_THAT(output_2->elements,
365 ::testing::ElementsAre(0, 0, 4, 6, 8, 12, 12, 18, 16, 24));
366
367 latch.Signal();
368 }));
369
370 latch.Wait();
371 }

References impeller::kCount1, and impeller::ComputeCommand::pipeline.

## ◆ TEST_P() [170/317]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | ReturnsEarlyWhenAnyGridDimensionIsZero |
| ) |  |

Definition at line 450 of file compute_unittests.cc.

450 {
451 using CS = SampleComputeShader;
452 auto context = GetContext();
453 ASSERT_TRUE(context);
454 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
455
456 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
457 auto pipeline_desc =
458 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
459 ASSERT_TRUE(pipeline_desc.has_value());
460 auto compute_pipeline =
461 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
462 ASSERT_TRUE(compute_pipeline);
463
464 auto cmd_buffer = context->CreateCommandBuffer();
465 auto pass = cmd_buffer->CreateComputePass();
466 ASSERT_TRUE(pass && pass->IsValid());
467
468 static constexpr size_t kCount = 5;
469
470 // Intentionally making the grid size zero in one dimension. No GPU will
471 // tolerate this.
472 pass->SetGridSize(ISize(0, 1));
473 pass->SetThreadGroupSize(ISize(0, 1));
474
475 ComputeCommand cmd;
476 cmd.pipeline = compute_pipeline;
477
478 CS::Info info{.count = kCount};
479 CS::Input0<kCount> input_0;
480 CS::Input1<kCount> input_1;
481 for (size_t i = 0; i < kCount; i++) {
482 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
483 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
484 }
485
486 input_0.fixed_array[1] = IPoint32(2, 2);
487 input_1.fixed_array[0] = UintPoint32(3, 3);
488 input_0.some_int = 5;
489 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
490
491 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
492 context, "Output Buffer");
493
494 CS::BindInfo(cmd, pass->GetTransientsBuffer().EmplaceUniform(info));
495 CS::BindInput0(cmd,
496 pass->GetTransientsBuffer().EmplaceStorageBuffer(input_0));
497 CS::BindInput1(cmd,
498 pass->GetTransientsBuffer().EmplaceStorageBuffer(input_1));
499 CS::BindOutput(cmd, output_buffer->AsBufferView());
500
501 ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
502 ASSERT_FALSE(pass->EncodeCommands());
503 }

References impeller::ComputeCommand::pipeline.

## ◆ TEST_P() [171/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanBlendDstOverAndDstCorrectly |
| ) |  |

Definition at line 1263 of file dl_unittests.cc.

1263 {
1264 flutter::DisplayListBuilder builder;
1265
1266 {
1267 builder.SaveLayer(nullptr, nullptr);
1268 builder.Translate(100, 100);
1269 flutter::DlPaint paint;
1270 paint.setColor(flutter::DlColor::kRed());
1271 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1272 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1273 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
1274 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1275 builder.Restore();
1276 }
1277 {
1278 builder.SaveLayer(nullptr, nullptr);
1279 builder.Translate(300, 100);
1280 flutter::DlPaint paint;
1281 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1282 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1283 paint.setColor(flutter::DlColor::kRed());
1284 paint.setBlendMode(flutter::DlBlendMode::kDstOver);
1285 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1286 builder.Restore();
1287 }
1288 {
1289 builder.SaveLayer(nullptr, nullptr);
1290 builder.Translate(100, 300);
1291 flutter::DlPaint paint;
1292 paint.setColor(flutter::DlColor::kRed());
1293 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1294 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1295 paint.setBlendMode(flutter::DlBlendMode::kSrc);
1296 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1297 builder.Restore();
1298 }
1299 {
1300 builder.SaveLayer(nullptr, nullptr);
1301 builder.Translate(300, 300);
1302 flutter::DlPaint paint;
1303 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1304 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1305 paint.setColor(flutter::DlColor::kRed());
1306 paint.setBlendMode(flutter::DlBlendMode::kDst);
1307 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1308 builder.Restore();
1309 }
1310
1311 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1312 }

## ◆ TEST_P() [172/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanClampTheResultingColorOfColorMatrixFilter |
| ) |  |

Definition at line 627 of file dl_unittests.cc.

627 {
628 auto texture = CreateTextureForFixture("boston.jpg");
629 const float inner_color_matrix[20] = {
630 1, 0, 0, 0, 0, //
631 0, 1, 0, 0, 0, //
632 0, 0, 1, 0, 0, //
633 0, 0, 0, 2, 0, //
634 };
635 const float outer_color_matrix[20] = {
636 1, 0, 0, 0, 0, //
637 0, 1, 0, 0, 0, //
638 0, 0, 1, 0, 0, //
639 0, 0, 0, 0.5, 0, //
640 };
641 auto inner_color_filter =
642 std::make_shared<flutter::DlMatrixColorFilter>(inner_color_matrix);
643 auto outer_color_filter =
644 std::make_shared<flutter::DlMatrixColorFilter>(outer_color_matrix);
645 auto inner =
646 std::make_shared<flutter::DlColorFilterImageFilter>(inner_color_filter);
647 auto outer =
648 std::make_shared<flutter::DlColorFilterImageFilter>(outer_color_filter);
649 auto compose = std::make_shared<flutter::DlComposeImageFilter>(outer, inner);
650
651 flutter::DisplayListBuilder builder;
652 flutter::DlPaint paint;
653 paint.setImageFilter(compose.get());
654 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
655 flutter::DlImageSampling::kNearestNeighbor, &paint);
656 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
657 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [173/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanConvertTriangleFanToTriangles |
| ) |  |

Definition at line 974 of file dl_unittests.cc.

974 {
975 constexpr Scalar hexagon_radius = 125;
976 auto hex_start = Point(200.0, -hexagon_radius + 200.0);
977 auto center_to_flat = 1.73 / 2 * hexagon_radius;
978
979 // clang-format off
980 std::vector<SkPoint> vertices = {
981 SkPoint::Make(hex_start.x, hex_start.y),
982 SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 0.5 * hexagon_radius),
983 SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
984 SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
985 SkPoint::Make(hex_start.x, hex_start.y + 2 * hexagon_radius),
986 SkPoint::Make(hex_start.x, hex_start.y + 2 * hexagon_radius),
987 SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 1.5 * hexagon_radius),
988 SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 1.5 * hexagon_radius),
989 SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 0.5 * hexagon_radius)
990 };
991 // clang-format on
992 auto paint = flutter::DlPaint(flutter::DlColor::kDarkGrey());
993 auto dl_vertices = flutter::DlVertices::Make(
994 flutter::DlVertexMode::kTriangleFan, vertices.size(), vertices.data(),
995 nullptr, nullptr);
996 flutter::DisplayListBuilder builder;
997 builder.DrawVertices(dl_vertices, flutter::DlBlendMode::kSrcOver, paint);
998 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
999 }

## ◆ TEST_P() [174/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawAnOpenPath |
| ) |  |

Definition at line 417 of file dl_unittests.cc.

417 {
418 flutter::DisplayListBuilder builder;
419 flutter::DlPaint paint;
420
421 paint.setColor(flutter::DlColor::kRed());
422 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
423 paint.setStrokeWidth(10);
424
425 builder.Translate(300, 300);
426
427 // Move to (50, 50) and draw lines from:
428 // 1. (50, height)
429 // 2. (width, height)
430 // 3. (width, 50)
431 SkPath path;
432 path.moveTo(50, 50);
433 path.lineTo(50, 100);
434 path.lineTo(100, 100);
435 path.lineTo(100, 50);
436 builder.DrawPath(path, paint);
437
438 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
439 }

## ◆ TEST_P() [175/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawArc |
| ) |  |

Definition at line 164 of file dl_unittests.cc.

164 {
165 auto callback = [&]() {
166 static float start_angle = 45;
167 static float sweep_angle = 270;
168 static float stroke_width = 10;
169 static bool use_center = true;
170
171 static int selected_cap = 0;
172 const char* cap_names[] = {"Butt", "Round", "Square"};
173 flutter::DlStrokeCap cap;
174
175 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
176 ImGui::SliderFloat("Start angle", &start_angle, -360, 360);
177 ImGui::SliderFloat("Sweep angle", &sweep_angle, -360, 360);
178 ImGui::SliderFloat("Stroke width", &stroke_width, 0, 300);
179 ImGui::Combo("Cap", &selected_cap, cap_names,
180 sizeof(cap_names) / sizeof(char*));
181 ImGui::Checkbox("Use center", &use_center);
182 ImGui::End();
183
184 switch (selected_cap) {
185 case 0:
186 cap = flutter::DlStrokeCap::kButt;
187 break;
188 case 1:
189 cap = flutter::DlStrokeCap::kRound;
190 break;
191 case 2:
192 cap = flutter::DlStrokeCap::kSquare;
193 break;
194 default:
195 cap = flutter::DlStrokeCap::kButt;
196 break;
197 }
198
199 auto [p1, p2] = IMPELLER_PLAYGROUND_LINE(
200 Point(200, 200), Point(400, 400), 20, Color::White(), Color::White());
201
202 flutter::DisplayListBuilder builder;
203 flutter::DlPaint paint;
204
205 Vector2 scale = GetContentScale();
206 builder.Scale(scale.x, scale.y);
207 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
208 paint.setStrokeCap(cap);
209 paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
210 paint.setStrokeMiter(10);
211 auto rect = SkRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
212 paint.setColor(flutter::DlColor::kGreen());
213 paint.setStrokeWidth(2);
214 builder.DrawRect(rect, paint);
215 paint.setColor(flutter::DlColor::kRed());
216 paint.setStrokeWidth(stroke_width);
217 builder.DrawArc(rect, start_angle, sweep_angle, use_center, paint);
218
219 return builder.Build();
220 };
221 ASSERT_TRUE(OpenPlaygroundHere(callback));
222 }

References IMPELLER_PLAYGROUND_LINE, impeller::Color::White(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [176/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawBackdropFilter |
| ) |  |

Definition at line 659 of file dl_unittests.cc.

659 {
660 auto texture = CreateTextureForFixture("embarcadero.jpg");
661
662 auto callback = [&]() {
663 static float sigma[] = {10, 10};
664 static float ctm_scale = 1;
665 static bool use_bounds = true;
666 static bool draw_circle = true;
667 static bool add_clip = true;
668
669 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
670 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
671 ImGui::SliderFloat("Scale", &ctm_scale, 0, 10);
672 ImGui::NewLine();
673 ImGui::TextWrapped(
674 "If everything is working correctly, none of the options below should "
675 "impact the filter's appearance.");
676 ImGui::Checkbox("Use SaveLayer bounds", &use_bounds);
677 ImGui::Checkbox("Draw child element", &draw_circle);
678 ImGui::Checkbox("Add pre-clip", &add_clip);
679 ImGui::End();
680
681 flutter::DisplayListBuilder builder;
682
683 Vector2 scale = ctm_scale * GetContentScale();
684 builder.Scale(scale.x, scale.y);
685
686 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
687 flutter::DlTileMode::kClamp);
688
689 std::optional<SkRect> bounds;
690 if (use_bounds) {
691 auto [p1, p2] = IMPELLER_PLAYGROUND_LINE(
692 Point(350, 150), Point(800, 600), 20, Color::White(), Color::White());
693 bounds = SkRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
694 }
695
696 // Insert a clip to test that the backdrop filter handles stencil depths > 0
697 // correctly.
698 if (add_clip) {
699 builder.ClipRect(SkRect::MakeLTRB(0, 0, 99999, 99999),
700 flutter::DlCanvas::ClipOp::kIntersect, true);
701 }
702
703 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
704 flutter::DlImageSampling::kNearestNeighbor, nullptr);
705 builder.SaveLayer(bounds.has_value() ? &bounds.value() : nullptr, nullptr,
706 &filter);
707
708 if (draw_circle) {
709 auto circle_center =
710 IMPELLER_PLAYGROUND_POINT(Point(500, 400), 20, Color::Red());
711
712 flutter::DlPaint paint;
713 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
714 paint.setStrokeCap(flutter::DlStrokeCap::kButt);
715 paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
716 paint.setStrokeWidth(10);
717 paint.setColor(flutter::DlColor::kRed().withAlpha(100));
718 builder.DrawCircle({circle_center.x, circle_center.y}, 100, paint);
719 }
720
721 return builder.Build();
722 };
723
724 ASSERT_TRUE(OpenPlaygroundHere(callback));
725 }

References IMPELLER_PLAYGROUND_LINE, IMPELLER_PLAYGROUND_POINT, impeller::DlImageImpeller::Make(), impeller::Color::Red(), impeller::Color::White(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [177/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawCapsAndJoins |
| ) |  |

Definition at line 118 of file dl_unittests.cc.

118 {
119 flutter::DisplayListBuilder builder;
120 flutter::DlPaint paint;
121
122 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
123 paint.setStrokeWidth(30);
124 paint.setColor(flutter::DlColor::kRed());
125
126 auto path =
127 SkPathBuilder{}.moveTo(-50, 0).lineTo(0, -50).lineTo(50, 0).snapshot();
128
129 builder.Translate(100, 100);
130 {
131 paint.setStrokeCap(flutter::DlStrokeCap::kButt);
132 paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
133 paint.setStrokeMiter(4);
134 builder.DrawPath(path, paint);
135 }
136
137 {
138 builder.Save();
139 builder.Translate(0, 100);
140 // The joint in the path is 45 degrees. A miter length of 1 convert to a
141 // bevel in this case.
142 paint.setStrokeMiter(1);
143 builder.DrawPath(path, paint);
144 builder.Restore();
145 }
146
147 builder.Translate(150, 0);
148 {
149 paint.setStrokeCap(flutter::DlStrokeCap::kSquare);
150 paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
151 builder.DrawPath(path, paint);
152 }
153
154 builder.Translate(150, 0);
155 {
156 paint.setStrokeCap(flutter::DlStrokeCap::kRound);
157 paint.setStrokeJoin(flutter::DlStrokeJoin::kRound);
158 builder.DrawPath(path, paint);
159 }
160
161 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
162 }

## ◆ TEST_P() [178/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawCorrectlyWithColorFilterAndImageFilter |
| ) |  |

Definition at line 1314 of file dl_unittests.cc.

1314 {
1315 flutter::DisplayListBuilder builder;
1316 const float green_color_matrix[20] = {
1317 0, 0, 0, 0, 0, //
1318 0, 0, 0, 0, 1, //
1319 0, 0, 0, 0, 0, //
1320 0, 0, 0, 1, 0, //
1321 };
1322 const float blue_color_matrix[20] = {
1323 0, 0, 0, 0, 0, //
1324 0, 0, 0, 0, 0, //
1325 0, 0, 0, 0, 1, //
1326 0, 0, 0, 1, 0, //
1327 };
1328 auto green_color_filter =
1329 std::make_shared<flutter::DlMatrixColorFilter>(green_color_matrix);
1330 auto blue_color_filter =
1331 std::make_shared<flutter::DlMatrixColorFilter>(blue_color_matrix);
1332 auto blue_image_filter =
1333 std::make_shared<flutter::DlColorFilterImageFilter>(blue_color_filter);
1334
1335 flutter::DlPaint paint;
1336 paint.setColor(flutter::DlColor::kRed());
1337 paint.setColorFilter(green_color_filter);
1338 paint.setImageFilter(blue_image_filter);
1339 builder.DrawRect(SkRect::MakeLTRB(100, 100, 500, 500), paint);
1340 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1341 }

## ◆ TEST_P() [179/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawImage |
| ) |  |

Definition at line 110 of file dl_unittests.cc.

110 {
111 auto texture = CreateTextureForFixture("embarcadero.jpg");
112 flutter::DisplayListBuilder builder;
113 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
114 flutter::DlImageSampling::kNearestNeighbor, nullptr);
115 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
116 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [180/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImage |
| ) |  |

Definition at line 727 of file dl_unittests.cc.

727 {
728 // Image is drawn with corners to scale and center pieces stretched to fit.
729 auto texture = CreateTextureForFixture("embarcadero.jpg");
730 flutter::DisplayListBuilder builder;
731 auto size = texture->GetSize();
732 builder.DrawImageNine(
733 DlImageImpeller::Make(texture),
734 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
735 size.height * 3 / 4),
736 SkRect::MakeLTRB(0, 0, size.width * 2, size.height * 2),
737 flutter::DlFilterMode::kNearest, nullptr);
738 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
739 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [181/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterBiggerThanDest |
| ) |  |

Definition at line 773 of file dl_unittests.cc.

773 {
774 // Edge case, the width and height of the corners does not leave any
775 // room for the center slices. Only the corners are displayed.
776 auto texture = CreateTextureForFixture("embarcadero.jpg");
777 flutter::DisplayListBuilder builder;
778 auto size = texture->GetSize();
779 builder.DrawImageNine(
780 DlImageImpeller::Make(texture),
781 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
782 size.height * 3 / 4),
783 SkRect::MakeLTRB(0, 0, size.width / 2, size.height / 2),
784 flutter::DlFilterMode::kNearest, nullptr);
785 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
786 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [182/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterHeightBiggerThanDest |
| ) |  |

Definition at line 757 of file dl_unittests.cc.

757 {
758 // Edge case, the height of the corners does not leave any room for the
759 // center slice. The center (across the horizontal axis) is folded out of the
760 // resulting image.
761 auto texture = CreateTextureForFixture("embarcadero.jpg");
762 flutter::DisplayListBuilder builder;
763 auto size = texture->GetSize();
764 builder.DrawImageNine(
765 DlImageImpeller::Make(texture),
766 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
767 size.height * 3 / 4),
768 SkRect::MakeLTRB(0, 0, size.width, size.height / 2),
769 flutter::DlFilterMode::kNearest, nullptr);
770 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
771 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [183/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterWidthBiggerThanDest |
| ) |  |

Definition at line 741 of file dl_unittests.cc.

741 {
742 // Edge case, the width of the corners does not leave any room for the
743 // center slice. The center (across the vertical axis) is folded out of the
744 // resulting image.
745 auto texture = CreateTextureForFixture("embarcadero.jpg");
746 flutter::DisplayListBuilder builder;
747 auto size = texture->GetSize();
748 builder.DrawImageNine(
749 DlImageImpeller::Make(texture),
750 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
751 size.height * 3 / 4),
752 SkRect::MakeLTRB(0, 0, size.width / 2, size.height),
753 flutter::DlFilterMode::kNearest, nullptr);
754 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
755 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [184/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCornersScaledDown |
| ) |  |

Definition at line 788 of file dl_unittests.cc.

788 {
789 // Edge case, there is not enough room for the corners to be drawn
790 // without scaling them down.
791 auto texture = CreateTextureForFixture("embarcadero.jpg");
792 flutter::DisplayListBuilder builder;
793 auto size = texture->GetSize();
794 builder.DrawImageNine(
795 DlImageImpeller::Make(texture),
796 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
797 size.height * 3 / 4),
798 SkRect::MakeLTRB(0, 0, size.width / 4, size.height / 4),
799 flutter::DlFilterMode::kNearest, nullptr);
800 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
801 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [185/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawPaintWithColorSource |
| ) |  |

Definition at line 1211 of file dl_unittests.cc.

1211 {
1212 const flutter::DlColor colors[2] = {
1213 flutter::DlColor(0xFFF44336),
1214 flutter::DlColor(0xFF2196F3),
1215 };
1216 const float stops[2] = {0.0, 1.0};
1217 flutter::DlPaint paint;
1218 flutter::DisplayListBuilder builder;
1219 auto clip_bounds = SkRect::MakeWH(300.0, 300.0);
1220 builder.Save();
1221 builder.Translate(100, 100);
1222 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1223 auto linear =
1224 flutter::DlColorSource::MakeLinear({0.0, 0.0}, {100.0, 100.0}, 2, colors,
1225 stops, flutter::DlTileMode::kRepeat);
1226 paint.setColorSource(linear);
1227 builder.DrawPaint(paint);
1228 builder.Restore();
1229
1230 builder.Save();
1231 builder.Translate(500, 100);
1232 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1233 auto radial = flutter::DlColorSource::MakeRadial(
1234 {100.0, 100.0}, 100.0, 2, colors, stops, flutter::DlTileMode::kRepeat);
1235 paint.setColorSource(radial);
1236 builder.DrawPaint(paint);
1237 builder.Restore();
1238
1239 builder.Save();
1240 builder.Translate(100, 500);
1241 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1242 auto sweep =
1243 flutter::DlColorSource::MakeSweep({100.0, 100.0}, 180.0, 270.0, 2, colors,
1244 stops, flutter::DlTileMode::kRepeat);
1245 paint.setColorSource(sweep);
1246 builder.DrawPaint(paint);
1247 builder.Restore();
1248
1249 builder.Save();
1250 builder.Translate(500, 500);
1251 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1252 auto texture = CreateTextureForFixture("table_mountain_nx.png");
1253 auto image = std::make_shared<flutter::DlImageColorSource>(
1254 DlImageImpeller::Make(texture), flutter::DlTileMode::kRepeat,
1255 flutter::DlTileMode::kRepeat);
1256 paint.setColorSource(image);
1257 builder.DrawPaint(paint);
1258 builder.Restore();
1259
1260 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1261 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [186/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawPoints |
| ) |  |

Definition at line 803 of file dl_unittests.cc.

803 {
804 flutter::DisplayListBuilder builder;
805 SkPoint points[7] = {
806 {0, 0}, //
807 {100, 100}, //
808 {100, 0}, //
809 {0, 100}, //
810 {0, 0}, //
811 {48, 48}, //
812 {52, 52}, //
813 };
814 std::vector<flutter::DlStrokeCap> caps = {
815 flutter::DlStrokeCap::kButt,
816 flutter::DlStrokeCap::kRound,
817 flutter::DlStrokeCap::kSquare,
818 };
819 flutter::DlPaint paint =
820 flutter::DlPaint() //
821 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
822 .setStrokeWidth(20);
823 builder.Translate(50, 50);
824 for (auto cap : caps) {
825 paint.setStrokeCap(cap);
826 builder.Save();
827 builder.DrawPoints(flutter::DlCanvas::PointMode::kPoints, 7, points, paint);
828 builder.Translate(150, 0);
829 builder.DrawPoints(flutter::DlCanvas::PointMode::kLines, 5, points, paint);
830 builder.Translate(150, 0);
831 builder.DrawPoints(flutter::DlCanvas::PointMode::kPolygon, 5, points,
832 paint);
833 builder.Restore();
834 builder.Translate(0, 150);
835 }
836 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
837 }

## ◆ TEST_P() [187/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawRect |
| ) |  |

Definition at line 61 of file dl_unittests.cc.

61 {
62 flutter::DisplayListBuilder builder;
63 builder.DrawRect(SkRect::MakeXYWH(10, 10, 100, 100),
64 flutter::DlPaint(flutter::DlColor::kBlue()));
65 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
66 }

## ◆ TEST_P() [188/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawRectWithLinearToSrgbColorFilter |
| ) |  |

Definition at line 1195 of file dl_unittests.cc.

1195 {
1196 flutter::DlPaint paint;
1197 paint.setColor(flutter::DlColor(0xFF2196F3).withAlpha(128));
1198 flutter::DisplayListBuilder builder;
1199 paint.setColorFilter(
1200 flutter::DlLinearToSrgbGammaColorFilter::kInstance.get());
1201 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), paint);
1202 builder.Translate(0, 200);
1203
1204 paint.setColorFilter(
1205 flutter::DlSrgbToLinearGammaColorFilter::kInstance.get());
1206 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), paint);
1207
1208 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1209 }

## ◆ TEST_P() [189/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawShadow |
| ) |  |

Definition at line 862 of file dl_unittests.cc.

862 {
863 flutter::DisplayListBuilder builder;
864 flutter::DlPaint paint;
865
866 auto content_scale = GetContentScale() * 0.8;
867 builder.Scale(content_scale.x, content_scale.y);
868
869 constexpr size_t star_spikes = 5;
870 constexpr SkScalar half_spike_rotation = kPi / star_spikes;
871 constexpr SkScalar radius = 40;
872 constexpr SkScalar spike_size = 10;
873 constexpr SkScalar outer_radius = radius + spike_size;
874 constexpr SkScalar inner_radius = radius - spike_size;
875 std::array<SkPoint, star_spikes * 2> star;
876 for (size_t i = 0; i < star_spikes; i++) {
877 const SkScalar rotation = half_spike_rotation * i * 2;
878 star[i * 2] = SkPoint::Make(50 + std::sin(rotation) * outer_radius,
879 50 - std::cos(rotation) * outer_radius);
880 star[i * 2 + 1] = SkPoint::Make(
881 50 + std::sin(rotation + half_spike_rotation) * inner_radius,
882 50 - std::cos(rotation + half_spike_rotation) * inner_radius);
883 }
884
885 std::array<SkPath, 4> paths = {
886 SkPath{}.addRect(SkRect::MakeXYWH(0, 0, 200, 100)),
887 SkPath{}.addRRect(
888 SkRRect::MakeRectXY(SkRect::MakeXYWH(20, 0, 200, 100), 30, 30)),
889 SkPath{}.addCircle(100, 50, 50),
890 SkPath{}.addPoly(star.data(), star.size(), true),
891 };
892 paint.setColor(flutter::DlColor::kWhite());
893 builder.DrawPaint(paint);
894 paint.setColor(flutter::DlColor::kCyan());
895 builder.Translate(100, 50);
896 for (size_t x = 0; x < paths.size(); x++) {
897 builder.Save();
898 for (size_t y = 0; y < 6; y++) {
899 builder.DrawShadow(paths[x], flutter::DlColor::kBlack(), 3 + y * 8, false,
900 1);
901 builder.DrawPath(paths[x], paint);
902 builder.Translate(0, 150);
903 }
904 builder.Restore();
905 builder.Translate(250, 0);
906 }
907
908 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
909 }

References impeller::kPi.

## ◆ TEST_P() [190/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawStrokedText |
| ) |  |

Definition at line 477 of file dl_unittests.cc.

477 {
478 flutter::DisplayListBuilder builder;
479 flutter::DlPaint paint;
480
481 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
482 paint.setColor(flutter::DlColor::kRed());
483 builder.DrawTextBlob(
484 SkTextBlob::MakeFromString("stoked about stroked text", CreateTestFont()),
485 250, 250, paint);
486
487 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
488 }

## ◆ TEST_P() [191/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextBlob |
| ) |  |

Definition at line 68 of file dl_unittests.cc.

68 {
69 flutter::DisplayListBuilder builder;
70 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
71 100, 100, flutter::DlPaint(flutter::DlColor::kBlue()));
72 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
73 }

## ◆ TEST_P() [192/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextBlobWithGradient |
| ) |  |

Definition at line 75 of file dl_unittests.cc.

75 {
76 flutter::DisplayListBuilder builder;
77
78 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
79 flutter::DlColor::kRed()};
80 const float stops[2] = {0.0, 1.0};
81
82 auto linear = flutter::DlColorSource::MakeLinear({0.0, 0.0}, {300.0, 300.0},
83 2, colors.data(), stops,
84 flutter::DlTileMode::kClamp);
85 flutter::DlPaint paint;
86 paint.setColorSource(linear);
87
88 builder.DrawTextBlob(
89 SkTextBlob::MakeFromString("Hello World", CreateTestFont()), 100, 100,
90 paint);
91 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
92 }

## ◆ TEST_P() [193/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextWithSaveLayer |
| ) |  |

Definition at line 94 of file dl_unittests.cc.

94 {
95 flutter::DisplayListBuilder builder;
96 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
97 100, 100, flutter::DlPaint(flutter::DlColor::kRed()));
98
99 flutter::DlPaint save_paint;
100 float alpha = 0.5;
101 save_paint.setAlpha(static_cast<uint8_t>(255 * alpha));
102 builder.SaveLayer(nullptr, &save_paint);
103 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello with half alpha",
104 CreateTestFontOfSize(100)),
105 100, 300, flutter::DlPaint(flutter::DlColor::kRed()));
106 builder.Restore();
107 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
108 }

## ◆ TEST_P() [194/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithBlendColorFilter |
| ) |  |

Definition at line 529 of file dl_unittests.cc.

529 {
530 auto texture = CreateTextureForFixture("embarcadero.jpg");
531 flutter::DisplayListBuilder builder;
532 flutter::DlPaint paint;
533
534 // Pipeline blended image.
535 {
536 auto filter = flutter::DlBlendColorFilter(flutter::DlColor::kYellow(),
537 flutter::DlBlendMode::kModulate);
538 paint.setColorFilter(&filter);
539 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
540 flutter::DlImageSampling::kNearestNeighbor, &paint);
541 }
542
543 // Advanced blended image.
544 {
545 auto filter = flutter::DlBlendColorFilter(flutter::DlColor::kRed(),
546 flutter::DlBlendMode::kScreen);
547 paint.setColorFilter(&filter);
548 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(250, 250),
549 flutter::DlImageSampling::kNearestNeighbor, &paint);
550 }
551
552 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
553 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [195/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithColorFilterImageFilter |
| ) |  |

Definition at line 555 of file dl_unittests.cc.

555 {
556 const float invert_color_matrix[20] = {
557 -1, 0, 0, 0, 1, //
558 0, -1, 0, 0, 1, //
559 0, 0, -1, 0, 1, //
560 0, 0, 0, 1, 0, //
561 };
562 auto texture = CreateTextureForFixture("boston.jpg");
563 flutter::DisplayListBuilder builder;
564 flutter::DlPaint paint;
565
566 auto color_filter =
567 std::make_shared<flutter::DlMatrixColorFilter>(invert_color_matrix);
568 auto image_filter =
569 std::make_shared<flutter::DlColorFilterImageFilter>(color_filter);
570
571 paint.setImageFilter(image_filter.get());
572 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
573 flutter::DlImageSampling::kNearestNeighbor, &paint);
574
575 builder.Translate(0, 700);
576 paint.setColorFilter(color_filter.get());
577 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
578 flutter::DlImageSampling::kNearestNeighbor, &paint);
579 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
580 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [196/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithComposeImageFilter |
| ) |  |

Definition at line 607 of file dl_unittests.cc.

607 {
608 auto texture = CreateTextureForFixture("boston.jpg");
609 flutter::DisplayListBuilder builder;
610 flutter::DlPaint paint;
611
612 auto dilate = std::make_shared<flutter::DlDilateImageFilter>(10.0, 10.0);
613 auto erode = std::make_shared<flutter::DlErodeImageFilter>(10.0, 10.0);
614 auto open = std::make_shared<flutter::DlComposeImageFilter>(dilate, erode);
615 auto close = std::make_shared<flutter::DlComposeImageFilter>(erode, dilate);
616
617 paint.setImageFilter(open.get());
618 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
619 flutter::DlImageSampling::kNearestNeighbor, &paint);
620 builder.Translate(0, 700);
621 paint.setImageFilter(close.get());
622 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
623 flutter::DlImageSampling::kNearestNeighbor, &paint);
624 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
625 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [197/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithImageBlurFilter |
| ) |  |

Definition at line 582 of file dl_unittests.cc.

582 {
583 auto texture = CreateTextureForFixture("embarcadero.jpg");
584
585 auto callback = [&]() {
586 static float sigma[] = {10, 10};
587
588 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
589 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
590 ImGui::End();
591
592 flutter::DisplayListBuilder builder;
593 flutter::DlPaint paint;
594
595 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
596 flutter::DlTileMode::kClamp);
597 paint.setImageFilter(&filter);
598 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
599 flutter::DlImageSampling::kNearestNeighbor, &paint);
600
601 return builder.Build();
602 };
603
604 ASSERT_TRUE(OpenPlaygroundHere(callback));
605 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [198/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMaskBlur |
| ) |  |

Definition at line 441 of file dl_unittests.cc.

441 {
442 auto texture = CreateTextureForFixture("embarcadero.jpg");
443 flutter::DisplayListBuilder builder;
444 flutter::DlPaint paint;
445
446 // Mask blurred image.
447 {
448 auto filter =
449 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
450 paint.setMaskFilter(&filter);
451 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
452 flutter::DlImageSampling::kNearestNeighbor, &paint);
453 }
454
455 // Mask blurred filled path.
456 {
457 paint.setColor(flutter::DlColor::kYellow());
458 auto filter =
459 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kOuter, 10.0f);
460 paint.setMaskFilter(&filter);
461 builder.DrawArc(SkRect::MakeXYWH(410, 110, 100, 100), 45, 270, true, paint);
462 }
463
464 // Mask blurred text.
465 {
466 auto filter =
467 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kSolid, 10.0f);
468 paint.setMaskFilter(&filter);
469 builder.DrawTextBlob(
470 SkTextBlob::MakeFromString("Testing", CreateTestFont()), 220, 170,
471 paint);
472 }
473
474 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
475 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [199/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilter |
| ) |  |

Definition at line 1035 of file dl_unittests.cc.

1035 {
1036 auto boston = CreateTextureForFixture("boston.jpg");
1037
1038 auto callback = [&]() {
1039 static int selected_matrix_type = 0;
1040 const char* matrix_type_names[] = {"Matrix", "Local Matrix"};
1041
1042 static float ctm_translation[2] = {200, 200};
1043 static float ctm_scale[2] = {0.65, 0.65};
1044 static float ctm_skew[2] = {0, 0};
1045
1046 static bool enable = true;
1047 static float translation[2] = {100, 100};
1048 static float scale[2] = {0.8, 0.8};
1049 static float skew[2] = {0.2, 0.2};
1050
1051 static bool enable_savelayer = true;
1052
1053 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1054 {
1055 ImGui::Combo("Filter type", &selected_matrix_type, matrix_type_names,
1056 sizeof(matrix_type_names) / sizeof(char*));
1057
1058 ImGui::TextWrapped("Current Transform");
1059 ImGui::SliderFloat2("CTM Translation", ctm_translation, 0, 1000);
1060 ImGui::SliderFloat2("CTM Scale", ctm_scale, 0, 3);
1061 ImGui::SliderFloat2("CTM Skew", ctm_skew, -3, 3);
1062
1063 ImGui::TextWrapped(
1064 "MatrixFilter and LocalMatrixFilter modify the CTM in the same way. "
1065 "The only difference is that MatrixFilter doesn't affect the effect "
1066 "transform, whereas LocalMatrixFilter does.");
1067 // Note: See this behavior in:
1068 // https://fiddle.skia.org/c/6cbb551ab36d06f163db8693972be954
1069 ImGui::Checkbox("Enable", &enable);
1070 ImGui::SliderFloat2("Filter Translation", translation, 0, 1000);
1071 ImGui::SliderFloat2("Filter Scale", scale, 0, 3);
1072 ImGui::SliderFloat2("Filter Skew", skew, -3, 3);
1073
1074 ImGui::TextWrapped(
1075 "Rendering the filtered image within a layer can expose bounds "
1076 "issues. If the rendered image gets cut off when this setting is "
1077 "enabled, there's a coverage bug in the filter.");
1078 ImGui::Checkbox("Render in layer", &enable_savelayer);
1079 }
1080 ImGui::End();
1081
1082 flutter::DisplayListBuilder builder;
1083 flutter::DlPaint paint;
1084
1085 if (enable_savelayer) {
1086 builder.SaveLayer(nullptr, nullptr);
1087 }
1088 {
1089 auto content_scale = GetContentScale();
1090 builder.Scale(content_scale.x, content_scale.y);
1091
1092 // Set the current transform
1093 auto ctm_matrix =
1094 SkMatrix::MakeAll(ctm_scale[0], ctm_skew[0], ctm_translation[0], //
1095 ctm_skew[1], ctm_scale[1], ctm_translation[1], //
1096 0, 0, 1);
1097 builder.Transform(ctm_matrix);
1098
1099 // Set the matrix filter
1100 auto filter_matrix =
1101 SkMatrix::MakeAll(scale[0], skew[0], translation[0], //
1102 skew[1], scale[1], translation[1], //
1103 0, 0, 1);
1104
1105 if (enable) {
1106 switch (selected_matrix_type) {
1107 case 0: {
1108 auto filter = flutter::DlMatrixImageFilter(
1109 filter_matrix, flutter::DlImageSampling::kLinear);
1110 paint.setImageFilter(&filter);
1111 break;
1112 }
1113 case 1: {
1114 auto internal_filter =
1115 flutter::DlBlurImageFilter(10, 10, flutter::DlTileMode::kDecal)
1116 .shared();
1117 auto filter = flutter::DlLocalMatrixImageFilter(filter_matrix,
1118 internal_filter);
1119 paint.setImageFilter(&filter);
1120 break;
1121 }
1122 }
1123 }
1124
1125 builder.DrawImage(DlImageImpeller::Make(boston), {},
1126 flutter::DlImageSampling::kLinear, &paint);
1127 }
1128 if (enable_savelayer) {
1129 builder.Restore();
1130 }
1131
1132 return builder.Build();
1133 };
1134
1135 ASSERT_TRUE(OpenPlaygroundHere(callback));
1136 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [200/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilterWhenSavingLayer |
| ) |  |

Definition at line 1138 of file dl_unittests.cc.

1138 {
1139 auto callback = [&]() {
1140 static float translation[2] = {0, 0};
1141 static bool enable_save_layer = true;
1142
1143 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1144 ImGui::SliderFloat2("Translation", translation, -130, 130);
1145 ImGui::Checkbox("Enable save layer", &enable_save_layer);
1146 ImGui::End();
1147
1148 flutter::DisplayListBuilder builder;
1149 builder.Save();
1150 builder.Scale(2.0, 2.0);
1151 flutter::DlPaint paint;
1152 paint.setColor(flutter::DlColor::kYellow());
1153 builder.DrawRect(SkRect::MakeWH(300, 300), paint);
1154 paint.setStrokeWidth(1.0);
1155 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1156 paint.setColor(flutter::DlColor::kBlack().withAlpha(0x80));
1157 builder.DrawLine(SkPoint::Make(150, 0), SkPoint::Make(150, 300), paint);
1158 builder.DrawLine(SkPoint::Make(0, 150), SkPoint::Make(300, 150), paint);
1159
1160 flutter::DlPaint save_paint;
1161 SkRect bounds = SkRect::MakeXYWH(100, 100, 100, 100);
1162 SkMatrix translate_matrix =
1163 SkMatrix::Translate(translation[0], translation[1]);
1164 if (enable_save_layer) {
1165 auto filter = flutter::DlMatrixImageFilter(
1166 translate_matrix, flutter::DlImageSampling::kNearestNeighbor);
1167 save_paint.setImageFilter(filter.shared());
1168 builder.SaveLayer(&bounds, &save_paint);
1169 } else {
1170 builder.Save();
1171 builder.Transform(translate_matrix);
1172 }
1173
1174 SkMatrix filter_matrix = SkMatrix::I();
1175 filter_matrix.postTranslate(-150, -150);
1176 filter_matrix.postScale(0.2f, 0.2f);
1177 filter_matrix.postTranslate(150, 150);
1178 auto filter = flutter::DlMatrixImageFilter(
1179 filter_matrix, flutter::DlImageSampling::kNearestNeighbor);
1180
1181 save_paint.setImageFilter(filter.shared());
1182
1183 builder.SaveLayer(&bounds, &save_paint);
1184 flutter::DlPaint paint2;
1185 paint2.setColor(flutter::DlColor::kBlue());
1186 builder.DrawRect(bounds, paint2);
1187 builder.Restore();
1188 builder.Restore();
1189 return builder.Build();
1190 };
1191
1192 ASSERT_TRUE(OpenPlaygroundHere(callback));
1193 }

## ◆ TEST_P() [201/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithOddPathWinding |
| ) |  |

Definition at line 397 of file dl_unittests.cc.

397 {
398 flutter::DisplayListBuilder builder;
399 flutter::DlPaint paint;
400
401 paint.setColor(flutter::DlColor::kRed());
402 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
403
404 builder.Translate(300, 300);
405 SkPath path;
406 path.setFillType(SkPathFillType::kEvenOdd);
407 path.addCircle(0, 0, 100);
408 path.addCircle(0, 0, 50);
409 builder.DrawPath(path, paint);
410
411 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
412 }

## ◆ TEST_P() [202/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawZeroLengthLine |
| ) |  |

Definition at line 839 of file dl_unittests.cc.

839 {
840 flutter::DisplayListBuilder builder;
841 std::vector<flutter::DlStrokeCap> caps = {
842 flutter::DlStrokeCap::kButt,
843 flutter::DlStrokeCap::kRound,
844 flutter::DlStrokeCap::kSquare,
845 };
846 flutter::DlPaint paint =
847 flutter::DlPaint() //
848 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
849 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
850 .setStrokeCap(flutter::DlStrokeCap::kButt) //
851 .setStrokeWidth(20);
852 SkPath path = SkPath().addPoly({{150, 50}, {150, 50}}, false);
853 for (auto cap : caps) {
854 paint.setStrokeCap(cap);
855 builder.DrawLine({50, 50}, {50, 50}, paint);
856 builder.DrawPath(path, paint);
857 builder.Translate(0, 150);
858 }
859 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
860 }

## ◆ TEST_P() [203/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawZeroWidthLine |
| ) |  |

Definition at line 1001 of file dl_unittests.cc.

1001 {
1002 flutter::DisplayListBuilder builder;
1003 std::vector<flutter::DlStrokeCap> caps = {
1004 flutter::DlStrokeCap::kButt,
1005 flutter::DlStrokeCap::kRound,
1006 flutter::DlStrokeCap::kSquare,
1007 };
1008 flutter::DlPaint paint = //
1009 flutter::DlPaint() //
1010 .setColor(flutter::DlColor::kWhite()) //
1011 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1012 .setStrokeWidth(0);
1013 flutter::DlPaint outline_paint = //
1014 flutter::DlPaint() //
1015 .setColor(flutter::DlColor::kYellow()) //
1016 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1017 .setStrokeCap(flutter::DlStrokeCap::kSquare) //
1018 .setStrokeWidth(1);
1019 SkPath path = SkPath().addPoly({{150, 50}, {160, 50}}, false);
1020 for (auto cap : caps) {
1021 paint.setStrokeCap(cap);
1022 builder.DrawLine({50, 50}, {60, 50}, paint);
1023 builder.DrawRect({45, 45, 65, 55}, outline_paint);
1024 builder.DrawLine({100, 50}, {100, 50}, paint);
1025 if (cap != flutter::DlStrokeCap::kButt) {
1026 builder.DrawRect({95, 45, 105, 55}, outline_paint);
1027 }
1028 builder.DrawPath(path, paint);
1029 builder.DrawRect(path.getBounds().makeOutset(5, 5), outline_paint);
1030 builder.Translate(0, 150);
1031 }
1032 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1033 }

## ◆ TEST_P() [204/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DispatcherDoesNotCullPerspectiveTransformedChildDisplayLists |
| ) |  |

Definition at line 911 of file dl_unittests.cc.

912 {
913 // Regression test for https://github.com/flutter/flutter/issues/130613
914 flutter::DisplayListBuilder sub_builder(true);
915 sub_builder.DrawRect(SkRect::MakeXYWH(0, 0, 50, 50),
916 flutter::DlPaint(flutter::DlColor::kRed()));
917 auto display_list = sub_builder.Build();
918
919 DlDispatcher dispatcher(Rect::MakeLTRB(0, 0, 2400, 1800));
920 dispatcher.scale(2.0, 2.0);
921 dispatcher.translate(-93.0, 0.0);
922 // clang-format off
923 dispatcher.transformFullPerspective(
924 0.8, -0.2, -0.1, -0.0,
925 0.0, 1.0, 0.0, 0.0,
926 1.4, 1.3, 1.0, 0.0,
927 63.2, 65.3, 48.6, 1.1
928 );
929 // clang-format on
930 dispatcher.translate(35.0, 75.0);
931 dispatcher.drawDisplayList(display_list, 1.0f);
932 auto picture = dispatcher.EndRecordingAsPicture();
933
934 bool found = false;
935 picture.pass->IterateAllEntities([&found](Entity& entity) {
936 if (std::static_pointer_cast<SolidColorContents>(entity.GetContents())
937 ->GetColor() == Color::Red()) {
938 found = true;
939 return false;
940 }
941
942 return true;
943 });
944 EXPECT_TRUE(found);
945 }

References impeller::DlDispatcher::drawDisplayList(), impeller::DlDispatcher::EndRecordingAsPicture(), impeller::Entity::GetContents(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Picture::pass, impeller::Color::Red(), impeller::DlDispatcher::scale(), impeller::DlDispatcher::transformFullPerspective(), and impeller::DlDispatcher::translate().

## ◆ TEST_P() [205/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawPictureWithAClip |
| ) |  |

Definition at line 48 of file dl_unittests.cc.

48 {
49 flutter::DisplayListBuilder sub_builder;
50 sub_builder.ClipRect(SkRect::MakeXYWH(0, 0, 24, 24));
51 sub_builder.DrawPaint(flutter::DlPaint(flutter::DlColor::kBlue()));
52
53 auto display_list = sub_builder.Build();
54 flutter::DisplayListBuilder builder;
55 builder.DrawDisplayList(display_list);
56 builder.DrawRect(SkRect::MakeXYWH(30, 30, 24, 24),
57 flutter::DlPaint(flutter::DlColor::kRed()));
58 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
59 }

## ◆ TEST_P() [206/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawShapes |
| ) |  |

Definition at line 1555 of file dl_unittests.cc.

1555 {
1556 flutter::DisplayListBuilder builder;
1557 std::vector<flutter::DlStrokeJoin> joins = {
1558 flutter::DlStrokeJoin::kBevel,
1559 flutter::DlStrokeJoin::kRound,
1560 flutter::DlStrokeJoin::kMiter,
1561 };
1562 flutter::DlPaint paint = //
1563 flutter::DlPaint() //
1564 .setColor(flutter::DlColor::kWhite()) //
1565 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1566 .setStrokeWidth(10);
1567 flutter::DlPaint stroke_paint = //
1568 flutter::DlPaint() //
1569 .setColor(flutter::DlColor::kWhite()) //
1570 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1571 .setStrokeWidth(10);
1572 SkPath path = SkPath().addPoly({{150, 50}, {160, 50}}, false);
1573
1574 builder.Translate(300, 50);
1575 builder.Scale(0.8, 0.8);
1576 for (auto join : joins) {
1577 paint.setStrokeJoin(join);
1578 stroke_paint.setStrokeJoin(join);
1579 builder.DrawRect(SkRect::MakeXYWH(0, 0, 100, 100), paint);
1580 builder.DrawRect(SkRect::MakeXYWH(0, 150, 100, 100), stroke_paint);
1581 builder.DrawRRect(
1582 SkRRect::MakeRectXY(SkRect::MakeXYWH(150, 0, 100, 100), 30, 30), paint);
1583 builder.DrawRRect(
1584 SkRRect::MakeRectXY(SkRect::MakeXYWH(150, 150, 100, 100), 30, 30),
1585 stroke_paint);
1586 builder.DrawCircle({350, 50}, 50, paint);
1587 builder.DrawCircle({350, 200}, 50, stroke_paint);
1588 builder.Translate(0, 300);
1589 }
1590 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1591 }

## ◆ TEST_P() [207/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesBlendModes |
| ) |  |

Definition at line 1593 of file dl_unittests.cc.

1593 {
1594 std::vector<const char*> blend_mode_names;
1595 std::vector<flutter::DlBlendMode> blend_mode_values;
1596 {
1597 const std::vector<std::tuple<const char*, flutter::DlBlendMode>> blends = {
1598 // Pipeline blends (Porter-Duff alpha compositing)
1599 {"Clear", flutter::DlBlendMode::kClear},
1600 {"Source", flutter::DlBlendMode::kSrc},
1601 {"Destination", flutter::DlBlendMode::kDst},
1602 {"SourceOver", flutter::DlBlendMode::kSrcOver},
1603 {"DestinationOver", flutter::DlBlendMode::kDstOver},
1604 {"SourceIn", flutter::DlBlendMode::kSrcIn},
1605 {"DestinationIn", flutter::DlBlendMode::kDstIn},
1606 {"SourceOut", flutter::DlBlendMode::kSrcOut},
1607 {"DestinationOut", flutter::DlBlendMode::kDstOut},
1608 {"SourceATop", flutter::DlBlendMode::kSrcATop},
1609 {"DestinationATop", flutter::DlBlendMode::kDstATop},
1610 {"Xor", flutter::DlBlendMode::kXor},
1611 {"Plus", flutter::DlBlendMode::kPlus},
1612 {"Modulate", flutter::DlBlendMode::kModulate},
1613 // Advanced blends (color component blends)
1614 {"Screen", flutter::DlBlendMode::kScreen},
1615 {"Overlay", flutter::DlBlendMode::kOverlay},
1616 {"Darken", flutter::DlBlendMode::kDarken},
1617 {"Lighten", flutter::DlBlendMode::kLighten},
1618 {"ColorDodge", flutter::DlBlendMode::kColorDodge},
1619 {"ColorBurn", flutter::DlBlendMode::kColorBurn},
1620 {"HardLight", flutter::DlBlendMode::kHardLight},
1621 {"SoftLight", flutter::DlBlendMode::kSoftLight},
1622 {"Difference", flutter::DlBlendMode::kDifference},
1623 {"Exclusion", flutter::DlBlendMode::kExclusion},
1624 {"Multiply", flutter::DlBlendMode::kMultiply},
1625 {"Hue", flutter::DlBlendMode::kHue},
1626 {"Saturation", flutter::DlBlendMode::kSaturation},
1627 {"Color", flutter::DlBlendMode::kColor},
1628 {"Luminosity", flutter::DlBlendMode::kLuminosity},
1629 };
1630 assert(blends.size() ==
1631 static_cast<size_t>(flutter::DlBlendMode::kLastMode) + 1);
1632 for (const auto& [name, mode] : blends) {
1633 blend_mode_names.push_back(name);
1634 blend_mode_values.push_back(mode);
1635 }
1636 }
1637
1638 auto callback = [&]() {
1639 static int current_blend_index = 3;
1640 static float dst_alpha = 1;
1641 static float src_alpha = 1;
1642 static float color0[4] = {1.0f, 0.0f, 0.0f, 1.0f};
1643 static float color1[4] = {0.0f, 1.0f, 0.0f, 1.0f};
1644 static float color2[4] = {0.0f, 0.0f, 1.0f, 1.0f};
1645 static float src_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
1646
1647 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1648 {
1649 ImGui::ListBox("Blending mode", &current_blend_index,
1650 blend_mode_names.data(), blend_mode_names.size());
1651 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
1652 ImGui::ColorEdit4("Color A", color0);
1653 ImGui::ColorEdit4("Color B", color1);
1654 ImGui::ColorEdit4("Color C", color2);
1655 ImGui::ColorEdit4("Source Color", src_color);
1656 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
1657 }
1658 ImGui::End();
1659
1660 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1661 SkPoint::Make(200, 100),
1662 SkPoint::Make(300, 300)};
1663 std::vector<flutter::DlColor> colors = {
1664 toColor(color0).modulateOpacity(dst_alpha),
1665 toColor(color1).modulateOpacity(dst_alpha),
1666 toColor(color2).modulateOpacity(dst_alpha)};
1667
1668 auto vertices = flutter::DlVertices::Make(
1669 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1670 /*texture_coorindates=*/nullptr, colors.data());
1671
1672 flutter::DisplayListBuilder builder;
1673 flutter::DlPaint paint;
1674
1675 paint.setColor(toColor(src_color).modulateOpacity(src_alpha));
1676 builder.DrawVertices(vertices, blend_mode_values[current_blend_index],
1677 paint);
1678 return builder.Build();
1679 };
1680
1681 ASSERT_TRUE(OpenPlaygroundHere(callback));
1682 }

References impeller::kColor, and toColor().

## ◆ TEST_P() [208/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesImageSourceWithTextureCoordinates |
| ) |  |

Definition at line 1459 of file dl_unittests.cc.

1459 {
1460 auto texture = CreateTextureForFixture("embarcadero.jpg");
1461 auto dl_image = DlImageImpeller::Make(texture);
1462 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1463 SkPoint::Make(200, 100),
1464 SkPoint::Make(300, 300)};
1465 std::vector<SkPoint> texture_coordinates = {
1466 SkPoint::Make(0, 0), SkPoint::Make(100, 200), SkPoint::Make(200, 100)};
1467
1468 auto vertices = flutter::DlVertices::Make(
1469 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1470 texture_coordinates.data(), /*colors=*/nullptr);
1471
1472 flutter::DisplayListBuilder builder;
1473 flutter::DlPaint paint;
1474
1475 auto image_source = flutter::DlImageColorSource(
1476 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
1477
1478 paint.setColorSource(&image_source);
1479 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1480
1481 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1482 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [209/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesImageSourceWithTextureCoordinatesAndColorBlending |
| ) |  |

Definition at line 1484 of file dl_unittests.cc.

1485 {
1486 auto texture = CreateTextureForFixture("embarcadero.jpg");
1487 auto dl_image = DlImageImpeller::Make(texture);
1488 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1489 SkPoint::Make(200, 100),
1490 SkPoint::Make(300, 300)};
1491 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
1492 flutter::DlColor::kGreen(),
1493 flutter::DlColor::kWhite()};
1494 std::vector<SkPoint> texture_coordinates = {
1495 SkPoint::Make(0, 0), SkPoint::Make(100, 200), SkPoint::Make(200, 100)};
1496
1497 auto vertices = flutter::DlVertices::Make(
1498 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1499 texture_coordinates.data(), colors.data());
1500
1501 flutter::DisplayListBuilder builder;
1502 flutter::DlPaint paint;
1503
1504 auto image_source = flutter::DlImageColorSource(
1505 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
1506
1507 paint.setColorSource(&image_source);
1508 builder.DrawVertices(vertices, flutter::DlBlendMode::kModulate, paint);
1509
1510 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1511 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [210/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesLinearGradientWithoutIndices |
| ) |  |

Definition at line 1404 of file dl_unittests.cc.

1404 {
1405 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1406 SkPoint::Make(200, 100),
1407 SkPoint::Make(300, 300)};
1408
1409 auto vertices = flutter::DlVertices::Make(
1410 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1411 /*texture_coorindates=*/nullptr, /*colors=*/nullptr);
1412
1413 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
1414 flutter::DlColor::kRed()};
1415 const float stops[2] = {0.0, 1.0};
1416
1417 auto linear = flutter::DlColorSource::MakeLinear(
1418 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
1419 flutter::DlTileMode::kRepeat);
1420
1421 flutter::DisplayListBuilder builder;
1422 flutter::DlPaint paint;
1423
1424 paint.setColorSource(linear);
1425 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1426
1427 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1428 }

## ◆ TEST_P() [211/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesLinearGradientWithTextureCoordinates |
| ) |  |

Definition at line 1430 of file dl_unittests.cc.

1430 {
1431 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1432 SkPoint::Make(200, 100),
1433 SkPoint::Make(300, 300)};
1434 std::vector<SkPoint> texture_coordinates = {SkPoint::Make(300, 100),
1435 SkPoint::Make(100, 200),
1436 SkPoint::Make(300, 300)};
1437
1438 auto vertices = flutter::DlVertices::Make(
1439 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1440 texture_coordinates.data(), /*colors=*/nullptr);
1441
1442 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
1443 flutter::DlColor::kRed()};
1444 const float stops[2] = {0.0, 1.0};
1445
1446 auto linear = flutter::DlColorSource::MakeLinear(
1447 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
1448 flutter::DlTileMode::kRepeat);
1449
1450 flutter::DisplayListBuilder builder;
1451 flutter::DlPaint paint;
1452
1453 paint.setColorSource(linear);
1454 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1455
1456 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1457 }

## ◆ TEST_P() [212/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesPremultipliesColors |
| ) |  |

Definition at line 1532 of file dl_unittests.cc.

1532 {
1533 std::vector<SkPoint> positions = {
1534 SkPoint::Make(100, 300), SkPoint::Make(200, 100), SkPoint::Make(300, 300),
1535 SkPoint::Make(200, 500)};
1536 auto color = flutter::DlColor::kBlue().withAlpha(0x99);
1537 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
1538 std::vector<flutter::DlColor> colors = {color, color, color, color};
1539
1540 auto vertices = flutter::DlVertices::Make(
1541 flutter::DlVertexMode::kTriangles, 6, positions.data(),
1542 /*texture_coorindates=*/nullptr, colors.data(), 6, indices.data());
1543
1544 flutter::DisplayListBuilder builder;
1545 flutter::DlPaint paint;
1546 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
1547 paint.setColor(flutter::DlColor::kRed());
1548
1549 builder.DrawRect(SkRect::MakeLTRB(0, 0, 400, 400), paint);
1550 builder.DrawVertices(vertices, flutter::DlBlendMode::kDst, paint);
1551
1552 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1553 }

## ◆ TEST_P() [213/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesSolidColorTrianglesWithIndices |
| ) |  |

Definition at line 1513 of file dl_unittests.cc.

1513 {
1514 std::vector<SkPoint> positions = {
1515 SkPoint::Make(100, 300), SkPoint::Make(200, 100), SkPoint::Make(300, 300),
1516 SkPoint::Make(200, 500)};
1517 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
1518
1519 auto vertices = flutter::DlVertices::Make(
1520 flutter::DlVertexMode::kTriangles, 6, positions.data(),
1521 /*texture_coorindates=*/nullptr, /*colors=*/nullptr, 6, indices.data());
1522
1523 flutter::DisplayListBuilder builder;
1524 flutter::DlPaint paint;
1525
1526 paint.setColor(flutter::DlColor::kWhite());
1527 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1528
1529 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1530 }

## ◆ TEST_P() [214/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesSolidColorTrianglesWithoutIndices |
| ) |  |

Definition at line 1380 of file dl_unittests.cc.

1380 {
1381 // Use negative coordinates and then scale the transform by -1, -1 to make
1382 // sure coverage is taking the transform into account.
1383 std::vector<SkPoint> positions = {SkPoint::Make(-100, -300),
1384 SkPoint::Make(-200, -100),
1385 SkPoint::Make(-300, -300)};
1386 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
1387 flutter::DlColor::kGreen(),
1388 flutter::DlColor::kWhite()};
1389
1390 auto vertices = flutter::DlVertices::Make(
1391 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1392 /*texture_coorindates=*/nullptr, colors.data());
1393
1394 flutter::DisplayListBuilder builder;
1395 flutter::DlPaint paint;
1396
1397 paint.setColor(flutter::DlColor::kRed().modulateOpacity(0.5));
1398 builder.Scale(-1, -1);
1399 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
1400
1401 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1402 }

## ◆ TEST_P() [215/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | IgnoreMaskFilterWhenSavingLayer |
| ) |  |

Definition at line 516 of file dl_unittests.cc.

516 {
517 auto texture = CreateTextureForFixture("embarcadero.jpg");
518 flutter::DisplayListBuilder builder;
519 auto filter = flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
520 flutter::DlPaint paint;
521 paint.setMaskFilter(&filter);
522 builder.SaveLayer(nullptr, &paint);
523 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
524 flutter::DlImageSampling::kNearestNeighbor);
525 builder.Restore();
526 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
527 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [216/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | MaskBlursApplyCorrectlyToColorSources |
| ) |  |

Definition at line 1343 of file dl_unittests.cc.

1343 {
1344 auto blur_filter = std::make_shared<flutter::DlBlurMaskFilter>(
1345 flutter::DlBlurStyle::kNormal, 10);
1346
1347 flutter::DisplayListBuilder builder;
1348
1349 std::array<flutter::DlColor, 2> colors = {flutter::DlColor::kBlue(),
1350 flutter::DlColor::kGreen()};
1351 std::array<float, 2> stops = {0, 1};
1352 std::array<std::shared_ptr<flutter::DlColorSource>, 2> color_sources = {
1353 std::make_shared<flutter::DlColorColorSource>(flutter::DlColor::kWhite()),
1354 flutter::DlColorSource::MakeLinear(
1355 SkPoint::Make(0, 0), SkPoint::Make(100, 50), 2, colors.data(),
1356 stops.data(), flutter::DlTileMode::kClamp)};
1357
1358 int offset = 100;
1359 for (auto color_source : color_sources) {
1360 flutter::DlPaint paint;
1361 paint.setColorSource(color_source);
1362 paint.setMaskFilter(blur_filter);
1363
1364 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
1365 builder.DrawRRect(
1366 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, offset, 100, 50), 30, 30),
1367 paint);
1368 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1369 paint.setStrokeWidth(10);
1370 builder.DrawRRect(
1371 SkRRect::MakeRectXY(SkRect::MakeXYWH(300, offset, 100, 50), 30, 30),
1372 paint);
1373
1374 offset += 100;
1375 }
1376
1377 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1378 }

## ◆ TEST_P() [217/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | StrokedPathsDrawCorrectly |
| ) |  |

Definition at line 224 of file dl_unittests.cc.

224 {
225 auto callback = [&]() {
226 flutter::DisplayListBuilder builder;
227 flutter::DlPaint paint;
228
229 paint.setColor(flutter::DlColor::kRed());
230 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
231
232 static float stroke_width = 10.0f;
233 static int selected_stroke_type = 0;
234 static int selected_join_type = 0;
235 const char* stroke_types[] = {"Butte", "Round", "Square"};
236 const char* join_type[] = {"kMiter", "Round", "kBevel"};
237
238 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
239 ImGui::Combo("Cap", &selected_stroke_type, stroke_types,
240 sizeof(stroke_types) / sizeof(char*));
241 ImGui::Combo("Join", &selected_join_type, join_type,
242 sizeof(join_type) / sizeof(char*));
243 ImGui::SliderFloat("Stroke Width", &stroke_width, 10.0f, 50.0f);
244 ImGui::End();
245
246 flutter::DlStrokeCap cap;
247 flutter::DlStrokeJoin join;
248 switch (selected_stroke_type) {
249 case 0:
250 cap = flutter::DlStrokeCap::kButt;
251 break;
252 case 1:
253 cap = flutter::DlStrokeCap::kRound;
254 break;
255 case 2:
256 cap = flutter::DlStrokeCap::kSquare;
257 break;
258 default:
259 cap = flutter::DlStrokeCap::kButt;
260 break;
261 }
262 switch (selected_join_type) {
263 case 0:
264 join = flutter::DlStrokeJoin::kMiter;
265 break;
266 case 1:
267 join = flutter::DlStrokeJoin::kRound;
268 break;
269 case 2:
270 join = flutter::DlStrokeJoin::kBevel;
271 break;
272 default:
273 join = flutter::DlStrokeJoin::kMiter;
274 break;
275 }
276 paint.setStrokeCap(cap);
277 paint.setStrokeJoin(join);
278 paint.setStrokeWidth(stroke_width);
279
280 // Make rendering better to watch.
281 builder.Scale(1.5f, 1.5f);
282
283 // Rectangle
284 builder.Translate(100, 100);
285 builder.DrawRect(SkRect::MakeSize({100, 100}), paint);
286
287 // Rounded rectangle
288 builder.Translate(150, 0);
289 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10),
290 paint);
291
292 // Double rounded rectangle
293 builder.Translate(150, 0);
294 builder.DrawDRRect(
295 SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10),
296 SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 30), 10, 10), paint);
297
298 // Contour with duplicate join points
299 {
300 builder.Translate(150, 0);
301 SkPath path;
302 path.moveTo(0, 0);
303 path.lineTo(0, 0);
304 path.lineTo({100, 0});
305 path.lineTo({100, 0});
306 path.lineTo({100, 100});
307 builder.DrawPath(path, paint);
308 }
309
310 // Contour with duplicate start and end points
311
312 // Line.
313 builder.Translate(200, 0);
314 {
315 builder.Save();
316
317 SkPath line_path;
318 line_path.moveTo(0, 0);
319 line_path.moveTo(0, 0);
320 line_path.lineTo({0, 0});
321 line_path.lineTo({0, 0});
322 line_path.lineTo({50, 50});
323 line_path.lineTo({50, 50});
324 line_path.lineTo({100, 0});
325 line_path.lineTo({100, 0});
326 builder.DrawPath(line_path, paint);
327
328 builder.Translate(0, 100);
329 builder.DrawPath(line_path, paint);
330
331 builder.Translate(0, 100);
332 SkPath line_path2;
333 line_path2.moveTo(0, 0);
334 line_path2.lineTo(0, 0);
335 line_path2.lineTo(0, 0);
336 builder.DrawPath(line_path2, paint);
337
338 builder.Restore();
339 }
340
341 // Cubic.
342 builder.Translate(150, 0);
343 {
344 builder.Save();
345
346 SkPath cubic_path;
347 cubic_path.moveTo({0, 0});
348 cubic_path.cubicTo(0, 0, 140.0, 100.0, 140, 20);
349 builder.DrawPath(cubic_path, paint);
350
351 builder.Translate(0, 100);
352 SkPath cubic_path2;
353 cubic_path2.moveTo({0, 0});
354 cubic_path2.cubicTo(0, 0, 0, 0, 150, 150);
355 builder.DrawPath(cubic_path2, paint);
356
357 builder.Translate(0, 100);
358 SkPath cubic_path3;
359 cubic_path3.moveTo({0, 0});
360 cubic_path3.cubicTo(0, 0, 0, 0, 0, 0);
361 builder.DrawPath(cubic_path3, paint);
362
363 builder.Restore();
364 }
365
366 // Quad.
367 builder.Translate(200, 0);
368 {
369 builder.Save();
370
371 SkPath quad_path;
372 quad_path.moveTo(0, 0);
373 quad_path.moveTo(0, 0);
374 quad_path.quadTo({100, 40}, {50, 80});
375 builder.DrawPath(quad_path, paint);
376
377 builder.Translate(0, 150);
378 SkPath quad_path2;
379 quad_path2.moveTo(0, 0);
380 quad_path2.moveTo(0, 0);
381 quad_path2.quadTo({0, 0}, {100, 100});
382 builder.DrawPath(quad_path2, paint);
383
384 builder.Translate(0, 100);
385 SkPath quad_path3;
386 quad_path3.moveTo(0, 0);
387 quad_path3.quadTo({0, 0}, {0, 0});
388 builder.DrawPath(quad_path3, paint);
389
390 builder.Restore();
391 }
392 return builder.Build();
393 };
394 ASSERT_TRUE(OpenPlaygroundHere(callback));
395 }

## ◆ TEST_P() [218/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | StrokedTextNotOffsetFromNormalText |
| ) |  |

Definition at line 491 of file dl_unittests.cc.

491 {
492 flutter::DisplayListBuilder builder;
493 flutter::DlPaint paint;
494 auto const& text_blob = SkTextBlob::MakeFromString("00000", CreateTestFont());
495
496 // https://api.flutter.dev/flutter/material/Colors/blue-constant.html.
497 auto const& mat_blue = flutter::DlColor(0xFF2196f3);
498
499 // Draw a blue filled rectangle so the text is easier to see.
500 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
501 paint.setColor(mat_blue);
502 builder.DrawRect(SkRect::MakeXYWH(0, 0, 500, 500), paint);
503
504 // Draw stacked text, with stroked text on top.
505 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
506 paint.setColor(flutter::DlColor::kWhite());
507 builder.DrawTextBlob(text_blob, 250, 250, paint);
508
509 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
510 paint.setColor(flutter::DlColor::kBlack());
511 builder.DrawTextBlob(text_blob, 250, 250, paint);
512
513 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
514 }

## ◆ TEST_P() [219/317]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | TransparentShadowProducesCorrectColor |
| ) |  |

Definition at line 947 of file dl_unittests.cc.

947 {
948 DlDispatcher dispatcher;
949 dispatcher.save();
950 dispatcher.scale(1.618, 1.618);
951 dispatcher.drawShadow(SkPath{}.addRect(SkRect::MakeXYWH(0, 0, 200, 100)),
952 flutter::DlColor::kTransparent(), 15, false, 1);
953 dispatcher.restore();
954 auto picture = dispatcher.EndRecordingAsPicture();
955
956 std::shared_ptr<SolidRRectBlurContents> rrect_blur;
957 picture.pass->IterateAllEntities([&rrect_blur](Entity& entity) {
958 if (ScalarNearlyEqual(entity.GetTransformation().GetScale().x, 1.618f)) {
959 rrect_blur = std::static_pointer_cast<SolidRRectBlurContents>(
960 entity.GetContents());
961 return false;
962 }
963 return true;
964 });
965
966 ASSERT_NE(rrect_blur, nullptr);
967 ASSERT_EQ(rrect_blur->GetColor().red, 0);
968 ASSERT_EQ(rrect_blur->GetColor().green, 0);
969 ASSERT_EQ(rrect_blur->GetColor().blue, 0);
970 ASSERT_EQ(rrect_blur->GetColor().alpha, 0);
971 }

References impeller::DlDispatcher::drawShadow(), impeller::DlDispatcher::EndRecordingAsPicture(), impeller::Matrix::GetScale(), impeller::Entity::GetTransformation(), impeller::Picture::pass, impeller::DlDispatcher::restore(), impeller::DlDispatcher::save(), impeller::ScalarNearlyEqual(), impeller::DlDispatcher::scale(), and impeller::Vector3::x.

## ◆ TEST_P() [220/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | AdvancedBlendCoverageHintIsNotResetByEntityPass |
| ) |  |

Definition at line 2492 of file entity_unittests.cc.

2492 {
2493 if (GetContext()->GetCapabilities()->SupportsFramebufferFetch()) {
2494 GTEST_SKIP() << "Backends that support framebuffer fetch dont use coverage "
2495 "for advanced blends.";
2496 }
2497
2498 auto contents = std::make_shared<SolidColorContents>();
2499 contents->SetGeometry(Geometry::MakeRect({100, 100, 100, 100}));
2500 contents->SetColor(Color::Red());
2501
2502 Entity entity;
2503 entity.SetTransformation(Matrix::MakeScale(Vector3(2, 2, 1)));
2504 entity.SetBlendMode(BlendMode::kColorBurn);
2505 entity.SetContents(contents);
2506
2507 auto coverage = entity.GetCoverage();
2508 EXPECT_TRUE(coverage.has_value());
2509
2510 auto pass = std::make_unique<EntityPass>();
2511 auto test_allocator = std::make_shared<TestRenderTargetAllocator>(
2512 GetContext()->GetResourceAllocator());
2513 auto stencil_config = RenderTarget::AttachmentConfig{
2514 .storage_mode = StorageMode::kDevicePrivate,
2515 .load_action = LoadAction::kClear,
2516 .store_action = StoreAction::kDontCare,
2517 .clear_color = Color::BlackTransparent()};
2518 auto rt = RenderTarget::CreateOffscreen(
2519 *GetContext(), *test_allocator, ISize::MakeWH(1000, 1000), "Offscreen",
2520 RenderTarget::kDefaultColorAttachmentConfig, stencil_config);
2521 auto content_context = ContentContext(
2522 GetContext(), TypographerContextSkia::Make(), test_allocator);
2523 pass->AddEntity(entity);
2524
2525 EXPECT_TRUE(pass->Render(content_context, rt));
2526
2527 if (test_allocator->GetDescriptors().size() == 6u) {
2528 EXPECT_EQ(test_allocator->GetDescriptors()[0].size, ISize(1000, 1000));
2529 EXPECT_EQ(test_allocator->GetDescriptors()[1].size, ISize(1000, 1000));
2530
2531 EXPECT_EQ(test_allocator->GetDescriptors()[2].size, ISize(200, 200));
2532 EXPECT_EQ(test_allocator->GetDescriptors()[3].size, ISize(200, 200));
2533 EXPECT_EQ(test_allocator->GetDescriptors()[4].size, ISize(200, 200));
2534 EXPECT_EQ(test_allocator->GetDescriptors()[5].size, ISize(200, 200));
2535 } else if (test_allocator->GetDescriptors().size() == 9u) {
2536 // Onscreen render target.
2537 EXPECT_EQ(test_allocator->GetDescriptors()[0].size, ISize(1000, 1000));
2538 EXPECT_EQ(test_allocator->GetDescriptors()[1].size, ISize(1000, 1000));
2539 EXPECT_EQ(test_allocator->GetDescriptors()[2].size, ISize(1000, 1000));
2540 EXPECT_EQ(test_allocator->GetDescriptors()[3].size, ISize(1000, 1000));
2541 EXPECT_EQ(test_allocator->GetDescriptors()[4].size, ISize(1000, 1000));
2542
2543 EXPECT_EQ(test_allocator->GetDescriptors()[5].size, ISize(200, 200));
2544 EXPECT_EQ(test_allocator->GetDescriptors()[5].size, ISize(200, 200));
2545 EXPECT_EQ(test_allocator->GetDescriptors()[6].size, ISize(200, 200));
2546 EXPECT_EQ(test_allocator->GetDescriptors()[7].size, ISize(200, 200));
2547 } else {
2548 EXPECT_TRUE(false);
2549 }
2550 }

References impeller::Color::BlackTransparent(), impeller::RenderTarget::CreateOffscreen(), impeller::Entity::GetCoverage(), impeller::kClear, impeller::kColorBurn, impeller::RenderTarget::kDefaultColorAttachmentConfig, impeller::kDevicePrivate, impeller::kDontCare, impeller::TypographerContextSkia::Make(), impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), impeller::TSize< int64_t >::MakeWH(), impeller::Color::Red(), impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Entity::SetTransformation(), and impeller::RenderTarget::AttachmentConfig::storage_mode.

## ◆ TEST_P() [221/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | AtlasContentsSubAtlas |
| ) |  |

Definition at line 1949 of file entity_unittests.cc.

1949 {
1950 auto boston = CreateTextureForFixture("boston.jpg");
1951
1952 {
1953 auto contents = std::make_shared<AtlasContents>();
1954 contents->SetBlendMode(BlendMode::kSourceOver);
1955 contents->SetTexture(boston);
1956 contents->SetColors({
1957 Color::Red(),
1958 Color::Red(),
1959 Color::Red(),
1960 });
1961 contents->SetTextureCoordinates({
1962 Rect::MakeLTRB(0, 0, 10, 10),
1963 Rect::MakeLTRB(0, 0, 10, 10),
1964 Rect::MakeLTRB(0, 0, 10, 10),
1965 });
1966 contents->SetTransforms({
1967 Matrix::MakeTranslation(Vector2(0, 0)),
1968 Matrix::MakeTranslation(Vector2(100, 100)),
1969 Matrix::MakeTranslation(Vector2(200, 200)),
1970 });
1971
1972 // Since all colors and sample rects are the same, there should
1973 // only be a single entry in the sub atlas.
1974 auto subatlas = contents->GenerateSubAtlas();
1975 ASSERT_EQ(subatlas->sub_texture_coords.size(), 1u);
1976 }
1977
1978 {
1979 auto contents = std::make_shared<AtlasContents>();
1980 contents->SetBlendMode(BlendMode::kSourceOver);
1981 contents->SetTexture(boston);
1982 contents->SetColors({
1983 Color::Red(),
1984 Color::Green(),
1985 Color::Blue(),
1986 });
1987 contents->SetTextureCoordinates({
1988 Rect::MakeLTRB(0, 0, 10, 10),
1989 Rect::MakeLTRB(0, 0, 10, 10),
1990 Rect::MakeLTRB(0, 0, 10, 10),
1991 });
1992 contents->SetTransforms({
1993 Matrix::MakeTranslation(Vector2(0, 0)),
1994 Matrix::MakeTranslation(Vector2(100, 100)),
1995 Matrix::MakeTranslation(Vector2(200, 200)),
1996 });
1997
1998 // Since all colors are different, there are three entires.
1999 auto subatlas = contents->GenerateSubAtlas();
2000 ASSERT_EQ(subatlas->sub_texture_coords.size(), 3u);
2001
2002 // The translations are kept but the sample rects point into
2003 // different parts of the sub atlas.
2004 ASSERT_EQ(subatlas->result_texture_coords[0], Rect::MakeXYWH(0, 0, 10, 10));
2005 ASSERT_EQ(subatlas->result_texture_coords[1],
2006 Rect::MakeXYWH(11, 0, 10, 10));
2007 ASSERT_EQ(subatlas->result_texture_coords[2],
2008 Rect::MakeXYWH(22, 0, 10, 10));
2009 }
2010 }

References impeller::Color::Blue(), impeller::Color::Green(), impeller::kSourceOver, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::Color::Red().

## ◆ TEST_P() [222/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BezierCircleScaled |
| ) |  |

Definition at line 930 of file entity_unittests.cc.

930 {
931 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
932 static float scale = 20;
933
934 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
935 ImGui::SliderFloat("Scale", &scale, 1, 100);
936 ImGui::End();
937
938 Entity entity;
939 entity.SetTransformation(Matrix::MakeScale(GetContentScale()));
940 auto path = PathBuilder{}
941 .MoveTo({97.325, 34.818})
942 .CubicCurveTo({98.50862885295136, 34.81812293973836},
943 {99.46822048142015, 33.85863261475589},
944 {99.46822048142015, 32.67499810206613})
945 .CubicCurveTo({99.46822048142015, 31.491363589376355},
946 {98.50862885295136, 30.53187326439389},
947 {97.32499434685802, 30.531998226542708})
948 .CubicCurveTo({96.14153655073771, 30.532123170035373},
949 {95.18222070648729, 31.491540299350355},
950 {95.18222070648729, 32.67499810206613})
951 .CubicCurveTo({95.18222070648729, 33.85845590478189},
952 {96.14153655073771, 34.81787303409686},
953 {97.32499434685802, 34.81799797758954})
954 .Close()
955 .TakePath();
956 entity.SetTransformation(
957 Matrix::MakeScale({scale, scale, 1.0}).Translate({-90, -20, 0}));
958 entity.SetContents(SolidColorContents::Make(path, Color::Red()));
959 return entity.Render(context, pass);
960 };
961 ASSERT_TRUE(OpenPlaygroundHere(callback));
962 }

References impeller::Close(), impeller::SolidColorContents::Make(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [223/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BlendingModeOptions |
| ) |  |

Definition at line 803 of file entity_unittests.cc.

803 {
804 std::vector<const char*> blend_mode_names;
805 std::vector<BlendMode> blend_mode_values;
806 {
807 // Force an exhausiveness check with a switch. When adding blend modes,
808 // update this switch with a new name/value to make it selectable in the
809 // test GUI.
810
811 const BlendMode b{};
812 static_assert(b == BlendMode::kClear); // Ensure the first item in
813 // the switch is the first
814 // item in the enum.
815 static_assert(Entity::kLastPipelineBlendMode == BlendMode::kModulate);
816 switch (b) {
817 case BlendMode::kClear:
818 blend_mode_names.push_back("Clear");
819 blend_mode_values.push_back(BlendMode::kClear);
820 case BlendMode::kSource:
821 blend_mode_names.push_back("Source");
822 blend_mode_values.push_back(BlendMode::kSource);
823 case BlendMode::kDestination:
824 blend_mode_names.push_back("Destination");
825 blend_mode_values.push_back(BlendMode::kDestination);
826 case BlendMode::kSourceOver:
827 blend_mode_names.push_back("SourceOver");
828 blend_mode_values.push_back(BlendMode::kSourceOver);
829 case BlendMode::kDestinationOver:
830 blend_mode_names.push_back("DestinationOver");
831 blend_mode_values.push_back(BlendMode::kDestinationOver);
832 case BlendMode::kSourceIn:
833 blend_mode_names.push_back("SourceIn");
834 blend_mode_values.push_back(BlendMode::kSourceIn);
835 case BlendMode::kDestinationIn:
836 blend_mode_names.push_back("DestinationIn");
837 blend_mode_values.push_back(BlendMode::kDestinationIn);
838 case BlendMode::kSourceOut:
839 blend_mode_names.push_back("SourceOut");
840 blend_mode_values.push_back(BlendMode::kSourceOut);
841 case BlendMode::kDestinationOut:
842 blend_mode_names.push_back("DestinationOut");
843 blend_mode_values.push_back(BlendMode::kDestinationOut);
844 case BlendMode::kSourceATop:
845 blend_mode_names.push_back("SourceATop");
846 blend_mode_values.push_back(BlendMode::kSourceATop);
847 case BlendMode::kDestinationATop:
848 blend_mode_names.push_back("DestinationATop");
849 blend_mode_values.push_back(BlendMode::kDestinationATop);
850 case BlendMode::kXor:
851 blend_mode_names.push_back("Xor");
852 blend_mode_values.push_back(BlendMode::kXor);
853 case BlendMode::kPlus:
854 blend_mode_names.push_back("Plus");
855 blend_mode_values.push_back(BlendMode::kPlus);
856 case BlendMode::kModulate:
857 blend_mode_names.push_back("Modulate");
858 blend_mode_values.push_back(BlendMode::kModulate);
859 };
860 }
861
862 auto callback = [&](ContentContext& context, RenderPass& pass) {
863 auto world_matrix = Matrix::MakeScale(GetContentScale());
864 auto draw_rect = [&context, &pass, &world_matrix](
865 Rect rect, Color color, BlendMode blend_mode) -> bool {
866 using VS = SolidFillPipeline::VertexShader;
867
868 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
869 {
870 auto r = rect.GetLTRB();
871 vtx_builder.AddVertices({
872 {Point(r[0], r[1])},
873 {Point(r[2], r[1])},
874 {Point(r[2], r[3])},
875 {Point(r[0], r[1])},
876 {Point(r[2], r[3])},
877 {Point(r[0], r[3])},
878 });
879 }
880
881 Command cmd;
882 DEBUG_COMMAND_INFO(cmd, "Blended Rectangle");
883 auto options = OptionsFromPass(pass);
884 options.blend_mode = blend_mode;
885 options.primitive_type = PrimitiveType::kTriangle;
886 cmd.pipeline = context.GetSolidFillPipeline(options);
887 cmd.BindVertices(
888 vtx_builder.CreateVertexBuffer(pass.GetTransientsBuffer()));
889
890 VS::FrameInfo frame_info;
891 frame_info.mvp =
892 Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * world_matrix;
893 frame_info.color = color.Premultiply();
894 VS::BindFrameInfo(cmd,
895 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
896
897 return pass.AddCommand(std::move(cmd));
898 };
899
900 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
901 static Color color1(1, 0, 0, 0.5), color2(0, 1, 0, 0.5);
902 ImGui::ColorEdit4("Color 1", reinterpret_cast<float*>(&color1));
903 ImGui::ColorEdit4("Color 2", reinterpret_cast<float*>(&color2));
904 static int current_blend_index = 3;
905 ImGui::ListBox("Blending mode", &current_blend_index,
906 blend_mode_names.data(), blend_mode_names.size());
907 ImGui::End();
908
909 BlendMode selected_mode = blend_mode_values[current_blend_index];
910
911 Point a, b, c, d;
912 std::tie(a, b) = IMPELLER_PLAYGROUND_LINE(
913 Point(400, 100), Point(200, 300), 20, Color::White(), Color::White());
914 std::tie(c, d) = IMPELLER_PLAYGROUND_LINE(
915 Point(470, 190), Point(270, 390), 20, Color::White(), Color::White());
916
917 bool result = true;
918 result = result && draw_rect(Rect(0, 0, pass.GetRenderTargetSize().width,
919 pass.GetRenderTargetSize().height),
920 Color(), BlendMode::kClear);
921 result = result && draw_rect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), color1,
922 BlendMode::kSourceOver);
923 result = result && draw_rect(Rect::MakeLTRB(c.x, c.y, d.x, d.y), color2,
924 selected_mode);
925 return result;
926 };
927 ASSERT_TRUE(OpenPlaygroundHere(callback));
928 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::ContentContext::GetSolidFillPipeline(), IMPELLER_PLAYGROUND_LINE, impeller::kClear, impeller::kDestination, impeller::kDestinationATop, impeller::kDestinationIn, impeller::kDestinationOut, impeller::kDestinationOver, impeller::Entity::kLastPipelineBlendMode, impeller::kModulate, impeller::kPlus, impeller::kSource, impeller::kSourceATop, impeller::kSourceIn, impeller::kSourceOut, impeller::kSourceOver, impeller::kTriangle, impeller::kXor, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::OptionsFromPass(), impeller::Command::pipeline, impeller::Color::White(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [224/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BorderMaskBlurCoverageIsCorrect |
| ) |  |

Definition at line 1312 of file entity_unittests.cc.

1312 {
1313 auto fill = std::make_shared<SolidColorContents>();
1314 fill->SetGeometry(Geometry::MakeFillPath(
1315 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1316 fill->SetColor(Color::CornflowerBlue());
1317 auto border_mask_blur = FilterContents::MakeBorderMaskBlur(
1318 FilterInput::Make(fill), Radius{3}, Radius{4});
1319
1320 {
1321 Entity e;
1322 e.SetTransformation(Matrix());
1323 auto actual = border_mask_blur->GetCoverage(e);
1324 auto expected = Rect::MakeXYWH(-3, -4, 306, 408);
1325 ASSERT_TRUE(actual.has_value());
1326 ASSERT_RECT_NEAR(actual.value(), expected);
1327 }
1328
1329 {
1330 Entity e;
1331 e.SetTransformation(Matrix::MakeRotationZ(Radians{kPi / 4}));
1332 auto actual = border_mask_blur->GetCoverage(e);
1333 auto expected = Rect::MakeXYWH(-287.792, -4.94975, 504.874, 504.874);
1334 ASSERT_TRUE(actual.has_value());
1335 ASSERT_RECT_NEAR(actual.value(), expected);
1336 }
1337 }

References impeller::PathBuilder::AddRect(), ASSERT_RECT_NEAR, impeller::Color::CornflowerBlue(), impeller::kPi, impeller::FilterInput::Make(), impeller::FilterContents::MakeBorderMaskBlur(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeRotationZ(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [225/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanCreateEntity |
| ) |  |

Definition at line 70 of file entity_unittests.cc.

70 {
71 Entity entity;
72 ASSERT_TRUE(entity.GetTransformation().IsIdentity());
73 }

References impeller::Entity::GetTransformation(), and impeller::Matrix::IsIdentity().

## ◆ TEST_P() [226/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawCorrectlyWithRotatedTransformation |
| ) |  |

Definition at line 487 of file entity_unittests.cc.

487 {
488 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
489 const char* input_axis[] = {"X", "Y", "Z"};
490 static int rotation_axis_index = 0;
491 static float rotation = 0;
492 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
493 ImGui::SliderFloat("Rotation", &rotation, -kPi, kPi);
494 ImGui::Combo("Rotation Axis", &rotation_axis_index, input_axis,
495 sizeof(input_axis) / sizeof(char*));
496 Matrix rotation_matrix;
497 switch (rotation_axis_index) {
498 case 0:
499 rotation_matrix = Matrix::MakeRotationX(Radians(rotation));
500 break;
501 case 1:
502 rotation_matrix = Matrix::MakeRotationY(Radians(rotation));
503 break;
504 case 2:
505 rotation_matrix = Matrix::MakeRotationZ(Radians(rotation));
506 break;
507 default:
508 rotation_matrix = Matrix{};
509 break;
510 }
511
512 if (ImGui::Button("Reset")) {
513 rotation = 0;
514 }
515 ImGui::End();
516 Matrix current_transform =
517 Matrix::MakeScale(GetContentScale())
518 .MakeTranslation(
519 Vector3(Point(pass.GetRenderTargetSize().width / 2.0,
520 pass.GetRenderTargetSize().height / 2.0)));
521 Matrix result_transform = current_transform * rotation_matrix;
522 Path path =
523 PathBuilder{}.AddRect(Rect::MakeXYWH(-300, -400, 600, 800)).TakePath();
524
525 Entity entity;
526 entity.SetTransformation(result_transform);
527 entity.SetContents(SolidColorContents::Make(path, Color::Red()));
528 return entity.Render(context, pass);
529 };
530 ASSERT_TRUE(OpenPlaygroundHere(callback));
531 }

References impeller::PathBuilder::AddRect(), impeller::kPi, impeller::SolidColorContents::Make(), impeller::Matrix::MakeRotationX(), impeller::Matrix::MakeRotationY(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), impeller::Entity::SetTransformation(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [227/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawRect |
| ) |  |

Definition at line 225 of file entity_unittests.cc.

225 {
226 auto contents = std::make_shared<SolidColorContents>();
227 contents->SetGeometry(Geometry::MakeRect({100, 100, 100, 100}));
228 contents->SetColor(Color::Red());
229
230 Entity entity;
231 entity.SetTransformation(Matrix::MakeScale(GetContentScale()));
232 entity.SetContents(contents);
233
234 ASSERT_TRUE(OpenPlaygroundHere(entity));
235 }

References impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [228/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawRRect |
| ) |  |

Definition at line 237 of file entity_unittests.cc.

237 {
238 auto contents = std::make_shared<SolidColorContents>();
239 auto path = PathBuilder{}
240 .SetConvexity(Convexity::kConvex)
241 .AddRoundedRect({100, 100, 100, 100}, 10.0)
242 .TakePath();
243 contents->SetGeometry(Geometry::MakeFillPath(path));
244 contents->SetColor(Color::Red());
245
246 Entity entity;
247 entity.SetTransformation(Matrix::MakeScale(GetContentScale()));
248 entity.SetContents(contents);
249
250 ASSERT_TRUE(OpenPlaygroundHere(entity));
251 }

References impeller::PathBuilder::AddRoundedRect(), impeller::kConvex, impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::Color::Red(), impeller::Entity::SetContents(), impeller::PathBuilder::SetConvexity(), impeller::Entity::SetTransformation(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [229/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ClipContentsGetStencilCoverageIsCorrect |
| ) |  |

Definition at line 1648 of file entity_unittests.cc.

1648 {
1649 // Intersection: No stencil coverage, no geometry.
1650 {
1651 auto clip = std::make_shared<ClipContents>();
1652 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1653 auto result = clip->GetStencilCoverage(Entity{}, Rect{});
1654
1655 ASSERT_FALSE(result.coverage.has_value());
1656 }
1657
1658 // Intersection: No stencil coverage, with geometry.
1659 {
1660 auto clip = std::make_shared<ClipContents>();
1661 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1662 clip->SetGeometry(Geometry::MakeFillPath(
1663 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath()));
1664 auto result = clip->GetStencilCoverage(Entity{}, Rect{});
1665
1666 ASSERT_FALSE(result.coverage.has_value());
1667 }
1668
1669 // Intersection: With stencil coverage, no geometry.
1670 {
1671 auto clip = std::make_shared<ClipContents>();
1672 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1673 auto result =
1674 clip->GetStencilCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1675
1676 ASSERT_FALSE(result.coverage.has_value());
1677 }
1678
1679 // Intersection: With stencil coverage, with geometry.
1680 {
1681 auto clip = std::make_shared<ClipContents>();
1682 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1683 clip->SetGeometry(Geometry::MakeFillPath(
1684 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 50, 50)).TakePath()));
1685 auto result =
1686 clip->GetStencilCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1687
1688 ASSERT_TRUE(result.coverage.has_value());
1689 ASSERT_RECT_NEAR(result.coverage.value(), Rect::MakeLTRB(0, 0, 50, 50));
1690 ASSERT_EQ(result.type, Contents::StencilCoverage::Type::kAppend);
1691 }
1692
1693 // Difference: With stencil coverage, with geometry.
1694 {
1695 auto clip = std::make_shared<ClipContents>();
1696 clip->SetClipOperation(Entity::ClipOperation::kDifference);
1697 clip->SetGeometry(Geometry::MakeFillPath(
1698 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 50, 50)).TakePath()));
1699 auto result =
1700 clip->GetStencilCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1701
1702 ASSERT_TRUE(result.coverage.has_value());
1703 ASSERT_RECT_NEAR(result.coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
1704 ASSERT_EQ(result.type, Contents::StencilCoverage::Type::kAppend);
1705 }
1706 }

References impeller::PathBuilder::AddRect(), ASSERT_RECT_NEAR, impeller::Contents::StencilCoverage::kAppend, impeller::Entity::kDifference, impeller::Entity::kIntersect, impeller::Geometry::MakeFillPath(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [230/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ClipContentsShouldRenderIsCorrect |
| ) |  |

Definition at line 1624 of file entity_unittests.cc.

1624 {
1625 // For clip ops, `ShouldRender` should always return true.
1626
1627 // Clip.
1628 {
1629 auto clip = std::make_shared<ClipContents>();
1630 ASSERT_TRUE(clip->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1631 clip->SetGeometry(Geometry::MakeFillPath(
1632 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath()));
1633 ASSERT_TRUE(clip->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1634 ASSERT_TRUE(
1635 clip->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1636 }
1637
1638 // Clip restore.
1639 {
1640 auto restore = std::make_shared<ClipRestoreContents>();
1641 ASSERT_TRUE(
1642 restore->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1643 ASSERT_TRUE(
1644 restore->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1645 }
1646 }

References impeller::PathBuilder::AddRect(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeSize().

## ◆ TEST_P() [231/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterContentsWithLargeGeometry |
| ) |  |

Definition at line 2442 of file entity_unittests.cc.

2442 {
2443 Entity entity;
2444 entity.SetTransformation(Matrix::MakeScale(GetContentScale()));
2445 auto src_contents = std::make_shared<SolidColorContents>();
2446 src_contents->SetGeometry(
2447 Geometry::MakeRect(Rect::MakeLTRB(-300, -500, 30000, 50000)));
2448 src_contents->SetColor(Color::Red());
2449
2450 auto dst_contents = std::make_shared<SolidColorContents>();
2451 dst_contents->SetGeometry(
2452 Geometry::MakeRect(Rect::MakeLTRB(300, 500, 20000, 30000)));
2453 dst_contents->SetColor(Color::Blue());
2454
2455 auto contents = ColorFilterContents::MakeBlend(
2456 BlendMode::kSourceOver, {FilterInput::Make(dst_contents, false),
2457 FilterInput::Make(src_contents, false)});
2458 entity.SetContents(std::move(contents));
2459 ASSERT_TRUE(OpenPlaygroundHere(entity));
2460 }

References impeller::Color::Blue(), impeller::kSourceOver, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [232/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorAdvancedBlend |
| ) |  |

Definition at line 2225 of file entity_unittests.cc.

2225 {
2226 auto image = CreateTextureForFixture("boston.jpg");
2227 auto filter = ColorFilterContents::MakeBlend(
2228 BlendMode::kColorBurn, FilterInput::Make({image}), Color::Red());
2229
2230 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2231 Entity entity;
2232 entity.SetTransformation(Matrix::MakeScale(GetContentScale()) *
2233 Matrix::MakeTranslation({500, 300}) *
2234 Matrix::MakeScale(Vector2{0.5, 0.5}));
2235 entity.SetContents(filter);
2236 return entity.Render(context, pass);
2237 };
2238 ASSERT_TRUE(OpenPlaygroundHere(callback));
2239 }

References impeller::kColorBurn, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [233/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorClearBlend |
| ) |  |

Definition at line 2241 of file entity_unittests.cc.

2241 {
2242 auto image = CreateTextureForFixture("boston.jpg");
2243 auto filter = ColorFilterContents::MakeBlend(
2244 BlendMode::kClear, FilterInput::Make({image}), Color::Red());
2245
2246 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2247 Entity entity;
2248 entity.SetTransformation(Matrix::MakeScale(GetContentScale()) *
2249 Matrix::MakeTranslation({500, 300}) *
2250 Matrix::MakeScale(Vector2{0.5, 0.5}));
2251 entity.SetContents(filter);
2252 return entity.Render(context, pass);
2253 };
2254 ASSERT_TRUE(OpenPlaygroundHere(callback));
2255 }

References impeller::kClear, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [234/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorDstBlend |
| ) |  |

Definition at line 2273 of file entity_unittests.cc.

2273 {
2274 auto image = CreateTextureForFixture("boston.jpg");
2275 auto filter = ColorFilterContents::MakeBlend(
2276 BlendMode::kDestination, FilterInput::Make({image}), Color::Red());
2277
2278 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2279 Entity entity;
2280 entity.SetTransformation(Matrix::MakeScale(GetContentScale()) *
2281 Matrix::MakeTranslation({500, 300}) *
2282 Matrix::MakeScale(Vector2{0.5, 0.5}));
2283 entity.SetContents(filter);
2284 return entity.Render(context, pass);
2285 };
2286 ASSERT_TRUE(OpenPlaygroundHere(callback));
2287 }

References impeller::kDestination, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [235/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcBlend |
| ) |  |

Definition at line 2257 of file entity_unittests.cc.

2257 {
2258 auto image = CreateTextureForFixture("boston.jpg");
2259 auto filter = ColorFilterContents::MakeBlend(
2260 BlendMode::kSource, FilterInput::Make({image}), Color::Red());
2261
2262 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2263 Entity entity;
2264 entity.SetTransformation(Matrix::MakeScale(GetContentScale()) *
2265 Matrix::MakeTranslation({500, 300}) *
2266 Matrix::MakeScale(Vector2{0.5, 0.5}));
2267 entity.SetContents(filter);
2268 return entity.Render(context, pass);
2269 };
2270 ASSERT_TRUE(OpenPlaygroundHere(callback));
2271 }

References impeller::kSource, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [236/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcInBlend |
| ) |  |

Definition at line 2289 of file entity_unittests.cc.

2289 {
2290 auto image = CreateTextureForFixture("boston.jpg");
2291 auto filter = ColorFilterContents::MakeBlend(
2292 BlendMode::kSourceIn, FilterInput::Make({image}), Color::Red());
2293
2294 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2295 Entity entity;
2296 entity.SetTransformation(Matrix::MakeScale(GetContentScale()) *
2297 Matrix::MakeTranslation({500, 300}) *
2298 Matrix::MakeScale(Vector2{0.5, 0.5}));
2299 entity.SetContents(filter);
2300 return entity.Render(context, pass);
2301 };
2302 ASSERT_TRUE(OpenPlaygroundHere(callback));
2303 }

References impeller::kSourceIn, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [237/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterCoverageIsCorrect |
| ) |  |

Definition at line 1758 of file entity_unittests.cc.

1758 {
1759 // Set up a simple color background.
1760 auto fill = std::make_shared<SolidColorContents>();
1761 fill->SetGeometry(Geometry::MakeFillPath(
1762 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1763 fill->SetColor(Color::Coral());
1764
1765 // Set the color matrix filter.
1766 ColorMatrix matrix = {
1767 1, 1, 1, 1, 1, //
1768 1, 1, 1, 1, 1, //
1769 1, 1, 1, 1, 1, //
1770 1, 1, 1, 1, 1, //
1771 };
1772
1773 auto filter =
1774 ColorFilterContents::MakeColorMatrix(FilterInput::Make(fill), matrix);
1775
1776 Entity e;
1777 e.SetTransformation(Matrix());
1778
1779 // Confirm that the actual filter coverage matches the expected coverage.
1780 auto actual = filter->GetCoverage(e);
1781 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1782
1783 ASSERT_TRUE(actual.has_value());
1784 ASSERT_RECT_NEAR(actual.value(), expected);
1785 }

References impeller::PathBuilder::AddRect(), ASSERT_RECT_NEAR, impeller::Color::Coral(), impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeColorMatrix(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [238/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterEditable |
| ) |  |

Definition at line 1787 of file entity_unittests.cc.

1787 {
1788 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
1789 ASSERT_TRUE(bay_bridge);
1790
1791 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1792 // UI state.
1793 static ColorMatrix color_matrix = {
1794 1, 0, 0, 0, 0, //
1795 0, 3, 0, 0, 0, //
1796 0, 0, 1, 0, 0, //
1797 0, 0, 0, 1, 0, //
1798 };
1799 static float offset[2] = {500, 400};
1800 static float rotation = 0;
1801 static float scale[2] = {0.65, 0.65};
1802 static float skew[2] = {0, 0};
1803
1804 // Define the ImGui
1805 ImGui::Begin("Color Matrix", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1806 {
1807 std::string label = "##1";
1808 for (int i = 0; i < 20; i += 5) {
1809 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
1810 &(color_matrix.array[i]), 5, nullptr, nullptr,
1811 "%.2f", 0);
1812 label[2]++;
1813 }
1814
1815 ImGui::SliderFloat2("Translation", &offset[0], 0,
1816 pass.GetRenderTargetSize().width);
1817 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1818 ImGui::SliderFloat2("Scale", &scale[0], 0, 3);
1819 ImGui::SliderFloat2("Skew", &skew[0], -3, 3);
1820 }
1821 ImGui::End();
1822
1823 // Set the color matrix filter.
1824 auto filter = ColorFilterContents::MakeColorMatrix(
1825 FilterInput::Make(bay_bridge), color_matrix);
1826
1827 // Define the entity with the color matrix filter.
1828 Entity entity;
1829 entity.SetTransformation(
1830 Matrix::MakeScale(GetContentScale()) *
1831 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1832 Matrix::MakeRotationZ(Radians(rotation)) *
1833 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1834 Matrix::MakeSkew(skew[0], skew[1]) *
1835 Matrix::MakeTranslation(-Point(bay_bridge->GetSize()) / 2));
1836 entity.SetContents(filter);
1837 entity.Render(context, pass);
1838
1839 return true;
1840 };
1841
1842 ASSERT_TRUE(OpenPlaygroundHere(callback));
1843 }

References impeller::ColorMatrix::array, impeller::kPi, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeColorMatrix(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeSkew(), impeller::Matrix::MakeTranslation(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [239/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ConicalGradientContentsIsOpaque |
| ) |  |

Definition at line 2329 of file entity_unittests.cc.

2329 {
2330 ConicalGradientContents contents;
2331 contents.SetColors({Color::CornflowerBlue()});
2332 ASSERT_FALSE(contents.IsOpaque());
2333 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2334 ASSERT_FALSE(contents.IsOpaque());
2335 }

References impeller::Color::CornflowerBlue(), impeller::Contents::IsOpaque(), impeller::ConicalGradientContents::SetColors(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [240/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentsGetBoundsForEmptyPathReturnsNullopt |
| ) |  |

Definition at line 1253 of file entity_unittests.cc.

1253 {
1254 Entity entity;
1255 entity.SetContents(std::make_shared<SolidColorContents>());
1256 ASSERT_FALSE(entity.GetCoverage().has_value());
1257 }

References impeller::Entity::GetCoverage(), and impeller::Entity::SetContents().

## ◆ TEST_P() [241/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CoverageForStrokePathWithNegativeValuesInTransform |
| ) |  |

Definition at line 2305 of file entity_unittests.cc.

2305 {
2306 auto arrow_head = PathBuilder{}
2307 .MoveTo({50, 120})
2308 .LineTo({120, 190})
2309 .LineTo({190, 120})
2310 .TakePath();
2311 auto geometry = Geometry::MakeStrokePath(arrow_head, 15.0, 4.0, Cap::kRound,
2312 Join::kRound);
2313
2314 auto transform = Matrix::MakeTranslation({300, 300}) *
2315 Matrix::MakeRotationZ(Radians(kPiOver2));
2316 EXPECT_LT(transform.e[0][0], 0.f);
2317 auto coverage = geometry->GetCoverage(transform);
2318 ASSERT_RECT_NEAR(coverage.value(), Rect::MakeXYWH(102.5, 342.5, 85, 155));
2319 }

References ASSERT_RECT_NEAR, impeller::kPiOver2, impeller::kRound, impeller::LineTo(), impeller::Matrix::MakeRotationZ(), impeller::Geometry::MakeStrokePath(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::MoveTo().

## ◆ TEST_P() [242/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CubicCurveAndOverlapTest |
| ) |  |

Definition at line 533 of file entity_unittests.cc.

533 {
534 // Compare with https://fiddle.skia.org/c/7a05a3e186c65a8dfb732f68020aae06
535 Path path =
536 PathBuilder{}
537 .MoveTo({359.934, 96.6335})
538 .CubicCurveTo({358.189, 96.7055}, {356.436, 96.7908},
539 {354.673, 96.8895})
540 .CubicCurveTo({354.571, 96.8953}, {354.469, 96.9016},
541 {354.367, 96.9075})
542 .CubicCurveTo({352.672, 97.0038}, {350.969, 97.113},
543 {349.259, 97.2355})
544 .CubicCurveTo({349.048, 97.2506}, {348.836, 97.2678},
545 {348.625, 97.2834})
546 .CubicCurveTo({347.019, 97.4014}, {345.407, 97.5299},
547 {343.789, 97.6722})
548 .CubicCurveTo({343.428, 97.704}, {343.065, 97.7402},
549 {342.703, 97.7734})
550 .CubicCurveTo({341.221, 97.9086}, {339.736, 98.0505},
551 {338.246, 98.207})
552 .CubicCurveTo({337.702, 98.2642}, {337.156, 98.3292},
553 {336.612, 98.3894})
554 .CubicCurveTo({335.284, 98.5356}, {333.956, 98.6837},
555 {332.623, 98.8476})
556 .CubicCurveTo({332.495, 98.8635}, {332.366, 98.8818},
557 {332.237, 98.8982})
558 .LineTo({332.237, 102.601})
559 .LineTo({321.778, 102.601})
560 .LineTo({321.778, 100.382})
561 .CubicCurveTo({321.572, 100.413}, {321.367, 100.442},
562 {321.161, 100.476})
563 .CubicCurveTo({319.22, 100.79}, {317.277, 101.123},
564 {315.332, 101.479})
565 .CubicCurveTo({315.322, 101.481}, {315.311, 101.482},
566 {315.301, 101.484})
567 .LineTo({310.017, 105.94})
568 .LineTo({309.779, 105.427})
569 .LineTo({314.403, 101.651})
570 .CubicCurveTo({314.391, 101.653}, {314.379, 101.656},
571 {314.368, 101.658})
572 .CubicCurveTo({312.528, 102.001}, {310.687, 102.366},
573 {308.846, 102.748})
574 .CubicCurveTo({307.85, 102.955}, {306.855, 103.182}, {305.859, 103.4})
575 .CubicCurveTo({305.048, 103.579}, {304.236, 103.75},
576 {303.425, 103.936})
577 .LineTo({299.105, 107.578})
578 .LineTo({298.867, 107.065})
579 .LineTo({302.394, 104.185})
580 .LineTo({302.412, 104.171})
581 .CubicCurveTo({301.388, 104.409}, {300.366, 104.67},
582 {299.344, 104.921})
583 .CubicCurveTo({298.618, 105.1}, {297.89, 105.269}, {297.165, 105.455})
584 .CubicCurveTo({295.262, 105.94}, {293.36, 106.445},
585 {291.462, 106.979})
586 .CubicCurveTo({291.132, 107.072}, {290.802, 107.163},
587 {290.471, 107.257})
588 .CubicCurveTo({289.463, 107.544}, {288.455, 107.839},
589 {287.449, 108.139})
590 .CubicCurveTo({286.476, 108.431}, {285.506, 108.73},
591 {284.536, 109.035})
592 .CubicCurveTo({283.674, 109.304}, {282.812, 109.579},
593 {281.952, 109.859})
594 .CubicCurveTo({281.177, 110.112}, {280.406, 110.377},
595 {279.633, 110.638})
596 .CubicCurveTo({278.458, 111.037}, {277.256, 111.449},
597 {276.803, 111.607})
598 .CubicCurveTo({276.76, 111.622}, {276.716, 111.637},
599 {276.672, 111.653})
600 .CubicCurveTo({275.017, 112.239}, {273.365, 112.836},
601 {271.721, 113.463})
602 .LineTo({271.717, 113.449})
603 .CubicCurveTo({271.496, 113.496}, {271.238, 113.559},
604 {270.963, 113.628})
605 .CubicCurveTo({270.893, 113.645}, {270.822, 113.663},
606 {270.748, 113.682})
607 .CubicCurveTo({270.468, 113.755}, {270.169, 113.834},
608 {269.839, 113.926})
609 .CubicCurveTo({269.789, 113.94}, {269.732, 113.957},
610 {269.681, 113.972})
611 .CubicCurveTo({269.391, 114.053}, {269.081, 114.143},
612 {268.756, 114.239})
613 .CubicCurveTo({268.628, 114.276}, {268.5, 114.314},
614 {268.367, 114.354})
615 .CubicCurveTo({268.172, 114.412}, {267.959, 114.478},
616 {267.752, 114.54})
617 .CubicCurveTo({263.349, 115.964}, {258.058, 117.695},
618 {253.564, 119.252})
619 .CubicCurveTo({253.556, 119.255}, {253.547, 119.258},
620 {253.538, 119.261})
621 .CubicCurveTo({251.844, 119.849}, {250.056, 120.474},
622 {248.189, 121.131})
623 .CubicCurveTo({248, 121.197}, {247.812, 121.264}, {247.621, 121.331})
624 .CubicCurveTo({247.079, 121.522}, {246.531, 121.715},
625 {245.975, 121.912})
626 .CubicCurveTo({245.554, 122.06}, {245.126, 122.212},
627 {244.698, 122.364})
628 .CubicCurveTo({244.071, 122.586}, {243.437, 122.811},
629 {242.794, 123.04})
630 .CubicCurveTo({242.189, 123.255}, {241.58, 123.472},
631 {240.961, 123.693})
632 .CubicCurveTo({240.659, 123.801}, {240.357, 123.909},
633 {240.052, 124.018})
634 .CubicCurveTo({239.12, 124.351}, {238.18, 124.687}, {237.22, 125.032})
635 .LineTo({237.164, 125.003})
636 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
637 {235.81, 125.538})
638 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
639 {234.592, 125.977})
640 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
641 {234.59, 125.977})
642 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
643 {192.381, 141.429})
644 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
645 .LineTo({360, 160})
646 .LineTo({360, 119.256})
647 .LineTo({360, 106.332})
648 .LineTo({360, 96.6307})
649 .CubicCurveTo({359.978, 96.6317}, {359.956, 96.6326},
650 {359.934, 96.6335})
651 .Close()
652 .MoveTo({337.336, 124.143})
653 .CubicCurveTo({337.274, 122.359}, {338.903, 121.511},
654 {338.903, 121.511})
655 .CubicCurveTo({338.903, 121.511}, {338.96, 123.303},
656 {337.336, 124.143})
657 .Close()
658 .MoveTo({340.082, 121.849})
659 .CubicCurveTo({340.074, 121.917}, {340.062, 121.992},
660 {340.046, 122.075})
661 .CubicCurveTo({340.039, 122.109}, {340.031, 122.142},
662 {340.023, 122.177})
663 .CubicCurveTo({340.005, 122.26}, {339.98, 122.346},
664 {339.952, 122.437})
665 .CubicCurveTo({339.941, 122.473}, {339.931, 122.507},
666 {339.918, 122.544})
667 .CubicCurveTo({339.873, 122.672}, {339.819, 122.804},
668 {339.75, 122.938})
669 .CubicCurveTo({339.747, 122.944}, {339.743, 122.949},
670 {339.74, 122.955})
671 .CubicCurveTo({339.674, 123.08}, {339.593, 123.205},
672 {339.501, 123.328})
673 .CubicCurveTo({339.473, 123.366}, {339.441, 123.401},
674 {339.41, 123.438})
675 .CubicCurveTo({339.332, 123.534}, {339.243, 123.625},
676 {339.145, 123.714})
677 .CubicCurveTo({339.105, 123.75}, {339.068, 123.786},
678 {339.025, 123.821})
679 .CubicCurveTo({338.881, 123.937}, {338.724, 124.048},
680 {338.539, 124.143})
681 .CubicCurveTo({338.532, 123.959}, {338.554, 123.79},
682 {338.58, 123.626})
683 .CubicCurveTo({338.58, 123.625}, {338.58, 123.625}, {338.58, 123.625})
684 .CubicCurveTo({338.607, 123.455}, {338.65, 123.299},
685 {338.704, 123.151})
686 .CubicCurveTo({338.708, 123.14}, {338.71, 123.127},
687 {338.714, 123.117})
688 .CubicCurveTo({338.769, 122.971}, {338.833, 122.838},
689 {338.905, 122.712})
690 .CubicCurveTo({338.911, 122.702}, {338.916, 122.69200000000001},
691 {338.922, 122.682})
692 .CubicCurveTo({338.996, 122.557}, {339.072, 122.444},
693 {339.155, 122.34})
694 .CubicCurveTo({339.161, 122.333}, {339.166, 122.326},
695 {339.172, 122.319})
696 .CubicCurveTo({339.256, 122.215}, {339.339, 122.12},
697 {339.425, 122.037})
698 .CubicCurveTo({339.428, 122.033}, {339.431, 122.03},
699 {339.435, 122.027})
700 .CubicCurveTo({339.785, 121.687}, {340.106, 121.511},
701 {340.106, 121.511})
702 .CubicCurveTo({340.106, 121.511}, {340.107, 121.645},
703 {340.082, 121.849})
704 .Close()
705 .MoveTo({340.678, 113.245})
706 .CubicCurveTo({340.594, 113.488}, {340.356, 113.655},
707 {340.135, 113.775})
708 .CubicCurveTo({339.817, 113.948}, {339.465, 114.059},
709 {339.115, 114.151})
710 .CubicCurveTo({338.251, 114.379}, {337.34, 114.516},
711 {336.448, 114.516})
712 .CubicCurveTo({335.761, 114.516}, {335.072, 114.527},
713 {334.384, 114.513})
714 .CubicCurveTo({334.125, 114.508}, {333.862, 114.462},
715 {333.605, 114.424})
716 .CubicCurveTo({332.865, 114.318}, {332.096, 114.184},
717 {331.41, 113.883})
718 .CubicCurveTo({330.979, 113.695}, {330.442, 113.34},
719 {330.672, 112.813})
720 .CubicCurveTo({331.135, 111.755}, {333.219, 112.946},
721 {334.526, 113.833})
722 .CubicCurveTo({334.54, 113.816}, {334.554, 113.8}, {334.569, 113.784})
723 .CubicCurveTo({333.38, 112.708}, {331.749, 110.985},
724 {332.76, 110.402})
725 .CubicCurveTo({333.769, 109.82}, {334.713, 111.93},
726 {335.228, 113.395})
727 .CubicCurveTo({334.915, 111.889}, {334.59, 109.636},
728 {335.661, 109.592})
729 .CubicCurveTo({336.733, 109.636}, {336.408, 111.889},
730 {336.07, 113.389})
731 .CubicCurveTo({336.609, 111.93}, {337.553, 109.82},
732 {338.563, 110.402})
733 .CubicCurveTo({339.574, 110.984}, {337.942, 112.708},
734 {336.753, 113.784})
735 .CubicCurveTo({336.768, 113.8}, {336.782, 113.816},
736 {336.796, 113.833})
737 .CubicCurveTo({338.104, 112.946}, {340.187, 111.755},
738 {340.65, 112.813})
739 .CubicCurveTo({340.71, 112.95}, {340.728, 113.102},
740 {340.678, 113.245})
741 .Close()
742 .MoveTo({346.357, 106.771})
743 .CubicCurveTo({346.295, 104.987}, {347.924, 104.139},
744 {347.924, 104.139})
745 .CubicCurveTo({347.924, 104.139}, {347.982, 105.931},
746 {346.357, 106.771})
747 .Close()
748 .MoveTo({347.56, 106.771})
749 .CubicCurveTo({347.498, 104.987}, {349.127, 104.139},
750 {349.127, 104.139})
751 .CubicCurveTo({349.127, 104.139}, {349.185, 105.931},
752 {347.56, 106.771})
753 .Close()
754 .TakePath();
755 Entity entity;
756 entity.SetTransformation(Matrix::MakeScale(GetContentScale()));
757 entity.SetContents(SolidColorContents::Make(path, Color::Red()));
758 ASSERT_TRUE(OpenPlaygroundHere(entity));
759 }

References impeller::Close(), impeller::LineTo(), impeller::SolidColorContents::Make(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [243/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CubicCurveTest |
| ) |  |

Definition at line 465 of file entity_unittests.cc.

465 {
466 // Compare with https://fiddle.skia.org/c/b3625f26122c9de7afe7794fcf25ead3
467 Path path =
468 PathBuilder{}
469 .MoveTo({237.164, 125.003})
470 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
471 {235.81, 125.538})
472 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
473 {234.592, 125.977})
474 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
475 {234.59, 125.977})
476 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
477 {192.381, 141.429})
478 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
479 .Close()
480 .TakePath();
481 Entity entity;
482 entity.SetTransformation(Matrix::MakeScale(GetContentScale()));
483 entity.SetContents(SolidColorContents::Make(path, Color::Red()));
484 ASSERT_TRUE(OpenPlaygroundHere(entity));
485 }

References impeller::Close(), impeller::SolidColorContents::Make(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [244/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DoesNotCullEntitiesByDefault |
| ) |  |

Definition at line 1610 of file entity_unittests.cc.

1610 {
1611 auto fill = std::make_shared<SolidColorContents>();
1612 fill->SetColor(Color::CornflowerBlue());
1613 fill->SetGeometry(
1614 Geometry::MakeRect(Rect::MakeLTRB(-1000, -1000, -900, -900)));
1615
1616 Entity entity;
1617 entity.SetContents(fill);
1618
1619 // Even though the entity is offscreen, this should still render because we do
1620 // not compute the coverage intersection by default.
1621 EXPECT_TRUE(entity.ShouldRender(Rect::MakeLTRB(0, 0, 100, 100)));
1622 }

References impeller::Color::CornflowerBlue(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Entity::SetContents(), and impeller::Entity::ShouldRender().

## ◆ TEST_P() [245/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawAtlasNoColor |
| ) |  |

Definition at line 1339 of file entity_unittests.cc.

1339 {
1340 // Draws the image as four squares stiched together.
1341 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1342 auto size = atlas->GetSize();
1343 // Divide image into four quadrants.
1344 Scalar half_width = size.width / 2;
1345 Scalar half_height = size.height / 2;
1346 std::vector<Rect> texture_coordinates = {
1347 Rect::MakeLTRB(0, 0, half_width, half_height),
1348 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1349 Rect::MakeLTRB(0, half_height, half_width, size.height),
1350 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1351 // Position quadrants adjacent to eachother.
1352 std::vector<Matrix> transforms = {
1353 Matrix::MakeTranslation({0, 0, 0}),
1354 Matrix::MakeTranslation({half_width, 0, 0}),
1355 Matrix::MakeTranslation({0, half_height, 0}),
1356 Matrix::MakeTranslation({half_width, half_height, 0})};
1357 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1358
1359 contents->SetTransforms(std::move(transforms));
1360 contents->SetTextureCoordinates(std::move(texture_coordinates));
1361 contents->SetTexture(atlas);
1362 contents->SetBlendMode(BlendMode::kSource);
1363
1364 Entity e;
1365 e.SetTransformation(Matrix::MakeScale(GetContentScale()));
1366 e.SetContents(contents);
1367
1368 ASSERT_TRUE(OpenPlaygroundHere(e));
1369 }

References impeller::kSource, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [246/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawAtlasNoColorFullSize |
| ) |  |

Definition at line 1515 of file entity_unittests.cc.

1515 {
1516 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1517 auto size = atlas->GetSize();
1518 std::vector<Rect> texture_coordinates = {
1519 Rect::MakeLTRB(0, 0, size.width, size.height)};
1520 std::vector<Matrix> transforms = {Matrix::MakeTranslation({0, 0, 0})};
1521 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1522
1523 contents->SetTransforms(std::move(transforms));
1524 contents->SetTextureCoordinates(std::move(texture_coordinates));
1525 contents->SetTexture(atlas);
1526 contents->SetBlendMode(BlendMode::kSource);
1527
1528 Entity e;
1529 e.SetTransformation(Matrix::MakeScale(GetContentScale()));
1530 e.SetContents(contents);
1531
1532 ASSERT_TRUE(OpenPlaygroundHere(e));
1533 }

References impeller::kSource, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [247/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawAtlasUsesProvidedCullRectForCoverage |
| ) |  |

Definition at line 1442 of file entity_unittests.cc.

1442 {
1443 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1444 auto size = atlas->GetSize();
1445
1446 Scalar half_width = size.width / 2;
1447 Scalar half_height = size.height / 2;
1448 std::vector<Rect> texture_coordinates = {
1449 Rect::MakeLTRB(0, 0, half_width, half_height),
1450 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1451 Rect::MakeLTRB(0, half_height, half_width, size.height),
1452 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1453 std::vector<Matrix> transforms = {
1454 Matrix::MakeTranslation({0, 0, 0}),
1455 Matrix::MakeTranslation({half_width, 0, 0}),
1456 Matrix::MakeTranslation({0, half_height, 0}),
1457 Matrix::MakeTranslation({half_width, half_height, 0})};
1458
1459 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1460
1461 contents->SetTransforms(std::move(transforms));
1462 contents->SetTextureCoordinates(std::move(texture_coordinates));
1463 contents->SetTexture(atlas);
1464 contents->SetBlendMode(BlendMode::kSource);
1465
1466 auto transform = Matrix::MakeScale(GetContentScale());
1467 Entity e;
1468 e.SetTransformation(transform);
1469 e.SetContents(contents);
1470
1471 ASSERT_EQ(contents->GetCoverage(e).value(),
1472 Rect::MakeSize(size).TransformBounds(transform));
1473
1474 contents->SetCullRect(Rect::MakeLTRB(0, 0, 10, 10));
1475
1476 ASSERT_EQ(contents->GetCoverage(e).value(),
1477 Rect::MakeLTRB(0, 0, 10, 10).TransformBounds(transform));
1478 }

References impeller::kSource, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeSize(), impeller::Matrix::MakeTranslation(), impeller::Entity::SetContents(), impeller::Entity::SetTransformation(), and impeller::TRect< T >::TransformBounds().

## ◆ TEST_P() [248/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawAtlasWithColorAdvanced |
| ) |  |

Definition at line 1371 of file entity_unittests.cc.

1371 {
1372 // Draws the image as four squares stiched together.
1373 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1374 auto size = atlas->GetSize();
1375 // Divide image into four quadrants.
1376 Scalar half_width = size.width / 2;
1377 Scalar half_height = size.height / 2;
1378 std::vector<Rect> texture_coordinates = {
1379 Rect::MakeLTRB(0, 0, half_width, half_height),
1380 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1381 Rect::MakeLTRB(0, half_height, half_width, size.height),
1382 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1383 // Position quadrants adjacent to eachother.
1384 std::vector<Matrix> transforms = {
1385 Matrix::MakeTranslation({0, 0, 0}),
1386 Matrix::MakeTranslation({half_width, 0, 0}),
1387 Matrix::MakeTranslation({0, half_height, 0}),
1388 Matrix::MakeTranslation({half_width, half_height, 0})};
1389 std::vector<Color> colors = {Color::Red(), Color::Green(), Color::Blue(),
1390 Color::Yellow()};
1391 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1392
1393 contents->SetTransforms(std::move(transforms));
1394 contents->SetTextureCoordinates(std::move(texture_coordinates));
1395 contents->SetTexture(atlas);
1396 contents->SetColors(colors);
1397 contents->SetBlendMode(BlendMode::kModulate);
1398
1399 Entity e;
1400 e.SetTransformation(Matrix::MakeScale(GetContentScale()));
1401 e.SetContents(contents);
1402
1403 ASSERT_TRUE(OpenPlaygroundHere(e));
1404 }

References impeller::Color::Blue(), impeller::Color::Green(), impeller::kModulate, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Color::Red(), impeller::Entity::SetContents(), impeller::Entity::SetTransformation(), and impeller::Color::Yellow().

## ◆ TEST_P() [249/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawAtlasWithColorSimple |
| ) |  |

Definition at line 1406 of file entity_unittests.cc.

1406 {
1407 // Draws the image as four squares stiched together. Because blend modes
1408 // aren't implented this ends up as four solid color blocks.
1409 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1410 auto size = atlas->GetSize();
1411 // Divide image into four quadrants.
1412 Scalar half_width = size.width / 2;
1413 Scalar half_height = size.height / 2;
1414 std::vector<Rect> texture_coordinates = {
1415 Rect::MakeLTRB(0, 0, half_width, half_height),
1416 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1417 Rect::MakeLTRB(0, half_height, half_width, size.height),
1418 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1419 // Position quadrants adjacent to eachother.
1420 std::vector<Matrix> transforms = {
1421 Matrix::MakeTranslation({0, 0, 0}),
1422 Matrix::MakeTranslation({half_width, 0, 0}),
1423 Matrix::MakeTranslation({0, half_height, 0}),
1424 Matrix::MakeTranslation({half_width, half_height, 0})};
1425 std::vector<Color> colors = {Color::Red(), Color::Green(), Color::Blue(),
1426 Color::Yellow()};
1427 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1428
1429 contents->SetTransforms(std::move(transforms));
1430 contents->SetTextureCoordinates(std::move(texture_coordinates));
1431 contents->SetTexture(atlas);
1432 contents->SetColors(colors);
1433 contents->SetBlendMode(BlendMode::kSourceATop);
1434
1435 Entity e;
1436 e.SetTransformation(Matrix::MakeScale(GetContentScale()));
1437 e.SetContents(contents);
1438
1439 ASSERT_TRUE(OpenPlaygroundHere(e));
1440 }

References impeller::Color::Blue(), impeller::Color::Green(), impeller::kSourceATop, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Color::Red(), impeller::Entity::SetContents(), impeller::Entity::SetTransformation(), and impeller::Color::Yellow().

## ◆ TEST_P() [250/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DrawAtlasWithOpacity |
| ) |  |

Definition at line 1480 of file entity_unittests.cc.

1480 {
1481 // Draws the image as four squares stiched together slightly
1482 // opaque
1483 auto atlas = CreateTextureForFixture("bay_bridge.jpg");
1484 auto size = atlas->GetSize();
1485 // Divide image into four quadrants.
1486 Scalar half_width = size.width / 2;
1487 Scalar half_height = size.height / 2;
1488 std::vector<Rect> texture_coordinates = {
1489 Rect::MakeLTRB(0, 0, half_width, half_height),
1490 Rect::MakeLTRB(half_width, 0, size.width, half_height),
1491 Rect::MakeLTRB(0, half_height, half_width, size.height),
1492 Rect::MakeLTRB(half_width, half_height, size.width, size.height)};
1493 // Position quadrants adjacent to eachother.
1494 std::vector<Matrix> transforms = {
1495 Matrix::MakeTranslation({0, 0, 0}),
1496 Matrix::MakeTranslation({half_width, 0, 0}),
1497 Matrix::MakeTranslation({0, half_height, 0}),
1498 Matrix::MakeTranslation({half_width, half_height, 0})};
1499
1500 std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
1501
1502 contents->SetTransforms(std::move(transforms));
1503 contents->SetTextureCoordinates(std::move(texture_coordinates));
1504 contents->SetTexture(atlas);
1505 contents->SetBlendMode(BlendMode::kSource);
1506 contents->SetAlpha(0.5);
1507
1508 Entity e;
1509 e.SetTransformation(Matrix::MakeScale(GetContentScale()));
1510 e.SetContents(contents);
1511
1512 ASSERT_TRUE(OpenPlaygroundHere(e));
1513 }

References impeller::kSource, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [251/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | EntityPassCanMergeSubpassIntoParent |
| ) |  |

Definition at line 149 of file entity_unittests.cc.

149 {
150 // Both a red and a blue box should appear if the pass merging has worked
151 // correctly.
152
153 EntityPass pass;
154 auto subpass = CreatePassWithRectPath(Rect::MakeLTRB(0, 0, 100, 100),
155 Rect::MakeLTRB(50, 50, 150, 150), true);
156 pass.AddSubpass(std::move(subpass));
157
158 Entity entity;
159 entity.SetTransformation(Matrix::MakeScale(GetContentScale()));
160 auto contents = std::make_unique<SolidColorContents>();
161 contents->SetGeometry(Geometry::MakeRect(Rect::MakeLTRB(100, 100, 200, 200)));
162 contents->SetColor(Color::Blue());
163 entity.SetContents(std::move(contents));
164
165 pass.AddEntity(entity);
166
167 ASSERT_TRUE(OpenPlaygroundHere(pass));
168 }

References impeller::EntityPass::AddEntity(), impeller::EntityPass::AddSubpass(), impeller::Color::Blue(), CreatePassWithRectPath(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [252/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | EntityPassCoverageRespectsCoverageLimit |
| ) |  |

Definition at line 170 of file entity_unittests.cc.

170 {
171 // Rect is drawn entirely in negative area.
172 auto pass = CreatePassWithRectPath(Rect::MakeLTRB(-200, -200, -100, -100),
173 std::nullopt);
174
175 // Without coverage limit.
176 {
177 auto pass_coverage = pass->GetElementsCoverage(std::nullopt);
178 ASSERT_TRUE(pass_coverage.has_value());
179 ASSERT_RECT_NEAR(pass_coverage.value(),
180 Rect::MakeLTRB(-200, -200, -100, -100));
181 }
182
183 // With limit that doesn't overlap.
184 {
185 auto pass_coverage =
186 pass->GetElementsCoverage(Rect::MakeLTRB(0, 0, 100, 100));
187 ASSERT_FALSE(pass_coverage.has_value());
188 }
189
190 // With limit that partially overlaps.
191 {
192 auto pass_coverage =
193 pass->GetElementsCoverage(Rect::MakeLTRB(-150, -150, 0, 0));
194 ASSERT_TRUE(pass_coverage.has_value());
195 ASSERT_RECT_NEAR(pass_coverage.value(),
196 Rect::MakeLTRB(-150, -150, -100, -100));
197 }
198 }

References ASSERT_RECT_NEAR, CreatePassWithRectPath(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [253/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | EntityPassRespectsSubpassBoundsLimit |
| ) |  |

Definition at line 122 of file entity_unittests.cc.

122 {
123 EntityPass pass;
124
125 auto subpass0 = CreatePassWithRectPath(Rect::MakeLTRB(0, 0, 100, 100),
126 Rect::MakeLTRB(50, 50, 150, 150));
127 auto subpass1 = CreatePassWithRectPath(Rect::MakeLTRB(500, 500, 1000, 1000),
128 Rect::MakeLTRB(800, 800, 900, 900));
129
130 auto subpass0_coverage =
131 pass.GetSubpassCoverage(*subpass0.get(), std::nullopt);
132 ASSERT_TRUE(subpass0_coverage.has_value());
133 ASSERT_RECT_NEAR(subpass0_coverage.value(), Rect::MakeLTRB(50, 50, 100, 100));
134
135 auto subpass1_coverage =
136 pass.GetSubpassCoverage(*subpass1.get(), std::nullopt);
137 ASSERT_TRUE(subpass1_coverage.has_value());
138 ASSERT_RECT_NEAR(subpass1_coverage.value(),
139 Rect::MakeLTRB(800, 800, 900, 900));
140
141 pass.AddSubpass(std::move(subpass0));
142 pass.AddSubpass(std::move(subpass1));
143
144 auto coverage = pass.GetElementsCoverage(std::nullopt);
145 ASSERT_TRUE(coverage.has_value());
146 ASSERT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(50, 50, 900, 900));
147 }

References impeller::EntityPass::AddSubpass(), ASSERT_RECT_NEAR, CreatePassWithRectPath(), impeller::EntityPass::GetElementsCoverage(), impeller::EntityPass::GetSubpassCoverage(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [254/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FilterCoverageRespectsCropRect |
| ) |  |

Definition at line 200 of file entity_unittests.cc.

200 {
201 auto image = CreateTextureForFixture("boston.jpg");
202 auto filter = ColorFilterContents::MakeBlend(BlendMode::kSoftLight,
203 FilterInput::Make({image}));
204
205 // Without the crop rect (default behavior).
206 {
207 auto actual = filter->GetCoverage({});
208 auto expected = Rect::MakeSize(image->GetSize());
209
210 ASSERT_TRUE(actual.has_value());
211 ASSERT_RECT_NEAR(actual.value(), expected);
212 }
213
214 // With the crop rect.
215 {
216 auto expected = Rect::MakeLTRB(50, 50, 100, 100);
217 filter->SetCoverageHint(expected);
218 auto actual = filter->GetCoverage({});
219
220 ASSERT_TRUE(actual.has_value());
221 ASSERT_RECT_NEAR(actual.value(), expected);
222 }
223 }

References ASSERT_RECT_NEAR, impeller::kSoftLight, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeSize().

## ◆ TEST_P() [255/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | Filters |
| ) |  |

Definition at line 964 of file entity_unittests.cc.

964 {
965 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
966 auto boston = CreateTextureForFixture("boston.jpg");
967 auto kalimba = CreateTextureForFixture("kalimba.jpg");
968 ASSERT_TRUE(bridge && boston && kalimba);
969
970 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
971 auto fi_bridge = FilterInput::Make(bridge);
972 auto fi_boston = FilterInput::Make(boston);
973 auto fi_kalimba = FilterInput::Make(kalimba);
974
975 std::shared_ptr<FilterContents> blend0 = ColorFilterContents::MakeBlend(
976 BlendMode::kModulate, {fi_kalimba, fi_boston});
977
978 auto blend1 = ColorFilterContents::MakeBlend(
979 BlendMode::kScreen,
980 {FilterInput::Make(blend0), fi_bridge, fi_bridge, fi_bridge});
981
982 Entity entity;
983 entity.SetTransformation(Matrix::MakeScale(GetContentScale()) *
984 Matrix::MakeTranslation({500, 300}) *
985 Matrix::MakeScale(Vector2{0.5, 0.5}));
986 entity.SetContents(blend1);
987 return entity.Render(context, pass);
988 };
989 ASSERT_TRUE(OpenPlaygroundHere(callback));
990 }

References impeller::kModulate, impeller::kScreen, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [256/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GaussianBlurFilter |
| ) |  |

Definition at line 992 of file entity_unittests.cc.

992 {
993 auto boston = CreateTextureForFixture("boston.jpg");
994 ASSERT_TRUE(boston);
995
996 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
997 const char* input_type_names[] = {"Texture", "Solid Color"};
998 const char* blur_type_names[] = {"Image blur", "Mask blur"};
999 const char* pass_variation_names[] = {"Two pass", "Directional"};
1000 const char* blur_style_names[] = {"Normal", "Solid", "Outer", "Inner"};
1001 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1002 const FilterContents::BlurStyle blur_styles[] = {
1003 FilterContents::BlurStyle::kNormal, FilterContents::BlurStyle::kSolid,
1004 FilterContents::BlurStyle::kOuter, FilterContents::BlurStyle::kInner};
1005 const Entity::TileMode tile_modes[] = {
1006 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
1007 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
1008
1009 // UI state.
1010 static int selected_input_type = 0;
1011 static Color input_color = Color::Black();
1012 static int selected_blur_type = 0;
1013 static int selected_pass_variation = 0;
1014 static float blur_amount_coarse[2] = {0, 0};
1015 static float blur_amount_fine[2] = {10, 10};
1016 static int selected_blur_style = 0;
1017 static int selected_tile_mode = 3;
1018 static Color cover_color(1, 0, 0, 0.2);
1019 static Color bounds_color(0, 1, 0, 0.1);
1020 static float offset[2] = {500, 400};
1021 static float rotation = 0;
1022 static float scale[2] = {0.65, 0.65};
1023 static float skew[2] = {0, 0};
1024 static float path_rect[4] = {0, 0,
1025 static_cast<float>(boston->GetSize().width),
1026 static_cast<float>(boston->GetSize().height)};
1027
1028 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1029 {
1030 ImGui::Combo("Input type", &selected_input_type, input_type_names,
1031 sizeof(input_type_names) / sizeof(char*));
1032 if (selected_input_type == 0) {
1033 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
1034 } else {
1035 ImGui::ColorEdit4("Input color",
1036 reinterpret_cast<float*>(&input_color));
1037 }
1038 ImGui::Combo("Blur type", &selected_blur_type, blur_type_names,
1039 sizeof(blur_type_names) / sizeof(char*));
1040 if (selected_blur_type == 0) {
1041 ImGui::Combo("Pass variation", &selected_pass_variation,
1042 pass_variation_names,
1043 sizeof(pass_variation_names) / sizeof(char*));
1044 }
1045 ImGui::SliderFloat2("Sigma (coarse)", blur_amount_coarse, 0, 1000);
1046 ImGui::SliderFloat2("Sigma (fine)", blur_amount_fine, 0, 10);
1047 ImGui::Combo("Blur style", &selected_blur_style, blur_style_names,
1048 sizeof(blur_style_names) / sizeof(char*));
1049 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1050 sizeof(tile_mode_names) / sizeof(char*));
1051 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1052 ImGui::ColorEdit4("Bounds color",
1053 reinterpret_cast<float*>(&bounds_color));
1054 ImGui::SliderFloat2("Translation", offset, 0,
1055 pass.GetRenderTargetSize().width);
1056 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1057 ImGui::SliderFloat2("Scale", scale, 0, 3);
1058 ImGui::SliderFloat2("Skew", skew, -3, 3);
1059 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1060 }
1061 ImGui::End();
1062
1063 auto blur_sigma_x = Sigma{blur_amount_coarse[0] + blur_amount_fine[0]};
1064 auto blur_sigma_y = Sigma{blur_amount_coarse[1] + blur_amount_fine[1]};
1065
1066 std::shared_ptr<Contents> input;
1067 Size input_size;
1068
1069 auto input_rect =
1070 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1071 if (selected_input_type == 0) {
1072 auto texture = std::make_shared<TextureContents>();
1073 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1074 texture->SetDestinationRect(input_rect);
1075 texture->SetTexture(boston);
1076 texture->SetOpacity(input_color.alpha);
1077
1078 input = texture;
1079 input_size = input_rect.size;
1080 } else {
1081 auto fill = std::make_shared<SolidColorContents>();
1082 fill->SetColor(input_color);
1083 fill->SetGeometry(
1084 Geometry::MakeFillPath(PathBuilder{}.AddRect(input_rect).TakePath()));
1085
1086 input = fill;
1087 input_size = input_rect.size;
1088 }
1089
1090 std::shared_ptr<FilterContents> blur;
1091 if (selected_pass_variation == 0) {
1092 blur = FilterContents::MakeGaussianBlur(
1093 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1094 blur_styles[selected_blur_style], tile_modes[selected_tile_mode]);
1095 } else {
1096 Vector2 blur_vector(blur_sigma_x.sigma, blur_sigma_y.sigma);
1097 blur = FilterContents::MakeDirectionalGaussianBlur(
1098 FilterInput::Make(input), Sigma{blur_vector.GetLength()},
1099 blur_vector.Normalize());
1100 }
1101
1102 auto mask_blur = FilterContents::MakeBorderMaskBlur(
1103 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1104 blur_styles[selected_blur_style]);
1105
1106 auto ctm = Matrix::MakeScale(GetContentScale()) *
1107 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1108 Matrix::MakeRotationZ(Radians(rotation)) *
1109 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1110 Matrix::MakeSkew(skew[0], skew[1]) *
1111 Matrix::MakeTranslation(-Point(input_size) / 2);
1112
1113 auto target_contents = selected_blur_type == 0 ? blur : mask_blur;
1114
1115 Entity entity;
1116 entity.SetContents(target_contents);
1117 entity.SetTransformation(ctm);
1118
1119 entity.Render(context, pass);
1120
1121 // Renders a red "cover" rectangle that shows the original position of the
1122 // unfiltered input.
1123 Entity cover_entity;
1124 cover_entity.SetContents(SolidColorContents::Make(
1125 PathBuilder{}.AddRect(input_rect).TakePath(), cover_color));
1126 cover_entity.SetTransformation(ctm);
1127
1128 cover_entity.Render(context, pass);
1129
1130 // Renders a green bounding rect of the target filter.
1131 Entity bounds_entity;
1132 bounds_entity.SetContents(SolidColorContents::Make(
1133 PathBuilder{}
1134 .AddRect(target_contents->GetCoverage(entity).value())
1135 .TakePath(),
1136 bounds_color));
1137 bounds_entity.SetTransformation(Matrix());
1138
1139 bounds_entity.Render(context, pass);
1140
1141 return true;
1142 };
1143 ASSERT_TRUE(OpenPlaygroundHere(callback));
1144 }

References impeller::PathBuilder::AddRect(), impeller::Color::alpha, impeller::Color::Black(), impeller::TPoint< T >::GetLength(), impeller::Entity::kClamp, impeller::Entity::kDecal, impeller::FilterContents::kInner, impeller::Entity::kMirror, impeller::FilterContents::kNormal, impeller::FilterContents::kOuter, impeller::kPi, impeller::Entity::kRepeat, impeller::FilterContents::kSolid, impeller::SolidColorContents::Make(), impeller::FilterInput::Make(), impeller::FilterContents::MakeBorderMaskBlur(), impeller::FilterContents::MakeDirectionalGaussianBlur(), impeller::Geometry::MakeFillPath(), impeller::FilterContents::MakeGaussianBlur(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeSize(), impeller::Matrix::MakeSkew(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::TPoint< T >::Normalize(), impeller::Entity::Render(), impeller::Entity::SetContents(), impeller::Entity::SetTransformation(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [257/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GeometryBoundsAreTransformed |
| ) |  |

Definition at line 253 of file entity_unittests.cc.

253 {
254 auto geometry = Geometry::MakeRect({100, 100, 100, 100});
255 auto transform = Matrix::MakeScale({2.0, 2.0, 2.0});
256
257 ASSERT_RECT_NEAR(geometry->GetCoverage(transform).value(),
258 Rect(200, 200, 200, 200));
259 }

References ASSERT_RECT_NEAR, impeller::Geometry::MakeRect(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [258/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | InheritOpacityTest |
| ) |  |

Definition at line 2154 of file entity_unittests.cc.

2154 {
2155 Entity entity;
2156
2157 // Texture contents can always accept opacity.
2158 auto texture_contents = std::make_shared<TextureContents>();
2159 texture_contents->SetOpacity(0.5);
2160 ASSERT_TRUE(texture_contents->CanInheritOpacity(entity));
2161
2162 texture_contents->SetInheritedOpacity(0.5);
2163 ASSERT_EQ(texture_contents->GetOpacity(), 0.25);
2164 texture_contents->SetInheritedOpacity(0.5);
2165 ASSERT_EQ(texture_contents->GetOpacity(), 0.25);
2166
2167 // Solid color contents can accept opacity if their geometry
2168 // doesn't overlap.
2169 auto solid_color = std::make_shared<SolidColorContents>();
2170 solid_color->SetGeometry(
2171 Geometry::MakeRect(Rect::MakeLTRB(100, 100, 200, 200)));
2172 solid_color->SetColor(Color::Blue().WithAlpha(0.5));
2173
2174 ASSERT_TRUE(solid_color->CanInheritOpacity(entity));
2175
2176 solid_color->SetInheritedOpacity(0.5);
2177 ASSERT_EQ(solid_color->GetColor().alpha, 0.25);
2178 solid_color->SetInheritedOpacity(0.5);
2179 ASSERT_EQ(solid_color->GetColor().alpha, 0.25);
2180
2181 // Color source contents can accept opacity if their geometry
2182 // doesn't overlap.
2183 auto tiled_texture = std::make_shared<TiledTextureContents>();
2184 tiled_texture->SetGeometry(
2185 Geometry::MakeRect(Rect::MakeLTRB(100, 100, 200, 200)));
2186 tiled_texture->SetOpacityFactor(0.5);
2187
2188 ASSERT_TRUE(tiled_texture->CanInheritOpacity(entity));
2189
2190 tiled_texture->SetInheritedOpacity(0.5);
2191 ASSERT_EQ(tiled_texture->GetOpacityFactor(), 0.25);
2192 tiled_texture->SetInheritedOpacity(0.5);
2193 ASSERT_EQ(tiled_texture->GetOpacityFactor(), 0.25);
2194
2195 // Text contents can accept opacity if the text frames do not
2196 // overlap
2197 SkFont font;
2198 font.setSize(30);
2199 auto blob = SkTextBlob::MakeFromString("A", font);
2200 auto frame = MakeTextFrameFromTextBlobSkia(blob);
2201 auto lazy_glyph_atlas =
2202 std::make_shared<LazyGlyphAtlas>(TypographerContextSkia::Make());
2203 lazy_glyph_atlas->AddTextFrame(*frame, 1.0f);
2204
2205 auto text_contents = std::make_shared<TextContents>();
2206 text_contents->SetTextFrame(frame);
2207 text_contents->SetColor(Color::Blue().WithAlpha(0.5));
2208
2209 ASSERT_TRUE(text_contents->CanInheritOpacity(entity));
2210
2211 text_contents->SetInheritedOpacity(0.5);
2212 ASSERT_EQ(text_contents->GetColor().alpha, 0.25);
2213 text_contents->SetInheritedOpacity(0.5);
2214 ASSERT_EQ(text_contents->GetColor().alpha, 0.25);
2215
2216 // Clips and restores trivially accept opacity.
2217 ASSERT_TRUE(ClipContents().CanInheritOpacity(entity));
2218 ASSERT_TRUE(ClipRestoreContents().CanInheritOpacity(entity));
2219
2220 // Runtime effect contents can't accept opacity.
2221 auto runtime_effect = std::make_shared<RuntimeEffectContents>();
2222 ASSERT_FALSE(runtime_effect->CanInheritOpacity(entity));
2223 }

References impeller::Color::Blue(), impeller::TypographerContextSkia::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [259/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearGradientContentsIsOpaque |
| ) |  |

Definition at line 2337 of file entity_unittests.cc.

2337 {
2338 LinearGradientContents contents;
2339 contents.SetColors({Color::CornflowerBlue()});
2340 ASSERT_TRUE(contents.IsOpaque());
2341 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2342 ASSERT_FALSE(contents.IsOpaque());
2343 contents.SetColors({Color::CornflowerBlue()});
2344 contents.SetTileMode(Entity::TileMode::kDecal);
2345 ASSERT_FALSE(contents.IsOpaque());
2346 }

References impeller::Color::CornflowerBlue(), impeller::LinearGradientContents::IsOpaque(), impeller::Entity::kDecal, impeller::LinearGradientContents::SetColors(), impeller::LinearGradientContents::SetTileMode(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [260/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilter |
| ) |  |

Definition at line 1866 of file entity_unittests.cc.

1866 {
1867 auto image = CreateTextureForFixture("kalimba.jpg");
1868 ASSERT_TRUE(image);
1869
1870 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1871 auto filtered =
1872 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(image));
1873
1874 // Define the entity that will serve as the control image as a Gaussian blur
1875 // filter with no filter at all.
1876 Entity entity_left;
1877 entity_left.SetTransformation(Matrix::MakeScale(GetContentScale()) *
1878 Matrix::MakeTranslation({100, 300}) *
1879 Matrix::MakeScale(Vector2{0.5, 0.5}));
1880 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1881 Sigma{0}, Sigma{0});
1882 entity_left.SetContents(unfiltered);
1883
1884 // Define the entity that will be filtered from linear to sRGB.
1885 Entity entity_right;
1886 entity_right.SetTransformation(Matrix::MakeScale(GetContentScale()) *
1887 Matrix::MakeTranslation({500, 300}) *
1888 Matrix::MakeScale(Vector2{0.5, 0.5}));
1889 entity_right.SetContents(filtered);
1890 return entity_left.Render(context, pass) &&
1891 entity_right.Render(context, pass);
1892 };
1893
1894 ASSERT_TRUE(OpenPlaygroundHere(callback));
1895 }

References impeller::FilterInput::Make(), impeller::FilterContents::MakeGaussianBlur(), impeller::ColorFilterContents::MakeLinearToSrgbFilter(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [261/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilterCoverageIsCorrect |
| ) |  |

Definition at line 1845 of file entity_unittests.cc.

1845 {
1846 // Set up a simple color background.
1847 auto fill = std::make_shared<SolidColorContents>();
1848 fill->SetGeometry(Geometry::MakeFillPath(
1849 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1850 fill->SetColor(Color::MintCream());
1851
1852 auto filter =
1853 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(fill));
1854
1855 Entity e;
1856 e.SetTransformation(Matrix());
1857
1858 // Confirm that the actual filter coverage matches the expected coverage.
1859 auto actual = filter->GetCoverage(e);
1860 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1861
1862 ASSERT_TRUE(actual.has_value());
1863 ASSERT_RECT_NEAR(actual.value(), expected);
1864 }

References impeller::PathBuilder::AddRect(), ASSERT_RECT_NEAR, impeller::FilterInput::Make(), impeller::Geometry::MakeFillPath(), impeller::ColorFilterContents::MakeLinearToSrgbFilter(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::MintCream(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [262/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | MorphologyFilter |
| ) |  |

Definition at line 1146 of file entity_unittests.cc.

1146 {
1147 auto boston = CreateTextureForFixture("boston.jpg");
1148 ASSERT_TRUE(boston);
1149
1150 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1151 const char* morphology_type_names[] = {"Dilate", "Erode"};
1152 const FilterContents::MorphType morphology_types[] = {
1153 FilterContents::MorphType::kDilate, FilterContents::MorphType::kErode};
1154 static Color input_color = Color::Black();
1155 // UI state.
1156 static int selected_morphology_type = 0;
1157 static float radius[2] = {20, 20};
1158 static Color cover_color(1, 0, 0, 0.2);
1159 static Color bounds_color(0, 1, 0, 0.1);
1160 static float offset[2] = {500, 400};
1161 static float rotation = 0;
1162 static float scale[2] = {0.65, 0.65};
1163 static float skew[2] = {0, 0};
1164 static float path_rect[4] = {0, 0,
1165 static_cast<float>(boston->GetSize().width),
1166 static_cast<float>(boston->GetSize().height)};
1167 static float effect_transform_scale = 1;
1168
1169 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1170 {
1171 ImGui::Combo("Morphology type", &selected_morphology_type,
1172 morphology_type_names,
1173 sizeof(morphology_type_names) / sizeof(char*));
1174 ImGui::SliderFloat2("Radius", radius, 0, 200);
1175 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
1176 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1177 ImGui::ColorEdit4("Bounds color",
1178 reinterpret_cast<float*>(&bounds_color));
1179 ImGui::SliderFloat2("Translation", offset, 0,
1180 pass.GetRenderTargetSize().width);
1181 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1182 ImGui::SliderFloat2("Scale", scale, 0, 3);
1183 ImGui::SliderFloat2("Skew", skew, -3, 3);
1184 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1185 ImGui::SliderFloat("Effect transform scale", &effect_transform_scale, 0,
1186 3);
1187 }
1188 ImGui::End();
1189
1190 std::shared_ptr<Contents> input;
1191 Size input_size;
1192
1193 auto input_rect =
1194 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1195 auto texture = std::make_shared<TextureContents>();
1196 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1197 texture->SetDestinationRect(input_rect);
1198 texture->SetTexture(boston);
1199 texture->SetOpacity(input_color.alpha);
1200
1201 input = texture;
1202 input_size = input_rect.size;
1203
1204 auto contents = FilterContents::MakeMorphology(
1205 FilterInput::Make(input), Radius{radius[0]}, Radius{radius[1]},
1206 morphology_types[selected_morphology_type]);
1207 contents->SetEffectTransform(Matrix::MakeScale(
1208 Vector2{effect_transform_scale, effect_transform_scale}));
1209
1210 auto ctm = Matrix::MakeScale(GetContentScale()) *
1211 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1212 Matrix::MakeRotationZ(Radians(rotation)) *
1213 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1214 Matrix::MakeSkew(skew[0], skew[1]) *
1215 Matrix::MakeTranslation(-Point(input_size) / 2);
1216
1217 Entity entity;
1218 entity.SetContents(contents);
1219 entity.SetTransformation(ctm);
1220
1221 entity.Render(context, pass);
1222
1223 // Renders a red "cover" rectangle that shows the original position of the
1224 // unfiltered input.
1225 Entity cover_entity;
1226 cover_entity.SetContents(SolidColorContents::Make(
1227 PathBuilder{}.AddRect(input_rect).TakePath(), cover_color));
1228 cover_entity.SetTransformation(ctm);
1229
1230 cover_entity.Render(context, pass);
1231
1232 // Renders a green bounding rect of the target filter.
1233 Entity bounds_entity;
1234 bounds_entity.SetContents(SolidColorContents::Make(
1235 PathBuilder{}.AddRect(contents->GetCoverage(entity).value()).TakePath(),
1236 bounds_color));
1237 bounds_entity.SetTransformation(Matrix());
1238
1239 bounds_entity.Render(context, pass);
1240
1241 return true;
1242 };
1243 ASSERT_TRUE(OpenPlaygroundHere(callback));
1244 }

References impeller::PathBuilder::AddRect(), impeller::Color::alpha, impeller::Color::Black(), impeller::FilterContents::kDilate, impeller::FilterContents::kErode, impeller::kPi, impeller::SolidColorContents::Make(), impeller::FilterInput::Make(), impeller::FilterContents::MakeMorphology(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeSize(), impeller::Matrix::MakeSkew(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Entity::Render(), impeller::Entity::SetContents(), impeller::Entity::SetTransformation(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [263/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | PointFieldGeometryCoverage |
| ) |  |

Definition at line 2434 of file entity_unittests.cc.

2434 {
2435 std::vector<Point> points = {{10, 20}, {100, 200}};
2436 auto geometry = Geometry::MakePointField(points, 5.0, false);
2437 ASSERT_EQ(*geometry->GetCoverage(Matrix()), Rect::MakeLTRB(5, 15, 105, 205));
2438 ASSERT_EQ(*geometry->GetCoverage(Matrix::MakeTranslation({30, 0, 0})),
2439 Rect::MakeLTRB(35, 15, 135, 205));
2440 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakePointField(), and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [264/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | PointFieldGeometryDivisions |
| ) |  |

Definition at line 2416 of file entity_unittests.cc.

2416 {
2417 // Square always gives 4 divisions.
2418 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(24.0, false), 4u);
2419 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(2.0, false), 4u);
2420 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(200.0, false), 4u);
2421
2422 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(0.5, true), 4u);
2423 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(1.5, true), 8u);
2424 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(5.5, true), 24u);
2425 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(12.5, true), 34u);
2426 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(22.3, true), 22u);
2427 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(40.5, true), 40u);
2428 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(100.0, true), 100u);
2429 // Caps at 140.
2430 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(1000.0, true), 140u);
2431 ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(20000.0, true), 140u);
2432 }

References impeller::PointFieldGeometry::ComputeCircleDivisions().

## ◆ TEST_P() [265/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RadialGradientContentsIsOpaque |
| ) |  |

Definition at line 2348 of file entity_unittests.cc.

2348 {
2349 RadialGradientContents contents;
2350 contents.SetColors({Color::CornflowerBlue()});
2351 ASSERT_TRUE(contents.IsOpaque());
2352 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2353 ASSERT_FALSE(contents.IsOpaque());
2354 contents.SetColors({Color::CornflowerBlue()});
2355 contents.SetTileMode(Entity::TileMode::kDecal);
2356 ASSERT_FALSE(contents.IsOpaque());
2357 }

References impeller::Color::CornflowerBlue(), impeller::RadialGradientContents::IsOpaque(), impeller::Entity::kDecal, impeller::RadialGradientContents::SetColors(), impeller::RadialGradientContents::SetTileMode(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [266/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RRectShadowTest |
| ) |  |

Definition at line 1708 of file entity_unittests.cc.

1708 {
1709 auto callback = [&](ContentContext& context, RenderPass& pass) {
1710 static Color color = Color::Red();
1711 static float corner_radius = 100;
1712 static float blur_radius = 100;
1713 static bool show_coverage = false;
1714 static Color coverage_color = Color::Green().WithAlpha(0.2);
1715
1716 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1717 ImGui::SliderFloat("Corner radius", &corner_radius, 0, 300);
1718 ImGui::SliderFloat("Blur radius", &blur_radius, 0, 300);
1719 ImGui::ColorEdit4("Color", reinterpret_cast<Scalar*>(&color));
1720 ImGui::Checkbox("Show coverage", &show_coverage);
1721 if (show_coverage) {
1722 ImGui::ColorEdit4("Coverage color",
1723 reinterpret_cast<Scalar*>(&coverage_color));
1724 }
1725 ImGui::End();
1726
1727 auto [top_left, bottom_right] = IMPELLER_PLAYGROUND_LINE(
1728 Point(200, 200), Point(600, 400), 30, Color::White(), Color::White());
1729 auto rect =
1730 Rect::MakeLTRB(top_left.x, top_left.y, bottom_right.x, bottom_right.y);
1731
1732 auto contents = std::make_unique<SolidRRectBlurContents>();
1733 contents->SetRRect(rect, corner_radius);
1734 contents->SetColor(color);
1735 contents->SetSigma(Radius(blur_radius));
1736
1737 Entity entity;
1738 entity.SetTransformation(Matrix::MakeScale(GetContentScale()));
1739 entity.SetContents(std::move(contents));
1740 entity.Render(context, pass);
1741
1742 auto coverage = entity.GetCoverage();
1743 if (show_coverage && coverage.has_value()) {
1744 auto bounds_contents = std::make_unique<SolidColorContents>();
1745 bounds_contents->SetGeometry(Geometry::MakeFillPath(
1746 PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath()));
1747 bounds_contents->SetColor(coverage_color.Premultiply());
1748 Entity bounds_entity;
1749 bounds_entity.SetContents(std::move(bounds_contents));
1750 bounds_entity.Render(context, pass);
1751 }
1752
1753 return true;
1754 };
1755 ASSERT_TRUE(OpenPlaygroundHere(callback));
1756 }

References impeller::PathBuilder::AddRect(), impeller::Entity::GetCoverage(), impeller::Color::Green(), IMPELLER_PLAYGROUND_LINE, impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Color::Premultiply(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), impeller::Entity::SetTransformation(), impeller::PathBuilder::TakePath(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [267/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffect |
| ) |  |

Definition at line 2113 of file entity_unittests.cc.

2113 {
2114 if (GetParam() != PlaygroundBackend::kMetal) {
2115 GTEST_SKIP_("This backend doesn't support runtime effects.");
2116 }
2117
2118 auto runtime_stage =
2119 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2120 ASSERT_TRUE(runtime_stage->IsDirty());
2121
2122 bool first_frame = true;
2123 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2124 if (first_frame) {
2125 first_frame = false;
2126 } else {
2127 assert(runtime_stage->IsDirty() == false);
2128 }
2129
2130 auto contents = std::make_shared<RuntimeEffectContents>();
2131 contents->SetGeometry(Geometry::MakeCover());
2132
2133 contents->SetRuntimeStage(runtime_stage);
2134
2135 struct FragUniforms {
2136 Vector2 iResolution;
2137 Scalar iTime;
2138 } frag_uniforms = {
2139 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
2140 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
2141 };
2142 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2143 uniform_data->resize(sizeof(FragUniforms));
2144 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2145 contents->SetUniformData(uniform_data);
2146
2147 Entity entity;
2148 entity.SetContents(contents);
2149 return contents->Render(context, entity, pass);
2150 };
2151 ASSERT_TRUE(OpenPlaygroundHere(callback));
2152 }

References impeller::kMetal, impeller::Geometry::MakeCover(), and impeller::Entity::SetContents().

## ◆ TEST_P() [268/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SetBlendMode |
| ) |  |

Definition at line 1246 of file entity_unittests.cc.

1246 {
1247 Entity entity;
1248 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kSourceOver);
1249 entity.SetBlendMode(BlendMode::kClear);
1250 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kClear);
1251 }

References impeller::Entity::GetBlendMode(), impeller::kClear, impeller::kSourceOver, and impeller::Entity::SetBlendMode().

## ◆ TEST_P() [269/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsIsOpaque |
| ) |  |

Definition at line 2321 of file entity_unittests.cc.

2321 {
2322 SolidColorContents contents;
2323 contents.SetColor(Color::CornflowerBlue());
2324 ASSERT_TRUE(contents.IsOpaque());
2325 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.5));
2326 ASSERT_FALSE(contents.IsOpaque());
2327 }

References impeller::Color::CornflowerBlue(), impeller::SolidColorContents::IsOpaque(), and impeller::SolidColorContents::SetColor().

## ◆ TEST_P() [270/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsStrokeSetMiterLimit |
| ) |  |

Definition at line 783 of file entity_unittests.cc.

783 {
784 {
785 auto geometry = Geometry::MakeStrokePath(Path{});
786 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
787 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
788 }
789
790 {
791 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, /*miter_limit=*/8.0);
792 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
793 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 8);
794 }
795
796 {
797 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, /*miter_limit=*/-1.0);
798 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
799 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
800 }
801 }

References impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [271/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsStrokeSetStrokeCapsAndJoins |
| ) |  |

Definition at line 761 of file entity_unittests.cc.

761 {
762 {
763 auto geometry = Geometry::MakeStrokePath(Path{});
764 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
765 // Defaults.
766 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kButt);
767 ASSERT_EQ(path_geometry->GetStrokeJoin(), Join::kMiter);
768 }
769
770 {
771 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, 4.0, Cap::kSquare);
772 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
773 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kSquare);
774 }
775
776 {
777 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, 4.0, Cap::kRound);
778 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
779 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kRound);
780 }
781 }

References impeller::kButt, impeller::kMiter, impeller::kRound, impeller::kSquare, and impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [272/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidFillCoverageIsCorrect |
| ) |  |

Definition at line 1535 of file entity_unittests.cc.

1535 {
1536 // No transform
1537 {
1538 auto fill = std::make_shared<SolidColorContents>();
1539 fill->SetColor(Color::CornflowerBlue());
1540 auto expected = Rect::MakeLTRB(100, 110, 200, 220);
1541 fill->SetGeometry(
1542 Geometry::MakeFillPath(PathBuilder{}.AddRect(expected).TakePath()));
1543
1544 auto coverage = fill->GetCoverage({});
1545 ASSERT_TRUE(coverage.has_value());
1546 ASSERT_RECT_NEAR(coverage.value(), expected);
1547 }
1548
1549 // Entity transform
1550 {
1551 auto fill = std::make_shared<SolidColorContents>();
1552 fill->SetColor(Color::CornflowerBlue());
1553 fill->SetGeometry(Geometry::MakeFillPath(
1554 PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath()));
1555
1556 Entity entity;
1557 entity.SetTransformation(Matrix::MakeTranslation(Vector2(4, 5)));
1558 entity.SetContents(std::move(fill));
1559
1560 auto coverage = entity.GetCoverage();
1561 auto expected = Rect::MakeLTRB(104, 115, 204, 225);
1562 ASSERT_TRUE(coverage.has_value());
1563 ASSERT_RECT_NEAR(coverage.value(), expected);
1564 }
1565
1566 // No coverage for fully transparent colors
1567 {
1568 auto fill = std::make_shared<SolidColorContents>();
1569 fill->SetColor(Color::WhiteTransparent());
1570 fill->SetGeometry(Geometry::MakeFillPath(
1571 PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath()));
1572
1573 auto coverage = fill->GetCoverage({});
1574 ASSERT_FALSE(coverage.has_value());
1575 }
1576 }

References impeller::PathBuilder::AddRect(), ASSERT_RECT_NEAR, impeller::Color::CornflowerBlue(), impeller::Entity::GetCoverage(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeTranslation(), impeller::Entity::SetContents(), impeller::Entity::SetTransformation(), and impeller::Color::WhiteTransparent().

## ◆ TEST_P() [273/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidFillShouldRenderIsCorrect |
| ) |  |

Definition at line 1578 of file entity_unittests.cc.

1578 {
1579 // No path.
1580 {
1581 auto fill = std::make_shared<SolidColorContents>();
1582 fill->SetColor(Color::CornflowerBlue());
1583 ASSERT_FALSE(fill->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1584 ASSERT_FALSE(
1585 fill->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1586 }
1587
1588 // With path.
1589 {
1590 auto fill = std::make_shared<SolidColorContents>();
1591 fill->SetColor(Color::CornflowerBlue());
1592 fill->SetGeometry(Geometry::MakeFillPath(
1593 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath()));
1594 ASSERT_TRUE(fill->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1595 ASSERT_FALSE(
1596 fill->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1597 }
1598
1599 // With paint cover.
1600 {
1601 auto fill = std::make_shared<SolidColorContents>();
1602 fill->SetColor(Color::CornflowerBlue());
1603 fill->SetGeometry(Geometry::MakeCover());
1604 ASSERT_TRUE(fill->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1605 ASSERT_TRUE(
1606 fill->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1607 }
1608 }

References impeller::PathBuilder::AddRect(), impeller::Color::CornflowerBlue(), impeller::Geometry::MakeCover(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeSize().

## ◆ TEST_P() [274/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidStrokeCoverageIsCorrect |
| ) |  |

Definition at line 1259 of file entity_unittests.cc.

1259 {
1260 {
1261 auto geometry = Geometry::MakeStrokePath(
1262 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 4.0,
1263 Cap::kButt, Join::kBevel);
1264
1265 Entity entity;
1266 auto contents = std::make_unique<SolidColorContents>();
1267 contents->SetGeometry(std::move(geometry));
1268 contents->SetColor(Color::Black());
1269 entity.SetContents(std::move(contents));
1270 auto actual = entity.GetCoverage();
1271 auto expected = Rect::MakeLTRB(-2, -2, 12, 12);
1272 ASSERT_TRUE(actual.has_value());
1273 ASSERT_RECT_NEAR(actual.value(), expected);
1274 }
1275
1276 // Cover the Cap::kSquare case.
1277 {
1278 auto geometry = Geometry::MakeStrokePath(
1279 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 4.0,
1280 Cap::kSquare, Join::kBevel);
1281
1282 Entity entity;
1283 auto contents = std::make_unique<SolidColorContents>();
1284 contents->SetGeometry(std::move(geometry));
1285 contents->SetColor(Color::Black());
1286 entity.SetContents(std::move(contents));
1287 auto actual = entity.GetCoverage();
1288 auto expected =
1289 Rect::MakeLTRB(-sqrt(8), -sqrt(8), 10 + sqrt(8), 10 + sqrt(8));
1290 ASSERT_TRUE(actual.has_value());
1291 ASSERT_RECT_NEAR(actual.value(), expected);
1292 }
1293
1294 // Cover the Join::kMiter case.
1295 {
1296 auto geometry = Geometry::MakeStrokePath(
1297 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 2.0,
1298 Cap::kSquare, Join::kMiter);
1299
1300 Entity entity;
1301 auto contents = std::make_unique<SolidColorContents>();
1302 contents->SetGeometry(std::move(geometry));
1303 contents->SetColor(Color::Black());
1304 entity.SetContents(std::move(contents));
1305 auto actual = entity.GetCoverage();
1306 auto expected = Rect::MakeLTRB(-4, -4, 14, 14);
1307 ASSERT_TRUE(actual.has_value());
1308 ASSERT_RECT_NEAR(actual.value(), expected);
1309 }
1310 }

References impeller::PathBuilder::AddLine(), ASSERT_RECT_NEAR, impeller::Color::Black(), impeller::Entity::GetCoverage(), impeller::kBevel, impeller::kButt, impeller::kMiter, impeller::kSquare, impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeStrokePath(), and impeller::Entity::SetContents().

## ◆ TEST_P() [275/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilter |
| ) |  |

Definition at line 1918 of file entity_unittests.cc.

1918 {
1919 auto image = CreateTextureForFixture("embarcadero.jpg");
1920 ASSERT_TRUE(image);
1921
1922 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1923 auto filtered =
1924 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(image));
1925
1926 // Define the entity that will serve as the control image as a Gaussian blur
1927 // filter with no filter at all.
1928 Entity entity_left;
1929 entity_left.SetTransformation(Matrix::MakeScale(GetContentScale()) *
1930 Matrix::MakeTranslation({100, 300}) *
1931 Matrix::MakeScale(Vector2{0.5, 0.5}));
1932 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1933 Sigma{0}, Sigma{0});
1934 entity_left.SetContents(unfiltered);
1935
1936 // Define the entity that will be filtered from sRGB to linear.
1937 Entity entity_right;
1938 entity_right.SetTransformation(Matrix::MakeScale(GetContentScale()) *
1939 Matrix::MakeTranslation({500, 300}) *
1940 Matrix::MakeScale(Vector2{0.5, 0.5}));
1941 entity_right.SetContents(filtered);
1942 return entity_left.Render(context, pass) &&
1943 entity_right.Render(context, pass);
1944 };
1945
1946 ASSERT_TRUE(OpenPlaygroundHere(callback));
1947 }

References impeller::FilterInput::Make(), impeller::FilterContents::MakeGaussianBlur(), impeller::Matrix::MakeScale(), impeller::ColorFilterContents::MakeSrgbToLinearFilter(), impeller::Matrix::MakeTranslation(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [276/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilterCoverageIsCorrect |
| ) |  |

Definition at line 1897 of file entity_unittests.cc.

1897 {
1898 // Set up a simple color background.
1899 auto fill = std::make_shared<SolidColorContents>();
1900 fill->SetGeometry(Geometry::MakeFillPath(
1901 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1902 fill->SetColor(Color::DeepPink());
1903
1904 auto filter =
1905 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(fill));
1906
1907 Entity e;
1908 e.SetTransformation(Matrix());
1909
1910 // Confirm that the actual filter coverage matches the expected coverage.
1911 auto actual = filter->GetCoverage(e);
1912 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1913
1914 ASSERT_TRUE(actual.has_value());
1915 ASSERT_RECT_NEAR(actual.value(), expected);
1916 }

References impeller::PathBuilder::AddRect(), ASSERT_RECT_NEAR, impeller::Color::DeepPink(), impeller::FilterInput::Make(), impeller::Geometry::MakeFillPath(), impeller::ColorFilterContents::MakeSrgbToLinearFilter(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [277/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeCapAndJoinTest |
| ) |  |

Definition at line 343 of file entity_unittests.cc.

343 {
344 const Point padding(300, 250);
345 const Point margin(140, 180);
346
347 auto callback = [&](ContentContext& context, RenderPass& pass) {
348 // Slightly above sqrt(2) by default, so that right angles are just below
349 // the limit and acute angles are over the limit (causing them to get
350 // beveled).
351 static Scalar miter_limit = 1.41421357;
352 static Scalar width = 30;
353
354 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
355 {
356 ImGui::SliderFloat("Miter limit", &miter_limit, 0, 30);
357 ImGui::SliderFloat("Stroke width", &width, 0, 100);
358 if (ImGui::Button("Reset")) {
359 miter_limit = 1.41421357;
360 width = 30;
361 }
362 }
363 ImGui::End();
364
365 auto world_matrix = Matrix::MakeScale(GetContentScale());
366 auto render_path = [width = width, &context, &pass, &world_matrix](
367 const Path& path, Cap cap, Join join) {
368 auto contents = std::make_unique<SolidColorContents>();
369 contents->SetGeometry(
370 Geometry::MakeStrokePath(path, width, miter_limit, cap, join));
371 contents->SetColor(Color::Red());
372
373 Entity entity;
374 entity.SetTransformation(world_matrix);
375 entity.SetContents(std::move(contents));
376
377 auto coverage = entity.GetCoverage();
378 if (coverage.has_value()) {
379 auto bounds_contents = std::make_unique<SolidColorContents>();
380 bounds_contents->SetGeometry(Geometry::MakeFillPath(
381 PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath()));
382 bounds_contents->SetColor(Color::Green().WithAlpha(0.5));
383 Entity bounds_entity;
384 bounds_entity.SetContents(std::move(bounds_contents));
385 bounds_entity.Render(context, pass);
386 }
387
388 entity.Render(context, pass);
389 };
390
391 const Point a_def(0, 0), b_def(0, 100), c_def(150, 0), d_def(150, -100),
392 e_def(75, 75);
393 const Scalar r = 30;
394 // Cap::kButt demo.
395 {
396 Point off = Point(0, 0) * padding + margin;
397 auto [a, b] = IMPELLER_PLAYGROUND_LINE(off + a_def, off + b_def, r,
398 Color::Black(), Color::White());
399 auto [c, d] = IMPELLER_PLAYGROUND_LINE(off + c_def, off + d_def, r,
400 Color::Black(), Color::White());
401 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
402 Cap::kButt, Join::kBevel);
403 }
404
405 // Cap::kSquare demo.
406 {
407 Point off = Point(1, 0) * padding + margin;
408 auto [a, b] = IMPELLER_PLAYGROUND_LINE(off + a_def, off + b_def, r,
409 Color::Black(), Color::White());
410 auto [c, d] = IMPELLER_PLAYGROUND_LINE(off + c_def, off + d_def, r,
411 Color::Black(), Color::White());
412 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
413 Cap::kSquare, Join::kBevel);
414 }
415
416 // Cap::kRound demo.
417 {
418 Point off = Point(2, 0) * padding + margin;
419 auto [a, b] = IMPELLER_PLAYGROUND_LINE(off + a_def, off + b_def, r,
420 Color::Black(), Color::White());
421 auto [c, d] = IMPELLER_PLAYGROUND_LINE(off + c_def, off + d_def, r,
422 Color::Black(), Color::White());
423 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
424 Cap::kRound, Join::kBevel);
425 }
426
427 // Join::kBevel demo.
428 {
429 Point off = Point(0, 1) * padding + margin;
430 Point a = IMPELLER_PLAYGROUND_POINT(off + a_def, r, Color::White());
431 Point b = IMPELLER_PLAYGROUND_POINT(off + e_def, r, Color::White());
432 Point c = IMPELLER_PLAYGROUND_POINT(off + c_def, r, Color::White());
433 render_path(
434 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
435 Cap::kButt, Join::kBevel);
436 }
437
438 // Join::kMiter demo.
439 {
440 Point off = Point(1, 1) * padding + margin;
441 Point a = IMPELLER_PLAYGROUND_POINT(off + a_def, r, Color::White());
442 Point b = IMPELLER_PLAYGROUND_POINT(off + e_def, r, Color::White());
443 Point c = IMPELLER_PLAYGROUND_POINT(off + c_def, r, Color::White());
444 render_path(
445 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
446 Cap::kButt, Join::kMiter);
447 }
448
449 // Join::kRound demo.
450 {
451 Point off = Point(2, 1) * padding + margin;
452 Point a = IMPELLER_PLAYGROUND_POINT(off + a_def, r, Color::White());
453 Point b = IMPELLER_PLAYGROUND_POINT(off + e_def, r, Color::White());
454 Point c = IMPELLER_PLAYGROUND_POINT(off + c_def, r, Color::White());
455 render_path(
456 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
457 Cap::kButt, Join::kRound);
458 }
459
460 return true;
461 };
462 ASSERT_TRUE(OpenPlaygroundHere(callback));
463 }

References impeller::PathBuilder::AddCubicCurve(), impeller::PathBuilder::AddRect(), impeller::Color::Black(), impeller::Close(), impeller::Entity::GetCoverage(), impeller::Color::Green(), IMPELLER_PLAYGROUND_LINE, IMPELLER_PLAYGROUND_POINT, impeller::kBevel, impeller::kButt, impeller::kMiter, impeller::kRound, impeller::kSquare, impeller::LineTo(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), impeller::Entity::SetTransformation(), impeller::PathBuilder::TakePath(), and impeller::Color::White().

## ◆ TEST_P() [278/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeWithTextureContents |
| ) |  |

Definition at line 280 of file entity_unittests.cc.

280 {
281 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
282 Path path = PathBuilder{}
283 .MoveTo({100, 100})
284 .LineTo({100, 200})
285 .MoveTo({100, 300})
286 .LineTo({100, 400})
287 .MoveTo({100, 500})
288 .LineTo({100, 600})
289 .TakePath();
290
291 Entity entity;
292 entity.SetTransformation(Matrix::MakeScale(GetContentScale()));
293 auto contents = std::make_unique<TiledTextureContents>();
294 contents->SetGeometry(Geometry::MakeStrokePath(path, 100.0));
295 contents->SetTexture(bridge);
296 contents->SetTileModes(Entity::TileMode::kClamp, Entity::TileMode::kClamp);
297 entity.SetContents(std::move(contents));
298 ASSERT_TRUE(OpenPlaygroundHere(entity));
299 }

References impeller::Entity::kClamp, impeller::LineTo(), impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), impeller::MoveTo(), impeller::PathBuilder::MoveTo(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [279/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SweepGradientContentsIsOpaque |
| ) |  |

Definition at line 2359 of file entity_unittests.cc.

2359 {
2360 RadialGradientContents contents;
2361 contents.SetColors({Color::CornflowerBlue()});
2362 ASSERT_TRUE(contents.IsOpaque());
2363 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2364 ASSERT_FALSE(contents.IsOpaque());
2365 contents.SetColors({Color::CornflowerBlue()});
2366 contents.SetTileMode(Entity::TileMode::kDecal);
2367 ASSERT_FALSE(contents.IsOpaque());
2368 }

References impeller::Color::CornflowerBlue(), impeller::RadialGradientContents::IsOpaque(), impeller::Entity::kDecal, impeller::RadialGradientContents::SetColors(), impeller::RadialGradientContents::SetTileMode(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [280/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TessellateConvex |
| ) |  |

Definition at line 2380 of file entity_unittests.cc.

2380 {
2381 {
2382 // Sanity check simple rectangle.
2383 auto [pts, indices] =
2384 TessellateConvex(PathBuilder{}
2385 .AddRect(Rect::MakeLTRB(0, 0, 10, 10))
2386 .TakePath()
2387 .CreatePolyline(1.0));
2388
2389 std::vector<Point> expected = {
2390 {0, 0}, {10, 0}, {10, 10}, {0, 10}, //
2391 };
2392 std::vector<uint16_t> expected_indices = {0, 1, 2, 0, 2, 3};
2393 ASSERT_EQ(pts, expected);
2394 ASSERT_EQ(indices, expected_indices);
2395 }
2396
2397 {
2398 auto [pts, indices] =
2399 TessellateConvex(PathBuilder{}
2400 .AddRect(Rect::MakeLTRB(0, 0, 10, 10))
2401 .AddRect(Rect::MakeLTRB(20, 20, 30, 30))
2402 .TakePath()
2403 .CreatePolyline(1.0));
2404
2405 std::vector<Point> expected = {
2406 {0, 0}, {10, 0}, {10, 10}, {0, 10}, //
2407 {20, 20}, {30, 20}, {30, 30}, {20, 30} //
2408 };
2409 std::vector<uint16_t> expected_indices = {0, 1, 2, 0, 2, 3,
2410 0, 6, 7, 0, 7, 8};
2411 ASSERT_EQ(pts, expected);
2412 ASSERT_EQ(indices, expected_indices);
2413 }
2414 }

References impeller::PathBuilder::AddRect(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TessellateConvex().

## ◆ TEST_P() [281/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TextContentsCeilsGlyphScaleToDecimal |
| ) |  |

Definition at line 2462 of file entity_unittests.cc.

2462 {
2463 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.4321111f, 12), 0.43f);
2464 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.5321111f, 12), 0.53f);
2465 ASSERT_EQ(TextFrame::RoundScaledFontSize(2.1f, 12), 2.1f);
2466 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.0f, 12), 0.0f);
2467 }

References impeller::TextFrame::RoundScaledFontSize().

## ◆ TEST_P() [282/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ThreeStrokesInOnePath |
| ) |  |

Definition at line 261 of file entity_unittests.cc.

261 {
262 Path path = PathBuilder{}
263 .MoveTo({100, 100})
264 .LineTo({100, 200})
265 .MoveTo({100, 300})
266 .LineTo({100, 400})
267 .MoveTo({100, 500})
268 .LineTo({100, 600})
269 .TakePath();
270
271 Entity entity;
272 entity.SetTransformation(Matrix::MakeScale(GetContentScale()));
273 auto contents = std::make_unique<SolidColorContents>();
274 contents->SetGeometry(Geometry::MakeStrokePath(path, 5.0));
275 contents->SetColor(Color::Red());
276 entity.SetContents(std::move(contents));
277 ASSERT_TRUE(OpenPlaygroundHere(entity));
278 }

References impeller::LineTo(), impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), impeller::MoveTo(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [283/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsIsOpaque |
| ) |  |

Definition at line 2370 of file entity_unittests.cc.

2370 {
2371 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
2372 TiledTextureContents contents;
2373 contents.SetTexture(bay_bridge);
2374 // This is a placeholder test. Images currently never decompress as opaque
2375 // (whether in Flutter or the playground), and so this should currently always
2376 // return false in practice.
2377 ASSERT_FALSE(contents.IsOpaque());
2378 }

References impeller::TiledTextureContents::IsOpaque(), and impeller::TiledTextureContents::SetTexture().

## ◆ TEST_P() [284/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TriangleInsideASquare |
| ) |  |

Definition at line 301 of file entity_unittests.cc.

301 {
302 auto callback = [&](ContentContext& context, RenderPass& pass) {
303 Point offset(100, 100);
304
305 Point a =
306 IMPELLER_PLAYGROUND_POINT(Point(10, 10) + offset, 20, Color::White());
307 Point b =
308 IMPELLER_PLAYGROUND_POINT(Point(210, 10) + offset, 20, Color::White());
309 Point c =
310 IMPELLER_PLAYGROUND_POINT(Point(210, 210) + offset, 20, Color::White());
311 Point d =
312 IMPELLER_PLAYGROUND_POINT(Point(10, 210) + offset, 20, Color::White());
313 Point e =
314 IMPELLER_PLAYGROUND_POINT(Point(50, 50) + offset, 20, Color::White());
315 Point f =
316 IMPELLER_PLAYGROUND_POINT(Point(100, 50) + offset, 20, Color::White());
317 Point g =
318 IMPELLER_PLAYGROUND_POINT(Point(50, 150) + offset, 20, Color::White());
319 Path path = PathBuilder{}
320 .MoveTo(a)
321 .LineTo(b)
322 .LineTo(c)
323 .LineTo(d)
324 .Close()
325 .MoveTo(e)
326 .LineTo(f)
327 .LineTo(g)
328 .Close()
329 .TakePath();
330
331 Entity entity;
332 entity.SetTransformation(Matrix::MakeScale(GetContentScale()));
333 auto contents = std::make_unique<SolidColorContents>();
334 contents->SetGeometry(Geometry::MakeStrokePath(path, 20.0));
335 contents->SetColor(Color::Red());
336 entity.SetContents(std::move(contents));
337
338 return entity.Render(context, pass);
339 };
340 ASSERT_TRUE(OpenPlaygroundHere(callback));
341 }

References impeller::PathBuilder::Close(), IMPELLER_PLAYGROUND_POINT, impeller::PathBuilder::LineTo(), impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), impeller::Entity::SetTransformation(), impeller::PathBuilder::TakePath(), and impeller::Color::White().

## ◆ TEST_P() [285/317]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | YUVToRGBFilter |
| ) |  |

Definition at line 2080 of file entity_unittests.cc.

2080 {
2081 if (GetParam() == PlaygroundBackend::kOpenGLES) {
2082 // TODO(114588) : Support YUV to RGB filter on OpenGLES backend.
2083 GTEST_SKIP_("YUV to RGB filter is not supported on OpenGLES backend yet.");
2084 }
2085
2086 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2087 YUVColorSpace yuv_color_space_array[2]{YUVColorSpace::kBT601FullRange,
2088 YUVColorSpace::kBT601LimitedRange};
2089 for (int i = 0; i < 2; i++) {
2090 auto yuv_color_space = yuv_color_space_array[i];
2091 auto textures =
2092 CreateTestYUVTextures(GetContext().get(), yuv_color_space);
2093 auto filter_contents = FilterContents::MakeYUVToRGBFilter(
2094 textures[0], textures[1], yuv_color_space);
2095 Entity filter_entity;
2096 filter_entity.SetContents(filter_contents);
2097 auto snapshot = filter_contents->RenderToSnapshot(context, filter_entity);
2098
2099 Entity entity;
2100 auto contents = TextureContents::MakeRect(Rect::MakeLTRB(0, 0, 256, 256));
2101 contents->SetTexture(snapshot->texture);
2102 contents->SetSourceRect(Rect::MakeSize(snapshot->texture->GetSize()));
2103 entity.SetContents(contents);
2104 entity.SetTransformation(
2105 Matrix::MakeTranslation({static_cast<Scalar>(100 + 400 * i), 300}));
2106 entity.Render(context, pass);
2107 }
2108 return true;
2109 };
2110 ASSERT_TRUE(OpenPlaygroundHere(callback));
2111 }

References CreateTestYUVTextures(), impeller::kBT601FullRange, impeller::kBT601LimitedRange, impeller::kOpenGLES, impeller::TRect< Scalar >::MakeLTRB(), impeller::TextureContents::MakeRect(), impeller::TRect< Scalar >::MakeSize(), impeller::Matrix::MakeTranslation(), impeller::FilterContents::MakeYUVToRGBFilter(), impeller::Entity::Render(), impeller::Entity::SetContents(), and impeller::Entity::SetTransformation().

## ◆ TEST_P() [286/317]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanEmplaceHostBuffer |
| ) |  |

Definition at line 114 of file renderer_dart_unittests.cc.

114 {
115 auto isolate = GetIsolate();
116 bool result = isolate->RunInIsolateScope([]() -> bool {
117 if (tonic::CheckAndHandleError(
118 ::Dart_Invoke(Dart_RootLibrary(),
119 tonic::ToDart("canEmplaceHostBuffer"), 0, nullptr))) {
120 return false;
121 }
122 return true;
123 });
124
125 ASSERT_TRUE(result);
126 }

## ◆ TEST_P() [287/317]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanInstantiateFlutterGPUContext |
| ) |  |

Definition at line 100 of file renderer_dart_unittests.cc.

100 {
101 auto isolate = GetIsolate();
102 bool result = isolate->RunInIsolateScope([]() -> bool {
103 if (tonic::CheckAndHandleError(::Dart_Invoke(
104 Dart_RootLibrary(), tonic::ToDart("instantiateDefaultContext"), 0,
105 nullptr))) {
106 return false;
107 }
108 return true;
109 });
110
111 ASSERT_TRUE(result);
112 }

## ◆ TEST_P() [288/317]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanRunDartInPlaygroundFrame |
| ) |  |

Definition at line 80 of file renderer_dart_unittests.cc.

80 {
81 auto isolate = GetIsolate();
82
83 SinglePassCallback callback = [&](RenderPass& pass) {
84 ImGui::Begin("Dart test", nullptr);
85 ImGui::Text(
86 "This test executes Dart code during the playground frame callback.");
87 ImGui::End();
88
89 return isolate->RunInIsolateScope([]() -> bool {
90 if (tonic::CheckAndHandleError(::Dart_Invoke(
91 Dart_RootLibrary(), tonic::ToDart("sayHi"), 0, nullptr))) {
92 return false;
93 }
94 return true;
95 });
96 };
97 OpenPlaygroundHere(callback);
98 }

## ◆ TEST_P() [289/317]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | ArrayUniforms |
| ) |  |

Definition at line 881 of file renderer_unittests.cc.

881 {
882 using VS = ArrayVertexShader;
883 using FS = ArrayFragmentShader;
884
885 auto context = GetContext();
886 auto pipeline_descriptor =
887 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
888 ASSERT_TRUE(pipeline_descriptor.has_value());
889 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
890 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
891 auto pipeline =
892 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
893 ASSERT_TRUE(pipeline && pipeline->IsValid());
894
895 SinglePassCallback callback = [&](RenderPass& pass) {
896 auto size = pass.GetRenderTargetSize();
897
898 Command cmd;
899 cmd.pipeline = pipeline;
900 DEBUG_COMMAND_INFO(cmd, "Google Dots");
901 VertexBufferBuilder<VS::PerVertexData> builder;
902 builder.AddVertices({{Point()},
903 {Point(0, size.height)},
904 {Point(size.width, 0)},
905 {Point(size.width, 0)},
906 {Point(0, size.height)},
907 {Point(size.width, size.height)}});
908 cmd.BindVertices(builder.CreateVertexBuffer(pass.GetTransientsBuffer()));
909
910 VS::FrameInfo frame_info;
911 frame_info.mvp =
912 Matrix::MakeOrthographic(size) * Matrix::MakeScale(GetContentScale());
913 VS::BindFrameInfo(cmd,
914 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
915
916 auto time = GetSecondsElapsed();
917 auto y_pos = [&time](float x) {
918 return 400 + 10 * std::cos(time * 5 + x / 6);
919 };
920
921 FS::FragInfo fs_uniform = {
922 .circle_positions = {Point(430, y_pos(0)), Point(480, y_pos(1)),
923 Point(530, y_pos(2)), Point(580, y_pos(3))},
924 .colors = {Color::MakeRGBA8(66, 133, 244, 255),
925 Color::MakeRGBA8(219, 68, 55, 255),
926 Color::MakeRGBA8(244, 180, 0, 255),
927 Color::MakeRGBA8(15, 157, 88, 255)},
928 };
929 FS::BindFragInfo(cmd,
930 pass.GetTransientsBuffer().EmplaceUniform(fs_uniform));
931
932 pass.AddCommand(std::move(cmd));
933 return true;
934 };
935 OpenPlaygroundHere(callback);
936 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::kCount4, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Color::MakeRGBA8(), impeller::Matrix::MakeScale(), and impeller::Command::pipeline.

## ◆ TEST_P() [290/317]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanBlitTextureToBuffer |
| ) |  |

Definition at line 571 of file renderer_unittests.cc.

571 {
572 auto context = GetContext();
573 ASSERT_TRUE(context);
574
575 using VS = MipmapsVertexShader;
576 using FS = MipmapsFragmentShader;
577 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
578 ASSERT_TRUE(desc.has_value());
579 desc->SetSampleCount(SampleCount::kCount4);
580 desc->SetStencilAttachmentDescriptors(std::nullopt);
581 auto mipmaps_pipeline =
582 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
583 ASSERT_TRUE(mipmaps_pipeline);
584
585 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
586 auto boston = CreateTextureForFixture("boston.jpg");
587 ASSERT_TRUE(bridge && boston);
588 auto sampler = context->GetSamplerLibrary()->GetSampler({});
589 ASSERT_TRUE(sampler);
590
591 TextureDescriptor texture_desc;
592 texture_desc.storage_mode = StorageMode::kHostVisible;
593 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
594 texture_desc.size = bridge->GetTextureDescriptor().size;
595 texture_desc.mip_count = 1u;
596 texture_desc.usage =
597 static_cast<TextureUsageMask>(TextureUsage::kRenderTarget) |
598 static_cast<TextureUsageMask>(TextureUsage::kShaderWrite) |
599 static_cast<TextureUsageMask>(TextureUsage::kShaderRead);
600 DeviceBufferDescriptor device_buffer_desc;
601 device_buffer_desc.storage_mode = StorageMode::kHostVisible;
602 device_buffer_desc.size =
603 bridge->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
604 auto device_buffer =
605 context->GetResourceAllocator()->CreateBuffer(device_buffer_desc);
606
607 // Vertex buffer.
608 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
609 vertex_builder.SetLabel("Box");
610 auto size = Point(boston->GetSize());
611 vertex_builder.AddVertices({
612 {{0, 0}, {0.0, 0.0}}, // 1
613 {{size.x, 0}, {1.0, 0.0}}, // 2
614 {{size.x, size.y}, {1.0, 1.0}}, // 3
615 {{0, 0}, {0.0, 0.0}}, // 1
616 {{size.x, size.y}, {1.0, 1.0}}, // 3
617 {{0, size.y}, {0.0, 1.0}}, // 4
618 });
619 auto vertex_buffer =
620 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
621 ASSERT_TRUE(vertex_buffer);
622
623 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
624 {
625 auto buffer = context->CreateCommandBuffer();
626 if (!buffer) {
627 return false;
628 }
629 buffer->SetLabel("Playground Command Buffer");
630 auto pass = buffer->CreateBlitPass();
631 if (!pass) {
632 return false;
633 }
634 pass->SetLabel("Playground Blit Pass");
635
636 if (render_target.GetColorAttachments().empty()) {
637 return false;
638 }
639
640 // Blit `bridge` to the top left corner of the texture.
641 pass->AddCopy(bridge, device_buffer);
642
643 pass->EncodeCommands(context->GetResourceAllocator());
644
645 if (!buffer->SubmitCommands()) {
646 return false;
647 }
648 }
649
650 {
651 auto buffer = context->CreateCommandBuffer();
652 if (!buffer) {
653 return false;
654 }
655 buffer->SetLabel("Playground Command Buffer");
656
657 auto pass = buffer->CreateRenderPass(render_target);
658 if (!pass) {
659 return false;
660 }
661 pass->SetLabel("Playground Render Pass");
662 {
663 Command cmd;
664 DEBUG_COMMAND_INFO(cmd, "Image");
665 cmd.pipeline = mipmaps_pipeline;
666
667 cmd.BindVertices(vertex_buffer);
668
669 VS::FrameInfo frame_info;
670 frame_info.mvp = Matrix::MakeOrthographic(pass->GetRenderTargetSize()) *
671 Matrix::MakeScale(GetContentScale());
672 VS::BindFrameInfo(
673 cmd, pass->GetTransientsBuffer().EmplaceUniform(frame_info));
674
675 FS::FragInfo frag_info;
676 frag_info.lod = 0;
677 FS::BindFragInfo(cmd,
678 pass->GetTransientsBuffer().EmplaceUniform(frag_info));
679
680 auto sampler = context->GetSamplerLibrary()->GetSampler({});
681 auto buffer_view = device_buffer->AsBufferView();
682 auto texture =
683 context->GetResourceAllocator()->CreateTexture(texture_desc);
684 if (!texture->SetContents(buffer_view.contents,
685 buffer_view.range.length)) {
686 VALIDATION_LOG << "Could not upload texture to device memory";
687 return false;
688 }
689 FS::BindTex(cmd, texture, sampler);
690
691 pass->AddCommand(std::move(cmd));
692 }
693 pass->EncodeCommands();
694 if (!buffer->SubmitCommands()) {
695 return false;
696 }
697 }
698 return true;
699 };
700 OpenPlaygroundHere(callback);
701 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::TextureDescriptor::format, impeller::kCount4, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::kRenderTarget, impeller::kShaderRead, impeller::kShaderWrite, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::TextureDescriptor::mip_count, impeller::Command::pipeline, impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel(), impeller::DeviceBufferDescriptor::size, impeller::TextureDescriptor::size, impeller::DeviceBufferDescriptor::storage_mode, impeller::TextureDescriptor::storage_mode, impeller::TextureDescriptor::usage, and VALIDATION_LOG.

## ◆ TEST_P() [291/317]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanBlitTextureToTexture |
| ) |  |

Definition at line 458 of file renderer_unittests.cc.

458 {
459 auto context = GetContext();
460 ASSERT_TRUE(context);
461
462 using VS = MipmapsVertexShader;
463 using FS = MipmapsFragmentShader;
464 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
465 ASSERT_TRUE(desc.has_value());
466 desc->SetSampleCount(SampleCount::kCount4);
467 desc->SetStencilAttachmentDescriptors(std::nullopt);
468 auto mipmaps_pipeline =
469 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
470 ASSERT_TRUE(mipmaps_pipeline);
471
472 TextureDescriptor texture_desc;
473 texture_desc.storage_mode = StorageMode::kHostVisible;
474 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
475 texture_desc.size = {800, 600};
476 texture_desc.mip_count = 1u;
477 texture_desc.usage =
478 static_cast<TextureUsageMask>(TextureUsage::kRenderTarget) |
479 static_cast<TextureUsageMask>(TextureUsage::kShaderRead);
480 auto texture = context->GetResourceAllocator()->CreateTexture(texture_desc);
481 ASSERT_TRUE(texture);
482
483 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
484 auto boston = CreateTextureForFixture("boston.jpg");
485 ASSERT_TRUE(bridge && boston);
486 auto sampler = context->GetSamplerLibrary()->GetSampler({});
487 ASSERT_TRUE(sampler);
488
489 // Vertex buffer.
490 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
491 vertex_builder.SetLabel("Box");
492 auto size = Point(boston->GetSize());
493 vertex_builder.AddVertices({
494 {{0, 0}, {0.0, 0.0}}, // 1
495 {{size.x, 0}, {1.0, 0.0}}, // 2
496 {{size.x, size.y}, {1.0, 1.0}}, // 3
497 {{0, 0}, {0.0, 0.0}}, // 1
498 {{size.x, size.y}, {1.0, 1.0}}, // 3
499 {{0, size.y}, {0.0, 1.0}}, // 4
500 });
501 auto vertex_buffer =
502 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
503 ASSERT_TRUE(vertex_buffer);
504
505 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
506 auto buffer = context->CreateCommandBuffer();
507 if (!buffer) {
508 return false;
509 }
510 buffer->SetLabel("Playground Command Buffer");
511
512 {
513 auto pass = buffer->CreateBlitPass();
514 if (!pass) {
515 return false;
516 }
517 pass->SetLabel("Playground Blit Pass");
518
519 if (render_target.GetColorAttachments().empty()) {
520 return false;
521 }
522
523 // Blit `bridge` to the top left corner of the texture.
524 pass->AddCopy(bridge, texture);
525
526 if (!pass->EncodeCommands(context->GetResourceAllocator())) {
527 return false;
528 }
529 }
530
531 {
532 auto pass = buffer->CreateRenderPass(render_target);
533 if (!pass) {
534 return false;
535 }
536 pass->SetLabel("Playground Render Pass");
537 {
538 Command cmd;
539 DEBUG_COMMAND_INFO(cmd, "Image");
540 cmd.pipeline = mipmaps_pipeline;
541
542 cmd.BindVertices(vertex_buffer);
543
544 VS::FrameInfo frame_info;
545 frame_info.mvp = Matrix::MakeOrthographic(pass->GetRenderTargetSize()) *
546 Matrix::MakeScale(GetContentScale());
547 VS::BindFrameInfo(
548 cmd, pass->GetTransientsBuffer().EmplaceUniform(frame_info));
549
550 FS::FragInfo frag_info;
551 frag_info.lod = 0;
552 FS::BindFragInfo(cmd,
553 pass->GetTransientsBuffer().EmplaceUniform(frag_info));
554
555 auto sampler = context->GetSamplerLibrary()->GetSampler({});
556 FS::BindTex(cmd, texture, sampler);
557
558 pass->AddCommand(std::move(cmd));
559 }
560 pass->EncodeCommands();
561 }
562
563 if (!buffer->SubmitCommands()) {
564 return false;
565 }
566 return true;
567 };
568 OpenPlaygroundHere(callback);
569 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::TextureDescriptor::format, impeller::kCount4, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::kRenderTarget, impeller::kShaderRead, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::TextureDescriptor::mip_count, impeller::Command::pipeline, impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, and impeller::TextureDescriptor::usage.

## ◆ TEST_P() [292/317]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanCreateBoxPrimitive |
| ) |  |

Definition at line 52 of file renderer_unittests.cc.

52 {
53 using VS = BoxFadeVertexShader;
54 using FS = BoxFadeFragmentShader;
55 auto context = GetContext();
56 ASSERT_TRUE(context);
57 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
58 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
59 ASSERT_TRUE(desc.has_value());
60 desc->SetSampleCount(SampleCount::kCount4);
61 desc->SetStencilAttachmentDescriptors(std::nullopt);
62
63 // Vertex buffer.
64 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
65 vertex_builder.SetLabel("Box");
66 vertex_builder.AddVertices({
67 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
68 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
69 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
70 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
71 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
72 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
73 });
74 auto vertex_buffer =
75 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
76 ASSERT_TRUE(vertex_buffer);
77
78 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
79 auto boston = CreateTextureForFixture("boston.jpg");
80 ASSERT_TRUE(bridge && boston);
81 auto sampler = context->GetSamplerLibrary()->GetSampler({});
82 ASSERT_TRUE(sampler);
83 SinglePassCallback callback = [&](RenderPass& pass) {
84 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
85 static bool wireframe;
86 ImGui::Checkbox("Wireframe", &wireframe);
87 ImGui::End();
88
89 desc->SetPolygonMode(wireframe ? PolygonMode::kLine : PolygonMode::kFill);
90 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
91
92 assert(pipeline && pipeline->IsValid());
93
94 Command cmd;
95 DEBUG_COMMAND_INFO(cmd, "Box");
96 cmd.pipeline = pipeline;
97
98 cmd.BindVertices(vertex_buffer);
99
100 VS::UniformBuffer uniforms;
101 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
102 Matrix::MakeScale(GetContentScale());
103 VS::BindUniformBuffer(cmd,
104 pass.GetTransientsBuffer().EmplaceUniform(uniforms));
105
106 FS::FrameInfo frame_info;
107 frame_info.current_time = GetSecondsElapsed();
108 frame_info.cursor_position = GetCursorPosition();
109 frame_info.window_size.x = GetWindowSize().width;
110 frame_info.window_size.y = GetWindowSize().height;
111
112 FS::BindFrameInfo(cmd,
113 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
114 FS::BindContents1(cmd, boston, sampler);
115 FS::BindContents2(cmd, bridge, sampler);
116 if (!pass.AddCommand(std::move(cmd))) {
117 return false;
118 }
119 return true;
120 };
121 OpenPlaygroundHere(callback);
122 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::kCount4, impeller::kFill, impeller::kLine, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::Command::pipeline, and impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel().

## ◆ TEST_P() [293/317]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanCreateCPUBackedTexture |
| ) |  |

Definition at line 984 of file renderer_unittests.cc.

984 {
985 if (GetParam() == PlaygroundBackend::kOpenGLES) {
986 GTEST_SKIP_("CPU backed textures are not supported on OpenGLES.");
987 }
988
989 auto context = GetContext();
990 auto allocator = context->GetResourceAllocator();
991 size_t dimension = 2;
992
993 do {
994 ISize size(dimension, dimension);
995 TextureDescriptor texture_descriptor;
996 texture_descriptor.storage_mode = StorageMode::kHostVisible;
997 texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
998 texture_descriptor.size = size;
999 auto row_bytes =
1000 std::max(static_cast<uint16_t>(size.width * 4),
1001 allocator->MinimumBytesPerRow(texture_descriptor.format));
1002 auto buffer_size = size.height * row_bytes;
1003
1004 DeviceBufferDescriptor buffer_descriptor;
1005 buffer_descriptor.storage_mode = StorageMode::kHostVisible;
1006 buffer_descriptor.size = buffer_size;
1007
1008 auto buffer = allocator->CreateBuffer(buffer_descriptor);
1009
1010 ASSERT_TRUE(buffer);
1011
1012 auto texture = buffer->AsTexture(*allocator, texture_descriptor, row_bytes);
1013
1014 ASSERT_TRUE(texture);
1015 ASSERT_TRUE(texture->IsValid());
1016
1017 dimension *= 2;
1018 } while (dimension <= 8192);
1019 }

References impeller::TextureDescriptor::format, impeller::TSize< T >::height, impeller::kHostVisible, impeller::kOpenGLES, impeller::kR8G8B8A8UNormInt, impeller::DeviceBufferDescriptor::size, impeller::TextureDescriptor::size, impeller::DeviceBufferDescriptor::storage_mode, impeller::TextureDescriptor::storage_mode, and impeller::TSize< T >::width.

## ◆ TEST_P() [294/317]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanGenerateMipmaps |
| ) |  |

Definition at line 703 of file renderer_unittests.cc.

703 {
704 auto context = GetContext();
705 ASSERT_TRUE(context);
706
707 using VS = MipmapsVertexShader;
708 using FS = MipmapsFragmentShader;
709 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
710 ASSERT_TRUE(desc.has_value());
711 desc->SetSampleCount(SampleCount::kCount4);
712 desc->SetStencilAttachmentDescriptors(std::nullopt);
713 auto mipmaps_pipeline =
714 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
715 ASSERT_TRUE(mipmaps_pipeline);
716
717 auto boston = CreateTextureForFixture("boston.jpg", true);
718 ASSERT_TRUE(boston);
719
720 // Vertex buffer.
721 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
722 vertex_builder.SetLabel("Box");
723 auto size = Point(boston->GetSize());
724 vertex_builder.AddVertices({
725 {{0, 0}, {0.0, 0.0}}, // 1
726 {{size.x, 0}, {1.0, 0.0}}, // 2
727 {{size.x, size.y}, {1.0, 1.0}}, // 3
728 {{0, 0}, {0.0, 0.0}}, // 1
729 {{size.x, size.y}, {1.0, 1.0}}, // 3
730 {{0, size.y}, {0.0, 1.0}}, // 4
731 });
732 auto vertex_buffer =
733 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
734 ASSERT_TRUE(vertex_buffer);
735
736 bool first_frame = true;
737 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
738 const char* mip_filter_names[] = {"Nearest", "Linear"};
739 const MipFilter mip_filters[] = {MipFilter::kNearest, MipFilter::kLinear};
740 const char* min_filter_names[] = {"Nearest", "Linear"};
741 const MinMagFilter min_filters[] = {MinMagFilter::kNearest,
742 MinMagFilter::kLinear};
743
744 // UI state.
745 static int selected_mip_filter = 1;
746 static int selected_min_filter = 0;
747 static float lod = 4.5;
748
749 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
750 ImGui::Combo("Mip filter", &selected_mip_filter, mip_filter_names,
751 sizeof(mip_filter_names) / sizeof(char*));
752 ImGui::Combo("Min filter", &selected_min_filter, min_filter_names,
753 sizeof(min_filter_names) / sizeof(char*));
754 ImGui::SliderFloat("LOD", &lod, 0, boston->GetMipCount() - 1);
755 ImGui::End();
756
757 auto buffer = context->CreateCommandBuffer();
758 if (!buffer) {
759 return false;
760 }
761 buffer->SetLabel("Playground Command Buffer");
762
763 if (first_frame) {
764 auto pass = buffer->CreateBlitPass();
765 if (!pass) {
766 return false;
767 }
768 pass->SetLabel("Playground Blit Pass");
769
770 pass->GenerateMipmap(boston, "Boston Mipmap");
771
772 pass->EncodeCommands(context->GetResourceAllocator());
773 }
774
775 first_frame = false;
776
777 {
778 auto pass = buffer->CreateRenderPass(render_target);
779 if (!pass) {
780 return false;
781 }
782 pass->SetLabel("Playground Render Pass");
783 {
784 Command cmd;
785 DEBUG_COMMAND_INFO(cmd, "Image LOD");
786 cmd.pipeline = mipmaps_pipeline;
787
788 cmd.BindVertices(vertex_buffer);
789
790 VS::FrameInfo frame_info;
791 frame_info.mvp = Matrix::MakeOrthographic(pass->GetRenderTargetSize()) *
792 Matrix::MakeScale(GetContentScale());
793 VS::BindFrameInfo(
794 cmd, pass->GetTransientsBuffer().EmplaceUniform(frame_info));
795
796 FS::FragInfo frag_info;
797 frag_info.lod = lod;
798 FS::BindFragInfo(cmd,
799 pass->GetTransientsBuffer().EmplaceUniform(frag_info));
800
801 SamplerDescriptor sampler_desc;
802 sampler_desc.mip_filter = mip_filters[selected_mip_filter];
803 sampler_desc.min_filter = min_filters[selected_min_filter];
804 auto sampler = context->GetSamplerLibrary()->GetSampler(sampler_desc);
805 FS::BindTex(cmd, boston, sampler);
806
807 pass->AddCommand(std::move(cmd));
808 }
809 pass->EncodeCommands();
810 }
811
812 if (!buffer->SubmitCommands()) {
813 return false;
814 }
815 return true;
816 };
817 OpenPlaygroundHere(callback);
818 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::kCount4, impeller::kLinear, impeller::kNearest, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::SamplerDescriptor::min_filter, impeller::SamplerDescriptor::mip_filter, impeller::Command::pipeline, and impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel().

## ◆ TEST_P() [295/317]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderInstanced |
| ) |  |

Definition at line 391 of file renderer_unittests.cc.

391 {
392 if (GetParam() == PlaygroundBackend::kOpenGLES) {
393 GTEST_SKIP_("Instancing is not supported on OpenGL.");
394 }
395 using VS = InstancedDrawVertexShader;
396 using FS = InstancedDrawFragmentShader;
397
398 VertexBufferBuilder<VS::PerVertexData> builder;
399
400 ASSERT_EQ(Tessellator::Result::kSuccess,
401 Tessellator{}.Tessellate(
402 FillType::kPositive,
403 PathBuilder{}
404 .AddRect(Rect::MakeXYWH(10, 10, 100, 100))
405 .TakePath()
406 .CreatePolyline(1.0f),
407 [&builder](const float* vertices, size_t vertices_count,
408 const uint16_t* indices, size_t indices_count) {
409 for (auto i = 0u; i < vertices_count * 2; i += 2) {
410 VS::PerVertexData data;
411 data.vtx = {vertices[i], vertices[i + 1]};
412 builder.AppendVertex(data);
413 }
414 for (auto i = 0u; i < indices_count; i++) {
415 builder.AppendIndex(indices[i]);
416 }
417 return true;
418 }));
419
420 ASSERT_NE(GetContext(), nullptr);
421 auto pipeline =
422 GetContext()
423 ->GetPipelineLibrary()
424 ->GetPipeline(PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(
425 *GetContext())
426 ->SetSampleCount(SampleCount::kCount4)
427 .SetStencilAttachmentDescriptors(std::nullopt))
428
429 .Get();
430 ASSERT_TRUE(pipeline && pipeline->IsValid());
431
432 Command cmd;
433 cmd.pipeline = pipeline;
434 DEBUG_COMMAND_INFO(cmd, "InstancedDraw");
435
436 static constexpr size_t kInstancesCount = 5u;
437 VS::InstanceInfo<kInstancesCount> instances;
438 for (size_t i = 0; i < kInstancesCount; i++) {
439 instances.colors[i] = Color::Random();
440 }
441
442 ASSERT_TRUE(OpenPlaygroundHere([&](RenderPass& pass) -> bool {
443 VS::FrameInfo frame_info;
444 frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
445 Matrix::MakeScale(GetContentScale());
446 VS::BindFrameInfo(cmd,
447 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
448 VS::BindInstanceInfo(
449 cmd, pass.GetTransientsBuffer().EmplaceStorageBuffer(instances));
450 cmd.BindVertices(builder.CreateVertexBuffer(pass.GetTransientsBuffer()));
451
452 cmd.instance_count = kInstancesCount;
453 pass.AddCommand(std::move(cmd));
454 return true;
455 }));
456 }

References impeller::RenderPass::AddCommand(), impeller::PathBuilder::AddRect(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendIndex(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendVertex(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::HostBuffer::EmplaceStorageBuffer(), impeller::HostBuffer::EmplaceUniform(), impeller::RenderPass::GetRenderTargetSize(), impeller::RenderPass::GetTransientsBuffer(), impeller::Command::instance_count, impeller::kCount4, impeller::kOpenGLES, impeller::kPositive, impeller::Tessellator::kSuccess, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Command::pipeline, impeller::Color::Random(), and impeller::Tessellator::Tessellate().

## ◆ TEST_P() [296/317]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderMultiplePrimitives |
| ) |  |

Definition at line 215 of file renderer_unittests.cc.

215 {
216 using VS = BoxFadeVertexShader;
217 using FS = BoxFadeFragmentShader;
218 auto context = GetContext();
219 ASSERT_TRUE(context);
220 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
221 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
222 ASSERT_TRUE(desc.has_value());
223 desc->SetSampleCount(SampleCount::kCount4);
224 desc->SetStencilAttachmentDescriptors(std::nullopt);
225 auto box_pipeline =
226 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
227 ASSERT_TRUE(box_pipeline);
228
229 // Vertex buffer.
230 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
231 vertex_builder.SetLabel("Box");
232 vertex_builder.AddVertices({
233 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
234 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
235 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
236 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
237 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
238 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
239 });
240 auto vertex_buffer =
241 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
242 ASSERT_TRUE(vertex_buffer);
243
244 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
245 auto boston = CreateTextureForFixture("boston.jpg");
246 ASSERT_TRUE(bridge && boston);
247 auto sampler = context->GetSamplerLibrary()->GetSampler({});
248 ASSERT_TRUE(sampler);
249
250 SinglePassCallback callback = [&](RenderPass& pass) {
251 Command cmd;
252 DEBUG_COMMAND_INFO(cmd, "Box");
253 cmd.pipeline = box_pipeline;
254
255 cmd.BindVertices(vertex_buffer);
256
257 FS::FrameInfo frame_info;
258 frame_info.current_time = GetSecondsElapsed();
259 frame_info.cursor_position = GetCursorPosition();
260 frame_info.window_size.x = GetWindowSize().width;
261 frame_info.window_size.y = GetWindowSize().height;
262
263 FS::BindFrameInfo(cmd,
264 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
265 FS::BindContents1(cmd, boston, sampler);
266 FS::BindContents2(cmd, bridge, sampler);
267
268 for (size_t i = 0; i < 1; i++) {
269 for (size_t j = 0; j < 1; j++) {
270 VS::UniformBuffer uniforms;
271 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
272 Matrix::MakeScale(GetContentScale()) *
273 Matrix::MakeTranslation({i * 50.0f, j * 50.0f, 0.0f});
274 VS::BindUniformBuffer(
275 cmd, pass.GetTransientsBuffer().EmplaceUniform(uniforms));
276 if (!pass.AddCommand(std::move(cmd))) {
277 return false;
278 }
279 }
280 }
281
282 return true;
283 };
284 OpenPlaygroundHere(callback);
285 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::kCount4, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Command::pipeline, and impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel().

## ◆ TEST_P() [297/317]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderPerspectiveCube |
| ) |  |

Definition at line 124 of file renderer_unittests.cc.

124 {
125 using VS = ColorsVertexShader;
126 using FS = ColorsFragmentShader;
127 auto context = GetContext();
128 ASSERT_TRUE(context);
129 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
130 ASSERT_TRUE(desc.has_value());
131 desc->SetCullMode(CullMode::kBackFace);
132 desc->SetWindingOrder(WindingOrder::kCounterClockwise);
133 desc->SetSampleCount(SampleCount::kCount4);
134 desc->SetStencilAttachmentDescriptors(std::nullopt);
135 auto pipeline =
136 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
137 ASSERT_TRUE(pipeline);
138
139 struct Cube {
140 VS::PerVertexData vertices[8] = {
141 // -Z
142 {{-1, -1, -1}, Color::Red()},
143 {{1, -1, -1}, Color::Yellow()},
144 {{1, 1, -1}, Color::Green()},
145 {{-1, 1, -1}, Color::Blue()},
146 // +Z
147 {{-1, -1, 1}, Color::Green()},
148 {{1, -1, 1}, Color::Blue()},
149 {{1, 1, 1}, Color::Red()},
150 {{-1, 1, 1}, Color::Yellow()},
151 };
152 uint16_t indices[36] = {
153 1, 5, 2, 2, 5, 6, // +X
154 4, 0, 7, 7, 0, 3, // -X
155 4, 5, 0, 0, 5, 1, // +Y
156 3, 2, 7, 7, 2, 6, // -Y
157 5, 4, 6, 6, 4, 7, // +Z
158 0, 1, 3, 3, 1, 2, // -Z
159 };
160 } cube;
161
162 VertexBuffer vertex_buffer;
163 {
164 auto device_buffer = context->GetResourceAllocator()->CreateBufferWithCopy(
165 reinterpret_cast<uint8_t*>(&cube), sizeof(cube));
166 vertex_buffer.vertex_buffer = {
167 .buffer = device_buffer,
168 .range = Range(offsetof(Cube, vertices), sizeof(Cube::vertices))};
169 vertex_buffer.index_buffer = {
170 .buffer = device_buffer,
171 .range = Range(offsetof(Cube, indices), sizeof(Cube::indices))};
172 vertex_buffer.vertex_count = 36;
173 vertex_buffer.index_type = IndexType::k16bit;
174 }
175
176 auto sampler = context->GetSamplerLibrary()->GetSampler({});
177 ASSERT_TRUE(sampler);
178
179 Vector3 euler_angles;
180 SinglePassCallback callback = [&](RenderPass& pass) {
181 static Degrees fov_y(60);
182 static Scalar distance = 10;
183
184 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
185 ImGui::SliderFloat("Field of view", &fov_y.degrees, 0, 180);
186 ImGui::SliderFloat("Camera distance", &distance, 0, 30);
187 ImGui::End();
188
189 Command cmd;
190 DEBUG_COMMAND_INFO(cmd, "Perspective Cube");
191 cmd.pipeline = pipeline;
192
193 cmd.BindVertices(vertex_buffer);
194
195 VS::UniformBuffer uniforms;
196 Scalar time = GetSecondsElapsed();
197 euler_angles = Vector3(0.19 * time, 0.7 * time, 0.43 * time);
198
199 uniforms.mvp =
200 Matrix::MakePerspective(fov_y, pass.GetRenderTargetSize(), 0, 10) *
201 Matrix::MakeTranslation({0, 0, distance}) *
202 Matrix::MakeRotationX(Radians(euler_angles.x)) *
203 Matrix::MakeRotationY(Radians(euler_angles.y)) *
204 Matrix::MakeRotationZ(Radians(euler_angles.z));
205 VS::BindUniformBuffer(cmd,
206 pass.GetTransientsBuffer().EmplaceUniform(uniforms));
207 if (!pass.AddCommand(std::move(cmd))) {
208 return false;
209 }
210 return true;
211 };
212 OpenPlaygroundHere(callback);
213 }

References impeller::Command::BindVertices(), impeller::Color::Blue(), impeller::BufferView::buffer, DEBUG_COMMAND_INFO, impeller::Degrees::degrees, impeller::Color::Green(), impeller::VertexBuffer::index_buffer, impeller::VertexBuffer::index_type, impeller::k16bit, impeller::kBackFace, impeller::kCount4, impeller::kCounterClockwise, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakePerspective(), impeller::Matrix::MakeRotationX(), impeller::Matrix::MakeRotationY(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeTranslation(), impeller::Command::pipeline, impeller::Color::Red(), impeller::VertexBuffer::vertex_buffer, impeller::VertexBuffer::vertex_count, impeller::Vector3::x, impeller::Vector3::y, impeller::Color::Yellow(), and impeller::Vector3::z.

## ◆ TEST_P() [298/317]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderToTexture |
| ) |  |

Definition at line 287 of file renderer_unittests.cc.

287 {
288 using VS = BoxFadeVertexShader;
289 using FS = BoxFadeFragmentShader;
290 auto context = GetContext();
291 ASSERT_TRUE(context);
292 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
293 auto pipeline_desc =
294 BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
295 pipeline_desc->SetSampleCount(SampleCount::kCount1);
296
297 ASSERT_TRUE(pipeline_desc.has_value());
298 auto box_pipeline =
299 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
300 ASSERT_TRUE(box_pipeline);
301
302 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
303 vertex_builder.SetLabel("Box");
304 vertex_builder.AddVertices({
305 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
306 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
307 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
308 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
309 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
310 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
311 });
312 auto vertex_buffer =
313 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
314 ASSERT_TRUE(vertex_buffer);
315
316 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
317 auto boston = CreateTextureForFixture("boston.jpg");
318 ASSERT_TRUE(bridge && boston);
319 auto sampler = context->GetSamplerLibrary()->GetSampler({});
320 ASSERT_TRUE(sampler);
321 std::shared_ptr<RenderPass> r2t_pass;
322 auto cmd_buffer = context->CreateCommandBuffer();
323 ASSERT_TRUE(cmd_buffer);
324 {
325 ColorAttachment color0;
326 color0.load_action = LoadAction::kClear;
327 color0.store_action = StoreAction::kStore;
328
329 TextureDescriptor texture_descriptor;
330 ASSERT_NE(pipeline_desc->GetColorAttachmentDescriptor(0u), nullptr);
331 texture_descriptor.format =
332 pipeline_desc->GetColorAttachmentDescriptor(0u)->format;
333 texture_descriptor.storage_mode = StorageMode::kHostVisible;
334 texture_descriptor.size = {400, 400};
335 texture_descriptor.mip_count = 1u;
336 texture_descriptor.usage =
337 static_cast<TextureUsageMask>(TextureUsage::kRenderTarget);
338
339 color0.texture =
340 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
341
342 ASSERT_TRUE(color0.IsValid());
343
344 color0.texture->SetLabel("r2t_target");
345
346 StencilAttachment stencil0;
347 stencil0.load_action = LoadAction::kClear;
348 stencil0.store_action = StoreAction::kDontCare;
349 TextureDescriptor stencil_texture_desc;
350 stencil_texture_desc.storage_mode = StorageMode::kDeviceTransient;
351 stencil_texture_desc.size = texture_descriptor.size;
352 stencil_texture_desc.format = PixelFormat::kS8UInt;
353 stencil_texture_desc.usage =
354 static_cast<TextureUsageMask>(TextureUsage::kRenderTarget);
355 stencil0.texture =
356 context->GetResourceAllocator()->CreateTexture(stencil_texture_desc);
357
358 RenderTarget r2t_desc;
359 r2t_desc.SetColorAttachment(color0, 0u);
360 r2t_desc.SetStencilAttachment(stencil0);
361 r2t_pass = cmd_buffer->CreateRenderPass(r2t_desc);
362 ASSERT_TRUE(r2t_pass && r2t_pass->IsValid());
363 }
364
365 Command cmd;
366 DEBUG_COMMAND_INFO(cmd, "Box");
367 cmd.pipeline = box_pipeline;
368
369 cmd.BindVertices(vertex_buffer);
370
371 FS::FrameInfo frame_info;
372 frame_info.current_time = GetSecondsElapsed();
373 frame_info.cursor_position = GetCursorPosition();
374 frame_info.window_size.x = GetWindowSize().width;
375 frame_info.window_size.y = GetWindowSize().height;
376
377 FS::BindFrameInfo(cmd,
378 r2t_pass->GetTransientsBuffer().EmplaceUniform(frame_info));
379 FS::BindContents1(cmd, boston, sampler);
380 FS::BindContents2(cmd, bridge, sampler);
381
382 VS::UniformBuffer uniforms;
383 uniforms.mvp = Matrix::MakeOrthographic(ISize{1024, 768}) *
384 Matrix::MakeTranslation({50.0f, 50.0f, 0.0f});
385 VS::BindUniformBuffer(
386 cmd, r2t_pass->GetTransientsBuffer().EmplaceUniform(uniforms));
387 ASSERT_TRUE(r2t_pass->AddCommand(std::move(cmd)));
388 ASSERT_TRUE(r2t_pass->EncodeCommands());
389 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::TextureDescriptor::format, impeller::Attachment::IsValid(), impeller::kClear, impeller::kCount1, impeller::kDeviceTransient, impeller::kDontCare, impeller::kHostVisible, impeller::kRenderTarget, impeller::kS8UInt, impeller::kStore, impeller::Attachment::load_action, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeTranslation(), impeller::TextureDescriptor::mip_count, impeller::Command::pipeline, impeller::RenderTarget::SetColorAttachment(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel(), impeller::RenderTarget::SetStencilAttachment(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, impeller::Attachment::store_action, impeller::Attachment::texture, and impeller::TextureDescriptor::usage.

## ◆ TEST_P() [299/317]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | DefaultIndexBehavior |
| ) |  |

Definition at line 1031 of file renderer_unittests.cc.

1031 {
1032 using VS = BoxFadeVertexShader;
1033
1034 // Do not create any index buffer if no indices were provided.
1035 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1036 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::kNone);
1037 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetIndexType(), and impeller::kNone.

## ◆ TEST_P() [300/317]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | DefaultIndexSize |
| ) |  |

Definition at line 1021 of file renderer_unittests.cc.

1021 {
1022 using VS = BoxFadeVertexShader;
1023
1024 // Default to 16bit index buffer size, as this is a reasonable default and
1025 // supported on all backends without extensions.
1026 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1027 vertex_builder.AppendIndex(0u);
1028 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::k16bit);
1029 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendIndex(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetIndexType(), and impeller::k16bit.

## ◆ TEST_P() [301/317]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | InactiveUniforms |
| ) |  |

Definition at line 938 of file renderer_unittests.cc.

938 {
939 using VS = InactiveUniformsVertexShader;
940 using FS = InactiveUniformsFragmentShader;
941
942 auto context = GetContext();
943 auto pipeline_descriptor =
944 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
945 ASSERT_TRUE(pipeline_descriptor.has_value());
946 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
947 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
948 auto pipeline =
949 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
950 ASSERT_TRUE(pipeline && pipeline->IsValid());
951
952 SinglePassCallback callback = [&](RenderPass& pass) {
953 auto size = pass.GetRenderTargetSize();
954
955 Command cmd;
956 cmd.pipeline = pipeline;
957 DEBUG_COMMAND_INFO(cmd, "Inactive Uniform");
958 VertexBufferBuilder<VS::PerVertexData> builder;
959 builder.AddVertices({{Point()},
960 {Point(0, size.height)},
961 {Point(size.width, 0)},
962 {Point(size.width, 0)},
963 {Point(0, size.height)},
964 {Point(size.width, size.height)}});
965 cmd.BindVertices(builder.CreateVertexBuffer(pass.GetTransientsBuffer()));
966
967 VS::FrameInfo frame_info;
968 frame_info.mvp =
969 Matrix::MakeOrthographic(size) * Matrix::MakeScale(GetContentScale());
970 VS::BindFrameInfo(cmd,
971 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
972
973 FS::FragInfo fs_uniform = {.unused_color = Color::Red(),
974 .color = Color::Green()};
975 FS::BindFragInfo(cmd,
976 pass.GetTransientsBuffer().EmplaceUniform(fs_uniform));
977
978 pass.AddCommand(std::move(cmd));
979 return true;
980 };
981 OpenPlaygroundHere(callback);
982 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::Color::Green(), impeller::kCount4, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::Command::pipeline, and impeller::Color::Red().

## ◆ TEST_P() [302/317]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | StencilMask |
| ) |  |

Definition at line 1109 of file renderer_unittests.cc.

1109 {
1110 using VS = BoxFadeVertexShader;
1111 using FS = BoxFadeFragmentShader;
1112 auto context = GetContext();
1113 ASSERT_TRUE(context);
1114 using BoxFadePipelineBuilder = PipelineBuilder<VS, FS>;
1115 auto desc = BoxFadePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1116 ASSERT_TRUE(desc.has_value());
1117
1118 // Vertex buffer.
1119 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1120 vertex_builder.SetLabel("Box");
1121 vertex_builder.AddVertices({
1122 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1123 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1124 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1125 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1126 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1127 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1128 });
1129 auto vertex_buffer =
1130 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
1131 ASSERT_TRUE(vertex_buffer);
1132
1133 desc->SetSampleCount(SampleCount::kCount4);
1134 desc->SetStencilAttachmentDescriptors(std::nullopt);
1135
1136 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
1137 auto boston = CreateTextureForFixture("boston.jpg");
1138 ASSERT_TRUE(bridge && boston);
1139 auto sampler = context->GetSamplerLibrary()->GetSampler({});
1140 ASSERT_TRUE(sampler);
1141
1142 static bool mirror = false;
1143 static int stencil_reference_write = 0xFF;
1144 static int stencil_reference_read = 0x1;
1145 std::vector<uint8_t> stencil_contents;
1146 static int last_stencil_contents_reference_value = 0;
1147 static int current_front_compare =
1148 CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
1149 static int current_back_compare =
1150 CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
1151 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
1152 auto buffer = context->CreateCommandBuffer();
1153 if (!buffer) {
1154 return false;
1155 }
1156 buffer->SetLabel("Playground Command Buffer");
1157
1158 {
1159 // Configure the stencil attachment for the test.
1160 RenderTarget::AttachmentConfig stencil_config;
1161 stencil_config.load_action = LoadAction::kLoad;
1162 stencil_config.store_action = StoreAction::kDontCare;
1163 stencil_config.storage_mode = StorageMode::kHostVisible;
1164 auto render_target_allocator =
1165 RenderTargetAllocator(context->GetResourceAllocator());
1166 render_target.SetupStencilAttachment(*context, render_target_allocator,
1167 render_target.GetRenderTargetSize(),
1168 true, "stencil", stencil_config);
1169 // Fill the stencil buffer with an checkerboard pattern.
1170 const auto target_width = render_target.GetRenderTargetSize().width;
1171 const auto target_height = render_target.GetRenderTargetSize().height;
1172 const size_t target_size = target_width * target_height;
1173 if (stencil_contents.size() != target_size ||
1174 last_stencil_contents_reference_value != stencil_reference_write) {
1175 stencil_contents.resize(target_size);
1176 last_stencil_contents_reference_value = stencil_reference_write;
1177 for (int y = 0; y < target_height; y++) {
1178 for (int x = 0; x < target_width; x++) {
1179 const auto index = y * target_width + x;
1180 const auto kCheckSize = 64;
1181 const auto value =
1182 (((y / kCheckSize) + (x / kCheckSize)) % 2 == 0) *
1183 stencil_reference_write;
1184 stencil_contents[index] = value;
1185 }
1186 }
1187 }
1188 if (!render_target.GetStencilAttachment()->texture->SetContents(
1189 stencil_contents.data(), stencil_contents.size(), 0, false)) {
1190 VALIDATION_LOG << "Could not upload stencil contents to device memory";
1191 return false;
1192 }
1193 auto pass = buffer->CreateRenderPass(render_target);
1194 if (!pass) {
1195 return false;
1196 }
1197 pass->SetLabel("Stencil Buffer");
1198 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1199 ImGui::SliderInt("Stencil Write Value", &stencil_reference_write, 0,
1200 0xFF);
1201 ImGui::SliderInt("Stencil Compare Value", &stencil_reference_read, 0,
1202 0xFF);
1203 ImGui::Checkbox("Back face mode", &mirror);
1204 ImGui::ListBox("Front face compare function", &current_front_compare,
1205 CompareFunctionUI().labels(), CompareFunctionUI().size());
1206 ImGui::ListBox("Back face compare function", &current_back_compare,
1207 CompareFunctionUI().labels(), CompareFunctionUI().size());
1208 ImGui::End();
1209
1210 StencilAttachmentDescriptor front;
1211 front.stencil_compare =
1212 CompareFunctionUI().FunctionOf(current_front_compare);
1213 StencilAttachmentDescriptor back;
1214 back.stencil_compare =
1215 CompareFunctionUI().FunctionOf(current_back_compare);
1216 desc->SetStencilAttachmentDescriptors(front, back);
1217 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
1218
1219 assert(pipeline && pipeline->IsValid());
1220
1221 Command cmd;
1222 DEBUG_COMMAND_INFO(cmd, "Box");
1223 cmd.pipeline = pipeline;
1224 cmd.stencil_reference = stencil_reference_read;
1225
1226 cmd.BindVertices(vertex_buffer);
1227
1228 VS::UniformBuffer uniforms;
1229 uniforms.mvp = Matrix::MakeOrthographic(pass->GetRenderTargetSize()) *
1230 Matrix::MakeScale(GetContentScale());
1231 if (mirror) {
1232 uniforms.mvp = Matrix::MakeScale(Vector2(-1, 1)) * uniforms.mvp;
1233 }
1234 VS::BindUniformBuffer(
1235 cmd, pass->GetTransientsBuffer().EmplaceUniform(uniforms));
1236
1237 FS::FrameInfo frame_info;
1238 frame_info.current_time = GetSecondsElapsed();
1239 frame_info.cursor_position = GetCursorPosition();
1240 frame_info.window_size.x = GetWindowSize().width;
1241 frame_info.window_size.y = GetWindowSize().height;
1242
1243 FS::BindFrameInfo(cmd,
1244 pass->GetTransientsBuffer().EmplaceUniform(frame_info));
1245 FS::BindContents1(cmd, boston, sampler);
1246 FS::BindContents2(cmd, bridge, sampler);
1247 if (!pass->AddCommand(std::move(cmd))) {
1248 return false;
1249 }
1250 pass->EncodeCommands();
1251 }
1252
1253 if (!buffer->SubmitCommands()) {
1254 return false;
1255 }
1256 return true;
1257 };
1258 OpenPlaygroundHere(callback);
1259 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), CompareFunctionUI(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::testing::CompareFunctionUIData::FunctionOf(), impeller::testing::CompareFunctionUIData::IndexOf(), impeller::kCount4, impeller::kDontCare, impeller::kHostVisible, impeller::kLessEqual, impeller::kLoad, impeller::RenderTarget::AttachmentConfig::load_action, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::Command::pipeline, impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel(), impeller::StencilAttachmentDescriptor::stencil_compare, impeller::Command::stencil_reference, impeller::RenderTarget::AttachmentConfig::storage_mode, impeller::RenderTarget::AttachmentConfig::store_action, and VALIDATION_LOG.

## ◆ TEST_P() [303/317]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | TheImpeller |
| ) |  |

Definition at line 820 of file renderer_unittests.cc.

820 {
821 using VS = ImpellerVertexShader;
822 using FS = ImpellerFragmentShader;
823
824 auto context = GetContext();
825 auto pipeline_descriptor =
826 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
827 ASSERT_TRUE(pipeline_descriptor.has_value());
828 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
829 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
830 auto pipeline =
831 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
832 ASSERT_TRUE(pipeline && pipeline->IsValid());
833
834 auto blue_noise = CreateTextureForFixture("blue_noise.png");
835 SamplerDescriptor noise_sampler_desc;
836 noise_sampler_desc.width_address_mode = SamplerAddressMode::kRepeat;
837 noise_sampler_desc.height_address_mode = SamplerAddressMode::kRepeat;
838 auto noise_sampler =
839 context->GetSamplerLibrary()->GetSampler(noise_sampler_desc);
840
841 auto cube_map = CreateTextureCubeForFixture(
842 {"table_mountain_px.png", "table_mountain_nx.png",
843 "table_mountain_py.png", "table_mountain_ny.png",
844 "table_mountain_pz.png", "table_mountain_nz.png"});
845 auto cube_map_sampler = context->GetSamplerLibrary()->GetSampler({});
846
847 SinglePassCallback callback = [&](RenderPass& pass) {
848 auto size = pass.GetRenderTargetSize();
849
850 Command cmd;
851 cmd.pipeline = pipeline;
852 DEBUG_COMMAND_INFO(cmd, "Impeller SDF scene");
853 VertexBufferBuilder<VS::PerVertexData> builder;
854 builder.AddVertices({{Point()},
855 {Point(0, size.height)},
856 {Point(size.width, 0)},
857 {Point(size.width, 0)},
858 {Point(0, size.height)},
859 {Point(size.width, size.height)}});
860 cmd.BindVertices(builder.CreateVertexBuffer(pass.GetTransientsBuffer()));
861
862 VS::FrameInfo frame_info;
863 frame_info.mvp = Matrix::MakeOrthographic(size);
864 VS::BindFrameInfo(cmd,
865 pass.GetTransientsBuffer().EmplaceUniform(frame_info));
866
867 FS::FragInfo fs_uniform;
868 fs_uniform.texture_size = Point(size);
869 fs_uniform.time = GetSecondsElapsed();
870 FS::BindFragInfo(cmd,
871 pass.GetTransientsBuffer().EmplaceUniform(fs_uniform));
872 FS::BindBlueNoise(cmd, blue_noise, noise_sampler);
873 FS::BindCubeMap(cmd, cube_map, cube_map_sampler);
874
875 pass.AddCommand(std::move(cmd));
876 return true;
877 };
878 OpenPlaygroundHere(callback);
879 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Command::BindVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), DEBUG_COMMAND_INFO, impeller::SamplerDescriptor::height_address_mode, impeller::kCount4, impeller::kRepeat, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Command::pipeline, and impeller::SamplerDescriptor::width_address_mode.

## ◆ TEST_P() [304/317]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | VertexBufferBuilder |
| ) |  |

Definition at line 1039 of file renderer_unittests.cc.

1039 {
1040 // Does not create index buffer if one is provided.
1041 using VS = BoxFadeVertexShader;
1042 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1043 vertex_builder.SetLabel("Box");
1044 vertex_builder.AddVertices({
1045 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1046 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1047 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1048 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1049 });
1050 vertex_builder.AppendIndex(0);
1051 vertex_builder.AppendIndex(1);
1052 vertex_builder.AppendIndex(2);
1053 vertex_builder.AppendIndex(1);
1054 vertex_builder.AppendIndex(2);
1055 vertex_builder.AppendIndex(3);
1056
1057 ASSERT_EQ(vertex_builder.GetIndexCount(), 6u);
1058 ASSERT_EQ(vertex_builder.GetVertexCount(), 4u);
1059 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendIndex(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetIndexCount(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetVertexCount(), and impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel().

## ◆ TEST_P() [305/317]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanCreatePipelineFromRuntimeStage |
| ) |  |

Definition at line 226 of file runtime_stage_unittests.cc.

226 {
227 if (GetParam() != PlaygroundBackend::kMetal) {
228 GTEST_SKIP_("Skipped: https://github.com/flutter/flutter/issues/105538");
229 }
230 auto stage = OpenAssetAsRuntimeStage("ink_sparkle.frag.iplr");
231 ASSERT_NE(stage, nullptr);
232 ASSERT_TRUE(RegisterStage(*stage));
233 auto library = GetContext()->GetShaderLibrary();
234 using VS = SimpleVertexShader;
235 PipelineDescriptor desc;
236 desc.SetLabel("Runtime Stage InkSparkle");
237 desc.AddStageEntrypoint(
238 library->GetFunction(VS::kEntrypointName, ShaderStage::kVertex));
239 desc.AddStageEntrypoint(
240 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment));
241 auto vertex_descriptor = std::make_shared<VertexDescriptor>();
242 vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs,
243 VS::kInterleavedBufferLayout);
244
245 desc.SetVertexDescriptor(std::move(vertex_descriptor));
246 ColorAttachmentDescriptor color0;
247 color0.format = GetContext()->GetCapabilities()->GetDefaultColorFormat();
248 StencilAttachmentDescriptor stencil0;
249 stencil0.stencil_compare = CompareFunction::kEqual;
250 desc.SetColorAttachmentDescriptor(0u, color0);
251 desc.SetStencilAttachmentDescriptors(stencil0);
252 const auto stencil_fmt =
253 GetContext()->GetCapabilities()->GetDefaultStencilFormat();
254 desc.SetStencilPixelFormat(stencil_fmt);
255 auto pipeline = GetContext()->GetPipelineLibrary()->GetPipeline(desc).Get();
256 ASSERT_NE(pipeline, nullptr);
257 }

References impeller::PipelineDescriptor::AddStageEntrypoint(), impeller::ColorAttachmentDescriptor::format, impeller::kEqual, impeller::kFragment, impeller::kMetal, impeller::kVertex, impeller::PipelineDescriptor::SetColorAttachmentDescriptor(), impeller::PipelineDescriptor::SetLabel(), impeller::PipelineDescriptor::SetStencilAttachmentDescriptors(), impeller::PipelineDescriptor::SetStencilPixelFormat(), impeller::PipelineDescriptor::SetVertexDescriptor(), and impeller::StencilAttachmentDescriptor::stencil_compare.

## ◆ TEST_P() [306/317]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanRegisterStage |
| ) |  |

Definition at line 189 of file runtime_stage_unittests.cc.

189 {
190 if (GetParam() != PlaygroundBackend::kMetal) {
191 GTEST_SKIP_("Skipped: https://github.com/flutter/flutter/issues/105538");
192 }
193 auto fixture =
194 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
195 ASSERT_TRUE(fixture);
196 ASSERT_GT(fixture->GetSize(), 0u);
197 RuntimeStage stage(std::move(fixture));
198 ASSERT_TRUE(stage.IsValid());
199 std::promise<bool> registration;
200 auto future = registration.get_future();
201 auto library = GetContext()->GetShaderLibrary();
202 library->RegisterFunction(
203 stage.GetEntrypoint(), //
204 ToShaderStage(stage.GetShaderStage()), //
205 stage.GetCodeMapping(), //
206 fml::MakeCopyable([reg = std::move(registration)](bool result) mutable {
207 reg.set_value(result);
208 }));
209 ASSERT_TRUE(future.get());
210 {
211 auto function =
212 library->GetFunction(stage.GetEntrypoint(), ShaderStage::kFragment);
213 ASSERT_NE(function, nullptr);
214 }
215
216 // Check if unregistering works.
217
218 library->UnregisterFunction(stage.GetEntrypoint(), ShaderStage::kFragment);
219 {
220 auto function =
221 library->GetFunction(stage.GetEntrypoint(), ShaderStage::kFragment);
222 ASSERT_EQ(function, nullptr);
223 }
224 }

References impeller::RuntimeStage::GetCodeMapping(), impeller::RuntimeStage::GetEntrypoint(), impeller::RuntimeStage::GetShaderStage(), impeller::RuntimeStage::IsValid(), impeller::kFragment, impeller::kMetal, and impeller::ToShaderStage().

## ◆ TEST_P() [307/317]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | CanConvertTextBlob |
| ) |  |

Definition at line 38 of file typographer_unittests.cc.

38 {
39 SkFont font;
40 auto blob = SkTextBlob::MakeFromString(
41 "the quick brown fox jumped over the lazy dog.", font);
42 ASSERT_TRUE(blob);
43 auto frame = MakeTextFrameFromTextBlobSkia(blob);
44 ASSERT_EQ(frame->GetRunCount(), 1u);
45 for (const auto& run : frame->GetRuns()) {
46 ASSERT_TRUE(run.IsValid());
47 ASSERT_EQ(run.GetGlyphCount(), 45u);
48 }
49 }

References impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [308/317]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | CanCreateGlyphAtlas |
| ) |  |

Definition at line 56 of file typographer_unittests.cc.

56 {
57 auto context = TypographerContextSkia::Make();
58 auto atlas_context = context->CreateGlyphAtlasContext();
59 ASSERT_TRUE(context && context->IsValid());
60 SkFont sk_font;
61 auto blob = SkTextBlob::MakeFromString("hello", sk_font);
62 ASSERT_TRUE(blob);
63 auto atlas = CreateGlyphAtlas(
64 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
65 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
66 ASSERT_NE(atlas, nullptr);
67 ASSERT_NE(atlas->GetTexture(), nullptr);
68 ASSERT_EQ(atlas->GetType(), GlyphAtlas::Type::kAlphaBitmap);
69 ASSERT_EQ(atlas->GetGlyphCount(), 4llu);
70
71 std::optional<impeller::ScaledFont> first_scaled_font;
72 std::optional<impeller::Glyph> first_glyph;
73 Rect first_rect;
74 atlas->IterateGlyphs([&](const ScaledFont& scaled_font, const Glyph& glyph,
75 const Rect& rect) -> bool {
76 first_scaled_font = scaled_font;
77 first_glyph = glyph;
78 first_rect = rect;
79 return false;
80 });
81
82 ASSERT_TRUE(first_scaled_font.has_value());
83 ASSERT_TRUE(atlas
84 ->FindFontGlyphBounds(
85 {first_scaled_font.value(), first_glyph.value()})
86 .has_value());
87 }

References CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [309/317]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | CanCreateRenderContext |
| ) |  |

Definition at line 51 of file typographer_unittests.cc.

51 {
52 auto context = TypographerContextSkia::Make();
53 ASSERT_TRUE(context && context->IsValid());
54 }

References impeller::TypographerContextSkia::Make().

## ◆ TEST_P() [310/317]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasIsRecycledIfUnchanged |
| ) |  |

Definition at line 158 of file typographer_unittests.cc.

158 {
159 auto context = TypographerContextSkia::Make();
160 auto atlas_context = context->CreateGlyphAtlasContext();
161 ASSERT_TRUE(context && context->IsValid());
162 SkFont sk_font;
163 auto blob = SkTextBlob::MakeFromString("spooky skellingtons", sk_font);
164 ASSERT_TRUE(blob);
165 auto atlas = CreateGlyphAtlas(
166 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
167 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
168 ASSERT_NE(atlas, nullptr);
169 ASSERT_NE(atlas->GetTexture(), nullptr);
170 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
171
172 // now attempt to re-create an atlas with the same text blob.
173
174 auto next_atlas = CreateGlyphAtlas(
175 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
176 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
177 ASSERT_EQ(atlas, next_atlas);
178 ASSERT_EQ(atlas_context->GetGlyphAtlas(), atlas);
179 }

References CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [311/317]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasTextureIsRecreatedIfTypeChanges |
| ) |  |

Definition at line 258 of file typographer_unittests.cc.

258 {
259 auto context = TypographerContextSkia::Make();
260 auto atlas_context = context->CreateGlyphAtlasContext();
261 ASSERT_TRUE(context && context->IsValid());
262 SkFont sk_font;
263 auto blob = SkTextBlob::MakeFromString("spooky 1", sk_font);
264 ASSERT_TRUE(blob);
265 auto atlas = CreateGlyphAtlas(
266 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
267 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
268 auto old_packer = atlas_context->GetRectPacker();
269
270 ASSERT_NE(atlas, nullptr);
271 ASSERT_NE(atlas->GetTexture(), nullptr);
272 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
273
274 auto* first_texture = atlas->GetTexture().get();
275
276 // now create a new glyph atlas with an identical blob,
277 // but change the type.
278
279 auto blob2 = SkTextBlob::MakeFromString("spooky 1", sk_font);
280 auto next_atlas = CreateGlyphAtlas(
281 *GetContext(), context.get(), GlyphAtlas::Type::kColorBitmap, 1.0f,
282 atlas_context, *MakeTextFrameFromTextBlobSkia(blob2));
283 ASSERT_NE(atlas, next_atlas);
284 auto* second_texture = next_atlas->GetTexture().get();
285
286 auto new_packer = atlas_context->GetRectPacker();
287
288 ASSERT_NE(second_texture, first_texture);
289 ASSERT_NE(old_packer, new_packer);
290 }

References CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::GlyphAtlas::kColorBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [312/317]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasTextureIsRecycledIfUnchanged |
| ) |  |

Definition at line 225 of file typographer_unittests.cc.

225 {
226 auto context = TypographerContextSkia::Make();
227 auto atlas_context = context->CreateGlyphAtlasContext();
228 ASSERT_TRUE(context && context->IsValid());
229 SkFont sk_font;
230 auto blob = SkTextBlob::MakeFromString("spooky 1", sk_font);
231 ASSERT_TRUE(blob);
232 auto atlas = CreateGlyphAtlas(
233 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
234 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
235 auto old_packer = atlas_context->GetRectPacker();
236
237 ASSERT_NE(atlas, nullptr);
238 ASSERT_NE(atlas->GetTexture(), nullptr);
239 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
240
241 auto* first_texture = atlas->GetTexture().get();
242
243 // Now create a new glyph atlas with a nearly identical blob.
244
245 auto blob2 = SkTextBlob::MakeFromString("spooky 2", sk_font);
246 auto next_atlas = CreateGlyphAtlas(
247 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
248 atlas_context, *MakeTextFrameFromTextBlobSkia(blob2));
249 ASSERT_EQ(atlas, next_atlas);
250 auto* second_texture = next_atlas->GetTexture().get();
251
252 auto new_packer = atlas_context->GetRectPacker();
253
254 ASSERT_EQ(second_texture, first_texture);
255 ASSERT_EQ(old_packer, new_packer);
256 }

References CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [313/317]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasWithLotsOfdUniqueGlyphSize |
| ) |  |

Definition at line 181 of file typographer_unittests.cc.

181 {
182 auto context = TypographerContextSkia::Make();
183 auto atlas_context = context->CreateGlyphAtlasContext();
184 ASSERT_TRUE(context && context->IsValid());
185
186 const char* test_string =
187 "QWERTYUIOPASDFGHJKLZXCVBNMqewrtyuiopasdfghjklzxcvbnm,.<>[]{};':"
188 "2134567890-=!@#$%^&*()_+"
189 "œ∑´®†¥¨ˆøπ““‘‘åß∂ƒ©˙∆˚¬…æ≈ç√∫˜µ≤≥≥≥≥÷¡™£¢∞§¶•ªº–≠⁄€‹›ﬁﬂ‡°·‚—±Œ„´‰Á¨Ø∏”’/"
190 "* Í˝ */¸˛Ç◊ı˜Â¯˘¿";
191
192 SkFont sk_font;
193 auto blob = SkTextBlob::MakeFromString(test_string, sk_font);
194 ASSERT_TRUE(blob);
195
196 FontGlyphMap font_glyph_map;
197 size_t size_count = 8;
198 for (size_t index = 0; index < size_count; index += 1) {
199 MakeTextFrameFromTextBlobSkia(blob)->CollectUniqueFontGlyphPairs(
200 font_glyph_map, 0.6 * index);
201 };
202 auto atlas =
203 context->CreateGlyphAtlas(*GetContext(), GlyphAtlas::Type::kAlphaBitmap,
204 std::move(atlas_context), font_glyph_map);
205 ASSERT_NE(atlas, nullptr);
206 ASSERT_NE(atlas->GetTexture(), nullptr);
207
208 std::set<uint16_t> unique_glyphs;
209 std::vector<uint16_t> total_glyphs;
210 atlas->IterateGlyphs(
211 [&](const ScaledFont& scaled_font, const Glyph& glyph, const Rect& rect) {
212 unique_glyphs.insert(glyph.index);
213 total_glyphs.push_back(glyph.index);
214 return true;
215 });
216
217 EXPECT_EQ(unique_glyphs.size() * size_count, atlas->GetGlyphCount());
218 EXPECT_EQ(total_glyphs.size(), atlas->GetGlyphCount());
219
220 EXPECT_TRUE(atlas->GetGlyphCount() > 0);
221 EXPECT_TRUE(atlas->GetTexture()->GetSize().width > 0);
222 EXPECT_TRUE(atlas->GetTexture()->GetSize().height > 0);
223 }

References impeller::Glyph::index, impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [314/317]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasWithOddUniqueGlyphSize |
| ) |  |

Definition at line 141 of file typographer_unittests.cc.

141 {
142 auto context = TypographerContextSkia::Make();
143 auto atlas_context = context->CreateGlyphAtlasContext();
144 ASSERT_TRUE(context && context->IsValid());
145 SkFont sk_font;
146 auto blob = SkTextBlob::MakeFromString("AGH", sk_font);
147 ASSERT_TRUE(blob);
148 auto atlas = CreateGlyphAtlas(
149 *GetContext(), context.get(), GlyphAtlas::Type::kAlphaBitmap, 1.0f,
150 atlas_context, *MakeTextFrameFromTextBlobSkia(blob));
151 ASSERT_NE(atlas, nullptr);
152 ASSERT_NE(atlas->GetTexture(), nullptr);
153
154 ASSERT_EQ(atlas->GetTexture()->GetSize().width,
155 atlas->GetTexture()->GetSize().height);
156 }

References CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [315/317]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | LazyAtlasTracksColor |
| ) |  |

Definition at line 104 of file typographer_unittests.cc.

104 {
105 #if FML_OS_MACOSX
106 auto mapping = OpenFixtureAsSkData("Apple Color Emoji.ttc");
107 #else
108 auto mapping = OpenFixtureAsSkData("NotoColorEmoji.ttf");
109 #endif
110 ASSERT_TRUE(mapping);
111 SkFont emoji_font(SkTypeface::MakeFromData(mapping), 50.0);
112 SkFont sk_font;
113
114 auto blob = SkTextBlob::MakeFromString("hello", sk_font);
115 ASSERT_TRUE(blob);
116 auto frame = MakeTextFrameFromTextBlobSkia(blob);
117
118 ASSERT_FALSE(frame->GetAtlasType() == GlyphAtlas::Type::kColorBitmap);
119
120 LazyGlyphAtlas lazy_atlas(TypographerContextSkia::Make());
121
122 lazy_atlas.AddTextFrame(*frame, 1.0f);
123
124 frame = MakeTextFrameFromTextBlobSkia(
125 SkTextBlob::MakeFromString("😀 ", emoji_font));
126
127 ASSERT_TRUE(frame->GetAtlasType() == GlyphAtlas::Type::kColorBitmap);
128
129 lazy_atlas.AddTextFrame(*frame, 1.0f);
130
131 // Creates different atlases for color and alpha bitmap.
132 auto color_atlas = lazy_atlas.CreateOrGetGlyphAtlas(
133 *GetContext(), GlyphAtlas::Type::kColorBitmap);
134
135 auto bitmap_atlas = lazy_atlas.CreateOrGetGlyphAtlas(
136 *GetContext(), GlyphAtlas::Type::kAlphaBitmap);
137
138 ASSERT_FALSE(color_atlas == bitmap_atlas);
139 }

References impeller::LazyGlyphAtlas::AddTextFrame(), impeller::LazyGlyphAtlas::CreateOrGetGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::GlyphAtlas::kColorBitmap, impeller::TypographerContextSkia::Make(), impeller::MakeTextFrameFromTextBlobSkia(), and OpenFixtureAsSkData().

## ◆ TEST_P() [316/317]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | MaybeHasOverlapping |
| ) |  |

Definition at line 292 of file typographer_unittests.cc.

292 {
293 sk_sp<SkFontMgr> font_mgr = SkFontMgr::RefDefault();
294 sk_sp<SkTypeface> typeface =
295 font_mgr->matchFamilyStyle("Arial", SkFontStyle::Normal());
296 SkFont sk_font(typeface, 0.5f);
297
298 auto frame =
299 MakeTextFrameFromTextBlobSkia(SkTextBlob::MakeFromString("1", sk_font));
300 // Single character has no overlapping
301 ASSERT_FALSE(frame->MaybeHasOverlapping());
302
303 auto frame_2 = MakeTextFrameFromTextBlobSkia(
304 SkTextBlob::MakeFromString("123456789", sk_font));
305 ASSERT_FALSE(frame_2->MaybeHasOverlapping());
306 }

References impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [317/317]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | RectanglePackerAddsNonoverlapingRectangles |
| ) |  |

Definition at line 308 of file typographer_unittests.cc.

308 {
309 auto packer = RectanglePacker::Factory(200, 100);
310 ASSERT_NE(packer, nullptr);
311 ASSERT_EQ(packer->percentFull(), 0);
312
313 const SkIRect packer_area = SkIRect::MakeXYWH(0, 0, 200, 100);
314
315 IPoint16 first_output = {-1, -1}; // Fill with sentinel values
316 ASSERT_TRUE(packer->addRect(20, 20, &first_output));
317 // Make sure the rectangle is placed such that it is inside the bounds of
318 // the packer's area.
319 const SkIRect first_rect =
320 SkIRect::MakeXYWH(first_output.x(), first_output.y(), 20, 20);
321 ASSERT_TRUE(SkIRect::Intersects(packer_area, first_rect));
322
323 // Initial area was 200 x 100 = 20_000
324 // We added 20x20 = 400. 400 / 20_000 == 0.02 == 2%
325 ASSERT_TRUE(flutter::testing::NumberNear(packer->percentFull(), 0.02));
326
327 IPoint16 second_output = {-1, -1};
328 ASSERT_TRUE(packer->addRect(140, 90, &second_output));
329 const SkIRect second_rect =
330 SkIRect::MakeXYWH(second_output.x(), second_output.y(), 140, 90);
331 // Make sure the rectangle is placed such that it is inside the bounds of
332 // the packer's area but not in the are of the first rectangle.
333 ASSERT_TRUE(SkIRect::Intersects(packer_area, second_rect));
334 ASSERT_FALSE(SkIRect::Intersects(first_rect, second_rect));
335
336 // We added another 90 x 140 = 12_600 units, now taking us to 13_000
337 // 13_000 / 20_000 == 0.65 == 65%
338 ASSERT_TRUE(flutter::testing::NumberNear(packer->percentFull(), 0.65));
339
340 // There's enough area to add this rectangle, but no space big enough for
341 // the 50 units of width.
342 IPoint16 output;
343 ASSERT_FALSE(packer->addRect(50, 50, &output));
344 // Should be unchanged.
345 ASSERT_TRUE(flutter::testing::NumberNear(packer->percentFull(), 0.65));
346
347 packer->reset();
348 // Should be empty now.
349 ASSERT_EQ(packer->percentFull(), 0);
350 }

References impeller::RectanglePacker::Factory(), NumberNear(), impeller::IPoint16::x(), and impeller::IPoint16::y().

## ◆ toColor()

flutter::DlColor impeller::testing::toColor | ( | const float * | components | ) |

Definition at line 40 of file dl_unittests.cc.

40 {
41 return flutter::DlColor(Color::ToIColor(
42 Color(components[0], components[1], components[2], components[3])));
43 }

References impeller::Color::ToIColor().

Referenced by TEST_P().

## Variable Documentation

## ◆ golden_cubic_and_quad_points

std::vector<Point> impeller::testing::golden_cubic_and_quad_points

Definition at line 15 of file golden_paths.h.

Referenced by TEST_P().

## ◆ LastSample

int64_t impeller::testing::LastSample = 0
| static

Definition at line 20 of file archivist_unittests.cc.

impeller::BlendMode
BlendMode
Definition: color.h:57
NumberNear
bool NumberNear(double a, double b)
Definition: geometry_asserts.h:17
ASSERT_COLOR_NEAR
#define ASSERT_COLOR_NEAR(a, b)
Definition: geometry_asserts.h:155
impeller::kFloat
@ kFloat
Definition: runtime_types.h:24
impeller::OptionsFromPass
ContentContextOptions OptionsFromPass(const RenderPass &pass)
Definition: contents.cc:20
impeller::k1OverSqrt2
constexpr float k1OverSqrt2
Definition: constants.h:49
DEBUG_COMMAND_INFO
#define DEBUG_COMMAND_INFO(obj, arg)
Definition: command.h:31
impeller::testing::CompareFunctionUI
static const CompareFunctionUIData & CompareFunctionUI()
Definition: renderer_unittests.cc:1104
impeller::BlendModeToString
const char * BlendModeToString(BlendMode blend_mode)
Definition: color.cc:47
impeller::TextureUsageMask
uint64_t TextureUsageMask
Definition: formats.h:274
impeller::Scalar
float Scalar
Definition: scalar.h:15
impeller::testing::RenderTextInCanvasSkia
bool RenderTextInCanvasSkia(const std::shared_ptr< Context > &context, Canvas &canvas, const std::string &text, const std::string &font_fixture, TextRenderOptions options={})
Definition: aiks_unittests.cc:1303
impeller::TPoint::Ceil
constexpr TPoint Ceil() const
Definition: point.h:189
impeller::testing::CompareFunctionUIData::IndexOf
int IndexOf(CompareFunction func) const
Definition: renderer_unittests.cc:1087
impeller::testing::CanRenderSweepGradientWithDithering
static void CanRenderSweepGradientWithDithering(AiksTest *aiks_test, bool use_dithering)
Definition: aiks_unittests.cc:480
impeller::skia_conversions::ConvertStops
void ConvertStops(const flutter::DlGradientColorSourceBase *gradient, std::vector< Color > &colors, std::vector< float > &stops)
Convert display list colors + stops into impeller colors and stops, taking care to ensure that the st...
Definition: skia_conversions.cc:192
impeller::testing::CreateMappingFromString
static std::shared_ptr< fml::Mapping > CreateMappingFromString(std::string p_string)
Definition: blobcat_unittests.cc:15
impeller::TPoint::Lerp
constexpr TPoint Lerp(const TPoint &p, Scalar t) const
Definition: point.h:223
impeller::TextureDescriptor::format
PixelFormat format
Definition: texture_descriptor.h:42
impeller::testing::CanRenderConicalGradientWithDithering
static void CanRenderConicalGradientWithDithering(AiksTest *aiks_test, bool use_dithering)
Definition: aiks_unittests.cc:509
impeller::TPoint::Min
constexpr TPoint Min(const TPoint &p) const
Definition: point.h:179
impeller::TPoint::Round
static constexpr TPoint Round(const TPoint< U > &other)
Definition: point.h:42
impeller::Vector2
Point Vector2
Definition: point.h:310
impeller::SampleCount::kCount1
@ kCount1
impeller::kPi
constexpr float kPi
Definition: constants.h:25
impeller::testing::OpenFixtureAsSkData
static sk_sp< SkData > OpenFixtureAsSkData(const char *fixture_name)
Definition: aiks_unittests.cc:1282
BLEND_MODE_TUPLE
#define BLEND_MODE_TUPLE(blend_mode)
Definition: aiks_unittests.cc:1603
impeller::skia_conversions::ToColor
Color ToColor(const flutter::DlColor &color)
Definition: skia_conversions.cc:142
IMPELLER_PLAYGROUND_POINT
#define IMPELLER_PLAYGROUND_POINT(default_position, radius, color)
Definition: widgets.h:14
impeller::FontGlyphMap
std::unordered_map< ScaledFont, std::unordered_set< Glyph > > FontGlyphMap
Definition: font_glyph_pair.h:28
impeller::TessellateConvex
std::pair< std::vector< Point >, std::vector< uint16_t > > TessellateConvex(Path::Polyline polyline)
Given a convex polyline, create a triangle fan structure.
Definition: geometry.cc:19
impeller::UintPoint32
TPoint< uint32_t > UintPoint32
Definition: point.h:309
impeller::testing::golden_cubic_and_quad_points
std::vector< Point > golden_cubic_and_quad_points
Definition: golden_paths.h:15
impeller::Size
TSize< Scalar > Size
Definition: size.h:135
impeller::StorageMode::kHostVisible
@ kHostVisible
ASSERT_POINT_NEAR
#define ASSERT_POINT_NEAR(a, b)
Definition: geometry_asserts.h:156
impeller::CreateMappingFromAllocation
std::shared_ptr< fml::Mapping > CreateMappingFromAllocation(const std::shared_ptr< Allocation > &allocation)
Definition: allocation.cc:100
ASSERT_VECTOR4_NEAR
#define ASSERT_VECTOR4_NEAR(a, b)
Definition: geometry_asserts.h:158
impeller::MoveTo
void MoveTo(PathBuilder *builder, Scalar x, Scalar y)
Definition: tessellator.cc:18
impeller::TPoint::Floor
constexpr TPoint Floor() const
Definition: point.h:187
impeller::ToShaderStage
constexpr ShaderStage ToShaderStage(RuntimeShaderStage stage)
Definition: shader_types.h:29
impeller::testing::RenderTextInCanvasSTB
bool RenderTextInCanvasSTB(const std::shared_ptr< Context > &context, Canvas &canvas, const std::string &text, const std::string &font_fixture, TextRenderOptions options={})
Definition: aiks_unittests.cc:1336
impeller::kPiOver2
constexpr float kPiOver2
Definition: constants.h:31
ASSERT_RECT_NEAR
#define ASSERT_RECT_NEAR(a, b)
Definition: geometry_asserts.h:154
impeller::MakeTextFrameSTB
std::shared_ptr< TextFrame > MakeTextFrameSTB(const std::shared_ptr< TypefaceSTB > &typeface_stb, Font::Metrics metrics, const std::string &text)
Definition: text_frame_stb.cc:11
impeller::kPhi
constexpr float kPhi
Definition: constants.h:52
impeller::kColor
@ kColor
Definition: geometry.h:27
impeller::testing::toColor
flutter::DlColor toColor(const float *components)
Definition: dl_unittests.cc:40
impeller::Point
TPoint< Scalar > Point
Definition: point.h:306
impeller::k2Pi
constexpr float k2Pi
Definition: constants.h:28
impeller::testing::CompareFunctionUIData::FunctionOf
CompareFunction FunctionOf(int index) const
Definition: renderer_unittests.cc:1097
impeller::testing::RGBToYUV
static Vector3 RGBToYUV(Vector3 rgb, YUVColorSpace yuv_color_space)
Definition: entity_unittests.cc:2012
impeller::MipFilter
MipFilter
Definition: formats.h:369
impeller::SPrintF
std::string SPrintF(const char *format,...)
Definition: strings.cc:12
impeller::testing::GetBlendModeSelection
static BlendModeSelection GetBlendModeSelection()
Definition: aiks_unittests.cc:1610
impeller::IPoint32
TPoint< int32_t > IPoint32
Definition: point.h:308
impeller::ScalarToHalf
constexpr InternalHalf ScalarToHalf(Scalar f)
Convert a scalar to a half precision float.
Definition: half.h:28
impeller::TPoint::Max
constexpr TPoint Max(const TPoint &p) const
Definition: point.h:183
impeller::testing::CanRenderRadialGradientWithDithering
static void CanRenderRadialGradientWithDithering(AiksTest *aiks_test, bool use_dithering)
Definition: aiks_unittests.cc:453
impeller::MinMagFilter
MinMagFilter
Definition: formats.h:361
impeller::testing::CanRenderLinearGradientWithDithering
static void CanRenderLinearGradientWithDithering(AiksTest *aiks_test, bool use_dithering)
Definition: aiks_unittests.cc:425
impeller::testing::CreateTestYUVTextures
static std::vector< std::shared_ptr< Texture > > CreateTestYUVTextures(Context *context, YUVColorSpace yuv_color_space)
Definition: entity_unittests.cc:2029
_BLEND_MODE_NAME_CHECK
#define _BLEND_MODE_NAME_CHECK(blend_mode)
Definition: geometry_unittests.cc:1561
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:306
ASSERT_MATRIX_NEAR
#define ASSERT_MATRIX_NEAR(a, b)
Definition: geometry_asserts.h:152
impeller::testing::CreateStringFromMapping
const std::string CreateStringFromMapping(const fml::Mapping &mapping)
Definition: blobcat_unittests.cc:23
impeller::CreateGradientBuffer
GradientData CreateGradientBuffer(const std::vector< Color > &colors, const std::vector< Scalar > &stops)
Populate a vector with the interpolated color bytes for the linear gradient described by colors and s...
Definition: gradient.cc:20
IMPELLER_FOR_EACH_BLEND_MODE
#define IMPELLER_FOR_EACH_BLEND_MODE(V)
Definition: color.h:17
impeller::testing::CreatePassWithRectPath
auto CreatePassWithRectPath(Rect rect, std::optional< Rect > bounds_hint, bool collapse=false)
Definition: entity_unittests.cc:109
impeller::IRect
TRect< int64_t > IRect
Definition: rect.h:307
impeller::MakeTextFrameFromTextBlobSkia
std::shared_ptr< TextFrame > MakeTextFrameFromTextBlobSkia(const sk_sp< SkTextBlob > &blob)
Definition: text_frame_skia.cc:41
ASSERT_QUATERNION_NEAR
#define ASSERT_QUATERNION_NEAR(a, b)
Definition: geometry_asserts.h:153
impeller::Close
void Close(PathBuilder *builder)
Definition: tessellator.cc:36
impeller::ISize
TSize< int64_t > ISize
Definition: size.h:136
impeller::TextureDescriptor::size
ISize size
Definition: texture_descriptor.h:43
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:60
impeller::LineTo
void LineTo(PathBuilder *builder, Scalar x, Scalar y)
Definition: tessellator.cc:22
impeller::Join
Join
Definition: path.h:23
impeller::IPoint
TPoint< int64_t > IPoint
Definition: point.h:307
ASSERT_VECTOR3_NEAR
#define ASSERT_VECTOR3_NEAR(a, b)
Definition: geometry_asserts.h:157
impeller::ScalarNearlyEqual
constexpr bool ScalarNearlyEqual(Scalar x, Scalar y, Scalar tolerance=kEhCloseEnough)
Definition: scalar.h:27
impeller::YUVColorSpace
YUVColorSpace
Definition: color.h:53
impeller::TextureDescriptor::storage_mode
StorageMode storage_mode
Definition: texture_descriptor.h:40
impeller::TPoint::GetDistance
constexpr Type GetDistance(const TPoint &p) const
Definition: point.h:193
impeller::TextureDescriptor
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
Definition: texture_descriptor.h:39
impeller::TRect::GetPositive
constexpr TRect GetPositive() const
Get a version of this rectangle that has a non-negative size.
Definition: rect.h:180
impeller::testing::CreateGlyphAtlas
static std::shared_ptr< GlyphAtlas > CreateGlyphAtlas(Context &context, const TypographerContext *typographer_context, GlyphAtlas::Type type, Scalar scale, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const TextFrame &frame)
Definition: typographer_unittests.cc:25
impeller::TPoint::Normalize
constexpr TPoint Normalize() const
Definition: point.h:201
ASSERT_COLOR_BUFFER_NEAR
#define ASSERT_COLOR_BUFFER_NEAR(a, b)
Definition: geometry_asserts.h:161
IMPELLER_PLAYGROUND_LINE
#define IMPELLER_PLAYGROUND_LINE(default_position_a, default_position_b, radius, color_a, color_b)
Definition: widgets.h:55
impeller::kPiOver4
constexpr float kPiOver4
Definition: constants.h:34
impeller::skia_conversions::ToPath
Path ToPath(const SkPath &path, Point shift)
Definition: skia_conversions.cc:49
impeller::Cap
Cap
Definition: path.h:17
ASSERT_ARRAY_4_NEAR
#define ASSERT_ARRAY_4_NEAR(a, b)
Definition: geometry_asserts.h:160