| Flutter Impeller |

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

## Classes
class | BlendFilterContentsTest
struct | BlendModeSelection
struct | ColorBlendTestData
class | CompareFunctionUIData
struct | CVTest
struct | Foo
class | GaussianBlurFilterContentsTest
class | GoldenDigest
| Manages a global variable for tracking instances of golden images. More...
class | GoldenTests
struct | MaskBlurTestConfig
class | MatrixFilterContentsTest
class | MetalScreenshot
| A screenshot that was produced from `MetalScreenshotter`. More...
class | MetalScreenshotter
class | RendererDartTest
struct | RWFoo
class | Screenshot
class | Screenshotter
class | TestAllocator
class | TestPassDelegate
struct | TextRenderOptions
class | VulkanScreenshotter
class | WorkingDirectory

## Typedefs
using | AiksTest = AiksPlayground
using | AiksCanvasTest = ::testing::Test
using | DisplayListTest = DlPlayground
using | EntityTest = EntityPlayground
using | HostBufferTest = EntityPlayground
using | EntityPassTargetTest = EntityPlayground
using | RenderTargetCacheTest = EntityPlayground
using | AllocatorMTLTest = PlaygroundTest
using | DriverInfoVKTest = PlaygroundTest
using | RendererTest = PlaygroundTest
using | BlitPassTest = PlaygroundTest
using | ComputeTest = ComputePlaygroundTest
using | DeviceBufferTest = Playground
using | RuntimeStageTest = RuntimeStagePlayground
using | TypographerTest = PlaygroundTest

## Functions
| TEST_P (AiksTest, CanRenderAdvancedBlendColorFilterWithSaveLayer)
| TEST_P (AiksTest, BlendModeShouldCoverWholeScreen)
| TEST_P (AiksTest, CanDrawPaintWithAdvancedBlend)
| TEST_P (AiksTest, DrawPaintWithAdvancedBlendOverFilter)
| TEST_P (AiksTest, DrawAdvancedBlendPartlyOffscreen)
| TEST_P (AiksTest, PaintBlendModeIsRespected)
| TEST_P (AiksTest, BlendModePlusAlphaWideGamut)
| TEST_P (AiksTest, BlendModePlusAlphaColorFilterWideGamut)
static BlendModeSelection | GetBlendModeSelection ()
| TEST_P (AiksTest, ColorWheel)
| TEST_P (AiksTest, ForegroundBlendSubpassCollapseOptimization)
| TEST_P (AiksTest, ClearBlend)
static Picture | BlendModeTest (Vector2 content_scale, BlendMode blend_mode, const std::shared_ptr< Image > &src_image, const std::shared_ptr< Image > &dst_image, Scalar src_alpha)
| TEST_P (AiksTest, CanDrawPaintMultipleTimesInteractive)
| TEST_P (AiksTest, ForegroundPipelineBlendAppliesTransformCorrectly)
| TEST_P (AiksTest, ForegroundAdvancedBlendAppliesTransformCorrectly)
| TEST_P (AiksTest, FramebufferAdvancedBlendCoverage)
| TEST_P (AiksTest, CanRenderMaskBlurHugeSigma)
| TEST_P (AiksTest, CanRenderForegroundBlendWithMaskBlur)
| TEST_P (AiksTest, CanRenderForegroundAdvancedBlendWithMaskBlur)
| TEST_P (AiksTest, CanRenderBackdropBlurInteractive)
| TEST_P (AiksTest, CanRenderBackdropBlur)
| TEST_P (AiksTest, CanRenderBackdropBlurHugeSigma)
| TEST_P (AiksTest, CanRenderClippedBlur)
| TEST_P (AiksTest, ClippedBlurFilterRendersCorrectlyInteractive)
| TEST_P (AiksTest, ClippedBlurFilterRendersCorrectly)
| TEST_P (AiksTest, ClearBlendWithBlur)
| TEST_P (AiksTest, BlurHasNoEdge)
| TEST_P (AiksTest, BlurredRectangleWithShader)
| TEST_P (AiksTest, MaskBlurWithZeroSigmaIsSkipped)
static Picture | MaskBlurVariantTest (const AiksTest &test_context, const MaskBlurTestConfig &config)
| TEST_P (AiksTest, GaussianBlurAtPeripheryVertical)
| TEST_P (AiksTest, GaussianBlurAtPeripheryHorizontal)
| TEST_P (AiksTest, GaussianBlurWithoutDecalSupport)
| TEST_P (AiksTest, GaussianBlurOneDimension)
| TEST_P (AiksTest, GaussianBlurRotatedAndClipped)
| TEST_P (AiksTest, GaussianBlurScaledAndClipped)
| TEST_P (AiksTest, GaussianBlurRotatedAndClippedInteractive)
| TEST_P (AiksTest, GaussianBlurRotatedNonUniform)
| TEST_P (AiksTest, GaussianBlurSolidColorTinyMipMap)
| TEST_P (AiksTest, GaussianBlurBackdropTinyMipMap)
| TEST_P (AiksTest, GaussianBlurAnimatedBackdrop)
| TEST_P (AiksTest, GaussianBlurStyleInnerGradient)
| TEST_P (AiksTest, GaussianBlurStyleSolidGradient)
| TEST_P (AiksTest, GaussianBlurStyleOuterGradient)
| TEST_P (AiksTest, GaussianBlurStyleInner)
| TEST_P (AiksTest, GaussianBlurStyleOuter)
| TEST_P (AiksTest, GaussianBlurStyleSolid)
| TEST_P (AiksTest, MaskBlurTexture)
| TEST_P (AiksTest, GuassianBlurUpdatesMipmapContents)
| TEST_P (AiksTest, GaussianBlurSetsMipCountOnPass)
| TEST_P (AiksTest, GaussianBlurAllocatesCorrectMipCountRenderTarget)
| TEST_P (AiksTest, GaussianBlurMipMapNestedLayer)
| TEST_P (AiksTest, GaussianBlurMipMapImageFilter)
| TEST_P (AiksTest, GaussianBlurMipMapSolidColor)
| TEST_P (AiksTest, MaskBlurDoesntStretchContents)
| 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, CanRenderStrokes)
| TEST_P (AiksTest, CanRenderCurvedStrokes)
| TEST_P (AiksTest, CanRenderThickCurvedStrokes)
| TEST_P (AiksTest, CanRenderThinCurvedStrokes)
| TEST_P (AiksTest, CanRenderStrokePathThatEndsAtSharpTurn)
| TEST_P (AiksTest, CanRenderStrokePathWithCubicLine)
| TEST_P (AiksTest, CanRenderQuadraticStrokeWithInstantTurn)
| TEST_P (AiksTest, CanRenderDifferencePaths)
| TEST_P (AiksTest, CanDrawAnOpenPath)
| TEST_P (AiksTest, CanDrawAnOpenPathThatIsntARect)
| TEST_P (AiksTest, SolidStrokesRenderCorrectly)
| TEST_P (AiksTest, DrawLinesRenderCorrectly)
| TEST_P (AiksTest, DrawRectStrokesRenderCorrectly)
| TEST_P (AiksTest, DrawRectStrokesWithBevelJoinRenderCorrectly)
| TEST_P (AiksTest, CanDrawMultiContourConvexPath)
| TEST_P (AiksTest, ArcWithZeroSweepAndBlur)
| TEST_P (AiksTest, CanRenderClips)
| TEST_P (AiksTest, CanRenderOverlappingMultiContourPath)
| INSTANTIATE_PLAYGROUND_SUITE (AiksTest)
| TEST_P (AiksTest, CanvasCTMCanBeUpdated)
| TEST_P (AiksTest, CanvasCanPushPopCTM)
| TEST_P (AiksTest, CanRenderColoredRect)
| TEST_P (AiksTest, CanRenderImage)
| TEST_P (AiksTest, CanRenderInvertedImageWithColorFilter)
| TEST_P (AiksTest, CanRenderColorFilterWithInvertColors)
| TEST_P (AiksTest, CanRenderColorFilterWithInvertColorsDrawPaint)
| 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, CanRenderSimpleClips)
| TEST_P (AiksTest, CanSaveLayerStandalone)
| TEST_P (AiksTest, CanRenderDifferentShapesWithSameColorSource)
| TEST_P (AiksTest, CanPictureConvertToImage)
| TEST_P (AiksTest, CanEmptyPictureConvertToImage)
| TEST_P (AiksTest, CoordinateConversionsAreCorrect)
| TEST_P (AiksTest, CanPerformFullScreenMSAA)
| TEST_P (AiksTest, CanPerformSkew)
| TEST_P (AiksTest, CanPerformSaveLayerWithBounds)
| TEST_P (AiksTest, CanPerformSaveLayerWithBoundsAndLargerIntermediateIsNotAllocated)
| TEST_P (AiksTest, CanRenderRoundedRectWithNonUniformRadii)
bool | RenderTextInCanvasSkia (const std::shared_ptr< Context > &context, Canvas &canvas, const std::string &text, const std::string_view &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, CanRenderTextFrameWithInvertedTransform)
| TEST_P (AiksTest, CanRenderStrokedTextFrame)
| TEST_P (AiksTest, CanRenderTextFrameWithHalfScaling)
| TEST_P (AiksTest, CanRenderTextFrameWithFractionScaling)
| TEST_P (AiksTest, CanRenderTextFrameSTB)
| TEST_P (AiksTest, TextFrameSubpixelAlignment)
| TEST_P (AiksTest, CanRenderItalicizedText)
| TEST_P (AiksTest, CanRenderEmojiTextFrame)
| TEST_P (AiksTest, CanRenderEmojiTextFrameWithBlur)
| 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, FormatWideGamut)
| TEST_P (AiksTest, FormatSRGB)
| TEST_P (AiksTest, TransformMultipliesCorrectly)
| TEST_P (AiksTest, FilledCirclesRenderCorrectly)
| TEST_P (AiksTest, StrokedCirclesRenderCorrectly)
| TEST_P (AiksTest, FilledEllipsesRenderCorrectly)
| TEST_P (AiksTest, FilledRoundRectsRenderCorrectly)
| TEST_P (AiksTest, SolidColorCirclesOvalsRRectsMaskBlurCorrectly)
| TEST_P (AiksTest, FastEllipticalRRectMaskBlursRenderCorrectly)
| TEST_P (AiksTest, FilledRoundRectPathsRenderCorrectly)
| TEST_P (AiksTest, CoverageOriginShouldBeAccountedForInSubpasses)
| TEST_P (AiksTest, SaveLayerDrawsBehindSubsequentEntities)
| TEST_P (AiksTest, SiblingSaveLayerBoundsAreRespected)
| TEST_P (AiksTest, CanRenderClippedLayers)
| TEST_P (AiksTest, SaveLayerFiltersScaleWithTransform)
| TEST_P (AiksTest, PaintWithFilters)
| 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, ColorMatrixFilterSubpassCollapseOptimization)
| TEST_P (AiksTest, LinearToSrgbFilterSubpassCollapseOptimization)
| TEST_P (AiksTest, SrgbToLinearFilterSubpassCollapseOptimization)
| TEST_P (AiksTest, TranslucentSaveLayerDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithBlendColorFilterDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithBlendImageFilterDrawsCorrectly)
| TEST_P (AiksTest, TranslucentSaveLayerWithColorAndImageFilterDrawsCorrectly)
| TEST_P (AiksTest, ImageFilteredSaveLayerWithUnboundedContents)
| TEST_P (AiksTest, ImageFilteredUnboundedSaveLayerWithUnboundedContents)
| 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, OpaqueEntitiesGetCoercedToSource)
| TEST_P (AiksTest, CanRenderDestructiveSaveLayer)
| TEST_P (AiksTest, CanRenderClippedRuntimeEffects)
| TEST_P (AiksTest, DrawPaintTransformsBounds)
| TEST_P (AiksTest, CanDrawPoints)
| TEST_P (AiksTest, CanDrawPointsWithTextureMap)
| TEST_P (AiksTest, TextForegroundShaderWithTransform)
| TEST_P (AiksTest, MatrixSaveLayerFilter)
| TEST_P (AiksTest, MatrixBackdropFilter)
| TEST_P (AiksTest, SolidColorApplyColorFilter)
| TEST_P (AiksTest, DrawScaledTextWithPerspectiveNoSaveLayer)
| TEST_P (AiksTest, DrawScaledTextWithPerspectiveSaveLayer)
| TEST_P (AiksTest, PipelineBlendSingleParameter)
| TEST_P (AiksTest, ReleasesTextureOnTeardown)
| TEST_P (AiksTest, MatrixImageFilterMagnify)
| TEST_P (AiksTest, MatrixImageFilterDoesntCullWhenTranslatedFromOffscreen)
| TEST_P (AiksTest, MatrixImageFilterDoesntCullWhenScaledAndTranslatedFromOffscreen)
| TEST_P (AiksTest, ClearColorOptimizationWhenSubpassIsBiggerThanParentPass)
| TEST_P (AiksTest, EmptySaveLayerIgnoresPaint)
| TEST_P (AiksTest, EmptySaveLayerRendersWithClear)
| TEST_P (AiksTest, SubpassWithClearColorOptimization)
| TEST_P (AiksTest, ImageColorSourceEffectTransform)
| TEST_P (AiksTest, CorrectClipDepthAssignedToEntities)
| TEST_P (AiksTest, CanDrawPerspectiveTransformWithClips)
| TEST_P (AiksTest, CanRenderClippedBackdropFilter)
| TEST_P (AiksTest, MipmapGenerationWorksCorrectly)
| TEST_P (AiksTest, StrokedPathWithMoveToThenCloseDrawnCorrectly)
| TEST_P (AiksTest, CanRenderTextWithLargePerspectiveTransform)
| TEST_P (AiksTest, SetContentsWithRegion)
| 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 (ThreadTest, CanCreateMutex)
| TEST (ThreadTest, CanCreateMutexLock)
| TEST (ThreadTest, CanCreateRWMutex)
| TEST (ThreadTest, CanCreateRWMutexLock)
| TEST (StringsTest, CanSPrintF)
| TEST (ConditionVariableTest, WaitUntil)
| TEST (ConditionVariableTest, WaitFor)
| TEST (ConditionVariableTest, WaitForever)
| TEST (ConditionVariableTest, TestsCriticalSectionAfterWaitForUntil)
| TEST (ConditionVariableTest, TestsCriticalSectionAfterWait)
| TEST (BaseTest, NoExceptionPromiseValue)
| TEST (BaseTest, NoExceptionPromiseEmpty)
| TEST (BaseTest, CanUseTypedMasks)
| TEST (AllocatorTest, TextureDescriptorCompatibility)
| TEST_P (AiksTest, DrawAtlasNoColor)
| TEST_P (AiksTest, DrawAtlasWithColorAdvanced)
| TEST_P (AiksTest, DrawAtlasWithColorSimple)
| TEST_P (AiksTest, DrawAtlasWithOpacity)
| TEST_P (AiksTest, DrawAtlasNoColorFullSize)
| TEST_P (AiksTest, DrawAtlasAdvancedAndTransform)
| TEST_P (AiksTest, DrawAtlasWithColorAdvancedAndTransform)
| TEST_P (AiksTest, DrawAtlasPlusWideGamut)
| TEST_P (AiksTest, CanRenderNestedClips)
| TEST_P (AiksTest, CanRenderDifferenceClips)
| TEST_P (AiksTest, CanRenderWithContiguousClipRestores)
| TEST_P (AiksTest, ClipsUseCurrentTransform)
| TEST_P (AiksTest, FramebufferBlendsRespectClips)
| 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)
| TEST_P (AiksTest, CanRenderLinearGradientWithDitheringEnabled)
static void | CanRenderRadialGradientWithDithering (AiksTest *aiks_test)
| TEST_P (AiksTest, CanRenderRadialGradientWithDitheringEnabled)
static void | CanRenderSweepGradientWithDithering (AiksTest *aiks_test)
| TEST_P (AiksTest, CanRenderSweepGradientWithDitheringEnabled)
static void | CanRenderConicalGradientWithDithering (AiksTest *aiks_test)
| 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, GradientStrokesRenderCorrectly)
| TEST_P (AiksTest, FastGradientTestHorizontal)
| TEST_P (AiksTest, FastGradientTestVertical)
| TEST_P (AiksTest, FastGradientTestHorizontalReversed)
| TEST_P (AiksTest, FastGradientTestVerticalReversed)
| TEST_P (AiksTest, VerifyNonOptimizedGradient)
| TEST_P (AiksTest, DrawOpacityPeephole)
| TEST_P (AiksTest, CanRenderGroupOpacity)
| TEST_P (AiksTest, CanRenderGroupOpacityToSavelayer)
| TEST_P (AiksTest, RotateColorFilteredPath)
| TEST_P (AiksTest, VerticesGeometryUVPositionData)
| TEST_P (AiksTest, VerticesGeometryUVPositionDataWithTranslate)
| TEST_P (AiksTest, VerticesGeometryColorUVPositionData)
| TEST_P (AiksTest, VerticesGeometryColorUVPositionDataAdvancedBlend)
| TEST_P (AiksTest, CanConvertTriangleFanToTriangles)
| TEST_P (AiksTest, DrawVerticesSolidColorTrianglesWithoutIndices)
| TEST_P (AiksTest, DrawVerticesLinearGradientWithoutIndices)
| TEST_P (AiksTest, DrawVerticesLinearGradientWithTextureCoordinates)
| TEST_P (AiksTest, DrawVerticesImageSourceWithTextureCoordinates)
| TEST_P (AiksTest, DrawVerticesImageSourceWithTextureCoordinatesAndColorBlending)
| TEST_P (AiksTest, DrawVerticesSolidColorTrianglesWithIndices)
| TEST_P (AiksTest, DrawVerticesPremultipliesColors)
| TEST_P (AiksTest, DrawVerticesTextureCoordinatesWithFragmentShader)
| TEST_P (AiksTest, DrawVerticesTextureCoordinatesWithFragmentShaderNonZeroOrigin)
flutter::DlColor | toColor (const float *components)
| INSTANTIATE_PLAYGROUND_SUITE (DisplayListTest)
| 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, NinePatchImagePrecision)
| TEST_P (DisplayListTest, CanDrawPoints)
| TEST_P (DisplayListTest, CanDrawZeroLengthLine)
| TEST_P (DisplayListTest, CanDrawShadow)
| TEST_P (DisplayListTest, DispatcherDoesNotCullPerspectiveTransformedChildDisplayLists)
| TEST_P (DisplayListTest, TransparentShadowProducesCorrectColor)
| 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, DrawShapes)
| TEST_P (DisplayListTest, ClipDrawRRectWithNonCircularRadii)
| TEST_P (DisplayListTest, DrawVerticesBlendModes)
template<typename Contents >
static std::optional< Rect > | GetCoverageOfFirstEntity (const Picture &picture)
| TEST (DisplayListTest, RRectBoundsComputation)
| TEST (DisplayListTest, CircleBoundsComputation)
| TEST_P (DisplayListTest, DrawPaintIgnoresMaskFilter)
| TEST_P (DisplayListTest, DrawMaskBlursThatMightUseSaveLayers)
| TEST (SkiaConversionsTest, SkPointToPoint)
| TEST (SkiaConversionsTest, SkPointToSize)
| TEST (SkiaConversionsTest, ToColor)
| TEST (SkiaConversionsTest, GradientStopConversion)
| TEST (SkiaConversionsTest, GradientMissing0)
| TEST (SkiaConversionsTest, GradientMissingLastValue)
| TEST (SkiaConversionsTest, GradientStopGreaterThan1)
| TEST (SkiaConversionsTest, GradientConversionNonMonotonic)
| TEST (SkiaConversionsTest, IsNearlySimpleRRect)
| TEST_P (EntityTest, ClipContentsOptimizesFullScreenIntersectClips)
| INSTANTIATE_PLAYGROUND_SUITE (BlendFilterContentsTest)
| TEST_P (BlendFilterContentsTest, AdvancedBlendColorAlignsColorTo4)
| INSTANTIATE_PLAYGROUND_SUITE (GaussianBlurFilterContentsTest)
| TEST (GaussianBlurFilterContentsTest, Create)
| TEST (GaussianBlurFilterContentsTest, CoverageEmpty)
| TEST (GaussianBlurFilterContentsTest, CoverageSimple)
| TEST (GaussianBlurFilterContentsTest, CoverageWithSigma)
| TEST_P (GaussianBlurFilterContentsTest, CoverageWithTexture)
| TEST_P (GaussianBlurFilterContentsTest, CoverageWithEffectTransform)
| TEST (GaussianBlurFilterContentsTest, FilterSourceCoverage)
| TEST (GaussianBlurFilterContentsTest, CalculateSigmaValues)
| TEST_P (GaussianBlurFilterContentsTest, RenderCoverageMatchesGetCoverage)
| TEST_P (GaussianBlurFilterContentsTest, RenderCoverageMatchesGetCoverageTranslate)
| TEST_P (GaussianBlurFilterContentsTest, RenderCoverageMatchesGetCoverageRotated)
| TEST_P (GaussianBlurFilterContentsTest, CalculateUVsSimple)
| TEST_P (GaussianBlurFilterContentsTest, TextureContentsWithDestinationRect)
| TEST_P (GaussianBlurFilterContentsTest, TextureContentsWithDestinationRectScaled)
| TEST_P (GaussianBlurFilterContentsTest, TextureContentsWithEffectTransform)
| TEST (GaussianBlurFilterContentsTest, CalculateSigmaForBlurRadius)
| TEST (GaussianBlurFilterContentsTest, Coefficients)
| TEST (GaussianBlurFilterContentsTest, LerpHackKernelSamplesSimple)
| TEST (GaussianBlurFilterContentsTest, LerpHackKernelSamplesComplex)
| TEST (GaussianBlurFilterContentsTest, ChopHugeBlurs)
| TEST (FilterInputTest, CanSetLocalTransformForTexture)
| TEST (FilterInputTest, IsLeaf)
| TEST (FilterInputTest, SetCoverageInputs)
| INSTANTIATE_PLAYGROUND_SUITE (MatrixFilterContentsTest)
| TEST (MatrixFilterContentsTest, Create)
| TEST (MatrixFilterContentsTest, CoverageEmpty)
| TEST (MatrixFilterContentsTest, CoverageSimple)
| TEST (MatrixFilterContentsTest, Coverage2x)
| TEST (MatrixFilterContentsTest, Coverage2xEffect)
| TEST_P (MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageIdentity)
| TEST_P (MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageTranslate)
| TEST_P (MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageClippedSubpassTranslate)
| TEST_P (MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageScale)
| TEST_P (MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageClippedSubpassScale)
| TEST_P (MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageSubpassScale)
| INSTANTIATE_PLAYGROUND_SUITE (HostBufferTest)
| TEST_P (HostBufferTest, CanEmplace)
| TEST_P (HostBufferTest, CanEmplaceWithAlignment)
| TEST_P (HostBufferTest, HostBufferInitialState)
| TEST_P (HostBufferTest, ResetIncrementsFrameCounter)
| TEST_P (HostBufferTest, EmplacingLargerThanBlockSizeCreatesOneOffBufferCallback)
| TEST_P (HostBufferTest, EmplacingLargerThanBlockSizeCreatesOneOffBuffer)
| TEST_P (HostBufferTest, UnusedBuffersAreDiscardedWhenResetting)
| TEST_P (HostBufferTest, EmplaceWithProcIsAligned)
| TEST_P (EntityTest, TiledTextureContentsRendersWithCorrectPipeline)
| TEST_P (EntityTest, TiledTextureContentsRendersWithCorrectPipelineExternalOES)
| TEST_P (EntityPassTargetTest, SwapWithMSAATexture)
| TEST_P (EntityPassTargetTest, SwapWithMSAAImplicitResolve)
| TEST (EntityPassClipStackTest, CanPushAndPopEntities)
| TEST (EntityPassClipStackTest, CanPopEntitiesSafely)
| TEST (EntityPassClipStackTest, CanAppendNoChange)
| TEST (EntityPassClipStackTest, AppendCoverageNoChange)
| TEST (EntityPassClipStackTest, AppendAndRestoreClipCoverage)
| TEST (EntityPassClipStackTest, UnbalancedRestore)
| TEST (EntityPassClipStackTest, ClipAndRestoreWithSubpasses)
| TEST_P (EntityTest, CanCreateEntity)
auto | CreatePassWithRectPath (Rect rect, std::optional< Rect > bounds_hint, ContentBoundsPromise bounds_promise=ContentBoundsPromise::kUnknown, bool collapse=false)
| TEST_P (EntityTest, EntityPassRespectsUntrustedSubpassBoundsLimit)
| TEST_P (EntityTest, EntityPassTrustsSnugSubpassBoundsLimit)
| 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, CanDrawCorrectlyWithRotatedTransform)
| 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, SolidFillCoverageIsCorrect)
| TEST_P (EntityTest, SolidFillShouldRenderIsCorrect)
| TEST_P (EntityTest, DoesNotCullEntitiesByDefault)
| TEST_P (EntityTest, ClipContentsShouldRenderIsCorrect)
| TEST_P (EntityTest, ClipContentsGetClipCoverageIsCorrect)
| 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)
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, RuntimeEffectCanSuccessfullyRender)
| TEST_P (EntityTest, RuntimeEffectCanPrecache)
| TEST_P (EntityTest, RuntimeEffectSetsRightSizeWhenUniformIsStruct)
| 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, PointFieldGeometryCoverage)
| TEST_P (EntityTest, ColorFilterContentsWithLargeGeometry)
| TEST_P (EntityTest, TextContentsCeilsGlyphScaleToDecimal)
| TEST_P (EntityTest, AdvancedBlendCoverageHintIsNotResetByEntityPass)
| TEST_P (EntityTest, SpecializationConstantsAreAppliedToVariants)
| TEST_P (EntityTest, DecalSpecializationAppliedToMorphologyFilter)
| TEST_P (EntityTest, ContentContextOptionsHasReasonableHashFunctions)
| TEST_P (EntityTest, FillPathGeometryGetPositionBufferReturnsExpectedMode)
| TEST_P (EntityTest, FailOnValidationError)
| TEST_P (EntityTest, CanComputeGeometryForEmptyPathsWithoutCrashing)
| TEST_P (EntityTest, CanRenderEmptyPathsWithoutCrashing)
| TEST (EntityGeometryTest, RectGeometryCoversArea)
| TEST (EntityGeometryTest, FillPathGeometryCoversArea)
| TEST (EntityGeometryTest, FillPathGeometryCoversAreaNoInnerRect)
| TEST (EntityGeometryTest, LineGeometryCoverage)
| TEST (EntityGeometryTest, RoundRectGeometryCoversArea)
| TEST (EntityGeometryTest, GeometryResultHasReasonableDefaults)
| TEST (EntityGeometryTest, AlphaCoverageStrokePaths)
| TEST_P (RenderTargetCacheTest, CachesUsedTexturesAcrossFrames)
| TEST_P (RenderTargetCacheTest, DoesNotPersistFailedAllocations)
| TEST_P (RenderTargetCacheTest, CachedTextureGetsNewAttachmentConfig)
| TEST_P (RenderTargetCacheTest, CreateWithEmptySize)
| 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, MatrixTranslationScaleOnly)
| TEST (GeometryTest, MatrixLookAt)
| TEST (GeometryTest, QuaternionLerp)
| TEST (GeometryTest, QuaternionVectorMultiply)
| 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, PointRotate)
| 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, SeparatedVector2NormalizesWithConstructor)
| TEST (GeometryTest, SeparatedVector2GetVector)
| TEST (GeometryTest, SeparatedVector2GetAlignment)
| TEST (GeometryTest, SeparatedVector2AngleTo)
| 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, ColorBlendReturnsExpectedResults)
| TEST (GeometryTest, BlendModeToString)
| TEST (GeometryTest, CanConvertBetweenDegressAndRadians)
| 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 (MatrixTest, Multiply)
| TEST (MatrixTest, HasPerspective2D)
| TEST (MatrixTest, HasPerspective)
| TEST (MatrixTest, HasTranslation)
| TEST (MatrixTest, IsAligned2D)
| TEST (MatrixTest, IsAligned)
| TEST (MatrixTest, TransformHomogenous)
| TEST (PathTest, CubicPathComponentPolylineDoesNotIncludePointOne)
| TEST (PathTest, PathCreatePolyLineDoesNotDuplicatePoints)
| TEST (PathTest, PathBuilderSetsCorrectContourPropertiesForAddCommands)
| TEST (PathTest, PathCreatePolylineGeneratesCorrectContourData)
| TEST (PathTest, PolylineGetContourPointBoundsReturnsCorrectRanges)
| TEST (PathTest, PathAddRectPolylineHasCorrectContourData)
| TEST (PathTest, PathPolylineDuplicatesAreRemovedForSameContour)
| TEST (PathTest, PolylineBufferReuse)
| TEST (PathTest, PolylineFailsWithNullptrBuffer)
| TEST (PathTest, PathShifting)
| TEST (PathTest, PathBuilderWillComputeBounds)
| TEST (PathTest, PathHorizontalLine)
| TEST (PathTest, PathVerticalLine)
| TEST (PathTest, QuadradicPath)
| TEST (PathTest, CubicPath)
| TEST (PathTest, BoundingBoxCubic)
| TEST (PathTest, BoundingBoxOfCompositePathIsCorrect)
| TEST (PathTest, ExtremaOfCubicPathComponentIsCorrect)
| TEST (PathTest, PathGetBoundingBoxForCubicWithNoDerivativeRootsIsCorrect)
| TEST (PathTest, EmptyPath)
| TEST (PathTest, SimplePath)
| TEST (PathTest, RepeatCloseDoesNotAddNewLines)
| TEST (PathTest, CloseAfterMoveDoesNotAddNewLines)
| TEST (PathTest, CloseAtOriginDoesNotAddNewLineSegment)
| TEST (PathTest, CanBeCloned)
| TEST (PathTest, PathBuilderDoesNotMutateCopiedPaths)
| TEST (RectTest, RectEmptyDeclaration)
| TEST (RectTest, IRectEmptyDeclaration)
| TEST (RectTest, RectDefaultConstructor)
| TEST (RectTest, IRectDefaultConstructor)
| TEST (RectTest, RectSimpleLTRB)
| TEST (RectTest, IRectSimpleLTRB)
| TEST (RectTest, RectSimpleXYWH)
| TEST (RectTest, IRectSimpleXYWH)
| TEST (RectTest, RectOverflowXYWH)
| TEST (RectTest, IRectOverflowXYWH)
| TEST (RectTest, RectOverflowLTRB)
| TEST (RectTest, IRectOverflowLTRB)
| TEST (RectTest, RectMakeSize)
| TEST (RectTest, RectMakeMaximum)
| TEST (RectTest, IRectMakeMaximum)
| TEST (RectTest, RectFromRect)
| TEST (RectTest, IRectFromIRect)
| TEST (RectTest, RectCopy)
| TEST (RectTest, IRectCopy)
| TEST (RectTest, RectOriginSizeXYWHGetters)
| TEST (RectTest, IRectOriginSizeXYWHGetters)
| TEST (RectTest, RectRoundOutEmpty)
| TEST (RectTest, RectRoundOutSimple)
| TEST (RectTest, RectRoundOutToIRectHuge)
| TEST (RectTest, RectDoesNotIntersectEmpty)
| TEST (RectTest, IRectDoesNotIntersectEmpty)
| TEST (RectTest, EmptyRectDoesNotIntersect)
| TEST (RectTest, EmptyIRectDoesNotIntersect)
| TEST (RectTest, RectScale)
| TEST (RectTest, IRectScale)
| TEST (RectTest, RectArea)
| TEST (RectTest, IRectArea)
| TEST (RectTest, RectGetNormalizingTransform)
| TEST (RectTest, IRectGetNormalizingTransform)
| TEST (RectTest, RectXYWHIsEmpty)
| TEST (RectTest, IRectXYWHIsEmpty)
| TEST (RectTest, MakePointBoundsQuad)
| TEST (RectTest, IsSquare)
| TEST (RectTest, GetCenter)
| TEST (RectTest, RectExpand)
| TEST (RectTest, IRectExpand)
| TEST (RectTest, ContainsFloatingPoint)
template<typename R >
static constexpr R | flip_lr (R rect)
template<typename R >
static constexpr R | flip_tb (R rect)
template<typename R >
static constexpr R | flip_lrtb (R rect)
static constexpr Rect | swap_nan (const Rect &rect, int index)
static constexpr Point | swap_nan (const Point &point, int index)
| TEST (RectTest, RectUnion)
| TEST (RectTest, OptRectUnion)
| TEST (RectTest, IRectUnion)
| TEST (RectTest, OptIRectUnion)
| TEST (RectTest, RectIntersection)
| TEST (RectTest, OptRectIntersection)
| TEST (RectTest, IRectIntersection)
| TEST (RectTest, OptIRectIntersection)
| TEST (RectTest, RectIntersectsWithRect)
| TEST (RectTest, IRectIntersectsWithRect)
| TEST (RectTest, RectContainsPoint)
| TEST (RectTest, IRectContainsIPoint)
| TEST (RectTest, RectContainsInclusivePoint)
| TEST (RectTest, IRectContainsInclusiveIPoint)
| TEST (RectTest, RectContainsRect)
| TEST (RectTest, IRectContainsIRect)
| TEST (RectTest, RectCutOut)
| TEST (RectTest, IRectCutOut)
| TEST (RectTest, RectGetPoints)
| TEST (RectTest, RectShift)
| TEST (RectTest, RectGetTransformedPoints)
| TEST (RectTest, RectMakePointBounds)
| TEST (RectTest, RectGetPositive)
| TEST (RectTest, RectDirections)
| TEST (RectTest, RectProject)
| TEST (RectTest, RectRoundOut)
| TEST (RectTest, IRectRoundOut)
| TEST (RectTest, RectRound)
| TEST (RectTest, IRectRound)
| TEST (RectTest, TransformAndClipBounds)
| TEST (SaturatedMath, ExplicitAddOfSignedInts)
| TEST (SaturatedMath, ImplicitAddOfSignedInts)
| TEST (SaturatedMath, ExplicitAddOfFloatingPoint)
| TEST (SaturatedMath, ImplicitAddOfFloatingPoint)
| TEST (SaturatedMath, ExplicitSubOfSignedInts)
| TEST (SaturatedMath, ImplicitSubOfSignedInts)
| TEST (SaturatedMath, ExplicitSubOfFloatingPoint)
| TEST (SaturatedMath, ImplicitSubOfFloatingPoint)
| TEST (SaturatedMath, ExplicitAverageScalarOfSignedInts)
| TEST (SaturatedMath, ImplicitAverageScalarOfSignedInts)
| TEST (SaturatedMath, ExplicitAverageScalarOfFloatingPoint)
| TEST (SaturatedMath, ImplicitAverageScalarOfFloatingPoint)
| TEST (SaturatedMath, CastingFiniteDoubleToFloatStaysFinite)
| TEST (SaturatedMath, CastingInfiniteDoubleToFloatStaysInfinite)
| TEST (SaturatedMath, CastingNaNDoubleToFloatStaysNaN)
| TEST (SaturatedMath, CastingLargeScalarToSignedIntProducesLimit)
| TEST (SaturatedMath, CastingInfiniteScalarToSignedIntProducesLimit)
| TEST (SaturatedMath, CastingNaNScalarToSignedIntProducesZero)
| TEST (SizeTest, SizeIsEmpty)
| TEST (SizeTest, ISizeIsEmpty)
| TEST (SizeTest, IsSquare)
| TEST (SizeTest, MaxDimension)
| TEST (SizeTest, NegationOperator)
| TEST (TrigTest, TrigAngles)
| TEST (TrigTest, MultiplyByScalarRadius)
| TEST_F (GoldenTests, ConicalGradient)
| INSTANTIATE_METAL_PLAYGROUND_SUITE (AllocatorMTLTest)
| TEST_P (AllocatorMTLTest, DebugTraceMemoryStatistics)
| TEST (TextureMTL, CreateFromDrawable)
| TEST (AllocatorVKTest, ToVKImageUsageFlags)
| TEST (AllocatorVKTest, MemoryTypeSelectionSingleHeap)
| TEST (AllocatorVKTest, MemoryTypeSelectionTwoHeap)
| TEST (CommandEncoderVKTest, DeleteEncoderAfterThreadDies)
| TEST (CommandEncoderVKTest, CleanupAfterSubmit)
| TEST (CommandPoolRecyclerVKTest, GetsACommandPoolPerThread)
| TEST (CommandPoolRecyclerVKTest, GetsTheSameCommandPoolOnSameThread)
| TEST (CommandPoolRecyclerVKTest, ReclaimMakesCommandPoolAvailable)
| TEST (CommandPoolRecyclerVKTest, CommandBuffersAreRecycled)
| TEST (ContextVKTest, CommonHardwareConcurrencyConfigurations)
| TEST (ContextVKTest, DeletesCommandPools)
| TEST (ContextVKTest, DeletesCommandPoolsOnAllThreads)
| TEST (ContextVKTest, DeletePipelineAfterContext)
| TEST (ContextVKTest, DeleteShaderFunctionAfterContext)
| TEST (ContextVKTest, DeletePipelineLibraryAfterContext)
| TEST (ContextVKTest, CanCreateContextInAbsenceOfValidationLayers)
| TEST (ContextVKTest, CanCreateContextWithValidationLayers)
| TEST (CapabilitiesVKTest, ContextInitializesWithNoStencilFormat)
| TEST (CapabilitiesVKTest, ContextFailsInitializationForNoCombinedDepthStencilFormat)
| TEST (ContextVKTest, WarmUpFunctionCreatesRenderPass)
| TEST (ContextVKTest, FatalMissingValidations)
| TEST (ContextVKTest, HasDefaultColorFormat)
| TEST (DescriptorPoolRecyclerVKTest, GetDescriptorPoolRecyclerCreatesNewPools)
| TEST (DescriptorPoolRecyclerVKTest, ReclaimMakesDescriptorPoolAvailable)
| TEST (DescriptorPoolRecyclerVKTest, ReclaimDropsDescriptorPoolIfSizeIsExceeded)
| INSTANTIATE_VULKAN_PLAYGROUND_SUITE (DriverInfoVKTest)
| TEST_P (DriverInfoVKTest, CanQueryDriverInfo)
| TEST_P (DriverInfoVKTest, CanDumpToLog)
| TEST (FenceWaiterVKTest, IgnoresNullFence)
| TEST (FenceWaiterVKTest, IgnoresNullCallback)
| TEST (FenceWaiterVKTest, ExecutesFenceCallback)
| TEST (FenceWaiterVKTest, ExecutesFenceCallbackX2)
| TEST (FenceWaiterVKTest, ExecutesNewFenceThenOldFence)
| TEST (FenceWaiterVKTest, AddFenceDoesNothingIfTerminating)
| TEST (FenceWaiterVKTest, InProgressFencesStillWaitIfTerminated)
| TEST (RenderPassBuilder, CreatesRenderPassWithNoDepthStencil)
| TEST (RenderPassBuilder, CreatesRenderPassWithCombinedDepthStencil)
| TEST (RenderPassBuilder, CreatesRenderPassWithOnlyStencil)
| TEST (RenderPassBuilder, CreatesMSAAResolveWithCorrectStore)
| TEST_P (RendererTest, CachesRenderPassAndFramebuffer)
| TEST (ResourceManagerVKTest, CreatesANewInstance)
| TEST (ResourceManagerVKTest, ReclaimMovesAResourceAndDestroysIt)
| TEST (ResourceManagerVKTest, TerminatesWhenOutOfScope)
| TEST (ResourceManagerVKTest, IsThreadSafe)
| INSTANTIATE_PLAYGROUND_SUITE (BlitPassTest)
| TEST_P (BlitPassTest, BlitAcrossDifferentPixelFormatsFails)
| TEST_P (BlitPassTest, BlitAcrossDifferentSampleCountsFails)
| TEST_P (BlitPassTest, BlitPassesForMatchingFormats)
| TEST_P (BlitPassTest, ChecksInvalidSliceParameters)
| TEST_P (BlitPassTest, CanBlitSmallRegionToUninitializedTexture)
| CAPABILITY_TEST (SupportsOffscreenMSAA, false)
| CAPABILITY_TEST (SupportsSSBO, false)
| CAPABILITY_TEST (SupportsTextureToTextureBlits, false)
| CAPABILITY_TEST (SupportsFramebufferFetch, false)
| CAPABILITY_TEST (SupportsCompute, false)
| CAPABILITY_TEST (SupportsComputeSubgroups, false)
| CAPABILITY_TEST (SupportsReadFromResolve, false)
| CAPABILITY_TEST (SupportsDecalSamplerAddressMode, false)
| CAPABILITY_TEST (SupportsDeviceTransientTextures, false)
| TEST (CapabilitiesTest, DefaultColorFormat)
| TEST (CapabilitiesTest, DefaultStencilFormat)
| TEST (CapabilitiesTest, DefaultDepthStencilFormat)
| TEST (CapabilitiesTest, DefaultGlyphAtlasFormat)
| INSTANTIATE_COMPUTE_SUITE (ComputeTest)
| 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 (PipelineDescriptorTest, PrimitiveTypeHashEquality)
| TEST (PoolTest, Simple)
| TEST (PoolTest, Overload)
static void | InstantiateTestShaderLibrary (Context::BackendType backend_type)
| INSTANTIATE_PLAYGROUND_SUITE (RendererDartTest)
| TEST_P (RendererDartTest, CanRunDartInPlaygroundFrame)
| TEST_P (RendererDartTest, CanInstantiateFlutterGPUContext)
| TEST_P (RendererDartTest, CanCreateShaderLibrary)
| TEST_P (RendererDartTest, CanReflectUniformStructs)
| TEST_P (RendererDartTest, UniformBindFailsForInvalidHostBufferOffset)
| TEST_P (RendererDartTest, CanCreateRenderPassAndSubmit)
| TEST_P (RendererTest, CanCreateBoxPrimitive)
| TEST_P (RendererTest, BabysFirstTriangle)
| 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, Planet)
| TEST_P (RendererTest, ArrayUniforms)
| TEST_P (RendererTest, InactiveUniforms)
| TEST_P (RendererTest, DefaultIndexSize)
| TEST_P (RendererTest, DefaultIndexBehavior)
| TEST_P (RendererTest, VertexBufferBuilder)
static const CompareFunctionUIData & | CompareFunctionUI ()
| TEST_P (RendererTest, StencilMask)
| TEST_P (RendererTest, CanLookupRenderTargetProperties)
| TEST_P (RendererTest, RenderTargetCreateOffscreenMSAASetsDefaultDepthStencilFormat)
template<class VertexShader , class FragmentShader >
std::shared_ptr< Pipeline< PipelineDescriptor > > | CreateDefaultPipeline (const std::shared_ptr< Context > &context)
| TEST_P (RendererTest, CanSepiaToneWithSubpasses)
| TEST_P (RendererTest, CanSepiaToneThenSwizzleWithSubpasses)
| INSTANTIATE_PLAYGROUND_SUITE (RuntimeStageTest)
| TEST_P (RuntimeStageTest, CanReadValidBlob)
| TEST_P (RuntimeStageTest, CanRejectInvalidBlob)
| TEST_P (RuntimeStageTest, CanReadUniforms)
| TEST_P (RuntimeStageTest, CanReadUniformsSamplerBeforeUBO)
| TEST_P (RuntimeStageTest, CanReadUniformsSamplerAfterUBO)
| TEST_P (RuntimeStageTest, CanRegisterStage)
| TEST_P (RuntimeStageTest, CanCreatePipelineFromRuntimeStage)
| TEST_P (RuntimeStageTest, ContainsExpectedShaderTypes)
static std::shared_ptr< fml::Mapping > | CreateMappingFromString (std::string p_string)
const std::string | CreateStringFromMapping (const fml::Mapping &mapping)
| TEST (ShaderArchiveTest, CanReadAndWriteBlobs)
| TEST (TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus)
| TEST (TessellatorTest, TessellateConvex)
| TEST (TessellatorTest, TessellateConvexUnclosedPath)
| TEST (TessellatorTest, CircleVertexCounts)
| TEST (TessellatorTest, FilledCircleTessellationVertices)
| TEST (TessellatorTest, StrokedCircleTessellationVertices)
| TEST (TessellatorTest, RoundCapLineTessellationVertices)
| TEST (TessellatorTest, FilledEllipseTessellationVertices)
| TEST (TessellatorTest, FilledRoundRectTessellationVertices)
| TEST (TessellatorTest, EarlyReturnEmptyConvexShape)
| TEST (TessellatorTest, ChecksConcurrentPolylineUsage)
static std::shared_ptr< GlyphAtlas > | CreateGlyphAtlas (Context &context, const TypographerContext *typographer_context, HostBuffer &host_buffer, GlyphAtlas::Type type, Scalar scale, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const TextFrame &frame)
static std::shared_ptr< GlyphAtlas > | CreateGlyphAtlas (Context &context, const TypographerContext *typographer_context, HostBuffer &host_buffer, GlyphAtlas::Type type, Scalar scale, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const std::vector< std::shared_ptr< TextFrame >> &frames, const std::vector< GlyphProperties > &properties)
| TEST_P (TypographerTest, CanConvertTextBlob)
| TEST_P (TypographerTest, CanCreateRenderContext)
| TEST_P (TypographerTest, CanCreateGlyphAtlas)
| TEST_P (TypographerTest, LazyAtlasTracksColor)
| TEST_P (TypographerTest, GlyphAtlasWithOddUniqueGlyphSize)
| TEST_P (TypographerTest, GlyphAtlasIsRecycledIfUnchanged)
| TEST_P (TypographerTest, GlyphAtlasWithLotsOfdUniqueGlyphSize)
| TEST_P (TypographerTest, GlyphAtlasTextureIsRecycledIfUnchanged)
| TEST_P (TypographerTest, GlyphColorIsPartOfCacheKey)
| TEST_P (TypographerTest, GlyphColorIsIgnoredForNonEmojiFonts)
| TEST_P (TypographerTest, RectanglePackerAddsNonoverlapingRectangles)
| TEST (TypographerTest, RectanglePackerFillsRows)
| TEST_P (TypographerTest, GlyphAtlasTextureWillGrowTilMaxTextureSize)

## Variables
static const std::map< std::string, MaskBlurTestConfig > | kPaintVariations
static constexpr std::string_view | kFontFixture
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 17 of file aiks_unittests.h.

## ◆ AllocatorMTLTest

using impeller::testing::AllocatorMTLTest = typedef PlaygroundTest

Definition at line 25 of file allocator_mtl_unittests.mm.

## ◆ BlitPassTest

using impeller::testing::BlitPassTest = typedef PlaygroundTest

Definition at line 16 of file blit_pass_unittests.cc.

## ◆ ComputeTest

using impeller::testing::ComputeTest = typedef ComputePlaygroundTest

Definition at line 21 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 46 of file dl_unittests.cc.

## ◆ DriverInfoVKTest

using impeller::testing::DriverInfoVKTest = typedef PlaygroundTest

Definition at line 11 of file driver_info_vk_unittests.cc.

## ◆ EntityPassTargetTest

using impeller::testing::EntityPassTargetTest = typedef EntityPlayground

Definition at line 16 of file entity_pass_target_unittests.cc.

## ◆ EntityTest

typedef EntityPlayground impeller::testing::EntityTest

Definition at line 21 of file clip_contents_unittests.cc.

## ◆ HostBufferTest

using impeller::testing::HostBufferTest = typedef EntityPlayground

Definition at line 12 of file host_buffer_unittests.cc.

## ◆ RendererTest

typedef PlaygroundTest impeller::testing::RendererTest

Definition at line 14 of file render_pass_cache_unittests.cc.

## ◆ RenderTargetCacheTest

using impeller::testing::RenderTargetCacheTest = typedef EntityPlayground

Definition at line 19 of file render_target_cache_unittests.cc.

## ◆ RuntimeStageTest

using impeller::testing::RuntimeStageTest = typedef RuntimeStagePlayground

Definition at line 26 of file runtime_stage_unittests.cc.

## ◆ TypographerTest

using impeller::testing::TypographerTest = typedef PlaygroundTest

Definition at line 29 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 | ( | Vector2 | content_scale,
|  | BlendMode | blend_mode,
|  | const std::shared_ptr< Image > & | src_image,
|  | const std::shared_ptr< Image > & | dst_image,
|  | Scalar | src_alpha
| ) |  |
| static

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

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

Definition at line 368 of file aiks_blend_unittests.cc.

372 {
373 if (AiksTest::ImGuiBegin("Controls", nullptr,
374 ImGuiWindowFlags_AlwaysAutoResize)) {
375 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
376 ImGui::End();
377 }
378
379 Color destination_color = Color::CornflowerBlue().WithAlpha(0.75);
380 auto source_colors = std::vector<Color>({Color::White().WithAlpha(0.75),
381 Color::LimeGreen().WithAlpha(0.75),
382 Color::Black().WithAlpha(0.75)});
383
384 Canvas canvas;
385 canvas.DrawPaint({.color = Color::Black()});
386 // TODO(bdero): Why does this cause the left image to double scale on high DPI
387 // displays.
388 // canvas.Scale(content_scale);
389
390 //----------------------------------------------------------------------------
391 /// 1. Save layer blending (top squares).
392 ///
393
394 canvas.Save();
395 for (const auto& color : source_colors) {
396 canvas.Save();
397 {
398 canvas.ClipRect(Rect::MakeXYWH(25, 25, 100, 100));
399 // Perform the blend in a SaveLayer so that the initial backdrop color is
400 // fully transparent black. SourceOver blend the result onto the parent
401 // pass.
402 canvas.SaveLayer({});
403 {
404 canvas.DrawPaint({.color = destination_color});
405 // Draw the source color in an offscreen pass and blend it to the parent
406 // pass.
407 canvas.SaveLayer({.blend_mode = blend_mode});
408 { //
409 canvas.DrawRect(Rect::MakeXYWH(25, 25, 100, 100), {.color = color});
410 }
411 canvas.Restore();
412 }
413 canvas.Restore();
414 }
415 canvas.Restore();
416 canvas.Translate(Vector2(100, 0));
417 }
418 canvas.RestoreToCount(0);
419
420 //----------------------------------------------------------------------------
421 /// 2. CPU blend modes (bottom squares).
422 ///
423
424 canvas.Save();
425 canvas.Translate({0, 100});
426 // Perform the blend in a SaveLayer so that the initial backdrop color is
427 // fully transparent black. SourceOver blend the result onto the parent pass.
428 canvas.SaveLayer({});
429 for (const auto& color : source_colors) {
430 // Simply write the CPU blended color to the pass.
431 canvas.DrawRect(Rect::MakeXYWH(25, 25, 100, 100),
432 {.color = destination_color.Blend(color, blend_mode),
433 .blend_mode = BlendMode::kSourceOver});
434 canvas.Translate(Vector2(100, 0));
435 }
436 canvas.Restore();
437 canvas.Restore();
438
439 //----------------------------------------------------------------------------
440 /// 3. Image blending (bottom images).
441 ///
442 /// Compare these results with the images in the Flutter blend mode
443 /// documentation: https://api.flutter.dev/flutter/dart-ui/BlendMode.html
444 ///
445
446 canvas.Translate({0, 250});
447
448 // Draw grid behind the images.
449 canvas.DrawRect(Rect::MakeLTRB(0, 0, 800, 400),
450 {.color = Color::MakeRGBA8(41, 41, 41, 255)});
451 Paint square_paint = {.color = Color::MakeRGBA8(15, 15, 15, 255)};
452 for (int y = 0; y < 400 / 8; y++) {
453 for (int x = 0; x < 800 / 16; x++) {
454 canvas.DrawRect(Rect::MakeXYWH(x * 16 + (y % 2) * 8, y * 8, 8, 8),
455 square_paint);
456 }
457 }
458
459 // Uploaded image source (left image).
460 canvas.Save();
461 canvas.SaveLayer({.blend_mode = BlendMode::kSourceOver});
462 {
463 canvas.DrawImage(dst_image, {0, 0},
464 {
465 .blend_mode = BlendMode::kSourceOver,
466 });
467 canvas.DrawImage(src_image, {0, 0},
468 {
469 .color = Color::White().WithAlpha(src_alpha),
470 .blend_mode = blend_mode,
471 });
472 }
473 canvas.Restore();
474 canvas.Restore();
475
476 // Rendered image source (right image).
477 canvas.Save();
478 canvas.SaveLayer({.blend_mode = BlendMode::kSourceOver});
479 {
480 canvas.DrawImage(dst_image, {400, 0},
481 {.blend_mode = BlendMode::kSourceOver});
482 canvas.SaveLayer({.color = Color::White().WithAlpha(src_alpha),
483 .blend_mode = blend_mode});
484 {
485 canvas.DrawImage(src_image, {400, 0},
486 {.blend_mode = BlendMode::kSourceOver});
487 }
488 canvas.Restore();
489 }
490 canvas.Restore();
491 canvas.Restore();
492
493 return canvas.EndRecordingAsPicture();
494 }

References impeller::Color::Black(), impeller::Color::Blend(), color, impeller::Paint::color, impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::AiksPlayground::ImGuiBegin(), impeller::kSourceOver, impeller::Color::LimeGreen(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Color::MakeRGBA8(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ CanRenderConicalGradientWithDithering()

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

Definition at line 167 of file aiks_dl_gradient_unittests.cc.

167 {
168 DisplayListBuilder builder;
169 builder.Scale(aiks_test->GetContentScale().x, aiks_test->GetContentScale().y);
170 DlPaint paint;
171 builder.Translate(100.0, 100.0);
172
173 // #FFF -> #000
174 std::vector<DlColor> colors = {DlColor(Color{1.0, 1.0, 1.0, 1.0}.ToARGB()),
175 DlColor(Color{0.0, 0.0, 0.0, 1.0}.ToARGB())};
176 std::vector<Scalar> stops = {0.0, 1.0};
177
178 paint.setColorSource(DlColorSource::MakeConical({0, 1}, 0, {100, 100}, 100, 2,
179 colors.data(), stops.data(),
180 DlTileMode::kMirror));
181
182 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
183 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
184 }

References impeller::Playground::GetContentScale(), impeller::AiksPlayground::OpenPlaygroundHere(), paint, impeller::Color::ToARGB(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by TEST_P().

## ◆ CanRenderLinearGradientWithDithering()

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

Definition at line 104 of file aiks_dl_gradient_unittests.cc.

104 {
105 DisplayListBuilder builder;
106 DlPaint paint;
107 builder.Translate(100.0, 100.0);
108
109 // 0xffcccccc --> 0xff333333, taken from
110 // https://github.com/flutter/flutter/issues/118073#issue-1521699748
111 std::vector<DlColor> colors = {DlColor(0xFFCCCCCC), DlColor(0xFF333333)};
112 std::vector<Scalar> stops = {0.0, 1.0};
113
114 paint.setColorSource(DlColorSource::MakeLinear(
115 {0, 0}, {800, 500}, 2, colors.data(), stops.data(), DlTileMode::kClamp));
116 builder.DrawRect(SkRect::MakeXYWH(0, 0, 800, 500), paint);
117 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
118 }

References impeller::AiksPlayground::OpenPlaygroundHere(), and paint.

Referenced by TEST_P().

## ◆ CanRenderRadialGradientWithDithering()

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

Definition at line 124 of file aiks_dl_gradient_unittests.cc.

124 {
125 DisplayListBuilder builder;
126 DlPaint paint;
127 builder.Translate(100.0, 100.0);
128
129 // #FFF -> #000
130 std::vector<DlColor> colors = {DlColor(Color{1.0, 1.0, 1.0, 1.0}.ToARGB()),
131 DlColor(Color{0.0, 0.0, 0.0, 1.0}.ToARGB())};
132 std::vector<Scalar> stops = {0.0, 1.0};
133
134 paint.setColorSource(DlColorSource::MakeRadial(
135 {600, 600}, 600, 2, colors.data(), stops.data(), DlTileMode::kClamp));
136 builder.DrawRect(SkRect::MakeXYWH(0, 0, 1200, 1200), paint);
137 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
138 }

References impeller::AiksPlayground::OpenPlaygroundHere(), paint, and impeller::Color::ToARGB().

Referenced by TEST_P().

## ◆ CanRenderSweepGradientWithDithering()

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

Definition at line 144 of file aiks_dl_gradient_unittests.cc.

144 {
145 DisplayListBuilder builder;
146 builder.Scale(aiks_test->GetContentScale().x, aiks_test->GetContentScale().y);
147 DlPaint paint;
148 builder.Translate(100.0, 100.0);
149
150 // #FFF -> #000
151 std::vector<DlColor> colors = {DlColor(Color{1.0, 1.0, 1.0, 1.0}.ToARGB()),
152 DlColor(Color{0.0, 0.0, 0.0, 1.0}.ToARGB())};
153 std::vector<Scalar> stops = {0.0, 1.0};
154
155 paint.setColorSource(DlColorSource::MakeSweep(
156 {100, 100}, /*start=*/45, /*end=*/135, 2, colors.data(), stops.data(),
157 DlTileMode::kMirror));
158
159 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
160 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
161 }

References impeller::Playground::GetContentScale(), impeller::AiksPlayground::OpenPlaygroundHere(), paint, impeller::Color::ToARGB(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by TEST_P().

## ◆ CAPABILITY_TEST() [1/9]

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

## ◆ CAPABILITY_TEST() [2/9]

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

## ◆ CAPABILITY_TEST() [3/9]

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

## ◆ CAPABILITY_TEST() [4/9]

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

## ◆ CAPABILITY_TEST() [5/9]

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

## ◆ CAPABILITY_TEST() [6/9]

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

## ◆ CAPABILITY_TEST() [7/9]

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

## ◆ CAPABILITY_TEST() [8/9]

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

## ◆ CAPABILITY_TEST() [9/9]

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

## ◆ CompareFunctionUI()

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

Definition at line 1184 of file renderer_unittests.cc.

1184 {
1185 static CompareFunctionUIData data;
1186 return data;
1187 }

References data.

Referenced by TEST_P().

## ◆ CreateDefaultPipeline()

template<class VertexShader , class FragmentShader >

std::shared_ptr<Pipeline<PipelineDescriptor> > impeller::testing::CreateDefaultPipeline | ( | const std::shared_ptr< Context > & | context | ) |

Definition at line 1376 of file renderer_unittests.cc.

1377 {
1378 using TexturePipelineBuilder = PipelineBuilder<VertexShader, FragmentShader>;
1379 auto pipeline_desc =
1380 TexturePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1381 if (!pipeline_desc.has_value()) {
1382 return nullptr;
1383 }
1384 pipeline_desc->SetSampleCount(SampleCount::kCount4);
1385 pipeline_desc->SetStencilAttachmentDescriptors(std::nullopt);
1386 auto pipeline =
1387 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
1388 if (!pipeline || !pipeline->IsValid()) {
1389 return nullptr;
1390 }
1391 return pipeline;
1392 }

References impeller::kCount4.

## ◆ CreateGlyphAtlas() [1/2]

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

Definition at line 46 of file typographer_unittests.cc.

54 {
55 FontGlyphMap font_glyph_map;
56 size_t offset = 0;
57 for (auto& frame : frames) {
58 frame->CollectUniqueFontGlyphPairs(font_glyph_map, scale, {0, 0},
59 properties[offset++]);
60 }
61 return typographer_context->CreateGlyphAtlas(context, type, host_buffer,
62 atlas_context, font_glyph_map);
63 }

References impeller::TypographerContext::CreateGlyphAtlas(), offset, scale, and type.

## ◆ CreateGlyphAtlas() [2/2]

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

Definition at line 32 of file typographer_unittests.cc.

39 {
40 FontGlyphMap font_glyph_map;
41 frame.CollectUniqueFontGlyphPairs(font_glyph_map, scale, {0, 0}, {});
42 return typographer_context->CreateGlyphAtlas(context, type, host_buffer,
43 atlas_context, font_glyph_map);
44 }

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

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 shader_archive_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,
|  | ContentBoundsPromise | bounds_promise = `ContentBoundsPromise::kUnknown`,
|  | bool | collapse = `false`
| ) |  |

Definition at line 110 of file entity_unittests.cc.

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

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 shader_archive_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 1855 of file entity_unittests.cc.

1857 {
1858 Vector3 red = {244.0 / 255.0, 67.0 / 255.0, 54.0 / 255.0};
1859 Vector3 green = {76.0 / 255.0, 175.0 / 255.0, 80.0 / 255.0};
1860 Vector3 blue = {33.0 / 255.0, 150.0 / 255.0, 243.0 / 255.0};
1861 Vector3 white = {1.0, 1.0, 1.0};
1862 Vector3 red_yuv = RGBToYUV(red, yuv_color_space);
1863 Vector3 green_yuv = RGBToYUV(green, yuv_color_space);
1864 Vector3 blue_yuv = RGBToYUV(blue, yuv_color_space);
1865 Vector3 white_yuv = RGBToYUV(white, yuv_color_space);
1866 std::vector<Vector3> yuvs{red_yuv, green_yuv, blue_yuv, white_yuv};
1867 std::vector<uint8_t> y_data;
1868 std::vector<uint8_t> uv_data;
1869 for (int i = 0; i < 4; i++) {
1870 auto yuv = yuvs[i];
1871 uint8_t y = std::round(yuv.x * 255.0);
1872 uint8_t u = std::round(yuv.y * 255.0);
1873 uint8_t v = std::round(yuv.z * 255.0);
1874 for (int j = 0; j < 16; j++) {
1875 y_data.push_back(y);
1876 }
1877 for (int j = 0; j < 8; j++) {
1878 uv_data.push_back(j % 2 == 0 ? u : v);
1879 }
1880 }
1881 auto cmd_buffer = context->CreateCommandBuffer();
1882 auto blit_pass = cmd_buffer->CreateBlitPass();
1883
1884 impeller::TextureDescriptor y_texture_descriptor;
1885 y_texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
1886 y_texture_descriptor.format = PixelFormat::kR8UNormInt;
1887 y_texture_descriptor.size = {8, 8};
1888 auto y_texture =
1889 context->GetResourceAllocator()->CreateTexture(y_texture_descriptor);
1890 auto y_mapping = std::make_shared<fml::DataMapping>(y_data);
1891 auto y_mapping_buffer =
1892 context->GetResourceAllocator()->CreateBufferWithCopy(*y_mapping);
1893
1894 blit_pass->AddCopy(DeviceBuffer::AsBufferView(y_mapping_buffer), y_texture);
1895
1896 impeller::TextureDescriptor uv_texture_descriptor;
1897 uv_texture_descriptor.storage_mode = impeller::StorageMode::kHostVisible;
1898 uv_texture_descriptor.format = PixelFormat::kR8G8UNormInt;
1899 uv_texture_descriptor.size = {4, 4};
1900 auto uv_texture =
1901 context->GetResourceAllocator()->CreateTexture(uv_texture_descriptor);
1902 auto uv_mapping = std::make_shared<fml::DataMapping>(uv_data);
1903 auto uv_mapping_buffer =
1904 context->GetResourceAllocator()->CreateBufferWithCopy(*uv_mapping);
1905
1906 blit_pass->AddCopy(DeviceBuffer::AsBufferView(uv_mapping_buffer), uv_texture);
1907
1908 if (!blit_pass->EncodeCommands(context->GetResourceAllocator()) ||
1909 !context->GetCommandQueue()->Submit({cmd_buffer}).ok()) {
1910 FML_DLOG(ERROR) << "Could not copy contents into Y/UV texture.";
1911 }
1912
1913 return {y_texture, uv_texture};
1914 }

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

Referenced by TEST_P().

## ◆ flip_lr()

template<typename R >

static constexpr R impeller::testing::flip_lr | ( | R | rect | ) |
| inline static constexpr

Definition at line 1279 of file rect_unittests.cc.

1279 {
1280 return R::MakeLTRB(rect.GetRight(), rect.GetTop(), //
1281 rect.GetLeft(), rect.GetBottom());
1282 }

Referenced by flip_lrtb(), and TEST().

## ◆ flip_lrtb()

template<typename R >

static constexpr R impeller::testing::flip_lrtb | ( | R | rect | ) |
| inline static constexpr

Definition at line 1291 of file rect_unittests.cc.

1291 {
1292 return flip_lr(flip_tb(rect));
1293 }

References flip_lr(), and flip_tb().

Referenced by TEST().

## ◆ flip_tb()

template<typename R >

static constexpr R impeller::testing::flip_tb | ( | R | rect | ) |
| inline static constexpr

Definition at line 1285 of file rect_unittests.cc.

1285 {
1286 return R::MakeLTRB(rect.GetLeft(), rect.GetBottom(), //
1287 rect.GetRight(), rect.GetTop());
1288 }

Referenced by flip_lrtb(), and TEST().

## ◆ GetBlendModeSelection()

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

Definition at line 188 of file aiks_blend_unittests.cc.

188 {
189 std::vector<const char*> blend_mode_names;
190 std::vector<BlendMode> blend_mode_values;
191 {
192 const std::vector<std::tuple<const char*, BlendMode>> blends = {
193 IMPELLER_FOR_EACH_BLEND_MODE(BLEND_MODE_TUPLE)};
194 assert(blends.size() ==
195 static_cast<size_t>(Entity::kLastAdvancedBlendMode) + 1);
196 for (const auto& [name, mode] : blends) {
197 blend_mode_names.push_back(name);
198 blend_mode_values.push_back(mode);
199 }
200 }
201
202 return {blend_mode_names, blend_mode_values};
203 }

References BLEND_MODE_TUPLE, IMPELLER_FOR_EACH_BLEND_MODE, and impeller::Entity::kLastAdvancedBlendMode.

Referenced by TEST_P().

## ◆ GetCoverageOfFirstEntity()

template<typename Contents >

static std::optional<Rect> impeller::testing::GetCoverageOfFirstEntity | ( | const Picture & | picture | ) |
| static

Definition at line 1547 of file dl_unittests.cc.

1547 {
1548 std::optional<Rect> coverage;
1549 picture.pass->IterateAllEntities([&coverage](Entity& entity) {
1550 if (std::static_pointer_cast<Contents>(entity.GetContents())) {
1551 auto contents = std::static_pointer_cast<Contents>(entity.GetContents());
1552 Entity entity;
1553 coverage = contents->GetCoverage(entity);
1554 return false;
1555 }
1556 return true;
1557 });
1558 return coverage;
1559 }

References impeller::Entity::GetContents(), and impeller::Picture::pass.

## ◆ INSTANTIATE_COMPUTE_SUITE()

impeller::testing::INSTANTIATE_COMPUTE_SUITE | ( | ComputeTest |  | ) |

## ◆ INSTANTIATE_METAL_PLAYGROUND_SUITE()

impeller::testing::INSTANTIATE_METAL_PLAYGROUND_SUITE | ( | AllocatorMTLTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [1/9]

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [2/9]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | BlendFilterContentsTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [3/9]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | BlitPassTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [4/9]

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [5/9]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | GaussianBlurFilterContentsTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [6/9]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | HostBufferTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [7/9]

impeller::testing::INSTANTIATE_PLAYGROUND_SUITE | ( | MatrixFilterContentsTest |  | ) |

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [8/9]

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

## ◆ INSTANTIATE_PLAYGROUND_SUITE() [9/9]

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

## ◆ INSTANTIATE_VULKAN_PLAYGROUND_SUITE()

impeller::testing::INSTANTIATE_VULKAN_PLAYGROUND_SUITE | ( | DriverInfoVKTest |  | ) |

## ◆ InstantiateTestShaderLibrary()

static void impeller::testing::InstantiateTestShaderLibrary | ( | Context::BackendType | backend_type | ) |
| static

Definition at line 34 of file renderer_dart_unittests.cc.

34 {
35 auto fixture =
36 flutter::testing::OpenFixtureAsMapping("playground.shaderbundle");
37 auto library = flutter::gpu::ShaderLibrary::MakeFromFlatbuffer(
38 backend_type, std::move(fixture));
39 flutter::gpu::ShaderLibrary::SetOverride(library);
40 }

Referenced by impeller::testing::RendererDartTest::GetIsolate().

## ◆ MaskBlurVariantTest()

static Picture impeller::testing::MaskBlurVariantTest | ( | const AiksTest & | test_context,
|  | const MaskBlurTestConfig & | config
| ) |  |
| static

Definition at line 304 of file aiks_blur_unittests.cc.

305 {
306 Canvas canvas;
307 canvas.Scale(test_context.GetContentScale());
308 canvas.Scale(Vector2{0.8f, 0.8f});
309 Paint paint;
310 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
311 .style = FilterContents::BlurStyle::kNormal,
312 .sigma = Sigma{1},
313 };
314
315 canvas.DrawPaint({.color = Color::AntiqueWhite()});
316
317 paint.mask_blur_descriptor->style = config.style;
318 paint.mask_blur_descriptor->sigma = Sigma{config.sigma};
319 paint.image_filter = config.image_filter;
320 paint.invert_colors = config.invert_colors;
321 paint.blend_mode = config.blend_mode;
322
323 const Scalar x = 50;
324 const Scalar radius = 20.0f;
325 const Scalar y_spacing = 100.0f;
326
327 Scalar y = 50;
328 paint.color = Color::Crimson().WithAlpha(config.alpha);
329 canvas.DrawRect(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
330 radius, 60.0f - radius),
331 paint);
332
333 y += y_spacing;
334 paint.color = Color::Blue().WithAlpha(config.alpha);
335 canvas.DrawCircle({x + 25, y + 25}, radius, paint);
336
337 y += y_spacing;
338 paint.color = Color::Green().WithAlpha(config.alpha);
339 canvas.DrawOval(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
340 radius, 60.0f - radius),
341 paint);
342
343 y += y_spacing;
344 paint.color = Color::Purple().WithAlpha(config.alpha);
345 canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), //
346 {radius, radius}, //
347 paint);
348
349 y += y_spacing;
350 paint.color = Color::Orange().WithAlpha(config.alpha);
351 canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), //
352 {radius, 5.0f}, paint);
353
354 y += y_spacing;
355 paint.color = Color::Maroon().WithAlpha(config.alpha);
356 canvas.DrawPath(PathBuilder{}
357 .MoveTo({x + 0, y + 60})
358 .LineTo({x + 30, y + 0})
359 .LineTo({x + 60, y + 60})
360 .Close()
361 .TakePath(),
362 paint);
363
364 y += y_spacing;
365 paint.color = Color::Maroon().WithAlpha(config.alpha);
366 canvas.DrawPath(PathBuilder{}
367 .AddArc(Rect::MakeXYWH(x + 5, y, 50, 50),
368 Radians{kPi / 2}, Radians{kPi})
369 .AddArc(Rect::MakeXYWH(x + 25, y, 50, 50),
370 Radians{kPi / 2}, Radians{kPi})
371 .Close()
372 .TakePath(),
373 paint);
374
375 return canvas.EndRecordingAsPicture();
376 }

References impeller::PathBuilder::AddArc(), impeller::testing::MaskBlurTestConfig::alpha, impeller::Color::AntiqueWhite(), impeller::testing::MaskBlurTestConfig::blend_mode, impeller::Color::Blue(), impeller::Close(), impeller::Color::Crimson(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawOval(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::DrawRRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Playground::GetContentScale(), impeller::Color::Green(), impeller::testing::MaskBlurTestConfig::image_filter, impeller::testing::MaskBlurTestConfig::invert_colors, impeller::FilterContents::kNormal, impeller::kPi, impeller::LineTo(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Maroon(), impeller::PathBuilder::MoveTo(), impeller::Color::Orange(), paint, impeller::Color::Purple(), impeller::Canvas::Scale(), impeller::testing::MaskBlurTestConfig::sigma, impeller::Paint::MaskBlurDescriptor::style, impeller::testing::MaskBlurTestConfig::style, and impeller::Color::WithAlpha().

## ◆ RenderTextInCanvasSkia()

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

Definition at line 550 of file aiks_unittests.cc.

554 {}) {
555 // Draw the baseline.
556 canvas.DrawRect(
557 Rect::MakeXYWH(options.position.x - 50, options.position.y, 900, 10),
558 Paint{.color = Color::Aqua().WithAlpha(0.25)});
559
560 // Mark the point at which the text is drawn.
561 canvas.DrawCircle(options.position, 5.0,
562 Paint{.color = Color::Red().WithAlpha(0.25)});
563
564 // Construct the text blob.
565 auto c_font_fixture = std::string(font_fixture);
566 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
567 if (!mapping) {
568 return false;
569 }
570 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
571 SkFont sk_font(font_mgr->makeFromData(mapping), options.font_size);
572 auto blob = SkTextBlob::MakeFromString(text.c_str(), sk_font);
573 if (!blob) {
574 return false;
575 }
576
577 // Create the Impeller text frame and draw it at the designated baseline.
578 auto frame = MakeTextFrameFromTextBlobSkia(blob);
579
580 Paint text_paint;
581 text_paint.color = options.color;
582 text_paint.mask_blur_descriptor = options.mask_blur_descriptor;
583 text_paint.stroke_width = 1;
584 text_paint.style =
585 options.stroke ? Paint::Style::kStroke : Paint::Style::kFill;
586 canvas.DrawTextFrame(frame, options.position, text_paint);
587 return true;
588 }

Referenced by flutter::testing::TEST_P(), and 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 590 of file aiks_unittests.cc.

594 {}) {
595 // Draw the baseline.
596 canvas.DrawRect(
597 Rect::MakeXYWH(options.position.x - 50, options.position.y, 900, 10),
598 Paint{.color = Color::Aqua().WithAlpha(0.25)});
599
600 // Mark the point at which the text is drawn.
601 canvas.DrawCircle(options.position, 5.0,
602 Paint{.color = Color::Red().WithAlpha(0.25)});
603
604 // Construct the text blob.
605 auto mapping = flutter::testing::OpenFixtureAsMapping(font_fixture.c_str());
606 if (!mapping) {
607 return false;
608 }
609 auto typeface_stb = std::make_shared<TypefaceSTB>(std::move(mapping));
610
611 auto frame = MakeTextFrameSTB(
612 typeface_stb, Font::Metrics{.point_size = options.font_size}, text);
613
614 Paint text_paint;
615 text_paint.color = options.color;
616 canvas.DrawTextFrame(frame, options.position, text_paint);
617 return true;
618 }

Referenced by TEST_P().

## ◆ RGBToYUV()

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

Definition at line 1838 of file entity_unittests.cc.

1838 {
1839 Vector3 yuv;
1840 switch (yuv_color_space) {
1841 case YUVColorSpace::kBT601FullRange:
1842 yuv.x = rgb.x * 0.299 + rgb.y * 0.587 + rgb.z * 0.114;
1843 yuv.y = rgb.x * -0.169 + rgb.y * -0.331 + rgb.z * 0.5 + 0.5;
1844 yuv.z = rgb.x * 0.5 + rgb.y * -0.419 + rgb.z * -0.081 + 0.5;
1845 break;
1846 case YUVColorSpace::kBT601LimitedRange:
1847 yuv.x = rgb.x * 0.257 + rgb.y * 0.516 + rgb.z * 0.100 + 0.063;
1848 yuv.y = rgb.x * -0.145 + rgb.y * -0.291 + rgb.z * 0.439 + 0.5;
1849 yuv.z = rgb.x * 0.429 + rgb.y * -0.368 + rgb.z * -0.071 + 0.5;
1850 break;
1851 }
1852 return yuv;
1853 }

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

Referenced by CreateTestYUVTextures().

## ◆ swap_nan() [1/2]

static constexpr Point impeller::testing::swap_nan | ( | const Point & | point,
|  | int | index
| ) |  |
| inline static constexpr

Definition at line 1305 of file rect_unittests.cc.

1305 {
1306 Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1307 FML_DCHECK(index >= 0 && index <= 3);
1308 Scalar x = ((index & (1 << 0)) != 0) ? nan : point.x;
1309 Scalar y = ((index & (1 << 1)) != 0) ? nan : point.y;
1310 return Point(x, y);
1311 }

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

## ◆ swap_nan() [2/2]

static constexpr Rect impeller::testing::swap_nan | ( | const Rect & | rect,
|  | int | index
| ) |  |
| inline static constexpr

Definition at line 1295 of file rect_unittests.cc.

1295 {
1296 Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1297 FML_DCHECK(index >= 0 && index <= 15);
1298 Scalar l = ((index & (1 << 0)) != 0) ? nan : rect.GetLeft();
1299 Scalar t = ((index & (1 << 1)) != 0) ? nan : rect.GetTop();
1300 Scalar r = ((index & (1 << 2)) != 0) ? nan : rect.GetRight();
1301 Scalar b = ((index & (1 << 3)) != 0) ? nan : rect.GetBottom();
1302 return Rect::MakeLTRB(l, t, r, b);
1303 }

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

Referenced by TEST().

## ◆ TEST() [1/360]

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

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

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

Definition at line 24 of file canvas_unittests.cc.

24 {
25 Rect initial_cull = Rect::MakeXYWH(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(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [4/360]

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

Definition at line 277 of file canvas_unittests.cc.

277 {
278 PathBuilder builder;
279 builder.AddRect(Rect::MakeXYWH(5, 5, 1, 1));
280 builder.AddRect(Rect::MakeXYWH(5, 14, 1, 1));
281 builder.AddRect(Rect::MakeXYWH(14, 5, 1, 1));
282 builder.AddRect(Rect::MakeXYWH(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, impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [5/360]

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

Definition at line 325 of file canvas_unittests.cc.

325 {
326 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
327 PathBuilder builder;
328 builder.AddRect(Rect::MakeXYWH(0, 0, 100, 100));
329 Path path = builder.TakePath();
330 // Diff clip of Paths is ignored due to complexity
331 Rect result_cull = Rect::MakeXYWH(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, impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [6/360]

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

Definition at line 308 of file canvas_unittests.cc.

308 {
309 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
310 PathBuilder builder;
311 builder.AddRect(Rect::MakeXYWH(5, 5, 1, 1));
312 builder.AddRect(Rect::MakeXYWH(5, 14, 1, 1));
313 builder.AddRect(Rect::MakeXYWH(14, 5, 1, 1));
314 builder.AddRect(Rect::MakeXYWH(14, 14, 1, 1));
315 Path path = builder.TakePath();
316 Rect result_cull = Rect::MakeXYWH(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, impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [7/360]

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

Definition at line 291 of file canvas_unittests.cc.

291 {
292 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
293 PathBuilder builder;
294 builder.AddRect(Rect::MakeXYWH(5, 5, 1, 1));
295 builder.AddRect(Rect::MakeXYWH(5, 14, 1, 1));
296 builder.AddRect(Rect::MakeXYWH(14, 5, 1, 1));
297 builder.AddRect(Rect::MakeXYWH(14, 14, 1, 1));
298 Path path = builder.TakePath();
299 Rect result_cull = Rect::MakeXYWH(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, impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [8/360]

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

Definition at line 261 of file canvas_unittests.cc.

261 {
262 PathBuilder builder;
263 builder.AddRect(Rect::MakeXYWH(5, 5, 1, 1));
264 builder.AddRect(Rect::MakeXYWH(5, 14, 1, 1));
265 builder.AddRect(Rect::MakeXYWH(14, 5, 1, 1));
266 builder.AddRect(Rect::MakeXYWH(14, 14, 1, 1));
267 Path path = builder.TakePath();
268 Rect rect_clip = Rect::MakeXYWH(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, impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [9/360]

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

Definition at line 98 of file canvas_unittests.cc.

98 {
99 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
100 Rect rect_clip = Rect::MakeXYWH(0, 0, 20, 4);
101 Rect result_cull = Rect::MakeXYWH(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(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [10/360]

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

Definition at line 65 of file canvas_unittests.cc.

65 {
66 Rect rect_clip = Rect::MakeXYWH(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(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [11/360]

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

Definition at line 158 of file canvas_unittests.cc.

158 {
159 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
160 Rect rect_clip = Rect::MakeXYWH(0, 5, 10, 10);
161 Rect result_cull = Rect::MakeXYWH(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(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [12/360]

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

Definition at line 86 of file canvas_unittests.cc.

86 {
87 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
88 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
89 Rect result_cull = Rect::MakeXYWH(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(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [13/360]

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

Definition at line 146 of file canvas_unittests.cc.

146 {
147 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
148 Rect rect_clip = Rect::MakeXYWH(5, 0, 10, 10);
149 Rect result_cull = Rect::MakeXYWH(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(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [14/360]

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

Definition at line 110 of file canvas_unittests.cc.

110 {
111 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
112 Rect rect_clip = Rect::MakeXYWH(0, 16, 20, 4);
113 Rect result_cull = Rect::MakeXYWH(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(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [15/360]

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

Definition at line 122 of file canvas_unittests.cc.

122 {
123 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
124 Rect rect_clip = Rect::MakeXYWH(0, 0, 4, 20);
125 Rect result_cull = Rect::MakeXYWH(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(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [16/360]

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

Definition at line 134 of file canvas_unittests.cc.

134 {
135 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
136 Rect rect_clip = Rect::MakeXYWH(16, 0, 4, 20);
137 Rect result_cull = Rect::MakeXYWH(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(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [17/360]

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

Definition at line 74 of file canvas_unittests.cc.

74 {
75 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
76 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
77 Rect result_cull = Rect::MakeXYWH(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(), impeller::Entity::kIntersect, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [18/360]

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

Definition at line 55 of file canvas_unittests.cc.

55 {
56 Rect rect_clip = Rect::MakeXYWH(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(), impeller::Entity::kIntersect, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [19/360]

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

Definition at line 180 of file canvas_unittests.cc.

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

References impeller::Canvas::ClipRRect(), impeller::Canvas::GetCurrentLocalCullingBounds(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [20/360]

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

Definition at line 249 of file canvas_unittests.cc.

249 {
250 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
251 Rect rect_clip = Rect::MakeXYWH(-2, 5, 14, 10);
252 Rect result_cull = Rect::MakeXYWH(0, 0, 10, 5);
253
254 Canvas canvas(initial_cull);
255 canvas.ClipRRect(rect_clip, {1, 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(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [21/360]

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

Definition at line 237 of file canvas_unittests.cc.

237 {
238 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
239 Rect rect_clip = Rect::MakeXYWH(0, 5, 10, 10);
240 Rect result_cull = Rect::MakeXYWH(0, 0, 10, 6);
241
242 Canvas canvas(initial_cull);
243 canvas.ClipRRect(rect_clip, {1, 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(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [22/360]

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

Definition at line 201 of file canvas_unittests.cc.

201 {
202 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
203 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
204 Rect result_cull = Rect::MakeXYWH(0, 0, 10, 10);
205
206 Canvas canvas(initial_cull);
207 canvas.ClipRRect(rect_clip, {1, 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(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [23/360]

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

Definition at line 225 of file canvas_unittests.cc.

225 {
226 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
227 Rect rect_clip = Rect::MakeXYWH(5, -2, 10, 14);
228 Rect result_cull = Rect::MakeXYWH(0, 0, 5, 10);
229
230 Canvas canvas(initial_cull);
231 canvas.ClipRRect(rect_clip, {1, 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(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [24/360]

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

Definition at line 213 of file canvas_unittests.cc.

213 {
214 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
215 Rect rect_clip = Rect::MakeXYWH(5, 0, 10, 10);
216 Rect result_cull = Rect::MakeXYWH(0, 0, 6, 10);
217
218 Canvas canvas(initial_cull);
219 canvas.ClipRRect(rect_clip, {1, 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(), impeller::Entity::kDifference, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [25/360]

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

Definition at line 189 of file canvas_unittests.cc.

189 {
190 Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10);
191 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
192 Rect result_cull = Rect::MakeXYWH(5, 5, 5, 5);
193
194 Canvas canvas(initial_cull);
195 canvas.ClipRRect(rect_clip, {1, 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(), impeller::Entity::kIntersect, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [26/360]

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

Definition at line 170 of file canvas_unittests.cc.

170 {
171 Rect rect_clip = Rect::MakeXYWH(5, 5, 10, 10);
172
173 Canvas canvas;
174 canvas.ClipRRect(rect_clip, {1, 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(), impeller::Entity::kIntersect, and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [27/360]

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

Definition at line 44 of file canvas_unittests.cc.

44 {
45 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
46 Rect scaled_cull = Rect::MakeXYWH(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(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::Canvas::Scale().

## ◆ TEST() [28/360]

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

Definition at line 33 of file canvas_unittests.cc.

33 {
34 Rect initial_cull = Rect::MakeXYWH(5, 5, 10, 10);
35 Rect translated_cull = Rect::MakeXYWH(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(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::Canvas::Translate().

## ◆ TEST() [29/360]

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

impeller::testing::TEST | ( | AllocatorVKTest | ,
|  | MemoryTypeSelectionSingleHeap |
| ) |  |

Definition at line 35 of file allocator_vk_unittests.cc.

35 {
36 vk::PhysicalDeviceMemoryProperties properties;
37 properties.memoryTypeCount = 1;
38 properties.memoryHeapCount = 1;
39 properties.memoryTypes[0].heapIndex = 0;
40 properties.memoryTypes[0].propertyFlags =
41 vk::MemoryPropertyFlagBits::eDeviceLocal;
42 properties.memoryHeaps[0].size = 1024 * 1024 * 1024;
43 properties.memoryHeaps[0].flags = vk::MemoryHeapFlagBits::eDeviceLocal;
44
45 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(1, properties), 0);
46 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(2, properties), -1);
47 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(3, properties), 0);
48 }

References impeller::AllocatorVK::FindMemoryTypeIndex().

## ◆ TEST() [31/360]

impeller::testing::TEST | ( | AllocatorVKTest | ,
|  | MemoryTypeSelectionTwoHeap |
| ) |  |

Definition at line 50 of file allocator_vk_unittests.cc.

50 {
51 vk::PhysicalDeviceMemoryProperties properties;
52 properties.memoryTypeCount = 2;
53 properties.memoryHeapCount = 2;
54 properties.memoryTypes[0].heapIndex = 0;
55 properties.memoryTypes[0].propertyFlags =
56 vk::MemoryPropertyFlagBits::eHostVisible;
57 properties.memoryHeaps[0].size = 1024 * 1024 * 1024;
58 properties.memoryHeaps[0].flags = vk::MemoryHeapFlagBits::eDeviceLocal;
59
60 properties.memoryTypes[1].heapIndex = 1;
61 properties.memoryTypes[1].propertyFlags =
62 vk::MemoryPropertyFlagBits::eDeviceLocal;
63 properties.memoryHeaps[1].size = 1024 * 1024 * 1024;
64 properties.memoryHeaps[1].flags = vk::MemoryHeapFlagBits::eDeviceLocal;
65
66 // First fails because this only looks for eDeviceLocal.
67 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(1, properties), -1);
68 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(2, properties), 1);
69 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(3, properties), 1);
70 EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(4, properties), -1);
71 }

References impeller::AllocatorVK::FindMemoryTypeIndex().

## ◆ TEST() [32/360]

impeller::testing::TEST | ( | AllocatorVKTest | ,
|  | ToVKImageUsageFlags |
| ) |  |

Definition at line 16 of file allocator_vk_unittests.cc.

16 {
17 EXPECT_EQ(AllocatorVK::ToVKImageUsageFlags(
18 PixelFormat::kR8G8B8A8UNormInt,
19 static_cast<TextureUsageMask>(TextureUsage::kRenderTarget),
20 StorageMode::kDeviceTransient,
21 /*supports_memoryless_textures=*/true),
22 vk::ImageUsageFlagBits::eInputAttachment |
23 vk::ImageUsageFlagBits::eColorAttachment |
24 vk::ImageUsageFlagBits::eTransientAttachment);
25
26 EXPECT_EQ(AllocatorVK::ToVKImageUsageFlags(
27 PixelFormat::kD24UnormS8Uint,
28 static_cast<TextureUsageMask>(TextureUsage::kRenderTarget),
29 StorageMode::kDeviceTransient,
30 /*supports_memoryless_textures=*/true),
31 vk::ImageUsageFlagBits::eDepthStencilAttachment |
32 vk::ImageUsageFlagBits::eTransientAttachment);
33 }

References impeller::kD24UnormS8Uint, impeller::kDeviceTransient, impeller::kR8G8B8A8UNormInt, impeller::kRenderTarget, and impeller::AllocatorVK::ToVKImageUsageFlags().

## ◆ TEST() [33/360]

impeller::testing::TEST | ( | BaseTest | ,
|  | CanUseTypedMasks |
| ) |  |

Definition at line 266 of file base_unittests.cc.

266 {
267 {
268 MyMask mask;
269 ASSERT_EQ(static_cast<uint32_t>(mask), 0u);
270 ASSERT_FALSE(mask);
271 }
272
273 {
274 MyMask mask(MyMaskBits::kBar);
275 ASSERT_EQ(static_cast<uint32_t>(mask), 1u);
276 ASSERT_TRUE(mask);
277 }
278
279 {
280 MyMask mask2(MyMaskBits::kBar);
281 MyMask mask(mask2);
282 ASSERT_EQ(static_cast<uint32_t>(mask), 1u);
283 ASSERT_TRUE(mask);
284 }
285
286 {
287 MyMask mask2(MyMaskBits::kBar);
288 MyMask mask(std::move(mask2)); // NOLINT
289 ASSERT_EQ(static_cast<uint32_t>(mask), 1u);
290 ASSERT_TRUE(mask);
291 }
292
293 ASSERT_LT(MyMaskBits::kBar, MyMaskBits::kBaz);
294 ASSERT_LE(MyMaskBits::kBar, MyMaskBits::kBaz);
295 ASSERT_GT(MyMaskBits::kBaz, MyMaskBits::kBar);
296 ASSERT_GE(MyMaskBits::kBaz, MyMaskBits::kBar);
297 ASSERT_EQ(MyMaskBits::kBaz, MyMaskBits::kBaz);
298 ASSERT_NE(MyMaskBits::kBaz, MyMaskBits::kBang);
299
300 {
301 MyMask m1(MyMaskBits::kBar);
302 MyMask m2(MyMaskBits::kBaz);
303 ASSERT_EQ(static_cast<uint32_t>(m1 & m2), 0u);
304 ASSERT_FALSE(m1 & m2);
305 }
306
307 {
308 MyMask m1(MyMaskBits::kBar);
309 MyMask m2(MyMaskBits::kBaz);
310 ASSERT_EQ(static_cast<uint32_t>(m1 | m2), ((1u << 0u) | (1u << 1u)));
311 ASSERT_TRUE(m1 | m2);
312 }
313
314 {
315 MyMask m1(MyMaskBits::kBar);
316 MyMask m2(MyMaskBits::kBaz);
317 ASSERT_EQ(static_cast<uint32_t>(m1 ^ m2), ((1u << 0u) ^ (1u << 1u)));
318 ASSERT_TRUE(m1 ^ m2);
319 }
320
321 {
322 MyMask m1(MyMaskBits::kBar);
323 ASSERT_EQ(static_cast<uint32_t>(~m1), (~(1u << 0u)));
324 ASSERT_TRUE(m1);
325 }
326
327 {
328 MyMask m1 = MyMaskBits::kBar;
329 MyMask m2 = MyMaskBits::kBaz;
330 m2 = m1;
331 ASSERT_EQ(m2, MyMaskBits::kBar);
332 }
333
334 {
335 MyMask m = MyMaskBits::kBar | MyMaskBits::kBaz;
336 ASSERT_TRUE(m);
337 }
338
339 {
340 MyMask m = MyMaskBits::kBar & MyMaskBits::kBaz;
341 ASSERT_FALSE(m);
342 }
343
344 {
345 MyMask m = MyMaskBits::kBar ^ MyMaskBits::kBaz;
346 ASSERT_TRUE(m);
347 }
348
349 {
350 MyMask m = ~MyMaskBits::kBar;
351 ASSERT_TRUE(m);
352 }
353
354 {
355 MyMask m1 = MyMaskBits::kBar;
356 MyMask m2 = MyMaskBits::kBaz;
357 m2 |= m1;
358 ASSERT_EQ(m1, MyMaskBits::kBar);
359 MyMask pred = MyMaskBits::kBar | MyMaskBits::kBaz;
360 ASSERT_EQ(m2, pred);
361 }
362
363 {
364 MyMask m1 = MyMaskBits::kBar;
365 MyMask m2 = MyMaskBits::kBaz;
366 m2 &= m1;
367 ASSERT_EQ(m1, MyMaskBits::kBar);
368 MyMask pred = MyMaskBits::kBar & MyMaskBits::kBaz;
369 ASSERT_EQ(m2, pred);
370 }
371
372 {
373 MyMask m1 = MyMaskBits::kBar;
374 MyMask m2 = MyMaskBits::kBaz;
375 m2 ^= m1;
376 ASSERT_EQ(m1, MyMaskBits::kBar);
377 MyMask pred = MyMaskBits::kBar ^ MyMaskBits::kBaz;
378 ASSERT_EQ(m2, pred);
379 }
380
381 {
382 MyMask x = MyMaskBits::kBar;
383 MyMask m = x | MyMaskBits::kBaz;
384 ASSERT_TRUE(m);
385 }
386
387 {
388 MyMask x = MyMaskBits::kBar;
389 MyMask m = MyMaskBits::kBaz | x;
390 ASSERT_TRUE(m);
391 }
392
393 {
394 MyMask x = MyMaskBits::kBar;
395 MyMask m = x & MyMaskBits::kBaz;
396 ASSERT_FALSE(m);
397 }
398
399 {
400 MyMask x = MyMaskBits::kBar;
401 MyMask m = MyMaskBits::kBaz & x;
402 ASSERT_FALSE(m);
403 }
404
405 {
406 MyMask x = MyMaskBits::kBar;
407 MyMask m = x ^ MyMaskBits::kBaz;
408 ASSERT_TRUE(m);
409 }
410
411 {
412 MyMask x = MyMaskBits::kBar;
413 MyMask m = MyMaskBits::kBaz ^ x;
414 ASSERT_TRUE(m);
415 }
416
417 {
418 MyMask x = MyMaskBits::kBar;
419 MyMask m = ~x;
420 ASSERT_TRUE(m);
421 }
422
423 {
424 MyMaskBits x = MyMaskBits::kBar;
425 MyMask m = MyMaskBits::kBaz;
426 ASSERT_TRUE(x < m);
427 ASSERT_TRUE(x <= m);
428 }
429
430 {
431 MyMaskBits x = MyMaskBits::kBar;
432 MyMask m = MyMaskBits::kBaz;
433 ASSERT_FALSE(x == m);
434 }
435
436 {
437 MyMaskBits x = MyMaskBits::kBar;
438 MyMask m = MyMaskBits::kBaz;
439 ASSERT_TRUE(x != m);
440 }
441
442 {
443 MyMaskBits x = MyMaskBits::kBar;
444 MyMask m = MyMaskBits::kBaz;
445 ASSERT_FALSE(x > m);
446 ASSERT_FALSE(x >= m);
447 }
448 }

References impeller::kBang, impeller::kBar, and impeller::kBaz.

## ◆ TEST() [34/360]

impeller::testing::TEST | ( | BaseTest | ,
|  | NoExceptionPromiseEmpty |
| ) |  |

Definition at line 257 of file base_unittests.cc.

257 {
258 auto wrapper = std::make_shared<NoExceptionPromise<int>>();
259 std::future future = wrapper->get_future();
260
261 // Destroy the empty promise with the future still pending. Verify that the
262 // process does not abort while destructing the promise.
263 wrapper.reset();
264 }

## ◆ TEST() [35/360]

impeller::testing::TEST | ( | BaseTest | ,
|  | NoExceptionPromiseValue |
| ) |  |

Definition at line 250 of file base_unittests.cc.

250 {
251 NoExceptionPromise<int> wrapper;
252 std::future future = wrapper.get_future();
253 wrapper.set_value(123);
254 ASSERT_EQ(future.get(), 123);
255 }

References impeller::NoExceptionPromise< T >::get_future(), and impeller::NoExceptionPromise< T >::set_value().

## ◆ TEST() [36/360]

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

Definition at line 31 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [37/360]

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

Definition at line 49 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [38/360]

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

Definition at line 59 of file capabilities_unittests.cc.

59 {
60 auto defaults = CapabilitiesBuilder().Build();
61 EXPECT_EQ(defaults->GetDefaultGlyphAtlasFormat(), PixelFormat::kUnknown);
62 auto mutated = CapabilitiesBuilder()
63 .SetDefaultGlyphAtlasFormat(PixelFormat::kA8UNormInt)
64 .Build();
65 EXPECT_EQ(mutated->GetDefaultGlyphAtlasFormat(), PixelFormat::kA8UNormInt);
66 }

References impeller::CapabilitiesBuilder::Build(), impeller::kA8UNormInt, impeller::kUnknown, and impeller::CapabilitiesBuilder::SetDefaultGlyphAtlasFormat().

## ◆ TEST() [39/360]

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

Definition at line 40 of file capabilities_unittests.cc.

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

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

## ◆ TEST() [40/360]

impeller::testing::TEST | ( | CapabilitiesVKTest | ,
|  | ContextFailsInitializationForNoCombinedDepthStencilFormat |
| ) |  |

Definition at line 195 of file context_vk_unittests.cc.

196 {
197 ScopedValidationDisable disable_validation;
198 const std::shared_ptr<ContextVK> context =
199 MockVulkanContextBuilder()
200 .SetPhysicalDeviceFormatPropertiesCallback(
201 [](VkPhysicalDevice physicalDevice, VkFormat format,
202 VkFormatProperties* pFormatProperties) {
203 if (format == VK_FORMAT_R8G8B8A8_UNORM) {
204 pFormatProperties->optimalTilingFeatures =
205 static_cast<VkFormatFeatureFlags>(
206 vk::FormatFeatureFlagBits::eColorAttachment);
207 }
208 // Ignore combined depth-stencil formats.
209 })
210 .Build();
211 ASSERT_EQ(context, nullptr);
212 }

## ◆ TEST() [41/360]

impeller::testing::TEST | ( | CapabilitiesVKTest | ,
|  | ContextInitializesWithNoStencilFormat |
| ) |  |

Definition at line 164 of file context_vk_unittests.cc.

164 {
165 const std::shared_ptr<ContextVK> context =
166 MockVulkanContextBuilder()
167 .SetPhysicalDeviceFormatPropertiesCallback(
168 [](VkPhysicalDevice physicalDevice, VkFormat format,
169 VkFormatProperties* pFormatProperties) {
170 if (format == VK_FORMAT_R8G8B8A8_UNORM) {
171 pFormatProperties->optimalTilingFeatures =
172 static_cast<VkFormatFeatureFlags>(
173 vk::FormatFeatureFlagBits::eColorAttachment);
174 } else if (format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
175 pFormatProperties->optimalTilingFeatures =
176 static_cast<VkFormatFeatureFlags>(
177 vk::FormatFeatureFlagBits::eDepthStencilAttachment);
178 }
179 // Ignore just the stencil format.
180 })
181 .Build();
182 ASSERT_NE(context, nullptr);
183 const CapabilitiesVK* capabilites_vk =
184 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
185 ASSERT_EQ(capabilites_vk->GetDefaultDepthStencilFormat(),
186 PixelFormat::kD32FloatS8UInt);
187 ASSERT_EQ(capabilites_vk->GetDefaultStencilFormat(),
188 PixelFormat::kD32FloatS8UInt);
189 }

References impeller::CapabilitiesVK::GetDefaultDepthStencilFormat(), impeller::CapabilitiesVK::GetDefaultStencilFormat(), and impeller::kD32FloatS8UInt.

## ◆ TEST() [42/360]

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

Definition at line 42 of file command_encoder_vk_unittests.cc.

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

References impeller::CommandBuffer::kCompleted.

## ◆ TEST() [43/360]

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

Definition at line 16 of file command_encoder_vk_unittests.cc.

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

References impeller::CommandEncoderFactoryVK::Create().

## ◆ TEST() [44/360]

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

Definition at line 115 of file command_pool_vk_unittests.cc.

115 {
116 auto const context = MockVulkanContextBuilder().Build();
117
118 {
119 // Fetch a pool (which will be created).
120 auto const recycler = context->GetCommandPoolRecycler();
121 auto pool = recycler->Get();
122
123 auto buffer = pool->CreateCommandBuffer();
124 pool->CollectCommandBuffer(std::move(buffer));
125
126 // This normally is called at the end of a frame.
127 recycler->Dispose();
128 }
129
130 // Wait for the pool to be reclaimed.
131 for (auto i = 0u; i < 2u; i++) {
132 auto waiter = fml::AutoResetWaitableEvent();
133 auto rattle = DeathRattle([&waiter]() { waiter.Signal(); });
134 {
135 UniqueResourceVKT<DeathRattle> resource(context->GetResourceManager(),
136 std::move(rattle));
137 }
138 waiter.Wait();
139 }
140
141 {
142 // Create a second pool and command buffer, which should reused the existing
143 // pool and cmd buffer.
144 auto const recycler = context->GetCommandPoolRecycler();
145 auto pool = recycler->Get();
146
147 auto buffer = pool->CreateCommandBuffer();
148 pool->CollectCommandBuffer(std::move(buffer));
149
150 // This normally is called at the end of a frame.
151 recycler->Dispose();
152 }
153
154 // Now check that we only ever created one pool and one command buffer.
155 auto const called = GetMockVulkanFunctions(context->GetDevice());
156 EXPECT_EQ(std::count(called->begin(), called->end(), "vkCreateCommandPool"),
157 1u);
158 EXPECT_EQ(
159 std::count(called->begin(), called->end(), "vkAllocateCommandBuffers"),
160 1u);
161
162 context->Shutdown();
163 }

## ◆ TEST() [45/360]

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() [46/360]

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() [47/360]

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() [48/360]

impeller::testing::TEST | ( | ConditionVariableTest | ,
|  | TestsCriticalSectionAfterWait |
| ) |  |

Definition at line 205 of file base_unittests.cc.

205 {
206 std::vector<std::thread> threads;
207 const auto kThreadCount = 10u;
208
209 Mutex mtx;
210 ConditionVariable cv;
211 size_t sum = 0u;
212
213 std::condition_variable start_cv;
214 std::mutex start_mtx;
215 bool start = false;
216 auto start_predicate = [&start]() { return start; };
217 auto thread_main = [&]() {
218 {
219 std::unique_lock start_lock(start_mtx);
220 start_cv.wait(start_lock, start_predicate);
221 }
222
223 mtx.Lock();
224 cv.Wait(mtx, []() { return true; });
225 auto old_val = sum;
226 std::this_thread::sleep_for(std::chrono::milliseconds{100u});
227 sum = old_val + 1u;
228 mtx.Unlock();
229 };
230 // Launch all threads. They will wait for the start CV to be signaled.
231 for (size_t i = 0; i < kThreadCount; i++) {
232 threads.emplace_back(thread_main);
233 }
234 // Notify all threads that the test may start.
235 {
236 {
237 std::scoped_lock start_lock(start_mtx);
238 start = true;
239 }
240 start_cv.notify_all();
241 }
242 // Join all threads.
243 ASSERT_EQ(threads.size(), kThreadCount);
244 for (size_t i = 0; i < kThreadCount; i++) {
245 threads[i].join();
246 }
247 ASSERT_EQ(sum, kThreadCount);
248 }

References impeller::ConditionVariable::Wait().

## ◆ TEST() [49/360]

impeller::testing::TEST | ( | ConditionVariableTest | ,
|  | TestsCriticalSectionAfterWaitForUntil |
| ) |  |

Definition at line 160 of file base_unittests.cc.

160 {
161 std::vector<std::thread> threads;
162 const auto kThreadCount = 10u;
163
164 Mutex mtx;
165 ConditionVariable cv;
166 size_t sum = 0u;
167
168 std::condition_variable start_cv;
169 std::mutex start_mtx;
170 bool start = false;
171 auto start_predicate = [&start]() { return start; };
172 auto thread_main = [&]() {
173 {
174 std::unique_lock start_lock(start_mtx);
175 start_cv.wait(start_lock, start_predicate);
176 }
177
178 mtx.Lock();
179 cv.WaitFor(mtx, std::chrono::milliseconds{0u}, []() { return true; });
180 auto old_val = sum;
181 std::this_thread::sleep_for(std::chrono::milliseconds{100u});
182 sum = old_val + 1u;
183 mtx.Unlock();
184 };
185 // Launch all threads. They will wait for the start CV to be signaled.
186 for (size_t i = 0; i < kThreadCount; i++) {
187 threads.emplace_back(thread_main);
188 }
189 // Notify all threads that the test may start.
190 {
191 {
192 std::scoped_lock start_lock(start_mtx);
193 start = true;
194 }
195 start_cv.notify_all();
196 }
197 // Join all threads.
198 ASSERT_EQ(threads.size(), kThreadCount);
199 for (size_t i = 0; i < kThreadCount; i++) {
200 threads[i].join();
201 }
202 ASSERT_EQ(sum, kThreadCount);
203 }

References impeller::ConditionVariable::WaitFor().

## ◆ TEST() [50/360]

impeller::testing::TEST | ( | ConditionVariableTest | ,
|  | WaitFor |
| ) |  |

Definition at line 122 of file base_unittests.cc.

122 {
123 CVTest test;
124 // test.rando_ivar = 12; // <--- Static analysis error
125 for (size_t i = 0; i < 2; ++i) {
126 test.mutex.Lock(); // <--- Static analysis error without this.
127 auto result = test.cv.WaitFor(
128 test.mutex, std::chrono::milliseconds{10},
129 [&]() IPLR_REQUIRES(test.mutex) {
130 test.rando_ivar = 12; // <-- Static analysics error without the
131 // IPLR_REQUIRES on the pred.
132 return false;
133 });
134 test.mutex.Unlock();
135 ASSERT_FALSE(result);
136 }
137 Lock lock(test.mutex); // <--- Static analysis error without this.
138 // The predicate never returns true. So return has to be due to a non-spurious
139 // wake.
140 ASSERT_EQ(test.rando_ivar, 12u);
141 }

References impeller::testing::CVTest::cv, IPLR_REQUIRES, impeller::testing::CVTest::mutex, and impeller::ConditionVariable::WaitFor().

## ◆ TEST() [51/360]

impeller::testing::TEST | ( | ConditionVariableTest | ,
|  | WaitForever |
| ) |  |

Definition at line 143 of file base_unittests.cc.

143 {
144 CVTest test;
145 // test.rando_ivar = 12; // <--- Static analysis error
146 for (size_t i = 0; i < 2; ++i) {
147 test.mutex.Lock(); // <--- Static analysis error without this.
148 test.cv.Wait(test.mutex, [&]() IPLR_REQUIRES(test.mutex) {
149 test.rando_ivar = 12; // <-- Static analysics error without
150 // the IPLR_REQUIRES on the pred.
151 return true;
152 });
153 test.mutex.Unlock();
154 }
155 Lock lock(test.mutex); // <--- Static analysis error without this.
156 // The wake only happens when the predicate returns true.
157 ASSERT_EQ(test.rando_ivar, 12u);
158 }

References impeller::testing::CVTest::cv, IPLR_REQUIRES, impeller::testing::CVTest::mutex, and impeller::ConditionVariable::Wait().

## ◆ TEST() [52/360]

impeller::testing::TEST | ( | ConditionVariableTest | ,
|  | WaitUntil |
| ) |  |

Definition at line 99 of file base_unittests.cc.

99 {
100 CVTest test;
101 // test.rando_ivar = 12; // <--- Static analysis error
102 for (size_t i = 0; i < 2; ++i) {
103 test.mutex.Lock(); // <--- Static analysis error without this.
104 auto result = test.cv.WaitUntil(
105 test.mutex,
106 std::chrono::high_resolution_clock::now() +
107 std::chrono::milliseconds{10},
108 [&]() IPLR_REQUIRES(test.mutex) {
109 test.rando_ivar = 12; // <-- Static analysics error without the
110 // IPLR_REQUIRES on the pred.
111 return false;
112 });
113 test.mutex.Unlock();
114 ASSERT_FALSE(result);
115 }
116 Lock lock(test.mutex); // <--- Static analysis error without this.
117 // The predicate never returns true. So return has to be due to a non-spurious
118 // wake.
119 ASSERT_EQ(test.rando_ivar, 12u);
120 }

References impeller::testing::CVTest::cv, IPLR_REQUIRES, impeller::testing::CVTest::mutex, and impeller::ConditionVariable::WaitUntil().

## ◆ TEST() [53/360]

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

Definition at line 132 of file context_vk_unittests.cc.

132 {
133 // The mocked methods don't report the presence of a validation layer but we
134 // explicitly ask for validation. Context creation should continue anyway.
135 auto context = MockVulkanContextBuilder()
136 .SetSettingsCallback([](auto& settings) {
137 settings.enable_validation = true;
138 })
139 .Build();
140 ASSERT_NE(context, nullptr);
141 const CapabilitiesVK* capabilites_vk =
142 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
143 ASSERT_FALSE(capabilites_vk->AreValidationsEnabled());
144 }

References impeller::CapabilitiesVK::AreValidationsEnabled().

## ◆ TEST() [54/360]

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

Definition at line 146 of file context_vk_unittests.cc.

146 {
147 auto context =
148 MockVulkanContextBuilder()
149 .SetSettingsCallback(
150 [](auto& settings) { settings.enable_validation = true; })
151 .SetInstanceExtensions(
152 {"VK_KHR_surface", "VK_MVK_macos_surface", "VK_EXT_debug_utils"})
153 .SetInstanceLayers({"VK_LAYER_KHRONOS_validation"})
154 .Build();
155 ASSERT_NE(context, nullptr);
156 const CapabilitiesVK* capabilites_vk =
157 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
158 ASSERT_TRUE(capabilites_vk->AreValidationsEnabled());
159 }

References impeller::CapabilitiesVK::AreValidationsEnabled().

## ◆ TEST() [55/360]

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

Definition at line 16 of file context_vk_unittests.cc.

16 {
17 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(100u), 4u);
18 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(9u), 4u);
19 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(8u), 4u);
20 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(7u), 3u);
21 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(6u), 3u);
22 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(5u), 2u);
23 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(4u), 2u);
24 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(3u), 1u);
25 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(2u), 1u);
26 EXPECT_EQ(ContextVK::ChooseThreadCountForWorkers(1u), 1u);
27 }

References impeller::ContextVK::ChooseThreadCountForWorkers().

## ◆ TEST() [56/360]

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

Definition at line 75 of file context_vk_unittests.cc.

75 {
76 std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline;
77 std::shared_ptr<std::vector<std::string>> functions;
78 {
79 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
80 PipelineDescriptor pipeline_desc;
81 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
82 PipelineFuture<PipelineDescriptor> pipeline_future =
83 context->GetPipelineLibrary()->GetPipeline(pipeline_desc);
84 pipeline = pipeline_future.Get();
85 ASSERT_TRUE(pipeline);
86 functions = GetMockVulkanFunctions(context->GetDevice());
87 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
88 "vkCreateGraphicsPipelines") != functions->end());
89 }
90 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
91 "vkDestroyDevice") != functions->end());
92 }

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

## ◆ TEST() [57/360]

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

Definition at line 116 of file context_vk_unittests.cc.

116 {
117 std::shared_ptr<PipelineLibrary> pipeline_library;
118 std::shared_ptr<std::vector<std::string>> functions;
119 {
120 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
121 PipelineDescriptor pipeline_desc;
122 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
123 pipeline_library = context->GetPipelineLibrary();
124 functions = GetMockVulkanFunctions(context->GetDevice());
125 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
126 "vkCreatePipelineCache") != functions->end());
127 }
128 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
129 "vkDestroyDevice") != functions->end());
130 }

References impeller::PipelineDescriptor::SetVertexDescriptor().

## ◆ TEST() [58/360]

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

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;
32 {
33 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
34 auto const pool = context->GetCommandPoolRecycler()->Get();
35 weak_pool = pool;
36 weak_context = context;
37 ASSERT_TRUE(weak_pool.lock());
38 ASSERT_TRUE(weak_context.lock());
39 }
40 ASSERT_FALSE(weak_pool.lock());
41 ASSERT_FALSE(weak_context.lock());
42 }

## ◆ TEST() [59/360]

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

Definition at line 44 of file context_vk_unittests.cc.

44 {
45 std::weak_ptr<ContextVK> weak_context;
46 std::weak_ptr<CommandPoolVK> weak_pool_main;
47
48 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
49 weak_pool_main = context->GetCommandPoolRecycler()->Get();
50 weak_context = context;
51 ASSERT_TRUE(weak_pool_main.lock());
52 ASSERT_TRUE(weak_context.lock());
53
54 // Start a second thread that obtains a command pool.
55 fml::AutoResetWaitableEvent latch1, latch2;
56 std::weak_ptr<CommandPoolVK> weak_pool_thread;
57 std::thread thread([&]() {
58 weak_pool_thread = context->GetCommandPoolRecycler()->Get();
59 latch1.Signal();
60 latch2.Wait();
61 });
62
63 // Delete the ContextVK on the main thread.
64 latch1.Wait();
65 context.reset();
66 ASSERT_FALSE(weak_pool_main.lock());
67 ASSERT_FALSE(weak_context.lock());
68
69 // Stop the second thread and check that its command pool has been deleted.
70 latch2.Signal();
71 thread.join();
72 ASSERT_FALSE(weak_pool_thread.lock());
73 }

## ◆ TEST() [60/360]

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

Definition at line 94 of file context_vk_unittests.cc.

94 {
95 std::shared_ptr<const ShaderFunction> shader_function;
96 std::shared_ptr<std::vector<std::string>> functions;
97 {
98 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
99 PipelineDescriptor pipeline_desc;
100 pipeline_desc.SetVertexDescriptor(std::make_shared<VertexDescriptor>());
101 std::vector<uint8_t> data = {0x03, 0x02, 0x23, 0x07};
102 context->GetShaderLibrary()->RegisterFunction(
103 "foobar_fragment_main", ShaderStage::kFragment,
104 std::make_shared<fml::DataMapping>(data), [](bool) {});
105 shader_function = context->GetShaderLibrary()->GetFunction(
106 "foobar_fragment_main", ShaderStage::kFragment);
107 ASSERT_TRUE(shader_function);
108 functions = GetMockVulkanFunctions(context->GetDevice());
109 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
110 "vkCreateShaderModule") != functions->end());
111 }
112 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
113 "vkDestroyDevice") != functions->end());
114 }

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

## ◆ TEST() [61/360]

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

Definition at line 225 of file context_vk_unittests.cc.

225 {
226 EXPECT_DEATH(const std::shared_ptr<ContextVK> context =
227 MockVulkanContextBuilder()
228 .SetSettingsCallback([](ContextVK::Settings& settings) {
229 settings.enable_validation = true;
230 settings.fatal_missing_validations = true;
231 })
232 .Build(),
233 "");
234 }

References impeller::ContextVK::Settings::enable_validation, and impeller::ContextVK::Settings::fatal_missing_validations.

## ◆ TEST() [62/360]

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

Definition at line 236 of file context_vk_unittests.cc.

236 {
237 std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
238
239 const CapabilitiesVK* capabilites_vk =
240 reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
241 ASSERT_NE(capabilites_vk->GetDefaultColorFormat(), PixelFormat::kUnknown);
242 }

References impeller::CapabilitiesVK::GetDefaultColorFormat(), and impeller::kUnknown.

## ◆ TEST() [63/360]

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

Definition at line 214 of file context_vk_unittests.cc.

214 {
215 const std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
216
217 context->SetOffscreenFormat(PixelFormat::kR8G8B8A8UNormInt);
218 context->InitializeCommonlyUsedShadersIfNeeded();
219
220 auto functions = GetMockVulkanFunctions(context->GetDevice());
221 ASSERT_TRUE(std::find(functions->begin(), functions->end(),
222 "vkCreateRenderPass") != functions->end());
223 }

References impeller::kR8G8B8A8UNormInt.

## ◆ TEST() [64/360]

impeller::testing::TEST | ( | DescriptorPoolRecyclerVKTest | ,
|  | GetDescriptorPoolRecyclerCreatesNewPools |
| ) |  |

Definition at line 15 of file descriptor_pool_vk_unittests.cc.

15 {
16 auto const context = MockVulkanContextBuilder().Build();
17
18 auto const pool1 = context->GetDescriptorPoolRecycler()->Get();
19 auto const pool2 = context->GetDescriptorPoolRecycler()->Get();
20
21 // The two descriptor pools should be different.
22 EXPECT_NE(pool1.get(), pool2.get());
23
24 context->Shutdown();
25 }

## ◆ TEST() [65/360]

impeller::testing::TEST | ( | DescriptorPoolRecyclerVKTest | ,
|  | ReclaimDropsDescriptorPoolIfSizeIsExceeded |
| ) |  |

Definition at line 65 of file descriptor_pool_vk_unittests.cc.

65 {
66 auto const context = MockVulkanContextBuilder().Build();
67
68 // Create 33 pools
69 {
70 std::vector<std::unique_ptr<DescriptorPoolVK>> pools;
71 for (auto i = 0u; i < 33; i++) {
72 auto pool = std::make_unique<DescriptorPoolVK>(context);
73 pool->AllocateDescriptorSets({}, *context);
74 pools.push_back(std::move(pool));
75 }
76 }
77
78 // See note above.
79 for (auto i = 0u; i < 2; i++) {
80 auto waiter = fml::AutoResetWaitableEvent();
81 auto rattle = fml::ScopedCleanupClosure([&waiter]() { waiter.Signal(); });
82 {
83 UniqueResourceVKT<fml::ScopedCleanupClosure> resource(
84 context->GetResourceManager(), std::move(rattle));
85 }
86 waiter.Wait();
87 }
88
89 auto const called = GetMockVulkanFunctions(context->GetDevice());
90 EXPECT_EQ(
91 std::count(called->begin(), called->end(), "vkCreateDescriptorPool"),
92 33u);
93 EXPECT_EQ(std::count(called->begin(), called->end(), "vkResetDescriptorPool"),
94 33u);
95
96 // Now create 33 more descriptor pools and observe that only one more is
97 // allocated.
98 {
99 std::vector<std::unique_ptr<DescriptorPoolVK>> pools;
100 for (auto i = 0u; i < 33; i++) {
101 auto pool = std::make_unique<DescriptorPoolVK>(context);
102 pool->AllocateDescriptorSets({}, *context);
103 pools.push_back(std::move(pool));
104 }
105 }
106
107 for (auto i = 0u; i < 2; i++) {
108 auto waiter = fml::AutoResetWaitableEvent();
109 auto rattle = fml::ScopedCleanupClosure([&waiter]() { waiter.Signal(); });
110 {
111 UniqueResourceVKT<fml::ScopedCleanupClosure> resource(
112 context->GetResourceManager(), std::move(rattle));
113 }
114 waiter.Wait();
115 }
116
117 auto const called_twice = GetMockVulkanFunctions(context->GetDevice());
118 // 32 of the descriptor pools were recycled, so only one more is created.
119 EXPECT_EQ(
120 std::count(called->begin(), called->end(), "vkCreateDescriptorPool"),
121 34u);
122
123 context->Shutdown();
124 }

## ◆ TEST() [66/360]

impeller::testing::TEST | ( | DescriptorPoolRecyclerVKTest | ,
|  | ReclaimMakesDescriptorPoolAvailable |
| ) |  |

Definition at line 27 of file descriptor_pool_vk_unittests.cc.

27 {
28 auto const context = MockVulkanContextBuilder().Build();
29
30 {
31 // Fetch a pool (which will be created).
32 auto pool = DescriptorPoolVK(context);
33 pool.AllocateDescriptorSets({}, *context);
34 }
35
36 // There is a chance that the first death rattle item below is destroyed in
37 // the same reclaim cycle as the pool allocation above. These items are placed
38 // into a std::vector and free'd, which may free in reverse order. That would
39 // imply that the death rattle and subsequent waitable event fires before the
40 // pool is reset. To work around this, we can either manually remove items
41 // from the vector or use two death rattles.
42 for (auto i = 0u; i < 2; i++) {
43 // Add something to the resource manager and have it notify us when it's
44 // destroyed. That should give us a non-flaky signal that the pool has been
45 // reclaimed as well.
46 auto waiter = fml::AutoResetWaitableEvent();
47 auto rattle = fml::ScopedCleanupClosure([&waiter]() { waiter.Signal(); });
48 {
49 UniqueResourceVKT<fml::ScopedCleanupClosure> resource(
50 context->GetResourceManager(), std::move(rattle));
51 }
52 waiter.Wait();
53 }
54
55 auto const pool = context->GetDescriptorPoolRecycler()->Get();
56
57 // Now check that we only ever created one pool.
58 auto const called = GetMockVulkanFunctions(context->GetDevice());
59 EXPECT_EQ(
60 std::count(called->begin(), called->end(), "vkCreateDescriptorPool"), 1u);
61
62 context->Shutdown();
63 }

## ◆ TEST() [67/360]

impeller::testing::TEST | ( | DisplayListTest | ,
|  | CircleBoundsComputation |
| ) |  |

Definition at line 1584 of file dl_unittests.cc.

1584 {
1585 SkPath path = SkPath().addCircle(0, 0, 5);
1586
1587 flutter::DlPaint paint;
1588 flutter::DisplayListBuilder builder;
1589
1590 builder.DrawPath(path, paint);
1591 auto display_list = builder.Build();
1592
1593 DlDispatcher dispatcher;
1594 display_list->Dispatch(dispatcher);
1595 auto picture = dispatcher.EndRecordingAsPicture();
1596
1597 std::optional<Rect> coverage =
1598 GetCoverageOfFirstEntity<SolidColorContents>(picture);
1599
1600 ASSERT_TRUE(coverage.has_value());
1601 ASSERT_EQ(coverage.value_or(Rect::MakeMaximum()),
1602 Rect::MakeLTRB(-5, -5, 5, 5));
1603 }

References impeller::DlDispatcherBase::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeMaximum(), and paint.

## ◆ TEST() [68/360]

impeller::testing::TEST | ( | DisplayListTest | ,
|  | RRectBoundsComputation |
| ) |  |

Definition at line 1561 of file dl_unittests.cc.

1561 {
1562 SkRRect rrect = SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 100, 100), 4, 4);
1563 SkPath path = SkPath().addRRect(rrect);
1564
1565 flutter::DlPaint paint;
1566 flutter::DisplayListBuilder builder;
1567
1568 builder.DrawPath(path, paint);
1569 auto display_list = builder.Build();
1570
1571 DlDispatcher dispatcher;
1572 display_list->Dispatch(dispatcher);
1573 auto picture = dispatcher.EndRecordingAsPicture();
1574
1575 std::optional<Rect> coverage =
1576 GetCoverageOfFirstEntity<SolidColorContents>(picture);
1577
1578 // Validate that the RRect coverage is _exactly_ the same as the input rect.
1579 ASSERT_TRUE(coverage.has_value());
1580 ASSERT_EQ(coverage.value_or(Rect::MakeMaximum()),
1581 Rect::MakeLTRB(0, 0, 100, 100));
1582 }

References impeller::DlDispatcherBase::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeMaximum(), and paint.

## ◆ TEST() [69/360]

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

Definition at line 139 of file geometry_unittests.cc.

139 {
140 Entity entity;
141 entity.SetTransform(Matrix::MakeScale(Vector2{3.0, 3.0}));
142 EXPECT_EQ(Geometry::MakeStrokePath({}, 0.5)->ComputeAlphaCoverage(entity), 1);
143 EXPECT_EQ(Geometry::MakeStrokePath({}, 0.1)->ComputeAlphaCoverage(entity), 1);
144 EXPECT_EQ(Geometry::MakeStrokePath({}, 0.05)->ComputeAlphaCoverage(entity),
145 1);
146 EXPECT_NEAR(Geometry::MakeStrokePath({}, 0.01)->ComputeAlphaCoverage(entity),
147 0.6, 0.1);
148 EXPECT_NEAR(
149 Geometry::MakeStrokePath({}, 0.0000005)->ComputeAlphaCoverage(entity),
150 1e-05, 0.001);
151 EXPECT_EQ(Geometry::MakeStrokePath({}, 0)->ComputeAlphaCoverage(entity), 1);
152 EXPECT_EQ(Geometry::MakeStrokePath({}, 40)->ComputeAlphaCoverage(entity), 1);
153 }

References impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), and impeller::Entity::SetTransform().

## ◆ TEST() [70/360]

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

Definition at line 78 of file geometry_unittests.cc.

78 {
79 auto path = PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath();
80 auto geometry = Geometry::MakeFillPath(
81 path, /* inner rect */ Rect::MakeLTRB(0, 0, 100, 100));
82 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
83 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
84 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
85 ASSERT_TRUE(geometry->CoversArea({}, Rect()));
86 }

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

## ◆ TEST() [71/360]

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

Definition at line 88 of file geometry_unittests.cc.

88 {
89 auto path = PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath();
90 auto geometry = Geometry::MakeFillPath(path);
91 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
92 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
93 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
94 ASSERT_FALSE(geometry->CoversArea({}, Rect()));
95 }

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

## ◆ TEST() [72/360]

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

Definition at line 132 of file geometry_unittests.cc.

132 {
133 GeometryResult result;
134 EXPECT_EQ(result.type, PrimitiveType::kTriangleStrip);
135 EXPECT_EQ(result.transform, Matrix());
136 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal);
137 }

References impeller::GeometryResult::kNormal, impeller::kTriangleStrip, impeller::GeometryResult::mode, impeller::GeometryResult::transform, and impeller::GeometryResult::type.

## ◆ TEST() [73/360]

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

Definition at line 97 of file geometry_unittests.cc.

97 {
98 {
99 auto geometry = Geometry::MakeLine({10, 10}, {20, 10}, 2, Cap::kButt);
100 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(10, 9, 20, 11));
101 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(10, 9, 20, 11)));
102 }
103
104 {
105 auto geometry = Geometry::MakeLine({10, 10}, {20, 10}, 2, Cap::kSquare);
106 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 9, 21, 11));
107 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 9, 21, 11)));
108 }
109
110 {
111 auto geometry = Geometry::MakeLine({10, 10}, {10, 20}, 2, Cap::kButt);
112 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 10, 11, 20));
113 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 10, 11, 20)));
114 }
115
116 {
117 auto geometry = Geometry::MakeLine({10, 10}, {10, 20}, 2, Cap::kSquare);
118 EXPECT_EQ(geometry->GetCoverage({}), Rect::MakeLTRB(9, 9, 11, 21));
119 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(9, 9, 11, 21)));
120 }
121 }

References impeller::kButt, impeller::kSquare, impeller::Geometry::MakeLine(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [74/360]

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

Definition at line 70 of file geometry_unittests.cc.

70 {
71 auto geometry = Geometry::MakeRect(Rect::MakeLTRB(0, 0, 100, 100));
72 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(0, 0, 100, 100)));
73 ASSERT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(-1, 0, 100, 100)));
74 ASSERT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 1, 100, 100)));
75 ASSERT_TRUE(geometry->CoversArea({}, Rect()));
76 }

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

## ◆ TEST() [75/360]

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

Definition at line 123 of file geometry_unittests.cc.

123 {
124 auto geometry =
125 Geometry::MakeRoundRect(Rect::MakeLTRB(0, 0, 100, 100), Size(20, 20));
126 EXPECT_FALSE(geometry->CoversArea({}, Rect::MakeLTRB(15, 15, 85, 85)));
127 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(20, 20, 80, 80)));
128 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(30, 1, 70, 99)));
129 EXPECT_TRUE(geometry->CoversArea({}, Rect::MakeLTRB(1, 30, 99, 70)));
130 }

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

## ◆ TEST() [76/360]

impeller::testing::TEST | ( | EntityPassClipStackTest | ,
|  | AppendAndRestoreClipCoverage |
| ) |  |

Definition at line 92 of file entity_pass_unittests.cc.

92 {
93 EntityPassClipStack recorder =
94 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
95
96 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
97
98 // Push a clip.
99 Entity entity;
100 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
101 Contents::ClipCoverage{
102 .type = Contents::ClipCoverage::Type::kAppend,
103 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
104 },
105 entity, 0, Point(0, 0));
106 EXPECT_TRUE(result.should_render);
107 EXPECT_TRUE(result.clip_did_change);
108
109 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 2u);
110 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
111 Rect::MakeLTRB(50, 50, 55, 55));
112 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].clip_height, 1u);
113 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
114
115 // Restore the clip.
116 auto restore_clip = std::make_shared<ClipRestoreContents>();
117 restore_clip->SetRestoreHeight(0);
118 entity.SetContents(std::move(restore_clip));
119 recorder.ApplyClipState(
120 Contents::ClipCoverage{
121 .type = Contents::ClipCoverage::Type::kRestore,
122 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
123 },
124 entity, 0, Point(0, 0));
125
126 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
127 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
128 Rect::MakeSize(Size::MakeWH(100, 100)));
129 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_height, 0u);
130 EXPECT_EQ(recorder.GetReplayEntities().size(), 0u);
131 }

References impeller::EntityPassClipStack::ApplyClipState(), impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::EntityPassClipStack::GetReplayEntities(), impeller::Contents::ClipCoverage::kAppend, impeller::Contents::ClipCoverage::kRestore, impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeSize(), impeller::TSize< Scalar >::MakeWH(), impeller::Entity::SetContents(), impeller::EntityPassClipStack::ClipStateResult::should_render, and impeller::Contents::ClipCoverage::type.

## ◆ TEST() [77/360]

impeller::testing::TEST | ( | EntityPassClipStackTest | ,
|  | AppendCoverageNoChange |
| ) |  |

Definition at line 69 of file entity_pass_unittests.cc.

69 {
70 EntityPassClipStack recorder =
71 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
72
73 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
74 Rect::MakeSize(Size::MakeWH(100, 100)));
75 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_height, 0u);
76
77 Entity entity;
78 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
79 Contents::ClipCoverage{
80 .type = Contents::ClipCoverage::Type::kNoChange,
81 .coverage = std::nullopt,
82 },
83 entity, 0, Point(0, 0));
84 EXPECT_TRUE(result.should_render);
85 EXPECT_FALSE(result.clip_did_change);
86
87 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
88 Rect::MakeSize(Size::MakeWH(100, 100)));
89 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_height, 0u);
90 }

References impeller::EntityPassClipStack::ApplyClipState(), impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::Contents::ClipCoverage::kNoChange, impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeSize(), impeller::TSize< Scalar >::MakeWH(), impeller::EntityPassClipStack::ClipStateResult::should_render, and impeller::Contents::ClipCoverage::type.

## ◆ TEST() [78/360]

impeller::testing::TEST | ( | EntityPassClipStackTest | ,
|  | CanAppendNoChange |
| ) |  |

Definition at line 57 of file entity_pass_unittests.cc.

57 {
58 EntityPassClipStack recorder =
59 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
60
61 EXPECT_TRUE(recorder.GetReplayEntities().empty());
62
63 Entity entity;
64 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kNoChange,
65 Rect());
66 EXPECT_TRUE(recorder.GetReplayEntities().empty());
67 }

References impeller::EntityPassClipStack::GetReplayEntities(), impeller::Contents::ClipCoverage::kNoChange, impeller::TRect< Scalar >::MakeLTRB(), and impeller::EntityPassClipStack::RecordEntity().

## ◆ TEST() [79/360]

impeller::testing::TEST | ( | EntityPassClipStackTest | ,
|  | CanPopEntitiesSafely |
| ) |  |

Definition at line 46 of file entity_pass_unittests.cc.

46 {
47 EntityPassClipStack recorder =
48 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
49
50 EXPECT_TRUE(recorder.GetReplayEntities().empty());
51
52 Entity entity;
53 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kRestore, Rect());
54 EXPECT_TRUE(recorder.GetReplayEntities().empty());
55 }

References impeller::EntityPassClipStack::GetReplayEntities(), impeller::Contents::ClipCoverage::kRestore, impeller::TRect< Scalar >::MakeLTRB(), and impeller::EntityPassClipStack::RecordEntity().

## ◆ TEST() [80/360]

impeller::testing::TEST | ( | EntityPassClipStackTest | ,
|  | CanPushAndPopEntities |
| ) |  |

Definition at line 16 of file entity_pass_unittests.cc.

16 {
17 EntityPassClipStack recorder =
18 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
19
20 EXPECT_TRUE(recorder.GetReplayEntities().empty());
21
22 Entity entity;
23 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kAppend,
24 Rect::MakeLTRB(0, 0, 100, 100));
25 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
26
27 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kAppend,
28 Rect::MakeLTRB(0, 0, 50, 50));
29 EXPECT_EQ(recorder.GetReplayEntities().size(), 2u);
30 ASSERT_TRUE(recorder.GetReplayEntities()[0].clip_coverage.has_value());
31 ASSERT_TRUE(recorder.GetReplayEntities()[1].clip_coverage.has_value());
32 // NOLINTBEGIN(bugprone-unchecked-optional-access)
33 EXPECT_EQ(recorder.GetReplayEntities()[0].clip_coverage.value(),
34 Rect::MakeLTRB(0, 0, 100, 100));
35 EXPECT_EQ(recorder.GetReplayEntities()[1].clip_coverage.value(),
36 Rect::MakeLTRB(0, 0, 50, 50));
37 // NOLINTEND(bugprone-unchecked-optional-access)
38
39 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kRestore, Rect());
40 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
41
42 recorder.RecordEntity(entity, Contents::ClipCoverage::Type::kRestore, Rect());
43 EXPECT_TRUE(recorder.GetReplayEntities().empty());
44 }

References impeller::EntityPassClipStack::GetReplayEntities(), impeller::Contents::ClipCoverage::kAppend, impeller::Contents::ClipCoverage::kRestore, impeller::TRect< Scalar >::MakeLTRB(), and impeller::EntityPassClipStack::RecordEntity().

## ◆ TEST() [81/360]

impeller::testing::TEST | ( | EntityPassClipStackTest | ,
|  | ClipAndRestoreWithSubpasses |
| ) |  |

Definition at line 160 of file entity_pass_unittests.cc.

160 {
161 EntityPassClipStack recorder =
162 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
163
164 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
165
166 // Push a clip.
167 Entity entity;
168 {
169 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
170 Contents::ClipCoverage{
171 .type = Contents::ClipCoverage::Type::kAppend,
172 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
173 },
174 entity, 0, Point(0, 0));
175 EXPECT_TRUE(result.should_render);
176 EXPECT_TRUE(result.clip_did_change);
177 }
178
179 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 2u);
180 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
181 Rect::MakeLTRB(50, 50, 55, 55));
182 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].clip_height, 1u);
183 EXPECT_EQ(recorder.GetReplayEntities().size(), 1u);
184
185 // Begin a subpass.
186 recorder.PushSubpass(Rect::MakeLTRB(50, 50, 55, 55), 1);
187 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
188 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
189 Rect::MakeLTRB(50, 50, 55, 55));
190
191 {
192 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
193 Contents::ClipCoverage{
194 .type = Contents::ClipCoverage::Type::kAppend,
195 .coverage = Rect::MakeLTRB(54, 54, 55, 55),
196 },
197 entity, 0, Point(0, 0));
198 EXPECT_TRUE(result.should_render);
199 EXPECT_TRUE(result.clip_did_change);
200 }
201
202 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
203 Rect::MakeLTRB(54, 54, 55, 55));
204
205 // End subpass.
206 recorder.PopSubpass();
207
208 EXPECT_EQ(recorder.GetClipCoverageLayers()[1].coverage,
209 Rect::MakeLTRB(50, 50, 55, 55));
210 }

References impeller::EntityPassClipStack::ApplyClipState(), impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::EntityPassClipStack::GetReplayEntities(), impeller::Contents::ClipCoverage::kAppend, impeller::TRect< Scalar >::MakeLTRB(), impeller::EntityPassClipStack::PopSubpass(), impeller::EntityPassClipStack::PushSubpass(), impeller::EntityPassClipStack::ClipStateResult::should_render, and impeller::Contents::ClipCoverage::type.

## ◆ TEST() [82/360]

impeller::testing::TEST | ( | EntityPassClipStackTest | ,
|  | UnbalancedRestore |
| ) |  |

Definition at line 133 of file entity_pass_unittests.cc.

133 {
134 EntityPassClipStack recorder =
135 EntityPassClipStack(Rect::MakeLTRB(0, 0, 100, 100));
136
137 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
138
139 // Restore the clip.
140 Entity entity;
141 auto restore_clip = std::make_shared<ClipRestoreContents>();
142 restore_clip->SetRestoreHeight(0);
143 entity.SetContents(std::move(restore_clip));
144 EntityPassClipStack::ClipStateResult result = recorder.ApplyClipState(
145 Contents::ClipCoverage{
146 .type = Contents::ClipCoverage::Type::kRestore,
147 .coverage = Rect::MakeLTRB(50, 50, 55, 55),
148 },
149 entity, 0, Point(0, 0));
150 EXPECT_FALSE(result.should_render);
151 EXPECT_FALSE(result.clip_did_change);
152
153 ASSERT_EQ(recorder.GetClipCoverageLayers().size(), 1u);
154 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].coverage,
155 Rect::MakeSize(Size::MakeWH(100, 100)));
156 EXPECT_EQ(recorder.GetClipCoverageLayers()[0].clip_height, 0u);
157 EXPECT_EQ(recorder.GetReplayEntities().size(), 0u);
158 }

References impeller::EntityPassClipStack::ApplyClipState(), impeller::EntityPassClipStack::ClipStateResult::clip_did_change, impeller::EntityPassClipStack::GetClipCoverageLayers(), impeller::EntityPassClipStack::GetReplayEntities(), impeller::Contents::ClipCoverage::kRestore, impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeSize(), impeller::TSize< Scalar >::MakeWH(), impeller::Entity::SetContents(), impeller::EntityPassClipStack::ClipStateResult::should_render, and impeller::Contents::ClipCoverage::type.

## ◆ TEST() [83/360]

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() [84/360]

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() [85/360]

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() [86/360]

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() [87/360]

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() [88/360]

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() [89/360]

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() [90/360]

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.SetTransform(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::SetTransform().

## ◆ TEST() [91/360]

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() [92/360]

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() [93/360]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | CalculateSigmaForBlurRadius |
| ) |  |

Definition at line 449 of file gaussian_blur_filter_contents_unittests.cc.

449 {
450 Scalar sigma = 1.0;
451 Scalar radius = GaussianBlurFilterContents::CalculateBlurRadius(
452 GaussianBlurFilterContents::ScaleSigma(sigma));
453 fml::StatusOr<Scalar> derived_sigma =
454 CalculateSigmaForBlurRadius(radius, Matrix());
455 ASSERT_TRUE(derived_sigma.ok());
456 EXPECT_NEAR(sigma, derived_sigma.value(), 0.01f);
457 }

References impeller::GaussianBlurFilterContents::CalculateBlurRadius(), and impeller::GaussianBlurFilterContents::ScaleSigma().

## ◆ TEST() [94/360]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | CalculateSigmaValues |
| ) |  |

Definition at line 216 of file gaussian_blur_filter_contents_unittests.cc.

216 {
217 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(1.0f), 1);
218 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(2.0f), 1);
219 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(3.0f), 1);
220 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(4.0f), 1);
221 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(16.0f), 0.25);
222 // Hang on to 1/8 as long as possible.
223 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(95.0f), 0.125);
224 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(96.0f), 0.0625);
225 // Downsample clamped to 1/16th.
226 EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(1024.0f), 0.0625);
227 }

References impeller::GaussianBlurFilterContents::CalculateScale().

## ◆ TEST() [95/360]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | ChopHugeBlurs |
| ) |  |

Definition at line 615 of file gaussian_blur_filter_contents_unittests.cc.

615 {
616 Scalar sigma = 30.5f;
617 int32_t blur_radius = static_cast<int32_t>(
618 std::ceil(GaussianBlurFilterContents::CalculateBlurRadius(sigma)));
619 BlurParameters parameters = {.blur_uv_offset = Point(1, 0),
620 .blur_sigma = sigma,
621 .blur_radius = blur_radius,
622 .step_size = 1};
623 KernelSamples kernel_samples = GenerateBlurInfo(parameters);
624 GaussianBlurPipeline::FragmentShader::KernelSamples frag_kernel_samples =
625 LerpHackKernelSamples(kernel_samples);
626 EXPECT_TRUE(frag_kernel_samples.sample_count <= kGaussianBlurMaxKernelSize);
627 }

References blur_radius, impeller::BlurParameters::blur_uv_offset, impeller::GaussianBlurFilterContents::CalculateBlurRadius(), impeller::GenerateBlurInfo(), impeller::kGaussianBlurMaxKernelSize, and impeller::LerpHackKernelSamples().

## ◆ TEST() [96/360]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | Coefficients |
| ) |  |

Definition at line 459 of file gaussian_blur_filter_contents_unittests.cc.

459 {
460 BlurParameters parameters = {.blur_uv_offset = Point(1, 0),
461 .blur_sigma = 1,
462 .blur_radius = 5,
463 .step_size = 1};
464 KernelSamples samples = GenerateBlurInfo(parameters);
465 EXPECT_EQ(samples.sample_count, 9);
466
467 // Coefficients should add up to 1.
468 Scalar tally = 0;
469 for (int i = 0; i < samples.sample_count; ++i) {
470 tally += samples.samples[i].coefficient;
471 }
472 EXPECT_FLOAT_EQ(tally, 1.0f);
473
474 // Verify the shape of the curve.
475 for (int i = 0; i < 4; ++i) {
476 EXPECT_FLOAT_EQ(samples.samples[i].coefficient,
477 samples.samples[8 - i].coefficient);
478 EXPECT_TRUE(samples.samples[i + 1].coefficient >
479 samples.samples[i].coefficient);
480 }
481 }

References impeller::BlurParameters::blur_uv_offset, impeller::GenerateBlurInfo(), impeller::KernelSamples::sample_count, and impeller::KernelSamples::samples.

## ◆ TEST() [97/360]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | CoverageEmpty |
| ) |  |

Definition at line 112 of file gaussian_blur_filter_contents_unittests.cc.

112 {
113 GaussianBlurFilterContents contents(
114 /*sigma_x=*/0.0, /*sigma_y=*/0.0, Entity::TileMode::kDecal,
115 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
116 FilterInput::Vector inputs = {};
117 Entity entity;
118 std::optional<Rect> coverage =
119 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
120 ASSERT_FALSE(coverage.has_value());
121 }

References impeller::GaussianBlurFilterContents::GetFilterCoverage(), impeller::Entity::kDecal, and impeller::FilterContents::kNormal.

## ◆ TEST() [98/360]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | CoverageSimple |
| ) |  |

Definition at line 123 of file gaussian_blur_filter_contents_unittests.cc.

123 {
124 GaussianBlurFilterContents contents(
125 /*sigma_x=*/0.0, /*sigma_y=*/0.0, Entity::TileMode::kDecal,
126 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
127 FilterInput::Vector inputs = {
128 FilterInput::Make(Rect::MakeLTRB(10, 10, 110, 110))};
129 Entity entity;
130 std::optional<Rect> coverage =
131 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
132
133 ASSERT_EQ(coverage, Rect::MakeLTRB(10, 10, 110, 110));
134 }

References impeller::GaussianBlurFilterContents::GetFilterCoverage(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::FilterInput::Make(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [99/360]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | CoverageWithSigma |
| ) |  |

Definition at line 136 of file gaussian_blur_filter_contents_unittests.cc.

136 {
137 fml::StatusOr<Scalar> sigma_radius_1 =
138 CalculateSigmaForBlurRadius(1.0, Matrix());
139 ASSERT_TRUE(sigma_radius_1.ok());
140 GaussianBlurFilterContents contents(
141 /*sigma_x=*/sigma_radius_1.value(),
142 /*sigma_y=*/sigma_radius_1.value(), Entity::TileMode::kDecal,
143 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
144 FilterInput::Vector inputs = {
145 FilterInput::Make(Rect::MakeLTRB(100, 100, 200, 200))};
146 Entity entity;
147 std::optional<Rect> coverage =
148 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
149
150 EXPECT_TRUE(coverage.has_value());
151 if (coverage.has_value()) {
152 EXPECT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(99, 99, 201, 201));
153 }
154 }

References EXPECT_RECT_NEAR, impeller::GaussianBlurFilterContents::GetFilterCoverage(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::FilterInput::Make(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [100/360]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | Create |
| ) |  |

Definition at line 104 of file gaussian_blur_filter_contents_unittests.cc.

104 {
105 GaussianBlurFilterContents contents(
106 /*sigma_x=*/0.0, /*sigma_y=*/0.0, Entity::TileMode::kDecal,
107 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
108 EXPECT_EQ(contents.GetSigmaX(), 0.0);
109 EXPECT_EQ(contents.GetSigmaY(), 0.0);
110 }

References impeller::GaussianBlurFilterContents::GetSigmaX(), impeller::GaussianBlurFilterContents::GetSigmaY(), impeller::Entity::kDecal, and impeller::FilterContents::kNormal.

## ◆ TEST() [101/360]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | FilterSourceCoverage |
| ) |  |

Definition at line 199 of file gaussian_blur_filter_contents_unittests.cc.

199 {
200 fml::StatusOr<Scalar> sigma_radius_1 =
201 CalculateSigmaForBlurRadius(1.0, Matrix());
202 ASSERT_TRUE(sigma_radius_1.ok());
203 auto contents = std::make_unique<GaussianBlurFilterContents>(
204 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
205 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
206 std::optional<Rect> coverage = contents->GetFilterSourceCoverage(
207 /*effect_transform=*/Matrix::MakeScale({2.0, 2.0, 1.0}),
208 /*output_limit=*/Rect::MakeLTRB(100, 100, 200, 200));
209 EXPECT_TRUE(coverage.has_value());
210 if (coverage.has_value()) {
211 EXPECT_RECT_NEAR(coverage.value(),
212 Rect::MakeLTRB(100 - 2, 100 - 2, 200 + 2, 200 + 2));
213 }
214 }

References EXPECT_RECT_NEAR, impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::TRect< Scalar >::MakeLTRB(), and impeller::Matrix::MakeScale().

## ◆ TEST() [102/360]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | LerpHackKernelSamplesComplex |
| ) |  |

Definition at line 561 of file gaussian_blur_filter_contents_unittests.cc.

561 {
562 Scalar sigma = 10.0f;
563 int32_t blur_radius = static_cast<int32_t>(
564 std::ceil(GaussianBlurFilterContents::CalculateBlurRadius(sigma)));
565 BlurParameters parameters = {.blur_uv_offset = Point(1, 0),
566 .blur_sigma = sigma,
567 .blur_radius = blur_radius,
568 .step_size = 1};
569 KernelSamples kernel_samples = GenerateBlurInfo(parameters);
570 EXPECT_EQ(kernel_samples.sample_count, 33);
571 GaussianBlurPipeline::FragmentShader::KernelSamples fast_kernel_samples =
572 LerpHackKernelSamples(kernel_samples);
573 EXPECT_EQ(fast_kernel_samples.sample_count, 17);
574 float data[33];
575 srand(0);
576 for (int i = 0; i < 33; i++) {
577 data[i] = 255.0 * static_cast<double>(IMPELLER_RAND()) / RAND_MAX;
578 }
579
580 auto sampler = [data](Point point) -> Scalar {
581 FML_CHECK(point.y == 0.0f);
582 FML_CHECK(point.x >= -16);
583 FML_CHECK(point.x <= 16);
584 Scalar fint_part;
585 Scalar fract = fabsf(modf(point.x, &fint_part));
586 if (fract == 0) {
587 int32_t int_part = static_cast<int32_t>(fint_part) + 16;
588 return data[int_part];
589 } else {
590 int32_t left = static_cast<int32_t>(floor(point.x)) + 16;
591 int32_t right = static_cast<int32_t>(ceil(point.x)) + 16;
592 if (point.x < 0) {
593 return fract * data[left] + (1.0 - fract) * data[right];
594 } else {
595 return (1.0 - fract) * data[left] + fract * data[right];
596 }
597 }
598 };
599
600 Scalar output = 0.0;
601 for (int i = 0; i < kernel_samples.sample_count; ++i) {
602 auto sample = kernel_samples.samples[i];
603 output += sample.coefficient * sampler(sample.uv_offset);
604 }
605
606 Scalar fast_output = 0.0;
607 for (int i = 0; i < fast_kernel_samples.sample_count; ++i) {
608 auto sample = fast_kernel_samples.samples[i];
609 fast_output += sample.coefficient * sampler(sample.uv_offset);
610 }
611
612 EXPECT_NEAR(output, fast_output, 0.1);
613 }

References blur_radius, impeller::BlurParameters::blur_uv_offset, impeller::GaussianBlurFilterContents::CalculateBlurRadius(), data, impeller::GenerateBlurInfo(), IMPELLER_RAND, impeller::LerpHackKernelSamples(), impeller::KernelSamples::sample_count, and impeller::KernelSamples::samples.

## ◆ TEST() [103/360]

impeller::testing::TEST | ( | GaussianBlurFilterContentsTest | ,
|  | LerpHackKernelSamplesSimple |
| ) |  |

Definition at line 483 of file gaussian_blur_filter_contents_unittests.cc.

483 {
484 KernelSamples kernel_samples = {
485 .sample_count = 5,
486 .samples =
487 {
488 {
489 .uv_offset = Vector2(-2, 0),
490 .coefficient = 0.1f,
491 },
492 {
493 .uv_offset = Vector2(-1, 0),
494 .coefficient = 0.2f,
495 },
496 {
497 .uv_offset = Vector2(0, 0),
498 .coefficient = 0.4f,
499 },
500 {
501 .uv_offset = Vector2(1, 0),
502 .coefficient = 0.2f,
503 },
504 {
505 .uv_offset = Vector2(2, 0),
506 .coefficient = 0.1f,
507 },
508 },
509 };
510
511 GaussianBlurPipeline::FragmentShader::KernelSamples fast_kernel_samples =
512 LerpHackKernelSamples(kernel_samples);
513 EXPECT_EQ(fast_kernel_samples.sample_count, 3);
514
515 GaussianBlurPipeline::FragmentShader::KernelSample* samples =
516 kernel_samples.samples;
517 GaussianBlurPipeline::FragmentShader::KernelSample* fast_samples =
518 fast_kernel_samples.samples;
519
520 //////////////////////////////////////////////////////////////////////////////
521 // Check output kernel.
522
523 EXPECT_FLOAT_EQ(fast_samples[0].uv_offset.x, -1.3333333);
524 EXPECT_FLOAT_EQ(fast_samples[0].uv_offset.y, 0);
525 EXPECT_FLOAT_EQ(fast_samples[0].coefficient, 0.3);
526 EXPECT_FLOAT_EQ(fast_samples[1].uv_offset.x, 0);
527 EXPECT_FLOAT_EQ(fast_samples[1].uv_offset.y, 0);
528 EXPECT_FLOAT_EQ(fast_samples[1].coefficient, 0.4);
529 EXPECT_FLOAT_EQ(fast_samples[2].uv_offset.x, 1.3333333);
530 EXPECT_FLOAT_EQ(fast_samples[2].uv_offset.y, 0);
531 EXPECT_FLOAT_EQ(fast_samples[2].coefficient, 0.3);
532
533 //////////////////////////////////////////////////////////////////////////////
534 // Check output of fast kernel versus original kernel.
535
536 Scalar data[5] = {0.25, 0.5, 0.5, 1.0, 0.2};
537 Scalar original_output =
538 samples[0].coefficient * data[0] + samples[1].coefficient * data[1] +
539 samples[2].coefficient * data[2] + samples[3].coefficient * data[3] +
540 samples[4].coefficient * data[4];
541
542 auto lerp = [](const Point& point, Scalar left, Scalar right) {
543 Scalar int_part;
544 Scalar fract = fabsf(modf(point.x, &int_part));
545 if (point.x < 0) {
546 return left * fract + right * (1.0 - fract);
547 } else {
548 return left * (1.0 - fract) + right * fract;
549 }
550 };
551 Scalar fast_output =
552 /*1st*/ lerp(fast_samples[0].uv_offset, data[0], data[1]) *
553 fast_samples[0].coefficient +
554 /*2nd*/ data[2] * fast_samples[1].coefficient +
555 /*3rd*/ lerp(fast_samples[2].uv_offset, data[3], data[4]) *
556 fast_samples[2].coefficient;
557
558 EXPECT_NEAR(original_output, fast_output, 0.01);
559 }

References data, impeller::LerpHackKernelSamples(), impeller::KernelSamples::sample_count, impeller::KernelSamples::samples, and impeller::TPoint< T >::x.

## ◆ TEST() [104/360]

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

Definition at line 1678 of file geometry_unittests.cc.

1678 {
1679 using BlendT = std::underlying_type_t<BlendMode>;
1680 for (BlendT i = 0; i <= static_cast<BlendT>(BlendMode::kLast); i++) {
1681 auto mode = static_cast<BlendMode>(i);
1682 auto result = BlendModeToString(mode);
1683 switch (mode) { IMPELLER_FOR_EACH_BLEND_MODE(_BLEND_MODE_NAME_CHECK) }
1684 }
1685 }

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

## ◆ TEST() [105/360]

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

Definition at line 1687 of file geometry_unittests.cc.

1687 {
1688 {
1689 auto deg = Degrees{90.0};
1690 Radians rad = deg;
1691 ASSERT_FLOAT_EQ(rad.radians, kPiOver2);
1692 }
1693 }

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

## ◆ TEST() [106/360]

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

Definition at line 608 of file geometry_unittests.cc.

608 {
609 {
610 Point p1(1.0, 2.0);
611 IPoint p2 = static_cast<IPoint>(p1);
612 ASSERT_EQ(p2.x, 1u);
613 ASSERT_EQ(p2.y, 2u);
614 }
615
616 {
617 Size s1(1.0, 2.0);
618 ISize s2 = static_cast<ISize>(s1);
619 ASSERT_EQ(s2.width, 1u);
620 ASSERT_EQ(s2.height, 2u);
621 }
622
623 {
624 Size s1(1.0, 2.0);
625 Point p1 = static_cast<Point>(s1);
626 ASSERT_EQ(p1.x, 1u);
627 ASSERT_EQ(p1.y, 2u);
628 }
629 }

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

## ◆ TEST() [107/360]

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

Definition at line 595 of file geometry_unittests.cc.

595 {
596 ASSERT_EQ((Size{128, 128}.MipCount()), 7u);
597 ASSERT_EQ((Size{128, 256}.MipCount()), 8u);
598 ASSERT_EQ((Size{128, 130}.MipCount()), 8u);
599 ASSERT_EQ((Size{128, 257}.MipCount()), 9u);
600 ASSERT_EQ((Size{257, 128}.MipCount()), 9u);
601 ASSERT_EQ((Size{128, 0}.MipCount()), 1u);
602 ASSERT_EQ((Size{128, -25}.MipCount()), 1u);
603 ASSERT_EQ((Size{-128, 25}.MipCount()), 1u);
604 ASSERT_EQ((Size{1, 1}.MipCount()), 1u);
605 ASSERT_EQ((Size{0, 0}.MipCount()), 1u);
606 }

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

## ◆ TEST() [108/360]

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

Definition at line 631 of file geometry_unittests.cc.

631 {
632 {
633 IPoint p1(1, 2);
634 IPoint p2 = p1 + IPoint(1, 2);
635 ASSERT_EQ(p2.x, 2u);
636 ASSERT_EQ(p2.y, 4u);
637 }
638
639 {
640 IPoint p1(3, 6);
641 IPoint p2 = p1 - IPoint(1, 2);
642 ASSERT_EQ(p2.x, 2u);
643 ASSERT_EQ(p2.y, 4u);
644 }
645
646 {
647 IPoint p1(1, 2);
648 IPoint p2 = p1 * IPoint(2, 3);
649 ASSERT_EQ(p2.x, 2u);
650 ASSERT_EQ(p2.y, 6u);
651 }
652
653 {
654 IPoint p1(2, 6);
655 IPoint p2 = p1 / IPoint(2, 3);
656 ASSERT_EQ(p2.x, 1u);
657 ASSERT_EQ(p2.y, 2u);
658 }
659 }

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

## ◆ TEST() [109/360]

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

Definition at line 661 of file geometry_unittests.cc.

661 {
662 // LHS
663 {
664 IPoint p1(1, 2);
665 IPoint p2 = p1 * 2.0f;
666 ASSERT_EQ(p2.x, 2u);
667 ASSERT_EQ(p2.y, 4u);
668 }
669
670 {
671 IPoint p1(2, 6);
672 IPoint p2 = p1 / 2.0f;
673 ASSERT_EQ(p2.x, 1u);
674 ASSERT_EQ(p2.y, 3u);
675 }
676
677 // RHS
678 {
679 IPoint p1(1, 2);
680 IPoint p2 = 2.0f * p1;
681 ASSERT_EQ(p2.x, 2u);
682 ASSERT_EQ(p2.y, 4u);
683 }
684
685 {
686 IPoint p1(2, 6);
687 IPoint p2 = 12.0f / p1;
688 ASSERT_EQ(p2.x, 6u);
689 ASSERT_EQ(p2.y, 2u);
690 }
691 }

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

## ◆ TEST() [110/360]

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

Definition at line 1245 of file geometry_unittests.cc.

1245 {
1246 {
1247 Vector3 p1(1, 2, 3);
1248 Vector3 p2 = p1 + Vector3(1, 2, 3);
1249 ASSERT_EQ(p2.x, 2u);
1250 ASSERT_EQ(p2.y, 4u);
1251 ASSERT_EQ(p2.z, 6u);
1252 }
1253
1254 {
1255 Vector3 p1(3, 6, 9);
1256 Vector3 p2 = p1 - Vector3(1, 2, 3);
1257 ASSERT_EQ(p2.x, 2u);
1258 ASSERT_EQ(p2.y, 4u);
1259 ASSERT_EQ(p2.z, 6u);
1260 }
1261
1262 {
1263 Vector3 p1(1, 2, 3);
1264 Vector3 p2 = p1 * Vector3(2, 3, 4);
1265 ASSERT_EQ(p2.x, 2u);
1266 ASSERT_EQ(p2.y, 6u);
1267 ASSERT_EQ(p2.z, 12u);
1268 }
1269
1270 {
1271 Vector3 p1(2, 6, 12);
1272 Vector3 p2 = p1 / Vector3(2, 3, 4);
1273 ASSERT_EQ(p2.x, 1u);
1274 ASSERT_EQ(p2.y, 2u);
1275 ASSERT_EQ(p2.z, 3u);
1276 }
1277 }

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

## ◆ TEST() [111/360]

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

Definition at line 1279 of file geometry_unittests.cc.

1279 {
1280 // LHS
1281 {
1282 Vector3 p1(1, 2, 3);
1283 Vector3 p2 = p1 + 2.0f;
1284 ASSERT_EQ(p2.x, 3);
1285 ASSERT_EQ(p2.y, 4);
1286 ASSERT_EQ(p2.z, 5);
1287 }
1288
1289 {
1290 Vector3 p1(1, 2, 3);
1291 Vector3 p2 = p1 - 2.0f;
1292 ASSERT_EQ(p2.x, -1);
1293 ASSERT_EQ(p2.y, 0);
1294 ASSERT_EQ(p2.z, 1);
1295 }
1296
1297 {
1298 Vector3 p1(1, 2, 3);
1299 Vector3 p2 = p1 * 2.0f;
1300 ASSERT_EQ(p2.x, 2);
1301 ASSERT_EQ(p2.y, 4);
1302 ASSERT_EQ(p2.z, 6);
1303 }
1304
1305 {
1306 Vector3 p1(2, 6, 12);
1307 Vector3 p2 = p1 / 2.0f;
1308 ASSERT_EQ(p2.x, 1);
1309 ASSERT_EQ(p2.y, 3);
1310 ASSERT_EQ(p2.z, 6);
1311 }
1312
1313 // RHS
1314 {
1315 Vector3 p1(1, 2, 3);
1316 Vector3 p2 = 2.0f + p1;
1317 ASSERT_EQ(p2.x, 3);
1318 ASSERT_EQ(p2.y, 4);
1319 ASSERT_EQ(p2.z, 5);
1320 }
1321
1322 {
1323 Vector3 p1(1, 2, 3);
1324 Vector3 p2 = 2.0f - p1;
1325 ASSERT_EQ(p2.x, 1);
1326 ASSERT_EQ(p2.y, 0);
1327 ASSERT_EQ(p2.z, -1);
1328 }
1329
1330 {
1331 Vector3 p1(1, 2, 3);
1332 Vector3 p2 = 2.0f * p1;
1333 ASSERT_EQ(p2.x, 2);
1334 ASSERT_EQ(p2.y, 4);
1335 ASSERT_EQ(p2.z, 6);
1336 }
1337
1338 {
1339 Vector3 p1(2, 6, 12);
1340 Vector3 p2 = 12.0f / p1;
1341 ASSERT_EQ(p2.x, 6);
1342 ASSERT_EQ(p2.y, 2);
1343 ASSERT_EQ(p2.z, 1);
1344 }
1345 }

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

## ◆ TEST() [112/360]

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

Definition at line 813 of file geometry_unittests.cc.

813 {
814 // Point on RHS
815 {
816 IPoint p(1, 2);
817 p += IPoint(1, 2);
818 ASSERT_EQ(p.x, 2u);
819 ASSERT_EQ(p.y, 4u);
820 }
821
822 {
823 IPoint p(3, 6);
824 p -= IPoint(1, 2);
825 ASSERT_EQ(p.x, 2u);
826 ASSERT_EQ(p.y, 4u);
827 }
828
829 {
830 IPoint p(1, 2);
831 p *= IPoint(2, 3);
832 ASSERT_EQ(p.x, 2u);
833 ASSERT_EQ(p.y, 6u);
834 }
835
836 {
837 IPoint p(2, 6);
838 p /= IPoint(2, 3);
839 ASSERT_EQ(p.x, 1u);
840 ASSERT_EQ(p.y, 2u);
841 }
842
843 // Size on RHS
844 {
845 IPoint p(1, 2);
846 p += ISize(1, 2);
847 ASSERT_EQ(p.x, 2u);
848 ASSERT_EQ(p.y, 4u);
849 }
850
851 {
852 IPoint p(3, 6);
853 p -= ISize(1, 2);
854 ASSERT_EQ(p.x, 2u);
855 ASSERT_EQ(p.y, 4u);
856 }
857
858 {
859 IPoint p(1, 2);
860 p *= ISize(2, 3);
861 ASSERT_EQ(p.x, 2u);
862 ASSERT_EQ(p.y, 6u);
863 }
864
865 {
866 IPoint p(2, 6);
867 p /= ISize(2, 3);
868 ASSERT_EQ(p.x, 1u);
869 ASSERT_EQ(p.y, 2u);
870 }
871
872 // Arithmetic type on RHS
873 {
874 IPoint p(1, 2);
875 p *= 3;
876 ASSERT_EQ(p.x, 3u);
877 ASSERT_EQ(p.y, 6u);
878 }
879
880 {
881 IPoint p(3, 6);
882 p /= 3;
883 ASSERT_EQ(p.x, 1u);
884 ASSERT_EQ(p.y, 2u);
885 }
886 }

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

## ◆ TEST() [113/360]

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

Definition at line 1195 of file geometry_unittests.cc.

1195 {
1196 {
1197 Vector3 p(1, 2, 4);
1198 p += Vector3(1, 2, 4);
1199 ASSERT_EQ(p.x, 2u);
1200 ASSERT_EQ(p.y, 4u);
1201 ASSERT_EQ(p.z, 8u);
1202 }
1203
1204 {
1205 Vector3 p(3, 6, 8);
1206 p -= Vector3(1, 2, 3);
1207 ASSERT_EQ(p.x, 2u);
1208 ASSERT_EQ(p.y, 4u);
1209 ASSERT_EQ(p.z, 5u);
1210 }
1211
1212 {
1213 Vector3 p(1, 2, 3);
1214 p *= Vector3(2, 3, 4);
1215 ASSERT_EQ(p.x, 2u);
1216 ASSERT_EQ(p.y, 6u);
1217 ASSERT_EQ(p.z, 12u);
1218 }
1219
1220 {
1221 Vector3 p(1, 2, 3);
1222 p *= 2;
1223 ASSERT_EQ(p.x, 2u);
1224 ASSERT_EQ(p.y, 4u);
1225 ASSERT_EQ(p.z, 6u);
1226 }
1227
1228 {
1229 Vector3 p(2, 6, 12);
1230 p /= Vector3(2, 3, 4);
1231 ASSERT_EQ(p.x, 1u);
1232 ASSERT_EQ(p.y, 2u);
1233 ASSERT_EQ(p.z, 3u);
1234 }
1235
1236 {
1237 Vector3 p(2, 6, 12);
1238 p /= 2;
1239 ASSERT_EQ(p.x, 1u);
1240 ASSERT_EQ(p.y, 3u);
1241 ASSERT_EQ(p.z, 6u);
1242 }
1243 }

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

## ◆ TEST() [114/360]

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

Definition at line 1452 of file geometry_unittests.cc.

1452 {
1453 {
1454 ColorMatrix color_matrix = {
1455 1, 1, 1, 1, 1, //
1456 1, 1, 1, 1, 1, //
1457 1, 1, 1, 1, 1, //
1458 1, 1, 1, 1, 1, //
1459 };
1460 auto result = Color::White().ApplyColorMatrix(color_matrix);
1461 auto expected = Color(1, 1, 1, 1);
1462 ASSERT_COLOR_NEAR(result, expected);
1463 }
1464
1465 {
1466 ColorMatrix color_matrix = {
1467 0.1, 0, 0, 0, 0.01, //
1468 0, 0.2, 0, 0, 0.02, //
1469 0, 0, 0.3, 0, 0.03, //
1470 0, 0, 0, 0.4, 0.04, //
1471 };
1472 auto result = Color::White().ApplyColorMatrix(color_matrix);
1473 auto expected = Color(0.11, 0.22, 0.33, 0.44);
1474 ASSERT_COLOR_NEAR(result, expected);
1475 }
1476 }

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

## ◆ TEST() [115/360]

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

Definition at line 1661 of file geometry_unittests.cc.

1661 {
1662 Color dst = ColorBlendTestData::kDestinationColor;
1663 for (size_t source_i = 0;
1664 source_i < sizeof(ColorBlendTestData::kSourceColors) / sizeof(Color);
1665 source_i++) {
1666 Color src = ColorBlendTestData::kSourceColors[source_i];
1667
1668 Color expected;
1669 IMPELLER_FOR_EACH_BLEND_MODE(_BLEND_MODE_RESULT_CHECK)
1670 }
1671 }

References _BLEND_MODE_RESULT_CHECK, IMPELLER_FOR_EACH_BLEND_MODE, impeller::testing::ColorBlendTestData::kDestinationColor, and impeller::testing::ColorBlendTestData::kSourceColors.

## ◆ TEST() [116/360]

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

Definition at line 1412 of file geometry_unittests.cc.

1412 {
1413 {
1414 Color result = Color(0.5, 0.5, 0.5, 0.5).Clamp01();
1415 Color expected = Color(0.5, 0.5, 0.5, 0.5);
1416 ASSERT_COLOR_NEAR(result, expected);
1417 }
1418
1419 {
1420 Color result = Color(-1, -1, -1, -1).Clamp01();
1421 Color expected = Color(0, 0, 0, 0);
1422 ASSERT_COLOR_NEAR(result, expected);
1423 }
1424
1425 {
1426 Color result = Color(2, 2, 2, 2).Clamp01();
1427 Color expected = Color(1, 1, 1, 1);
1428 ASSERT_COLOR_NEAR(result, expected);
1429 }
1430 }

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

## ◆ TEST() [117/360]

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

Definition at line 1390 of file geometry_unittests.cc.

1390 {
1391 {
1392 Color a(0.0, 0.0, 0.0, 0.0);
1393 Color b(1.0, 1.0, 1.0, 1.0);
1394
1395 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.5), Color(0.5, 0.5, 0.5, 0.5));
1396 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.0), a);
1397 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 1.0), b);
1398 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.2), Color(0.2, 0.2, 0.2, 0.2));
1399 }
1400
1401 {
1402 Color a(0.2, 0.4, 1.0, 0.5);
1403 Color b(0.4, 1.0, 0.2, 0.3);
1404
1405 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.5), Color(0.3, 0.7, 0.6, 0.4));
1406 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.0), a);
1407 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 1.0), b);
1408 ASSERT_COLOR_NEAR(Color::Lerp(a, b, 0.2), Color(0.24, 0.52, 0.84, 0.46));
1409 }
1410 }

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

## ◆ TEST() [118/360]

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

Definition at line 1478 of file geometry_unittests.cc.

1478 {
1479 {
1480 auto result = Color::White().LinearToSRGB();
1481 auto expected = Color(1, 1, 1, 1);
1482 ASSERT_COLOR_NEAR(result, expected);
1483 }
1484
1485 {
1486 auto result = Color::BlackTransparent().LinearToSRGB();
1487 auto expected = Color(0, 0, 0, 0);
1488 ASSERT_COLOR_NEAR(result, expected);
1489 }
1490
1491 {
1492 auto result = Color(0.2, 0.4, 0.6, 0.8).LinearToSRGB();
1493 auto expected = Color(0.484529, 0.665185, 0.797738, 0.8);
1494 ASSERT_COLOR_NEAR(result, expected);
1495 }
1496 }

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

## ◆ TEST() [119/360]

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

Definition at line 1432 of file geometry_unittests.cc.

1432 {
1433 {
1434 Color a = Color::MakeRGBA8(0, 0, 0, 0);
1435 Color b = Color::BlackTransparent();
1436 ASSERT_COLOR_NEAR(a, b);
1437 }
1438
1439 {
1440 Color a = Color::MakeRGBA8(255, 255, 255, 255);
1441 Color b = Color::White();
1442 ASSERT_COLOR_NEAR(a, b);
1443 }
1444
1445 {
1446 Color a = Color::MakeRGBA8(63, 127, 191, 127);
1447 Color b(0.247059, 0.498039, 0.74902, 0.498039);
1448 ASSERT_COLOR_NEAR(a, b);
1449 }
1450 }

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

## ◆ TEST() [120/360]

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

Definition at line 1347 of file geometry_unittests.cc.

1347 {
1348 {
1349 Color a(1.0, 0.5, 0.2, 0.5);
1350 Color premultiplied = a.Premultiply();
1351 Color expected = Color(0.5, 0.25, 0.1, 0.5);
1352 ASSERT_COLOR_NEAR(premultiplied, expected);
1353 }
1354
1355 {
1356 Color a(0.5, 0.25, 0.1, 0.5);
1357 Color unpremultiplied = a.Unpremultiply();
1358 Color expected = Color(1.0, 0.5, 0.2, 0.5);
1359 ASSERT_COLOR_NEAR(unpremultiplied, expected);
1360 }
1361
1362 {
1363 Color a(0.5, 0.25, 0.1, 0.0);
1364 Color unpremultiplied = a.Unpremultiply();
1365 Color expected = Color(0.0, 0.0, 0.0, 0.0);
1366 ASSERT_COLOR_NEAR(unpremultiplied, expected);
1367 }
1368 }

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

## ◆ TEST() [121/360]

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

Definition at line 1770 of file geometry_unittests.cc.

1770 {
1771 {
1772 std::stringstream stream;
1773 Color m;
1774 stream << m;
1775 ASSERT_EQ(stream.str(), "(0, 0, 0, 0)");
1776 }
1777
1778 {
1779 std::stringstream stream;
1780 Color m(1, 2, 3, 4);
1781 stream << m;
1782 ASSERT_EQ(stream.str(), "(1, 2, 3, 4)");
1783 }
1784 }

## ◆ TEST() [122/360]

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

Definition at line 1370 of file geometry_unittests.cc.

1370 {
1371 {
1372 Color a(1.0, 0.5, 0.2, 0.5);
1373 std::array<uint8_t, 4> expected = {255, 128, 51, 128};
1374 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1375 }
1376
1377 {
1378 Color a(0.0, 0.0, 0.0, 0.0);
1379 std::array<uint8_t, 4> expected = {0, 0, 0, 0};
1380 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1381 }
1382
1383 {
1384 Color a(1.0, 1.0, 1.0, 1.0);
1385 std::array<uint8_t, 4> expected = {255, 255, 255, 255};
1386 ASSERT_ARRAY_4_NEAR(a.ToR8G8B8A8(), expected);
1387 }
1388 }

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

## ◆ TEST() [123/360]

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

Definition at line 1498 of file geometry_unittests.cc.

1498 {
1499 {
1500 auto result = Color::White().SRGBToLinear();
1501 auto expected = Color(1, 1, 1, 1);
1502 ASSERT_COLOR_NEAR(result, expected);
1503 }
1504
1505 {
1506 auto result = Color::BlackTransparent().SRGBToLinear();
1507 auto expected = Color(0, 0, 0, 0);
1508 ASSERT_COLOR_NEAR(result, expected);
1509 }
1510
1511 {
1512 auto result = Color(0.2, 0.4, 0.6, 0.8).SRGBToLinear();
1513 auto expected = Color(0.0331048, 0.132868, 0.318547, 0.8);
1514 ASSERT_COLOR_NEAR(result, expected);
1515 }
1516 }

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

## ◆ TEST() [124/360]

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

Definition at line 121 of file geometry_unittests.cc.

121 {
122 auto matrix = Matrix{3, 4, 14, 155, 2, 1, 3, 4, 2, 3, 2, 1, 1, 2, 4, 2};
123 ASSERT_EQ(matrix.GetDeterminant(), -1889);
124 }

## ◆ TEST() [125/360]

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

Definition at line 1792 of file geometry_unittests.cc.

1792 {
1793 {
1794 // Simple 2 color gradient produces color buffer containing exactly those
1795 // values.
1796 std::vector<Color> colors = {Color::Red(), Color::Blue()};
1797 std::vector<Scalar> stops = {0.0, 1.0};
1798
1799 auto gradient = CreateGradientBuffer(colors, stops);
1800
1801 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, colors);
1802 ASSERT_EQ(gradient.texture_size, 2u);
1803 }
1804
1805 {
1806 // Gradient with duplicate stops does not create an empty texture.
1807 std::vector<Color> colors = {Color::Red(), Color::Yellow(), Color::Black(),
1808 Color::Blue()};
1809 std::vector<Scalar> stops = {0.0, 0.25, 0.25, 1.0};
1810
1811 auto gradient = CreateGradientBuffer(colors, stops);
1812 ASSERT_EQ(gradient.texture_size, 5u);
1813 }
1814
1815 {
1816 // Simple N color gradient produces color buffer containing exactly those
1817 // values.
1818 std::vector<Color> colors = {Color::Red(), Color::Blue(), Color::Green(),
1819 Color::White()};
1820 std::vector<Scalar> stops = {0.0, 0.33, 0.66, 1.0};
1821
1822 auto gradient = CreateGradientBuffer(colors, stops);
1823
1824 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, colors);
1825 ASSERT_EQ(gradient.texture_size, 4u);
1826 }
1827
1828 {
1829 // Gradient with color stops will lerp and scale buffer.
1830 std::vector<Color> colors = {Color::Red(), Color::Blue(), Color::Green()};
1831 std::vector<Scalar> stops = {0.0, 0.25, 1.0};
1832
1833 auto gradient = CreateGradientBuffer(colors, stops);
1834
1835 std::vector<Color> lerped_colors = {
1836 Color::Red(),
1837 Color::Blue(),
1838 Color::Lerp(Color::Blue(), Color::Green(), 0.3333),
1839 Color::Lerp(Color::Blue(), Color::Green(), 0.6666),
1840 Color::Green(),
1841 };
1842 ASSERT_COLOR_BUFFER_NEAR(gradient.color_bytes, lerped_colors);
1843 ASSERT_EQ(gradient.texture_size, 5u);
1844 }
1845
1846 {
1847 // Gradient size is capped at 1024.
1848 std::vector<Color> colors = {};
1849 std::vector<Scalar> stops = {};
1850 for (auto i = 0u; i < 1025; i++) {
1851 colors.push_back(Color::Blue());
1852 stops.push_back(i / 1025.0);
1853 }
1854
1855 auto gradient = CreateGradientBuffer(colors, stops);
1856
1857 ASSERT_EQ(gradient.texture_size, 1024u);
1858 ASSERT_EQ(gradient.color_bytes.size(), 1024u * 4);
1859 }
1860 }

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() [126/360]

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

Definition at line 1862 of file geometry_unittests.cc.

1862 {
1863 #if defined(FML_OS_MACOSX) || defined(FML_OS_IOS) || \
1864 defined(FML_OS_IOS_SIMULATOR)
1865 ASSERT_EQ(ScalarToHalf(0.0), 0.0f16);
1866 ASSERT_EQ(ScalarToHalf(0.05), 0.05f16);
1867 ASSERT_EQ(ScalarToHalf(2.43), 2.43f16);
1868 ASSERT_EQ(ScalarToHalf(-1.45), -1.45f16);
1869
1870 // 65504 is the largest possible half.
1871 ASSERT_EQ(ScalarToHalf(65504.0f), 65504.0f16);
1872 ASSERT_EQ(ScalarToHalf(65504.0f + 1), 65504.0f16);
1873
1874 // Colors
1875 ASSERT_EQ(HalfVector4(Color::Red()),
1876 HalfVector4(1.0f16, 0.0f16, 0.0f16, 1.0f16));
1877 ASSERT_EQ(HalfVector4(Color::Green()),
1878 HalfVector4(0.0f16, 1.0f16, 0.0f16, 1.0f16));
1879 ASSERT_EQ(HalfVector4(Color::Blue()),
1880 HalfVector4(0.0f16, 0.0f16, 1.0f16, 1.0f16));
1881 ASSERT_EQ(HalfVector4(Color::Black().WithAlpha(0)),
1882 HalfVector4(0.0f16, 0.0f16, 0.0f16, 0.0f16));
1883
1884 ASSERT_EQ(HalfVector3(Vector3(4.0, 6.0, -1.0)),
1885 HalfVector3(4.0f16, 6.0f16, -1.0f16));
1886 ASSERT_EQ(HalfVector2(Vector2(4.0, 6.0)), HalfVector2(4.0f16, 6.0f16));
1887
1888 ASSERT_EQ(Half(0.5f), Half(0.5f16));
1889 ASSERT_EQ(Half(0.5), Half(0.5f16));
1890 ASSERT_EQ(Half(5), Half(5.0f16));
1891 #else
1892 GTEST_SKIP() << "Half-precision floats (IEEE 754) are not portable and "
1893 "only used on Apple platforms.";
1894 #endif // FML_OS_MACOSX || FML_OS_IOS || FML_OS_IOS_SIMULATOR
1895 }

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

## ◆ TEST() [127/360]

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

Definition at line 126 of file geometry_unittests.cc.

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

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

## ◆ TEST() [128/360]

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

Definition at line 79 of file geometry_unittests.cc.

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

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

## ◆ TEST() [129/360]

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

Definition at line 40 of file geometry_unittests.cc.

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

References impeller::Matrix::MakeColumn().

## ◆ TEST() [130/360]

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

Definition at line 54 of file geometry_unittests.cc.

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

References impeller::Matrix::MakeRow().

## ◆ TEST() [131/360]

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

Definition at line 102 of file geometry_unittests.cc.

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

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

## ◆ TEST() [132/360]

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

Definition at line 423 of file geometry_unittests.cc.

423 {
424 {
425 auto m = Matrix();
426 Vector3 x = m.GetBasisX();
427 Vector3 y = m.GetBasisY();
428 Vector3 z = m.GetBasisZ();
429 ASSERT_VECTOR3_NEAR(x, Vector3(1, 0, 0));
430 ASSERT_VECTOR3_NEAR(y, Vector3(0, 1, 0));
431 ASSERT_VECTOR3_NEAR(z, Vector3(0, 0, 1));
432 }
433
434 {
435 auto m = Matrix::MakeRotationZ(Radians{kPiOver2}) *
436 Matrix::MakeRotationX(Radians{kPiOver2}) *
437 Matrix::MakeScale(Vector3(2, 3, 4));
438 Vector3 x = m.GetBasisX();
439 Vector3 y = m.GetBasisY();
440 Vector3 z = m.GetBasisZ();
441 ASSERT_VECTOR3_NEAR(x, Vector3(0, 2, 0));
442 ASSERT_VECTOR3_NEAR(y, Vector3(0, 0, 3));
443 ASSERT_VECTOR3_NEAR(z, Vector3(4, 0, 0));
444 }
445 }

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

## ◆ TEST() [133/360]

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

Definition at line 447 of file geometry_unittests.cc.

447 {
448 {
449 auto m = Matrix();
450 Scalar result = m.GetDirectionScale(Vector3{1, 0, 0});
451 ASSERT_FLOAT_EQ(result, 1);
452 }
453
454 {
455 auto m = Matrix::MakeRotationX(Degrees{10}) *
456 Matrix::MakeRotationY(Degrees{83}) *
457 Matrix::MakeRotationZ(Degrees{172});
458 Scalar result = m.GetDirectionScale(Vector3{0, 1, 0});
459 ASSERT_FLOAT_EQ(result, 1);
460 }
461
462 {
463 auto m = Matrix::MakeRotationZ(Radians{kPiOver2}) *
464 Matrix::MakeScale(Vector3(3, 4, 5));
465 Scalar result = m.GetDirectionScale(Vector3{2, 0, 0});
466 ASSERT_FLOAT_EQ(result, 8);
467 }
468 }

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

## ◆ TEST() [134/360]

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

Definition at line 333 of file geometry_unittests.cc.

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

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

## ◆ TEST() [135/360]

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

Definition at line 348 of file geometry_unittests.cc.

348 {
349 {
350 auto m = Matrix::MakeScale({3, 1, 1});
351 ASSERT_EQ(m.GetMaxBasisLengthXY(), 3);
352
353 m = m * Matrix::MakeSkew(0, 4);
354 ASSERT_EQ(m.GetMaxBasisLengthXY(), 5);
355 }
356
357 {
358 auto m = Matrix::MakeScale({-3, 4, 7});
359 ASSERT_EQ(m.GetMaxBasisLengthXY(), 4);
360 }
361
362 {
363 // clang-format off
364 auto m = Matrix::MakeColumn(
365 1.0f, 0.0f, 0.0f, 0.0f,
366 0.0f, 1.0f, 0.0f, 0.0f,
367 4.0f, 0.0f, 1.0f, 0.0f,
368 0.0f, 0.0f, 0.0f, 1.0f
369 );
370 // clang-format on
371 ASSERT_EQ(m.GetMaxBasisLengthXY(), 1.0f);
372 }
373 }

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

## ◆ TEST() [136/360]

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

Definition at line 496 of file geometry_unittests.cc.

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

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

## ◆ TEST() [137/360]

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

Definition at line 375 of file geometry_unittests.cc.

375 {
376 {
377 auto m = Matrix::MakeOrthographic(Size(100, 200));
378 auto expect = Matrix{
379 0.02, 0, 0, 0, //
380 0, -0.01, 0, 0, //
381 0, 0, 0, 0, //
382 -1, 1, 0.5, 1, //
383 };
384 ASSERT_MATRIX_NEAR(m, expect);
385 }
386
387 {
388 auto m = Matrix::MakeOrthographic(Size(400, 100));
389 auto expect = Matrix{
390 0.005, 0, 0, 0, //
391 0, -0.02, 0, 0, //
392 0, 0, 0, 0, //
393 -1, 1, 0.5, 1, //
394 };
395 ASSERT_MATRIX_NEAR(m, expect);
396 }
397 }

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

## ◆ TEST() [138/360]

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

Definition at line 399 of file geometry_unittests.cc.

399 {
400 {
401 auto m = Matrix::MakePerspective(Degrees(60), Size(100, 200), 1, 10);
402 auto expect = Matrix{
403 3.4641, 0, 0, 0, //
404 0, 1.73205, 0, 0, //
405 0, 0, 1.11111, 1, //
406 0, 0, -1.11111, 0, //
407 };
408 ASSERT_MATRIX_NEAR(m, expect);
409 }
410
411 {
412 auto m = Matrix::MakePerspective(Radians(1), 2, 10, 20);
413 auto expect = Matrix{
414 0.915244, 0, 0, 0, //
415 0, 1.83049, 0, 0, //
416 0, 0, 2, 1, //
417 0, 0, -20, 0, //
418 };
419 ASSERT_MATRIX_NEAR(m, expect);
420 }
421 }

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

## ◆ TEST() [139/360]

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

Definition at line 278 of file geometry_unittests.cc.

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

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

## ◆ TEST() [140/360]

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

Definition at line 1695 of file geometry_unittests.cc.

1695 {
1696 {
1697 std::stringstream stream;
1698 Matrix m;
1699 stream << m;
1700 ASSERT_EQ(stream.str(), R"((
1701 1.000000, 0.000000, 0.000000, 0.000000,
1702 0.000000, 1.000000, 0.000000, 0.000000,
1703 0.000000, 0.000000, 1.000000, 0.000000,
1704 0.000000, 0.000000, 0.000000, 1.000000,
1705 ))");
1706 }
1707
1708 {
1709 std::stringstream stream;
1710 Matrix m = Matrix::MakeTranslation(Vector3(10, 20, 30));
1711 stream << m;
1712
1713 ASSERT_EQ(stream.str(), R"((
1714 1.000000, 0.000000, 0.000000, 10.000000,
1715 0.000000, 1.000000, 0.000000, 20.000000,
1716 0.000000, 0.000000, 1.000000, 30.000000,
1717 0.000000, 0.000000, 0.000000, 1.000000,
1718 ))");
1719 }
1720 }

References impeller::Matrix::MakeTranslation().

## ◆ TEST() [141/360]

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

Definition at line 298 of file geometry_unittests.cc.

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

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

## ◆ TEST() [142/360]

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

Definition at line 470 of file geometry_unittests.cc.

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

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

## ◆ TEST() [143/360]

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

Definition at line 213 of file geometry_unittests.cc.

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

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() [144/360]

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

Definition at line 115 of file geometry_unittests.cc.

115 {
116 auto rotation = Matrix::MakeRotationZ(Radians{kPiOver4});
117 auto invert = rotation.Invert();
118 ASSERT_MATRIX_NEAR(rotation * invert, Matrix{});
119 }

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

## ◆ TEST() [145/360]

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

Definition at line 953 of file geometry_unittests.cc.

953 {
954 Point a(-1, -2);
955 auto a_abs = a.Abs();
956 auto expected = Point(1, 2);
957 ASSERT_POINT_NEAR(a_abs, expected);
958 }

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

## ◆ TEST() [146/360]

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

Definition at line 990 of file geometry_unittests.cc.

990 {
991 // Negative result in the CCW (with up = -Y) direction.
992 {
993 Point a(1, 1);
994 Point b(1, -1);
995 Radians actual = a.AngleTo(b);
996 Radians expected = Radians{-kPi / 2};
997 ASSERT_FLOAT_EQ(actual.radians, expected.radians);
998 }
999
1000 // Check the other direction to ensure the result is signed correctly.
1001 {
1002 Point a(1, -1);
1003 Point b(1, 1);
1004 Radians actual = a.AngleTo(b);
1005 Radians expected = Radians{kPi / 2};
1006 ASSERT_FLOAT_EQ(actual.radians, expected.radians);
1007 }
1008
1009 // Differences in magnitude should have no impact on the result.
1010 {
1011 Point a(100, -100);
1012 Point b(0.01, 0.01);
1013 Radians actual = a.AngleTo(b);
1014 Radians expected = Radians{kPi / 2};
1015 ASSERT_FLOAT_EQ(actual.radians, expected.radians);
1016 }
1017 }

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

## ◆ TEST() [147/360]

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

Definition at line 1082 of file geometry_unittests.cc.

1082 {
1083 Point p(1.5, 2.3);
1084 Point result = p.Ceil();
1085 Point expected(2, 3);
1086 ASSERT_POINT_NEAR(result, expected);
1087 }

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

## ◆ TEST() [148/360]

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

Definition at line 908 of file geometry_unittests.cc.

908 {
909 {
910 Point p(1, 0);
911 Scalar s = p.Cross(Point(-1, 0));
912 ASSERT_FLOAT_EQ(s, 0);
913 }
914
915 {
916 Point p(0, -1);
917 Scalar s = p.Cross(Point(-1, 0));
918 ASSERT_FLOAT_EQ(s, -1);
919 }
920
921 {
922 Point p(1, 2);
923 Scalar s = p.Cross(Point(3, -4));
924 ASSERT_FLOAT_EQ(s, -10);
925 }
926 }

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

## ◆ TEST() [149/360]

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

Definition at line 888 of file geometry_unittests.cc.

888 {
889 {
890 Point p(1, 0);
891 Scalar s = p.Dot(Point(-1, 0));
892 ASSERT_FLOAT_EQ(s, -1);
893 }
894
895 {
896 Point p(0, -1);
897 Scalar s = p.Dot(Point(-1, 0));
898 ASSERT_FLOAT_EQ(s, 0);
899 }
900
901 {
902 Point p(1, 2);
903 Scalar s = p.Dot(Point(3, -4));
904 ASSERT_FLOAT_EQ(s, -5);
905 }
906 }

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

## ◆ TEST() [150/360]

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

Definition at line 1061 of file geometry_unittests.cc.

1061 {
1062 Point p(1.5, 2.3);
1063 Point result = p.Floor();
1064 Point expected(1, 2);
1065 ASSERT_POINT_NEAR(result, expected);
1066 }

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

## ◆ TEST() [151/360]

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

Definition at line 693 of file geometry_unittests.cc.

693 {
694 // Integer on LHS, float on RHS
695 {
696 IPoint p1(1, 2);
697 Point p2 = p1 + Point(1, 2);
698 ASSERT_FLOAT_EQ(p2.x, 2u);
699 ASSERT_FLOAT_EQ(p2.y, 4u);
700 }
701
702 {
703 IPoint p1(3, 6);
704 Point p2 = p1 - Point(1, 2);
705 ASSERT_FLOAT_EQ(p2.x, 2u);
706 ASSERT_FLOAT_EQ(p2.y, 4u);
707 }
708
709 {
710 IPoint p1(1, 2);
711 Point p2 = p1 * Point(2, 3);
712 ASSERT_FLOAT_EQ(p2.x, 2u);
713 ASSERT_FLOAT_EQ(p2.y, 6u);
714 }
715
716 {
717 IPoint p1(2, 6);
718 Point p2 = p1 / Point(2, 3);
719 ASSERT_FLOAT_EQ(p2.x, 1u);
720 ASSERT_FLOAT_EQ(p2.y, 2u);
721 }
722
723 // Float on LHS, integer on RHS
724 {
725 Point p1(1, 2);
726 Point p2 = p1 + IPoint(1, 2);
727 ASSERT_FLOAT_EQ(p2.x, 2u);
728 ASSERT_FLOAT_EQ(p2.y, 4u);
729 }
730
731 {
732 Point p1(3, 6);
733 Point p2 = p1 - IPoint(1, 2);
734 ASSERT_FLOAT_EQ(p2.x, 2u);
735 ASSERT_FLOAT_EQ(p2.y, 4u);
736 }
737
738 {
739 Point p1(1, 2);
740 Point p2 = p1 * IPoint(2, 3);
741 ASSERT_FLOAT_EQ(p2.x, 2u);
742 ASSERT_FLOAT_EQ(p2.y, 6u);
743 }
744
745 {
746 Point p1(2, 6);
747 Point p2 = p1 / IPoint(2, 3);
748 ASSERT_FLOAT_EQ(p2.x, 1u);
749 ASSERT_FLOAT_EQ(p2.y, 2u);
750 }
751 }

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

## ◆ TEST() [152/360]

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

Definition at line 1124 of file geometry_unittests.cc.

1124 {
1125 Point p(1, 2);
1126 Point result = p.Lerp({5, 10}, 0.75);
1127 Point expected(4, 8);
1128 ASSERT_POINT_NEAR(result, expected);
1129 }

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

## ◆ TEST() [153/360]

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

Definition at line 1040 of file geometry_unittests.cc.

1040 {
1041 Point p(1, 2);
1042 Point result = p.Max({0, 10});
1043 Point expected(1, 10);
1044 ASSERT_POINT_NEAR(result, expected);
1045 }

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

## ◆ TEST() [154/360]

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

Definition at line 1019 of file geometry_unittests.cc.

1019 {
1020 Point p(1, 2);
1021 Point result = p.Min({0, 10});
1022 Point expected(0, 2);
1023 ASSERT_POINT_NEAR(result, expected);
1024 }

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

## ◆ TEST() [155/360]

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

Definition at line 1722 of file geometry_unittests.cc.

1722 {
1723 {
1724 std::stringstream stream;
1725 Point m;
1726 stream << m;
1727 ASSERT_EQ(stream.str(), "(0, 0)");
1728 }
1729
1730 {
1731 std::stringstream stream;
1732 Point m(13, 37);
1733 stream << m;
1734 ASSERT_EQ(stream.str(), "(13, 37)");
1735 }
1736 }

## ◆ TEST() [156/360]

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

Definition at line 928 of file geometry_unittests.cc.

928 {
929 {
930 Point axis = Point(0, 1);
931 Point a(2, 3);
932 auto reflected = a.Reflect(axis);
933 auto expected = Point(2, -3);
934 ASSERT_POINT_NEAR(reflected, expected);
935 }
936
937 {
938 Point axis = Point(1, 1).Normalize();
939 Point a(1, 0);
940 auto reflected = a.Reflect(axis);
941 auto expected = Point(0, -1);
942 ASSERT_POINT_NEAR(reflected, expected);
943 }
944
945 {
946 Point axis = Point(1, 1).Normalize();
947 Point a(-1, -1);
948 auto reflected = a.Reflect(axis);
949 ASSERT_POINT_NEAR(reflected, -a);
950 }
951 }

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

## ◆ TEST() [157/360]

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

Definition at line 960 of file geometry_unittests.cc.

960 {
961 {
962 Point a(1, 0);
963 auto rotated = a.Rotate(Radians{kPiOver2});
964 auto expected = Point(0, 1);
965 ASSERT_POINT_NEAR(rotated, expected);
966 }
967
968 {
969 Point a(1, 0);
970 auto rotated = a.Rotate(Radians{-kPiOver2});
971 auto expected = Point(0, -1);
972 ASSERT_POINT_NEAR(rotated, expected);
973 }
974
975 {
976 Point a(1, 0);
977 auto rotated = a.Rotate(Radians{kPi});
978 auto expected = Point(-1, 0);
979 ASSERT_POINT_NEAR(rotated, expected);
980 }
981
982 {
983 Point a(1, 0);
984 auto rotated = a.Rotate(Radians{kPi * 1.5});
985 auto expected = Point(0, -1);
986 ASSERT_POINT_NEAR(rotated, expected);
987 }
988 }

References ASSERT_POINT_NEAR, impeller::kPi, impeller::kPiOver2, and impeller::TPoint< T >::Rotate().

## ◆ TEST() [158/360]

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

Definition at line 1103 of file geometry_unittests.cc.

1103 {
1104 Point p(1.5, 2.3);
1105 Point result = p.Round();
1106 Point expected(2, 2);
1107 ASSERT_POINT_NEAR(result, expected);
1108 }

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

## ◆ TEST() [159/360]

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

Definition at line 542 of file geometry_unittests.cc.

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

References ASSERT_QUATERNION_NEAR, and impeller::kPiOver4.

## ◆ TEST() [160/360]

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

Definition at line 553 of file geometry_unittests.cc.

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

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

## ◆ TEST() [161/360]

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

Definition at line 68 of file geometry_unittests.cc.

68 {
69 auto rotation = Matrix::MakeRotationZ(Radians{kPiOver4});
70 // clang-format off
71 auto expect = Matrix{k1OverSqrt2, k1OverSqrt2, 0, 0,
72 -k1OverSqrt2, k1OverSqrt2, 0, 0,
73 0, 0, 1, 0,
74 0, 0, 0, 1};
75 // clang-format on
76 ASSERT_MATRIX_NEAR(rotation, expect);
77 }

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

## ◆ TEST() [162/360]

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

Definition at line 31 of file geometry_unittests.cc.

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

References impeller::ScalarNearlyEqual().

## ◆ TEST() [163/360]

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

Definition at line 1179 of file geometry_unittests.cc.

1179 {
1180 {
1181 SeparatedVector2 v(Vector2(10, 0));
1182 Radians actual = v.AngleTo(SeparatedVector2(Vector2(5, 0)));
1183 Radians expected = Radians{0};
1184 ASSERT_NEAR(actual.radians, expected.radians, kEhCloseEnough);
1185 }
1186
1187 {
1188 SeparatedVector2 v(Vector2(10, 0));
1189 Radians actual = v.AngleTo(SeparatedVector2(Vector2(0, -5)));
1190 Radians expected = Radians{-kPi / 2};
1191 ASSERT_NEAR(actual.radians, expected.radians, kEhCloseEnough);
1192 }
1193 }

References impeller::SeparatedVector2::AngleTo(), impeller::kEhCloseEnough, impeller::kPi, and impeller::Radians::radians.

## ◆ TEST() [164/360]

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

Definition at line 1156 of file geometry_unittests.cc.

1156 {
1157 // Parallel
1158 {
1159 SeparatedVector2 v(Vector2(10, 0));
1160 Scalar actual = v.GetAlignment(SeparatedVector2(Vector2(5, 0)));
1161 ASSERT_NEAR(actual, 1, kEhCloseEnough);
1162 }
1163
1164 // Perpendicular
1165 {
1166 SeparatedVector2 v(Vector2(10, 0));
1167 Scalar actual = v.GetAlignment(SeparatedVector2(Vector2(0, 5)));
1168 ASSERT_NEAR(actual, 0, kEhCloseEnough);
1169 }
1170
1171 // Opposite parallel
1172 {
1173 SeparatedVector2 v(Vector2(0, 10));
1174 Scalar actual = v.GetAlignment(SeparatedVector2(Vector2(0, -5)));
1175 ASSERT_NEAR(actual, -1, kEhCloseEnough);
1176 }
1177 }

References impeller::SeparatedVector2::GetAlignment(), and impeller::kEhCloseEnough.

## ◆ TEST() [165/360]

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

Definition at line 1151 of file geometry_unittests.cc.

1151 {
1152 SeparatedVector2 v(Vector2(10, 0));
1153 ASSERT_POINT_NEAR(v.GetVector(), Vector2(10, 0));
1154 }

References ASSERT_POINT_NEAR, and impeller::SeparatedVector2::GetVector().

## ◆ TEST() [166/360]

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

Definition at line 1145 of file geometry_unittests.cc.

1145 {
1146 SeparatedVector2 v(Vector2(10, 0));
1147 ASSERT_POINT_NEAR(v.direction, Vector2(1, 0));
1148 ASSERT_NEAR(v.magnitude, 10, kEhCloseEnough);
1149 }

References ASSERT_POINT_NEAR, impeller::SeparatedVector2::direction, impeller::kEhCloseEnough, and impeller::SeparatedVector2::magnitude.

## ◆ TEST() [167/360]

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

Definition at line 753 of file geometry_unittests.cc.

753 {
754 // Point on LHS, Size on RHS
755 {
756 IPoint p1(1, 2);
757 IPoint p2 = p1 + ISize(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 - ISize(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 * ISize(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 / ISize(2, 3);
779 ASSERT_EQ(p2.x, 1u);
780 ASSERT_EQ(p2.y, 2u);
781 }
782
783 // Size on LHS, Point on RHS
784 {
785 ISize p1(1, 2);
786 IPoint p2 = p1 + IPoint(1, 2);
787 ASSERT_EQ(p2.x, 2u);
788 ASSERT_EQ(p2.y, 4u);
789 }
790
791 {
792 ISize p1(3, 6);
793 IPoint p2 = p1 - IPoint(1, 2);
794 ASSERT_EQ(p2.x, 2u);
795 ASSERT_EQ(p2.y, 4u);
796 }
797
798 {
799 ISize p1(1, 2);
800 IPoint p2 = p1 * IPoint(2, 3);
801 ASSERT_EQ(p2.x, 2u);
802 ASSERT_EQ(p2.y, 6u);
803 }
804
805 {
806 ISize p1(2, 6);
807 IPoint p2 = p1 / IPoint(2, 3);
808 ASSERT_EQ(p2.x, 1u);
809 ASSERT_EQ(p2.y, 2u);
810 }
811 }

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

## ◆ TEST() [168/360]

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

Definition at line 142 of file geometry_unittests.cc.

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

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

## ◆ TEST() [169/360]

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

Definition at line 155 of file geometry_unittests.cc.

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

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() [170/360]

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

Definition at line 179 of file geometry_unittests.cc.

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

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

## ◆ TEST() [171/360]

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

Definition at line 201 of file geometry_unittests.cc.

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

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

## ◆ TEST() [172/360]

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

Definition at line 1786 of file geometry_unittests.cc.

1786 {
1787 ASSERT_EQ(Color::ToIColor(Color(0, 0, 0, 0)), 0u);
1788 ASSERT_EQ(Color::ToIColor(Color(1.0, 1.0, 1.0, 1.0)), 0xFFFFFFFF);
1789 ASSERT_EQ(Color::ToIColor(Color(0.5, 0.5, 1.0, 1.0)), 0xFF8080FF);
1790 }

References impeller::Color::ToIColor().

## ◆ TEST() [173/360]

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

Definition at line 1089 of file geometry_unittests.cc.

1089 {
1090 Vector3 p(1.5, 2.3, 3.9);
1091 Vector3 result = p.Ceil();
1092 Vector3 expected(2, 3, 4);
1093 ASSERT_VECTOR3_NEAR(result, expected);
1094 }

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

## ◆ TEST() [174/360]

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

Definition at line 1068 of file geometry_unittests.cc.

1068 {
1069 Vector3 p(1.5, 2.3, 3.9);
1070 Vector3 result = p.Floor();
1071 Vector3 expected(1, 2, 3);
1072 ASSERT_VECTOR3_NEAR(result, expected);
1073 }

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

## ◆ TEST() [175/360]

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

Definition at line 1131 of file geometry_unittests.cc.

1131 {
1132 Vector3 p(1, 2, 3);
1133 Vector3 result = p.Lerp({5, 10, 15}, 0.75);
1134 Vector3 expected(4, 8, 12);
1135 ASSERT_VECTOR3_NEAR(result, expected);
1136 }

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

## ◆ TEST() [176/360]

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

Definition at line 1047 of file geometry_unittests.cc.

1047 {
1048 Vector3 p(1, 2, 3);
1049 Vector3 result = p.Max({0, 10, 2});
1050 Vector3 expected(1, 10, 3);
1051 ASSERT_VECTOR3_NEAR(result, expected);
1052 }

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

## ◆ TEST() [177/360]

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

Definition at line 1026 of file geometry_unittests.cc.

1026 {
1027 Vector3 p(1, 2, 3);
1028 Vector3 result = p.Min({0, 10, 2});
1029 Vector3 expected(0, 2, 2);
1030 ASSERT_VECTOR3_NEAR(result, expected);
1031 }

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

## ◆ TEST() [178/360]

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

Definition at line 1738 of file geometry_unittests.cc.

1738 {
1739 {
1740 std::stringstream stream;
1741 Vector3 m;
1742 stream << m;
1743 ASSERT_EQ(stream.str(), "(0, 0, 0)");
1744 }
1745
1746 {
1747 std::stringstream stream;
1748 Vector3 m(1, 2, 3);
1749 stream << m;
1750 ASSERT_EQ(stream.str(), "(1, 2, 3)");
1751 }
1752 }

## ◆ TEST() [179/360]

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

Definition at line 1110 of file geometry_unittests.cc.

1110 {
1111 Vector3 p(1.5, 2.3, 3.9);
1112 Vector3 result = p.Round();
1113 Vector3 expected(2, 2, 4);
1114 ASSERT_VECTOR3_NEAR(result, expected);
1115 }

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

## ◆ TEST() [180/360]

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

Definition at line 1096 of file geometry_unittests.cc.

1096 {
1097 Vector4 p(1.5, 2.3, 3.9, 4.0);
1098 Vector4 result = p.Ceil();
1099 Vector4 expected(2, 3, 4, 4);
1100 ASSERT_VECTOR4_NEAR(result, expected);
1101 }

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

## ◆ TEST() [181/360]

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

Definition at line 1075 of file geometry_unittests.cc.

1075 {
1076 Vector4 p(1.5, 2.3, 3.9, 4.0);
1077 Vector4 result = p.Floor();
1078 Vector4 expected(1, 2, 3, 4);
1079 ASSERT_VECTOR4_NEAR(result, expected);
1080 }

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

## ◆ TEST() [182/360]

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

Definition at line 1138 of file geometry_unittests.cc.

1138 {
1139 Vector4 p(1, 2, 3, 4);
1140 Vector4 result = p.Lerp({5, 10, 15, 20}, 0.75);
1141 Vector4 expected(4, 8, 12, 16);
1142 ASSERT_VECTOR4_NEAR(result, expected);
1143 }

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

## ◆ TEST() [183/360]

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

Definition at line 1054 of file geometry_unittests.cc.

1054 {
1055 Vector4 p(1, 2, 3, 4);
1056 Vector4 result = p.Max({0, 10, 2, 1});
1057 Vector4 expected(1, 10, 3, 4);
1058 ASSERT_VECTOR4_NEAR(result, expected);
1059 }

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

## ◆ TEST() [184/360]

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

Definition at line 1033 of file geometry_unittests.cc.

1033 {
1034 Vector4 p(1, 2, 3, 4);
1035 Vector4 result = p.Min({0, 10, 2, 1});
1036 Vector4 expected(0, 2, 2, 1);
1037 ASSERT_VECTOR4_NEAR(result, expected);
1038 }

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

## ◆ TEST() [185/360]

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

Definition at line 1754 of file geometry_unittests.cc.

1754 {
1755 {
1756 std::stringstream stream;
1757 Vector4 m;
1758 stream << m;
1759 ASSERT_EQ(stream.str(), "(0, 0, 0, 1)");
1760 }
1761
1762 {
1763 std::stringstream stream;
1764 Vector4 m(1, 2, 3, 4);
1765 stream << m;
1766 ASSERT_EQ(stream.str(), "(1, 2, 3, 4)");
1767 }
1768 }

## ◆ TEST() [186/360]

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

Definition at line 1117 of file geometry_unittests.cc.

1117 {
1118 Vector4 p(1.5, 2.3, 3.9, 4.0);
1119 Vector4 result = p.Round();
1120 Vector4 expected(2, 2, 4, 4);
1121 ASSERT_VECTOR4_NEAR(result, expected);
1122 }

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

## ◆ TEST() [187/360]

impeller::testing::TEST | ( | MatrixFilterContentsTest | ,
|  | Coverage2x |
| ) |  |

Definition at line 70 of file matrix_filter_contents_unittests.cc.

70 {
71 MatrixFilterContents contents;
72 contents.SetMatrix(Matrix::MakeScale({2.0, 2.0, 1.0}));
73 FilterInput::Vector inputs = {
74 FilterInput::Make(Rect::MakeXYWH(10, 10, 100, 100))};
75 Entity entity;
76 std::optional<Rect> coverage =
77 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
78
79 ASSERT_EQ(coverage, Rect::MakeXYWH(20, 20, 200, 200));
80 }

References impeller::MatrixFilterContents::GetFilterCoverage(), impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::MatrixFilterContents::SetMatrix().

## ◆ TEST() [188/360]

impeller::testing::TEST | ( | MatrixFilterContentsTest | ,
|  | Coverage2xEffect |
| ) |  |

Definition at line 82 of file matrix_filter_contents_unittests.cc.

82 {
83 MatrixFilterContents contents;
84 FilterInput::Vector inputs = {
85 FilterInput::Make(Rect::MakeXYWH(10, 10, 100, 100))};
86 Entity entity;
87 std::optional<Rect> coverage = contents.GetFilterCoverage(
88 inputs, entity, /*effect_transform=*/Matrix::MakeScale({2.0, 2.0, 1.0}));
89
90 ASSERT_EQ(coverage, Rect::MakeXYWH(10, 10, 100, 100));
91 }

References impeller::MatrixFilterContents::GetFilterCoverage(), impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [189/360]

impeller::testing::TEST | ( | MatrixFilterContentsTest | ,
|  | CoverageEmpty |
| ) |  |

Definition at line 50 of file matrix_filter_contents_unittests.cc.

50 {
51 MatrixFilterContents contents;
52 FilterInput::Vector inputs = {};
53 Entity entity;
54 std::optional<Rect> coverage =
55 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
56 ASSERT_FALSE(coverage.has_value());
57 }

References impeller::MatrixFilterContents::GetFilterCoverage().

## ◆ TEST() [190/360]

impeller::testing::TEST | ( | MatrixFilterContentsTest | ,
|  | CoverageSimple |
| ) |  |

Definition at line 59 of file matrix_filter_contents_unittests.cc.

59 {
60 MatrixFilterContents contents;
61 FilterInput::Vector inputs = {
62 FilterInput::Make(Rect::MakeLTRB(10, 10, 110, 110))};
63 Entity entity;
64 std::optional<Rect> coverage =
65 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
66
67 ASSERT_EQ(coverage, Rect::MakeLTRB(10, 10, 110, 110));
68 }

References impeller::MatrixFilterContents::GetFilterCoverage(), impeller::FilterInput::Make(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [191/360]

impeller::testing::TEST | ( | MatrixFilterContentsTest | ,
|  | Create |
| ) |  |

Definition at line 45 of file matrix_filter_contents_unittests.cc.

45 {
46 MatrixFilterContents contents;
47 EXPECT_TRUE(contents.IsTranslationOnly());
48 }

References impeller::MatrixFilterContents::IsTranslationOnly().

## ◆ TEST() [192/360]

impeller::testing::TEST | ( | MatrixTest | ,
|  | HasPerspective |
| ) |  |

Definition at line 45 of file matrix_unittests.cc.

45 {
46 EXPECT_FALSE(Matrix().HasPerspective());
47
48 auto test = [](int index, bool expect) {
49 Matrix matrix;
50 EXPECT_FALSE(matrix.HasPerspective());
51 matrix.m[index] = 0.5f;
52 EXPECT_EQ(matrix.HasPerspective(), expect) << "index: " << index;
53 };
54
55 // clang-format off
56 test( 0, false); test( 1, false); test( 2, false); test( 3, true);
57 test( 4, false); test( 5, false); test( 6, false); test( 7, true);
58 test( 8, false); test( 9, false); test(10, false); test(11, true);
59 test(12, false); test(13, false); test(14, false); test(15, true);
60 // clang-format on
61 }

References impeller::Matrix::HasPerspective(), and impeller::Matrix::m.

## ◆ TEST() [193/360]

impeller::testing::TEST | ( | MatrixTest | ,
|  | HasPerspective2D |
| ) |  |

Definition at line 27 of file matrix_unittests.cc.

27 {
28 EXPECT_FALSE(Matrix().HasPerspective2D());
29
30 auto test = [](int index, bool expect) {
31 Matrix matrix;
32 EXPECT_FALSE(matrix.HasPerspective2D());
33 matrix.m[index] = 0.5f;
34 EXPECT_EQ(matrix.HasPerspective2D(), expect) << "index: " << index;
35 };
36
37 // clang-format off
38 test( 0, false); test( 1, false); test( 2, false); test( 3, true);
39 test( 4, false); test( 5, false); test( 6, false); test( 7, true);
40 test( 8, false); test( 9, false); test(10, false); test(11, false);
41 test(12, false); test(13, false); test(14, false); test(15, true);
42 // clang-format on
43 }

References impeller::Matrix::HasPerspective2D(), and impeller::Matrix::m.

## ◆ TEST() [194/360]

impeller::testing::TEST | ( | MatrixTest | ,
|  | HasTranslation |
| ) |  |

Definition at line 63 of file matrix_unittests.cc.

63 {
64 EXPECT_TRUE(Matrix::MakeTranslation({100, 100, 0}).HasTranslation());
65 EXPECT_TRUE(Matrix::MakeTranslation({0, 100, 0}).HasTranslation());
66 EXPECT_TRUE(Matrix::MakeTranslation({100, 0, 0}).HasTranslation());
67 EXPECT_FALSE(Matrix().HasTranslation());
68 }

References impeller::Matrix::MakeTranslation().

## ◆ TEST() [195/360]

impeller::testing::TEST | ( | MatrixTest | ,
|  | IsAligned |
| ) |  |

Definition at line 103 of file matrix_unittests.cc.

103 {
104 EXPECT_TRUE(Matrix().IsAligned());
105 EXPECT_TRUE(Matrix::MakeScale({1.0f, 1.0f, 2.0f}).IsAligned());
106
107 // Begin Legacy tests transferred over from geometry_unittests.cc
108 {
109 auto m = Matrix::MakeTranslation({1, 2, 3});
110 bool result = m.IsAligned();
111 ASSERT_TRUE(result);
112 }
113
114 {
115 auto m = Matrix::MakeRotationZ(Degrees{123});
116 bool result = m.IsAligned();
117 ASSERT_FALSE(result);
118 }
119 // End Legacy tests transferred over from geometry_unittests.cc
120
121 auto test = [](int index, bool expect) {
122 Matrix matrix;
123 EXPECT_TRUE(matrix.IsAligned());
124 matrix.m[index] = 0.5f;
125 EXPECT_EQ(matrix.IsAligned(), expect) << "index: " << index;
126 };
127
128 // clang-format off
129 test( 0, true); test( 1, false); test( 2, false); test( 3, false);
130 test( 4, false); test( 5, true); test( 6, false); test( 7, false);
131 test( 8, false); test( 9, false); test(10, true); test(11, false);
132 test(12, true); test(13, true); test(14, true); test(15, false);
133 // clang-format on
134
135 // True for quadrant rotations from -250 to +250 full circles
136 for (int i = -1000; i < 1000; i++) {
137 Degrees d = Degrees(i * 90);
138 Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
139 EXPECT_TRUE(matrix.IsAligned()) << "degrees: " << d.degrees;
140 }
141
142 // False for half degree rotations from -999.5 to +1000.5 degrees
143 for (int i = -1000; i < 1000; i++) {
144 Degrees d = Degrees(i + 0.5f);
145 Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
146 EXPECT_FALSE(matrix.IsAligned()) << "degrees: " << d.degrees;
147 }
148 }

References impeller::Degrees::degrees, impeller::Matrix::IsAligned(), impeller::Matrix::m, impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), and impeller::Matrix::MakeTranslation().

## ◆ TEST() [196/360]

impeller::testing::TEST | ( | MatrixTest | ,
|  | IsAligned2D |
| ) |  |

Definition at line 70 of file matrix_unittests.cc.

70 {
71 EXPECT_TRUE(Matrix().IsAligned2D());
72 EXPECT_TRUE(Matrix::MakeScale({1.0f, 1.0f, 2.0f}).IsAligned2D());
73
74 auto test = [](int index, bool expect) {
75 Matrix matrix;
76 EXPECT_TRUE(matrix.IsAligned2D());
77 matrix.m[index] = 0.5f;
78 EXPECT_EQ(matrix.IsAligned2D(), expect) << "index: " << index;
79 };
80
81 // clang-format off
82 test( 0, true); test( 1, false); test( 2, true); test( 3, false);
83 test( 4, false); test( 5, true); test( 6, true); test( 7, false);
84 test( 8, true); test( 9, true); test(10, true); test(11, true);
85 test(12, true); test(13, true); test(14, true); test(15, false);
86 // clang-format on
87
88 // True for quadrant rotations from -250 to +250 full circles
89 for (int i = -1000; i < 1000; i++) {
90 Degrees d = Degrees(i * 90);
91 Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
92 EXPECT_TRUE(matrix.IsAligned2D()) << "degrees: " << d.degrees;
93 }
94
95 // False for half degree rotations from -999.5 to +1000.5 degrees
96 for (int i = -1000; i < 1000; i++) {
97 Degrees d = Degrees(i + 0.5f);
98 Matrix matrix = Matrix::MakeRotationZ(Degrees(d));
99 EXPECT_FALSE(matrix.IsAligned2D()) << "degrees: " << d.degrees;
100 }
101 }

References impeller::Degrees::degrees, impeller::Matrix::IsAligned2D(), impeller::Matrix::m, impeller::Matrix::MakeRotationZ(), and impeller::Matrix::MakeScale().

## ◆ TEST() [197/360]

impeller::testing::TEST | ( | MatrixTest | ,
|  | Multiply |
| ) |  |

Definition at line 14 of file matrix_unittests.cc.

14 {
15 Matrix x(0.0, 0.0, 0.0, 1.0, //
16 1.0, 0.0, 0.0, 1.0, //
17 0.0, 1.0, 0.0, 1.0, //
18 1.0, 1.0, 0.0, 1.0);
19 Matrix translate = Matrix::MakeTranslation({10, 20, 0});
20 Matrix result = translate * x;
21 EXPECT_TRUE(MatrixNear(result, Matrix(10.0, 20.0, 0.0, 1.0, //
22 11.0, 20.0, 0.0, 1.0, //
23 10.0, 21.0, 0.0, 1.0, //
24 11.0, 21.0, 0.0, 1.0)));
25 }

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

## ◆ TEST() [198/360]

impeller::testing::TEST | ( | MatrixTest | ,
|  | TransformHomogenous |
| ) |  |

Definition at line 150 of file matrix_unittests.cc.

150 {
151 Matrix matrix = Matrix::MakeColumn(
152 // clang-format off
153 2.0f, 3.0f, 5.0f, 7.0f,
154 11.0f, 13.0f, 17.0f, 19.0f,
155 23.0f, 29.0f, 31.0f, 37.0f,
156 41.0f, 43.0f, 47.0f, 53.0f
157 // clang-format on
158 );
159 EXPECT_EQ(matrix.TransformHomogenous({1.0f, -1.0f}),
160 Vector3(32.0f, 33.0f, 41.0f));
161 }

References impeller::Matrix::MakeColumn(), and impeller::Matrix::TransformHomogenous().

## ◆ TEST() [199/360]

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

Definition at line 339 of file path_unittests.cc.

339 {
340 PathBuilder builder;
341 auto path =
342 builder.AddCubicCurve({120, 160}, {25, 200}, {220, 260}, {220, 40})
343 .TakePath();
344 auto box = path.GetBoundingBox();
345 Rect expected = Rect::MakeXYWH(93.9101, 40, 126.09, 158.862);
346 ASSERT_TRUE(box.has_value());
347 ASSERT_RECT_NEAR(box.value_or(Rect::MakeMaximum()), expected);
348 }

References impeller::PathBuilder::AddCubicCurve(), ASSERT_RECT_NEAR, impeller::TRect< Scalar >::MakeMaximum(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [200/360]

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

Definition at line 350 of file path_unittests.cc.

350 {
351 PathBuilder builder;
352 builder.AddRoundedRect(Rect::MakeXYWH(10, 10, 300, 300), {50, 50, 50, 50});
353 auto path = builder.TakePath();
354 auto actual = path.GetBoundingBox();
355 Rect expected = Rect::MakeXYWH(10, 10, 300, 300);
356
357 ASSERT_TRUE(actual.has_value());
358 ASSERT_RECT_NEAR(actual.value_or(Rect::MakeMaximum()), expected);
359 }

References impeller::PathBuilder::AddRoundedRect(), ASSERT_RECT_NEAR, impeller::Path::GetBoundingBox(), impeller::TRect< Scalar >::MakeMaximum(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [201/360]

impeller::testing::TEST | ( | PathTest | ,
|  | CanBeCloned |
| ) |  |

Definition at line 501 of file path_unittests.cc.

501 {
502 PathBuilder builder;
503 builder.MoveTo({10, 10});
504 builder.LineTo({20, 20});
505 builder.SetBounds(Rect::MakeLTRB(0, 0, 100, 100));
506 builder.SetConvexity(Convexity::kConvex);
507
508 auto path_a = builder.TakePath(FillType::kOdd);
509 // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
510 auto path_b = path_a;
511
512 EXPECT_EQ(path_a.GetBoundingBox(), path_b.GetBoundingBox());
513 EXPECT_EQ(path_a.GetFillType(), path_b.GetFillType());
514 EXPECT_EQ(path_a.IsConvex(), path_b.IsConvex());
515
516 auto poly_a = path_a.CreatePolyline(1.0);
517 auto poly_b = path_b.CreatePolyline(1.0);
518
519 ASSERT_EQ(poly_a.points->size(), poly_b.points->size());
520 ASSERT_EQ(poly_a.contours.size(), poly_b.contours.size());
521
522 for (auto i = 0u; i < poly_a.points->size(); i++) {
523 EXPECT_EQ((*poly_a.points)[i], (*poly_b.points)[i]);
524 }
525
526 for (auto i = 0u; i < poly_a.contours.size(); i++) {
527 EXPECT_EQ(poly_a.contours[i].start_index, poly_b.contours[i].start_index);
528 EXPECT_EQ(poly_a.contours[i].start_direction,
529 poly_b.contours[i].start_direction);
530 }
531 }

References impeller::kConvex, impeller::kOdd, impeller::PathBuilder::LineTo(), impeller::TRect< Scalar >::MakeLTRB(), impeller::PathBuilder::MoveTo(), impeller::PathBuilder::SetBounds(), impeller::PathBuilder::SetConvexity(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [202/360]

impeller::testing::TEST | ( | PathTest | ,
|  | CloseAfterMoveDoesNotAddNewLines |
| ) |  |

Definition at line 471 of file path_unittests.cc.

471 {
472 PathBuilder builder;
473 auto path = builder.LineTo({0, 10})
474 .LineTo({10, 10})
475 .MoveTo({30, 30}) // Moves to (30, 30)
476 .Close() // No Op
477 .Close() // Still No op
478 .TakePath();
479
480 EXPECT_EQ(path.GetComponentCount(), 4u);
481 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 2u);
482 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 2u);
483 }

References impeller::Close(), impeller::Path::kContour, impeller::Path::kLinear, impeller::LineTo(), impeller::PathBuilder::LineTo(), and impeller::MoveTo().

## ◆ TEST() [203/360]

impeller::testing::TEST | ( | PathTest | ,
|  | CloseAtOriginDoesNotAddNewLineSegment |
| ) |  |

Definition at line 485 of file path_unittests.cc.

485 {
486 PathBuilder builder;
487 // Create a path that has a current position at the origin when close is
488 // called. This should not insert a new line segment
489 auto path = builder.LineTo({10, 0})
490 .LineTo({10, 10})
491 .LineTo({0, 10})
492 .LineTo({0, 0})
493 .Close()
494 .TakePath();
495
496 EXPECT_EQ(path.GetComponentCount(), 6u);
497 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 4u);
498 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 2u);
499 }

References impeller::Close(), impeller::Path::kContour, impeller::Path::kLinear, impeller::LineTo(), and impeller::PathBuilder::LineTo().

## ◆ TEST() [204/360]

impeller::testing::TEST | ( | PathTest | ,
|  | CubicPath |
| ) |  |

Definition at line 324 of file path_unittests.cc.

324 {
325 PathBuilder builder;
326 auto path =
327 builder.CubicCurveTo(Point(10, 10), Point(-10, -10), Point(20, 20))
328 .TakePath();
329
330 CubicPathComponent cubic;
331 path.GetCubicComponentAtIndex(1, cubic);
332
333 EXPECT_EQ(cubic.p1, Point(0, 0));
334 EXPECT_EQ(cubic.cp1, Point(10, 10));
335 EXPECT_EQ(cubic.cp2, Point(-10, -10));
336 EXPECT_EQ(cubic.p2, Point(20, 20));
337 }

References impeller::CubicPathComponent::cp1, impeller::CubicPathComponent::cp2, impeller::PathBuilder::CubicCurveTo(), impeller::CubicPathComponent::p1, impeller::CubicPathComponent::p2, and impeller::PathBuilder::TakePath().

## ◆ TEST() [205/360]

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

Definition at line 15 of file path_unittests.cc.

15 {
16 CubicPathComponent component({10, 10}, {20, 35}, {35, 20}, {40, 40});
17 std::vector<Point> polyline;
18 component.AppendPolylinePoints(1.0f, polyline);
19 ASSERT_NE(polyline.front().x, 10);
20 ASSERT_NE(polyline.front().y, 10);
21 ASSERT_EQ(polyline.back().x, 40);
22 ASSERT_EQ(polyline.back().y, 40);
23 }

References polyline.

## ◆ TEST() [206/360]

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

Definition at line 384 of file path_unittests.cc.

384 {
385 auto path = PathBuilder{}.TakePath();
386 ASSERT_EQ(path.GetComponentCount(), 1u);
387
388 ContourComponent c;
389 path.GetContourComponentAtIndex(0, c);
390 ASSERT_POINT_NEAR(c.destination, Point());
391
392 Path::Polyline polyline = path.CreatePolyline(1.0f);
393 ASSERT_TRUE(polyline.points->empty());
394 ASSERT_TRUE(polyline.contours.empty());
395 }

References ASSERT_POINT_NEAR, impeller::ContourComponent::destination, polyline, and impeller::PathBuilder::TakePath().

## ◆ TEST() [207/360]

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

Definition at line 361 of file path_unittests.cc.

361 {
362 CubicPathComponent cubic{{11.769268, 252.883148},
363 {-6.2857933, 204.356461},
364 {-4.53997231, 156.552902},
365 {17.0067291, 109.472488}};
366 auto points = cubic.Extrema();
367
368 ASSERT_EQ(points.size(), static_cast<size_t>(3));
369 ASSERT_POINT_NEAR(points[2], cubic.Solve(0.455916));
370 }

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

## ◆ TEST() [208/360]

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

Definition at line 160 of file path_unittests.cc.

160 {
161 Path::Polyline polyline = PathBuilder{}
162 .AddRect(Rect::MakeLTRB(50, 60, 70, 80))
163 .TakePath()
164 .CreatePolyline(1.0f);
165 ASSERT_EQ(polyline.contours.size(), 1u);
166 ASSERT_TRUE(polyline.contours[0].is_closed);
167 ASSERT_EQ(polyline.contours[0].start_index, 0u);
168 ASSERT_EQ(polyline.points->size(), 5u);
169 ASSERT_EQ(polyline.GetPoint(0), Point(50, 60));
170 ASSERT_EQ(polyline.GetPoint(1), Point(70, 60));
171 ASSERT_EQ(polyline.GetPoint(2), Point(70, 80));
172 ASSERT_EQ(polyline.GetPoint(3), Point(50, 80));
173 ASSERT_EQ(polyline.GetPoint(4), Point(50, 60));
174 }

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

## ◆ TEST() [209/360]

impeller::testing::TEST | ( | PathTest | ,
|  | PathBuilderDoesNotMutateCopiedPaths |
| ) |  |

Definition at line 533 of file path_unittests.cc.

533 {
534 auto test_isolation =
535 [](const std::function<void(PathBuilder & builder)>& mutator,
536 bool will_close, Point mutation_offset, const std::string& label) {
537 PathBuilder builder;
538 builder.MoveTo({10, 10});
539 builder.LineTo({20, 20});
540 builder.LineTo({20, 10});
541
542 auto verify_path = [](const Path& path, bool is_mutated, bool is_closed,
543 Point offset, const std::string& label) {
544 if (is_mutated) {
545 // We can only test the initial state before the mutator did
546 // its work. We have >= 3 components and the first 3 components
547 // will match what we saw before the mutation.
548 EXPECT_GE(path.GetComponentCount(), 3u) << label;
549 } else {
550 EXPECT_EQ(path.GetComponentCount(), 3u) << label;
551 }
552 {
553 ContourComponent contour;
554 EXPECT_TRUE(path.GetContourComponentAtIndex(0, contour)) << label;
555 EXPECT_EQ(contour.destination, offset + Point(10, 10)) << label;
556 EXPECT_EQ(contour.is_closed, is_closed) << label;
557 }
558 {
559 LinearPathComponent line;
560 EXPECT_TRUE(path.GetLinearComponentAtIndex(1, line)) << label;
561 EXPECT_EQ(line.p1, offset + Point(10, 10)) << label;
562 EXPECT_EQ(line.p2, offset + Point(20, 20)) << label;
563 }
564 {
565 LinearPathComponent line;
566 EXPECT_TRUE(path.GetLinearComponentAtIndex(2, line)) << label;
567 EXPECT_EQ(line.p1, offset + Point(20, 20)) << label;
568 EXPECT_EQ(line.p2, offset + Point(20, 10)) << label;
569 }
570 };
571
572 auto path1 = builder.CopyPath();
573 verify_path(path1, false, false, {},
574 "Initial Path1 state before " + label);
575
576 for (int i = 0; i < 10; i++) {
577 auto path = builder.CopyPath();
578 verify_path(
579 path, false, false, {},
580 "Extra CopyPath #" + std::to_string(i + 1) + " for " + label);
581 }
582 mutator(builder);
583 verify_path(path1, false, false, {},
584 "Path1 state after subsequent " + label);
585
586 auto path2 = builder.CopyPath();
587 verify_path(path1, false, false, {},
588 "Path1 state after subsequent " + label + " and CopyPath");
589 verify_path(path2, true, will_close, mutation_offset,
590 "Initial Path2 state with subsequent " + label);
591 };
592
593 test_isolation(
594 [](PathBuilder& builder) { //
595 builder.SetConvexity(Convexity::kConvex);
596 },
597 false, {}, "SetConvex");
598
599 test_isolation(
600 [](PathBuilder& builder) { //
601 builder.SetConvexity(Convexity::kUnknown);
602 },
603 false, {}, "SetUnknownConvex");
604
605 test_isolation(
606 [](PathBuilder& builder) { //
607 builder.Close();
608 },
609 true, {}, "Close");
610
611 test_isolation(
612 [](PathBuilder& builder) {
613 builder.MoveTo({20, 30}, false);
614 },
615 false, {}, "Absolute MoveTo");
616
617 test_isolation(
618 [](PathBuilder& builder) {
619 builder.MoveTo({20, 30}, true);
620 },
621 false, {}, "Relative MoveTo");
622
623 test_isolation(
624 [](PathBuilder& builder) {
625 builder.LineTo({20, 30}, false);
626 },
627 false, {}, "Absolute LineTo");
628
629 test_isolation(
630 [](PathBuilder& builder) {
631 builder.LineTo({20, 30}, true);
632 },
633 false, {}, "Relative LineTo");
634
635 test_isolation(
636 [](PathBuilder& builder) { //
637 builder.HorizontalLineTo(100, false);
638 },
639 false, {}, "Absolute HorizontalLineTo");
640
641 test_isolation(
642 [](PathBuilder& builder) { //
643 builder.HorizontalLineTo(100, true);
644 },
645 false, {}, "Relative HorizontalLineTo");
646
647 test_isolation(
648 [](PathBuilder& builder) { //
649 builder.VerticalLineTo(100, false);
650 },
651 false, {}, "Absolute VerticalLineTo");
652
653 test_isolation(
654 [](PathBuilder& builder) { //
655 builder.VerticalLineTo(100, true);
656 },
657 false, {}, "Relative VerticalLineTo");
658
659 test_isolation(
660 [](PathBuilder& builder) {
661 builder.QuadraticCurveTo({20, 30}, {30, 20}, false);
662 },
663 false, {}, "Absolute QuadraticCurveTo");
664
665 test_isolation(
666 [](PathBuilder& builder) {
667 builder.QuadraticCurveTo({20, 30}, {30, 20}, true);
668 },
669 false, {}, "Relative QuadraticCurveTo");
670
671 test_isolation(
672 [](PathBuilder& builder) {
673 builder.CubicCurveTo({20, 30}, {30, 20}, {30, 30}, false);
674 },
675 false, {}, "Absolute CubicCurveTo");
676
677 test_isolation(
678 [](PathBuilder& builder) {
679 builder.CubicCurveTo({20, 30}, {30, 20}, {30, 30}, true);
680 },
681 false, {}, "Relative CubicCurveTo");
682
683 test_isolation(
684 [](PathBuilder& builder) {
685 builder.AddLine({100, 100}, {150, 100});
686 },
687 false, {}, "AddLine");
688
689 test_isolation(
690 [](PathBuilder& builder) {
691 builder.AddRect(Rect::MakeLTRB(100, 100, 120, 120));
692 },
693 false, {}, "AddRect");
694
695 test_isolation(
696 [](PathBuilder& builder) {
697 builder.AddOval(Rect::MakeLTRB(100, 100, 120, 120));
698 },
699 false, {}, "AddOval");
700
701 test_isolation(
702 [](PathBuilder& builder) {
703 builder.AddCircle({100, 100}, 20);
704 },
705 false, {}, "AddCircle");
706
707 test_isolation(
708 [](PathBuilder& builder) {
709 builder.AddArc(Rect::MakeLTRB(100, 100, 120, 120), Degrees(10),
710 Degrees(170));
711 },
712 false, {}, "AddArc");
713
714 test_isolation(
715 [](PathBuilder& builder) {
716 builder.AddQuadraticCurve({100, 100}, {150, 100}, {150, 150});
717 },
718 false, {}, "AddQuadraticCurve");
719
720 test_isolation(
721 [](PathBuilder& builder) {
722 builder.AddCubicCurve({100, 100}, {150, 100}, {100, 150}, {150, 150});
723 },
724 false, {}, "AddCubicCurve");
725
726 test_isolation(
727 [](PathBuilder& builder) {
728 builder.Shift({23, 42});
729 },
730 false, {23, 42}, "Shift");
731 }

References impeller::PathBuilder::AddArc(), impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddCubicCurve(), impeller::PathBuilder::AddLine(), impeller::PathBuilder::AddOval(), impeller::PathBuilder::AddQuadraticCurve(), impeller::PathBuilder::AddRect(), impeller::PathBuilder::Close(), impeller::PathBuilder::CopyPath(), impeller::PathBuilder::CubicCurveTo(), impeller::ContourComponent::destination, impeller::Path::GetComponentCount(), impeller::Path::GetContourComponentAtIndex(), impeller::Path::GetLinearComponentAtIndex(), impeller::PathBuilder::HorizontalLineTo(), impeller::ContourComponent::is_closed, impeller::kConvex, impeller::kUnknown, impeller::PathBuilder::LineTo(), impeller::TRect< Scalar >::MakeLTRB(), impeller::PathBuilder::MoveTo(), offset, impeller::LinearPathComponent::p1, impeller::LinearPathComponent::p2, impeller::PathBuilder::QuadraticCurveTo(), impeller::PathBuilder::SetConvexity(), impeller::PathBuilder::Shift(), and impeller::PathBuilder::VerticalLineTo().

## ◆ TEST() [210/360]

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

Definition at line 44 of file path_unittests.cc.

44 {
45 // Closed shapes.
46 {
47 Path path = PathBuilder{}.AddCircle({100, 100}, 50).TakePath();
48 ContourComponent contour;
49 path.GetContourComponentAtIndex(0, contour);
50 EXPECT_POINT_NEAR(contour.destination, Point(100, 50));
51 EXPECT_TRUE(contour.is_closed);
52 }
53
54 {
55 Path path =
56 PathBuilder{}.AddOval(Rect::MakeXYWH(100, 100, 100, 100)).TakePath();
57 ContourComponent contour;
58 path.GetContourComponentAtIndex(0, contour);
59 EXPECT_POINT_NEAR(contour.destination, Point(150, 100));
60 EXPECT_TRUE(contour.is_closed);
61 }
62
63 {
64 Path path =
65 PathBuilder{}.AddRect(Rect::MakeXYWH(100, 100, 100, 100)).TakePath();
66 ContourComponent contour;
67 path.GetContourComponentAtIndex(0, contour);
68 EXPECT_POINT_NEAR(contour.destination, Point(100, 100));
69 EXPECT_TRUE(contour.is_closed);
70 }
71
72 {
73 Path path = PathBuilder{}
74 .AddRoundedRect(Rect::MakeXYWH(100, 100, 100, 100), 10)
75 .TakePath();
76 ContourComponent contour;
77 path.GetContourComponentAtIndex(0, contour);
78 EXPECT_POINT_NEAR(contour.destination, Point(110, 100));
79 EXPECT_TRUE(contour.is_closed);
80 }
81
82 {
83 Path path =
84 PathBuilder{}
85 .AddRoundedRect(Rect::MakeXYWH(100, 100, 100, 100), Size(10, 20))
86 .TakePath();
87 ContourComponent contour;
88 path.GetContourComponentAtIndex(0, contour);
89 EXPECT_POINT_NEAR(contour.destination, Point(110, 100));
90 EXPECT_TRUE(contour.is_closed);
91 }
92
93 // Open shapes.
94 {
95 Point p(100, 100);
96 Path path = PathBuilder{}.AddLine(p, {200, 100}).TakePath();
97 ContourComponent contour;
98 path.GetContourComponentAtIndex(0, contour);
99 ASSERT_POINT_NEAR(contour.destination, p);
100 ASSERT_FALSE(contour.is_closed);
101 }
102
103 {
104 Path path =
105 PathBuilder{}
106 .AddCubicCurve({100, 100}, {100, 50}, {100, 150}, {200, 100})
107 .TakePath();
108 ContourComponent contour;
109 path.GetContourComponentAtIndex(0, contour);
110 ASSERT_POINT_NEAR(contour.destination, Point(100, 100));
111 ASSERT_FALSE(contour.is_closed);
112 }
113
114 {
115 Path path = PathBuilder{}
116 .AddQuadraticCurve({100, 100}, {100, 50}, {200, 100})
117 .TakePath();
118 ContourComponent contour;
119 path.GetContourComponentAtIndex(0, contour);
120 ASSERT_POINT_NEAR(contour.destination, Point(100, 100));
121 ASSERT_FALSE(contour.is_closed);
122 }
123 }

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, EXPECT_POINT_NEAR, impeller::Path::GetContourComponentAtIndex(), impeller::ContourComponent::is_closed, impeller::TRect< Scalar >::MakeXYWH(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [211/360]

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

Definition at line 268 of file path_unittests.cc.

268 {
269 PathBuilder builder;
270 auto path_1 = builder.AddLine({0, 0}, {1, 1}).TakePath();
271
272 ASSERT_EQ(path_1.GetBoundingBox().value_or(Rect::MakeMaximum()),
273 Rect::MakeLTRB(0, 0, 1, 1));
274
275 auto path_2 = builder.AddLine({-1, -1}, {1, 1}).TakePath();
276
277 // Verify that PathBuilder recomputes the bounds.
278 ASSERT_EQ(path_2.GetBoundingBox().value_or(Rect::MakeMaximum()),
279 Rect::MakeLTRB(-1, -1, 1, 1));
280
281 // PathBuilder can set the bounds to whatever it wants
282 auto path_3 = builder.AddLine({0, 0}, {1, 1})
283 .SetBounds(Rect::MakeLTRB(0, 0, 100, 100))
284 .TakePath();
285
286 ASSERT_EQ(path_3.GetBoundingBox().value_or(Rect::MakeMaximum()),
287 Rect::MakeLTRB(0, 0, 100, 100));
288 }

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

## ◆ TEST() [212/360]

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

Definition at line 25 of file path_unittests.cc.

25 {
26 PathBuilder builder;
27 builder.MoveTo({10, 10});
28 builder.LineTo({20, 20});
29 builder.LineTo({30, 30});
30 builder.MoveTo({40, 40});
31 builder.LineTo({50, 50});
32
33 auto polyline = builder.TakePath().CreatePolyline(1.0f);
34
35 ASSERT_EQ(polyline.contours.size(), 2u);
36 ASSERT_EQ(polyline.points->size(), 5u);
37 ASSERT_EQ(polyline.GetPoint(0).x, 10);
38 ASSERT_EQ(polyline.GetPoint(1).x, 20);
39 ASSERT_EQ(polyline.GetPoint(2).x, 30);
40 ASSERT_EQ(polyline.GetPoint(3).x, 40);
41 ASSERT_EQ(polyline.GetPoint(4).x, 50);
42 }

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

## ◆ TEST() [213/360]

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

Definition at line 125 of file path_unittests.cc.

125 {
126 Path::Polyline polyline = PathBuilder{}
127 .AddLine({100, 100}, {200, 100})
128 .MoveTo({100, 200})
129 .LineTo({150, 250})
130 .LineTo({200, 200})
131 .Close()
132 .TakePath()
133 .CreatePolyline(1.0f);
134 ASSERT_EQ(polyline.points->size(), 6u);
135 ASSERT_EQ(polyline.contours.size(), 2u);
136 ASSERT_EQ(polyline.contours[0].is_closed, false);
137 ASSERT_EQ(polyline.contours[0].start_index, 0u);
138 ASSERT_EQ(polyline.contours[1].is_closed, true);
139 ASSERT_EQ(polyline.contours[1].start_index, 2u);
140 }

References impeller::PathBuilder::AddLine(), impeller::Close(), impeller::LineTo(), impeller::MoveTo(), and polyline.

## ◆ TEST() [214/360]

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

Definition at line 372 of file path_unittests.cc.

372 {
373 PathBuilder builder;
374 // Straight diagonal line.
375 builder.AddCubicCurve({0, 1}, {2, 3}, {4, 5}, {6, 7});
376 auto path = builder.TakePath();
377 auto actual = path.GetBoundingBox();
378 auto expected = Rect::MakeLTRB(0, 1, 6, 7);
379
380 ASSERT_TRUE(actual.has_value());
381 ASSERT_RECT_NEAR(actual.value_or(Rect::MakeMaximum()), expected);
382 }

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

## ◆ TEST() [215/360]

impeller::testing::TEST | ( | PathTest | ,
|  | PathHorizontalLine |
| ) |  |

Definition at line 290 of file path_unittests.cc.

290 {
291 PathBuilder builder;
292 auto path = builder.HorizontalLineTo(10).TakePath();
293
294 LinearPathComponent linear;
295 path.GetLinearComponentAtIndex(1, linear);
296
297 EXPECT_EQ(linear.p1, Point(0, 0));
298 EXPECT_EQ(linear.p2, Point(10, 0));
299 }

References impeller::PathBuilder::HorizontalLineTo(), impeller::LinearPathComponent::p1, impeller::LinearPathComponent::p2, and impeller::PathBuilder::TakePath().

## ◆ TEST() [216/360]

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

Definition at line 176 of file path_unittests.cc.

176 {
177 Path::Polyline polyline =
178 PathBuilder{}
179 .MoveTo({50, 50})
180 .LineTo({50, 50}) // Insert duplicate at beginning of contour.
181 .LineTo({100, 50})
182 .LineTo({100, 50}) // Insert duplicate at contour join.
183 .LineTo({100, 100})
184 .Close() // Implicitly insert duplicate {50, 50} across contours.
185 .LineTo({0, 50})
186 .LineTo({0, 100})
187 .LineTo({0, 100}) // Insert duplicate at end of contour.
188 .TakePath()
189 .CreatePolyline(1.0f);
190 ASSERT_EQ(polyline.contours.size(), 2u);
191 ASSERT_EQ(polyline.contours[0].start_index, 0u);
192 ASSERT_TRUE(polyline.contours[0].is_closed);
193 ASSERT_EQ(polyline.contours[1].start_index, 4u);
194 ASSERT_FALSE(polyline.contours[1].is_closed);
195 ASSERT_EQ(polyline.points->size(), 7u);
196 ASSERT_EQ(polyline.GetPoint(0), Point(50, 50));
197 ASSERT_EQ(polyline.GetPoint(1), Point(100, 50));
198 ASSERT_EQ(polyline.GetPoint(2), Point(100, 100));
199 ASSERT_EQ(polyline.GetPoint(3), Point(50, 50));
200 ASSERT_EQ(polyline.GetPoint(4), Point(50, 50));
201 ASSERT_EQ(polyline.GetPoint(5), Point(0, 50));
202 ASSERT_EQ(polyline.GetPoint(6), Point(0, 100));
203 }

References impeller::Close(), impeller::LineTo(), impeller::PathBuilder::MoveTo(), and polyline.

## ◆ TEST() [217/360]

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

Definition at line 232 of file path_unittests.cc.

232 {
233 PathBuilder builder{};
234 auto path =
235 builder.AddLine(Point(0, 0), Point(10, 10))
236 .AddQuadraticCurve(Point(10, 10), Point(15, 15), Point(20, 20))
237 .AddCubicCurve(Point(20, 20), Point(25, 25), Point(-5, -5),
238 Point(30, 30))
239 .Close()
240 .Shift(Point(1, 1))
241 .TakePath();
242
243 ContourComponent contour;
244 LinearPathComponent linear;
245 QuadraticPathComponent quad;
246 CubicPathComponent cubic;
247
248 ASSERT_TRUE(path.GetContourComponentAtIndex(0, contour));
249 ASSERT_TRUE(path.GetLinearComponentAtIndex(1, linear));
250 ASSERT_TRUE(path.GetQuadraticComponentAtIndex(3, quad));
251 ASSERT_TRUE(path.GetCubicComponentAtIndex(5, cubic));
252
253 EXPECT_EQ(contour.destination, Point(1, 1));
254
255 EXPECT_EQ(linear.p1, Point(1, 1));
256 EXPECT_EQ(linear.p2, Point(11, 11));
257
258 EXPECT_EQ(quad.cp, Point(16, 16));
259 EXPECT_EQ(quad.p1, Point(11, 11));
260 EXPECT_EQ(quad.p2, Point(21, 21));
261
262 EXPECT_EQ(cubic.cp1, Point(26, 26));
263 EXPECT_EQ(cubic.cp2, Point(-4, -4));
264 EXPECT_EQ(cubic.p1, Point(21, 21));
265 EXPECT_EQ(cubic.p2, Point(31, 31));
266 }

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() [218/360]

impeller::testing::TEST | ( | PathTest | ,
|  | PathVerticalLine |
| ) |  |

Definition at line 301 of file path_unittests.cc.

301 {
302 PathBuilder builder;
303 auto path = builder.VerticalLineTo(10).TakePath();
304
305 LinearPathComponent linear;
306 path.GetLinearComponentAtIndex(1, linear);
307
308 EXPECT_EQ(linear.p1, Point(0, 0));
309 EXPECT_EQ(linear.p2, Point(0, 10));
310 }

References impeller::LinearPathComponent::p1, impeller::LinearPathComponent::p2, impeller::PathBuilder::TakePath(), and impeller::PathBuilder::VerticalLineTo().

## ◆ TEST() [219/360]

impeller::testing::TEST | ( | PathTest | ,
|  | PolylineBufferReuse |
| ) |  |

Definition at line 205 of file path_unittests.cc.

205 {
206 auto point_buffer = std::make_unique<std::vector<Point>>();
207 auto point_buffer_address = reinterpret_cast<uintptr_t>(point_buffer.get());
208 Path::Polyline polyline =
209 PathBuilder{}
210 .MoveTo({50, 50})
211 .LineTo({100, 100})
212 .TakePath()
213 .CreatePolyline(
214 1.0f, std::move(point_buffer),
215 [point_buffer_address](
216 Path::Polyline::PointBufferPtr point_buffer) {
217 ASSERT_EQ(point_buffer->size(), 0u);
218 ASSERT_EQ(point_buffer_address,
219 reinterpret_cast<uintptr_t>(point_buffer.get()));
220 });
221 }

References impeller::LineTo(), impeller::PathBuilder::MoveTo(), and polyline.

## ◆ TEST() [220/360]

impeller::testing::TEST | ( | PathTest | ,
|  | PolylineFailsWithNullptrBuffer |
| ) |  |

Definition at line 223 of file path_unittests.cc.

223 {
224 EXPECT_DEATH_IF_SUPPORTED(PathBuilder{}
225 .MoveTo({50, 50})
226 .LineTo({100, 100})
227 .TakePath()
228 .CreatePolyline(1.0f, nullptr),
229 "");
230 }

References impeller::LineTo(), and impeller::PathBuilder::MoveTo().

## ◆ TEST() [221/360]

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

Definition at line 142 of file path_unittests.cc.

142 {
143 Path::Polyline polyline = PathBuilder{}
144 .AddLine({100, 100}, {200, 100})
145 .MoveTo({100, 200})
146 .LineTo({150, 250})
147 .LineTo({200, 200})
148 .Close()
149 .TakePath()
150 .CreatePolyline(1.0f);
151 size_t a1, a2, b1, b2;
152 std::tie(a1, a2) = polyline.GetContourPointBounds(0);
153 std::tie(b1, b2) = polyline.GetContourPointBounds(1);
154 ASSERT_EQ(a1, 0u);
155 ASSERT_EQ(a2, 2u);
156 ASSERT_EQ(b1, 2u);
157 ASSERT_EQ(b2, 6u);
158 }

References impeller::PathBuilder::AddLine(), impeller::Close(), impeller::LineTo(), impeller::MoveTo(), and polyline.

## ◆ TEST() [222/360]

impeller::testing::TEST | ( | PathTest | ,
|  | QuadradicPath |
| ) |  |

Definition at line 312 of file path_unittests.cc.

312 {
313 PathBuilder builder;
314 auto path = builder.QuadraticCurveTo(Point(10, 10), Point(20, 20)).TakePath();
315
316 QuadraticPathComponent quad;
317 path.GetQuadraticComponentAtIndex(1, quad);
318
319 EXPECT_EQ(quad.p1, Point(0, 0));
320 EXPECT_EQ(quad.cp, Point(10, 10));
321 EXPECT_EQ(quad.p2, Point(20, 20));
322 }

References impeller::QuadraticPathComponent::cp, impeller::QuadraticPathComponent::p1, impeller::QuadraticPathComponent::p2, impeller::PathBuilder::QuadraticCurveTo(), and impeller::PathBuilder::TakePath().

## ◆ TEST() [223/360]

impeller::testing::TEST | ( | PathTest | ,
|  | RepeatCloseDoesNotAddNewLines |
| ) |  |

Definition at line 457 of file path_unittests.cc.

457 {
458 PathBuilder builder;
459 auto path = builder.LineTo({0, 10})
460 .LineTo({10, 10})
461 .Close() // Returns to (0, 0)
462 .Close() // No Op
463 .Close() // Still No op
464 .TakePath();
465
466 EXPECT_EQ(path.GetComponentCount(), 5u);
467 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 3u);
468 EXPECT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 2u);
469 }

References impeller::Close(), impeller::Path::kContour, impeller::Path::kLinear, impeller::LineTo(), and impeller::PathBuilder::LineTo().

## ◆ TEST() [224/360]

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

Definition at line 397 of file path_unittests.cc.

397 {
398 PathBuilder builder;
399
400 auto path = builder.AddLine({0, 0}, {100, 100})
401 .AddQuadraticCurve({100, 100}, {200, 200}, {300, 300})
402 .AddCubicCurve({300, 300}, {400, 400}, {500, 500}, {600, 600})
403 .TakePath();
404
405 ASSERT_EQ(path.GetComponentCount(), 6u);
406 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kLinear), 1u);
407 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kQuadratic), 1u);
408 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kCubic), 1u);
409 ASSERT_EQ(path.GetComponentCount(Path::ComponentType::kContour), 3u);
410
411 path.EnumerateComponents(
412 [](size_t index, const LinearPathComponent& linear) {
413 Point p1(0, 0);
414 Point p2(100, 100);
415 ASSERT_EQ(index, 1u);
416 ASSERT_EQ(linear.p1, p1);
417 ASSERT_EQ(linear.p2, p2);
418 },
419 [](size_t index, const QuadraticPathComponent& quad) {
420 Point p1(100, 100);
421 Point cp(200, 200);
422 Point p2(300, 300);
423 ASSERT_EQ(index, 3u);
424 ASSERT_EQ(quad.p1, p1);
425 ASSERT_EQ(quad.cp, cp);
426 ASSERT_EQ(quad.p2, p2);
427 },
428 [](size_t index, const CubicPathComponent& cubic) {
429 Point p1(300, 300);
430 Point cp1(400, 400);
431 Point cp2(500, 500);
432 Point p2(600, 600);
433 ASSERT_EQ(index, 5u);
434 ASSERT_EQ(cubic.p1, p1);
435 ASSERT_EQ(cubic.cp1, cp1);
436 ASSERT_EQ(cubic.cp2, cp2);
437 ASSERT_EQ(cubic.p2, p2);
438 },
439 [](size_t index, const ContourComponent& contour) {
440 // There is an initial countour added for each curve.
441 if (index == 0u) {
442 Point p1(0, 0);
443 ASSERT_EQ(contour.destination, p1);
444 } else if (index == 2u) {
445 Point p1(100, 100);
446 ASSERT_EQ(contour.destination, p1);
447 } else if (index == 4u) {
448 Point p1(300, 300);
449 ASSERT_EQ(contour.destination, p1);
450 } else {
451 ASSERT_FALSE(true);
452 }
453 ASSERT_FALSE(contour.is_closed);
454 });
455 }

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

## ◆ TEST() [225/360]

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() [226/360]

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 values.reserve(20);
52 for (int i = 0; i < 20; i++) {
53 values.push_back(pool.Grab());
54 }
55 for (const auto& value : values) {
56 value->SetSize(100);
57 pool.Recycle(value);
58 }
59 }
60 EXPECT_EQ(pool.GetSize(), 1'000u);
61 }

## ◆ TEST() [227/360]

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() [228/360]

impeller::testing::TEST | ( | RectTest | ,
|  | ContainsFloatingPoint |
| ) |  |

Definition at line 1271 of file rect_unittests.cc.

1271 {
1272 auto rect1 =
1273 Rect::MakeXYWH(472.599945f, 440.999969f, 1102.80005f, 654.000061f);
1274 auto rect2 = Rect::MakeXYWH(724.f, 618.f, 600.f, 300.f);
1275 EXPECT_TRUE(rect1.Contains(rect2));
1276 }

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

## ◆ TEST() [229/360]

impeller::testing::TEST | ( | RectTest | ,
|  | EmptyIRectDoesNotIntersect |
| ) |  |

Definition at line 854 of file rect_unittests.cc.

854 {
855 IRect rect = IRect::MakeLTRB(50, 50, 100, 100);
856
857 auto test = [&rect](int64_t l, int64_t t, int64_t r, int64_t b,
858 const std::string& label) {
859 EXPECT_FALSE(IRect::MakeLTRB(l, b, r, t).IntersectsWithRect(rect))
860 << label << " with Top/Bottom swapped";
861 EXPECT_FALSE(IRect::MakeLTRB(r, b, l, t).IntersectsWithRect(rect))
862 << label << " with Left/Right swapped";
863 EXPECT_FALSE(IRect::MakeLTRB(r, t, l, b).IntersectsWithRect(rect))
864 << label << " with all sides swapped";
865 };
866
867 test(20, 20, 30, 30, "Above and Left");
868 test(70, 20, 80, 30, "Above");
869 test(120, 20, 130, 30, "Above and Right");
870 test(120, 70, 130, 80, "Right");
871 test(120, 120, 130, 130, "Below and Right");
872 test(70, 120, 80, 130, "Below");
873 test(20, 120, 30, 130, "Below and Left");
874 test(20, 70, 30, 80, "Left");
875
876 test(70, 70, 80, 80, "Inside");
877
878 test(40, 70, 60, 80, "Straddling Left");
879 test(70, 40, 80, 60, "Straddling Top");
880 test(90, 70, 110, 80, "Straddling Right");
881 test(70, 90, 80, 110, "Straddling Bottom");
882 }

References impeller::saturated::b, and impeller::TRect< T >::MakeLTRB().

## ◆ TEST() [230/360]

impeller::testing::TEST | ( | RectTest | ,
|  | EmptyRectDoesNotIntersect |
| ) |  |

Definition at line 824 of file rect_unittests.cc.

824 {
825 Rect rect = Rect::MakeLTRB(50, 50, 100, 100);
826
827 auto test = [&rect](Scalar l, Scalar t, Scalar r, Scalar b,
828 const std::string& label) {
829 EXPECT_FALSE(Rect::MakeLTRB(l, b, r, t).IntersectsWithRect(rect))
830 << label << " with Top/Bottom swapped";
831 EXPECT_FALSE(Rect::MakeLTRB(r, b, l, t).IntersectsWithRect(rect))
832 << label << " with Left/Right swapped";
833 EXPECT_FALSE(Rect::MakeLTRB(r, t, l, b).IntersectsWithRect(rect))
834 << label << " with all sides swapped";
835 };
836
837 test(20, 20, 30, 30, "Above and Left");
838 test(70, 20, 80, 30, "Above");
839 test(120, 20, 130, 30, "Above and Right");
840 test(120, 70, 130, 80, "Right");
841 test(120, 120, 130, 130, "Below and Right");
842 test(70, 120, 80, 130, "Below");
843 test(20, 120, 30, 130, "Below and Left");
844 test(20, 70, 30, 80, "Left");
845
846 test(70, 70, 80, 80, "Inside");
847
848 test(40, 70, 60, 80, "Straddling Left");
849 test(70, 40, 80, 60, "Straddling Top");
850 test(90, 70, 110, 80, "Straddling Right");
851 test(70, 90, 80, 110, "Straddling Bottom");
852 }

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

## ◆ TEST() [231/360]

impeller::testing::TEST | ( | RectTest | ,
|  | GetCenter |
| ) |  |

Definition at line 1194 of file rect_unittests.cc.

1194 {
1195 EXPECT_EQ(Rect::MakeXYWH(10, 30, 20, 20).GetCenter(), Point(20, 40));
1196 EXPECT_EQ(Rect::MakeXYWH(10, 30, 20, 19).GetCenter(), Point(20, 39.5));
1197 EXPECT_EQ(Rect::MakeMaximum().GetCenter(), Point(0, 0));
1198
1199 // Note that we expect a Point as the answer from an IRect
1200 EXPECT_EQ(IRect::MakeXYWH(10, 30, 20, 20).GetCenter(), Point(20, 40));
1201 EXPECT_EQ(IRect::MakeXYWH(10, 30, 20, 19).GetCenter(), Point(20, 39.5));
1202 EXPECT_EQ(IRect::MakeMaximum().GetCenter(), Point(0, 0));
1203 }

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

## ◆ TEST() [232/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectArea |
| ) |  |

Definition at line 980 of file rect_unittests.cc.

980 {
981 EXPECT_EQ(IRect::MakeXYWH(0, 0, 100, 200).Area(), 20000);
982 EXPECT_EQ(IRect::MakeXYWH(10, 20, 100, 200).Area(), 20000);
983 EXPECT_EQ(IRect::MakeXYWH(0, 0, 200, 100).Area(), 20000);
984 EXPECT_EQ(IRect::MakeXYWH(10, 20, 200, 100).Area(), 20000);
985 EXPECT_EQ(IRect::MakeXYWH(0, 0, 100, 100).Area(), 10000);
986 EXPECT_EQ(IRect::MakeXYWH(10, 20, 100, 100).Area(), 10000);
987 }

References impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [233/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectContainsInclusiveIPoint |
| ) |  |

Definition at line 2355 of file rect_unittests.cc.

2355 {
2356 auto check_empty_flips = [](const IRect& rect, const IPoint& point,
2357 const std::string& label) {
2358 ASSERT_FALSE(rect.IsEmpty());
2359
2360 EXPECT_FALSE(flip_lr(rect).ContainsInclusive(point)) << label;
2361 EXPECT_FALSE(flip_tb(rect).ContainsInclusive(point)) << label;
2362 EXPECT_FALSE(flip_lrtb(rect).ContainsInclusive(point)) << label;
2363 };
2364
2365 auto test_inside = [&check_empty_flips](const IRect& rect,
2366 const IPoint& point) {
2367 ASSERT_FALSE(rect.IsEmpty()) << rect;
2368
2369 std::stringstream stream;
2370 stream << rect << " contains " << point;
2371 auto label = stream.str();
2372
2373 EXPECT_TRUE(rect.ContainsInclusive(point)) << label;
2374 check_empty_flips(rect, point, label);
2375 };
2376
2377 auto test_outside = [&check_empty_flips](const IRect& rect,
2378 const IPoint& point) {
2379 ASSERT_FALSE(rect.IsEmpty()) << rect;
2380
2381 std::stringstream stream;
2382 stream << rect << " contains " << point;
2383 auto label = stream.str();
2384
2385 EXPECT_FALSE(rect.ContainsInclusive(point)) << label;
2386 check_empty_flips(rect, point, label);
2387 };
2388
2389 {
2390 // Origin is inclusive
2391 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2392 auto p = IPoint(100, 100);
2393
2394 test_inside(r, p);
2395 }
2396 {
2397 // Size is inclusive
2398 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2399 auto p = IPoint(200, 200);
2400
2401 test_inside(r, p);
2402 }
2403 {
2404 // Size + "epsilon" is exclusive
2405 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2406 auto p = IPoint(201, 201);
2407
2408 test_outside(r, p);
2409 }
2410 {
2411 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2412 auto p = IPoint(99, 99);
2413
2414 test_outside(r, p);
2415 }
2416 {
2417 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2418 auto p = IPoint(199, 199);
2419
2420 test_inside(r, p);
2421 }
2422
2423 {
2424 auto r = IRect::MakeMaximum();
2425 auto p = IPoint(199, 199);
2426
2427 test_inside(r, p);
2428 }
2429 }

References impeller::TRect< T >::ContainsInclusive(), flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::MakeMaximum(), and impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [234/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectContainsIPoint |
| ) |  |

Definition at line 2193 of file rect_unittests.cc.

2193 {
2194 auto check_empty_flips = [](const IRect& rect, const IPoint& point,
2195 const std::string& label) {
2196 ASSERT_FALSE(rect.IsEmpty());
2197
2198 EXPECT_FALSE(flip_lr(rect).Contains(point)) << label;
2199 EXPECT_FALSE(flip_tb(rect).Contains(point)) << label;
2200 EXPECT_FALSE(flip_lrtb(rect).Contains(point)) << label;
2201 };
2202
2203 auto test_inside = [&check_empty_flips](const IRect& rect,
2204 const IPoint& point) {
2205 ASSERT_FALSE(rect.IsEmpty()) << rect;
2206
2207 std::stringstream stream;
2208 stream << rect << " contains " << point;
2209 auto label = stream.str();
2210
2211 EXPECT_TRUE(rect.Contains(point)) << label;
2212 check_empty_flips(rect, point, label);
2213 };
2214
2215 auto test_outside = [&check_empty_flips](const IRect& rect,
2216 const IPoint& point) {
2217 ASSERT_FALSE(rect.IsEmpty()) << rect;
2218
2219 std::stringstream stream;
2220 stream << rect << " contains " << point;
2221 auto label = stream.str();
2222
2223 EXPECT_FALSE(rect.Contains(point)) << label;
2224 check_empty_flips(rect, point, label);
2225 };
2226
2227 {
2228 // Origin is inclusive
2229 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2230 auto p = IPoint(100, 100);
2231
2232 test_inside(r, p);
2233 }
2234 {
2235 // Size is exclusive
2236 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2237 auto p = IPoint(200, 200);
2238
2239 test_outside(r, p);
2240 }
2241 {
2242 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2243 auto p = IPoint(99, 99);
2244
2245 test_outside(r, p);
2246 }
2247 {
2248 auto r = IRect::MakeXYWH(100, 100, 100, 100);
2249 auto p = IPoint(199, 199);
2250
2251 test_inside(r, p);
2252 }
2253
2254 {
2255 auto r = IRect::MakeMaximum();
2256 auto p = IPoint(199, 199);
2257
2258 test_inside(r, p);
2259 }
2260 }

References impeller::TRect< T >::Contains(), flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::MakeMaximum(), and impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [235/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectContainsIRect |
| ) |  |

Definition at line 2546 of file rect_unittests.cc.

2546 {
2547 auto check_empty_flips = [](const IRect& a, const IRect& b,
2548 const std::string& label) {
2549 ASSERT_FALSE(a.IsEmpty());
2550 // test b rects are allowed to have 0 w/h, but not be backwards
2551 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2552
2553 // unflipped a vs flipped (empty) b yields true
2554 EXPECT_TRUE(a.Contains(flip_lr(b))) << label;
2555 EXPECT_TRUE(a.Contains(flip_tb(b))) << label;
2556 EXPECT_TRUE(a.Contains(flip_lrtb(b))) << label;
2557
2558 // flipped (empty) a vs unflipped b yields false
2559 EXPECT_FALSE(flip_lr(a).Contains(b)) << label;
2560 EXPECT_FALSE(flip_tb(a).Contains(b)) << label;
2561 EXPECT_FALSE(flip_lrtb(a).Contains(b)) << label;
2562
2563 // flipped (empty) a vs flipped (empty) b yields empty
2564 EXPECT_FALSE(flip_lr(a).Contains(flip_lr(b))) << label;
2565 EXPECT_FALSE(flip_tb(a).Contains(flip_tb(b))) << label;
2566 EXPECT_FALSE(flip_lrtb(a).Contains(flip_lrtb(b))) << label;
2567 };
2568
2569 auto test_inside = [&check_empty_flips](const IRect& a, const IRect& b) {
2570 ASSERT_FALSE(a.IsEmpty()) << a;
2571 // test b rects are allowed to have 0 w/h, but not be backwards
2572 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2573
2574 std::stringstream stream;
2575 stream << a << " contains " << b;
2576 auto label = stream.str();
2577
2578 EXPECT_TRUE(a.Contains(b)) << label;
2579 check_empty_flips(a, b, label);
2580 };
2581
2582 auto test_not_inside = [&check_empty_flips](const IRect& a, const IRect& b) {
2583 ASSERT_FALSE(a.IsEmpty()) << a;
2584 // If b was empty, it would be contained and should not be tested with
2585 // this function - use |test_inside| instead.
2586 ASSERT_FALSE(b.IsEmpty()) << b;
2587
2588 std::stringstream stream;
2589 stream << a << " contains " << b;
2590 auto label = stream.str();
2591
2592 EXPECT_FALSE(a.Contains(b)) << label;
2593 check_empty_flips(a, b, label);
2594 };
2595
2596 {
2597 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2598
2599 test_inside(a, a);
2600 }
2601 {
2602 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2603 auto b = IRect::MakeXYWH(0, 0, 0, 0);
2604
2605 test_inside(a, b);
2606 }
2607 {
2608 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2609 auto b = IRect::MakeXYWH(150, 150, 20, 20);
2610
2611 test_inside(a, b);
2612 }
2613 {
2614 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2615 auto b = IRect::MakeXYWH(150, 150, 100, 100);
2616
2617 test_not_inside(a, b);
2618 }
2619 {
2620 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2621 auto b = IRect::MakeXYWH(50, 50, 100, 100);
2622
2623 test_not_inside(a, b);
2624 }
2625 {
2626 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2627 auto b = IRect::MakeXYWH(0, 0, 300, 300);
2628
2629 test_not_inside(a, b);
2630 }
2631 {
2632 auto a = IRect::MakeMaximum();
2633 auto b = IRect::MakeXYWH(0, 0, 300, 300);
2634
2635 test_inside(a, b);
2636 }
2637 }

References impeller::saturated::b, impeller::TRect< T >::Contains(), flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::MakeMaximum(), and impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [236/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectCopy |
| ) |  |

Definition at line 641 of file rect_unittests.cc.

641 {
642 IRect rect = IRect::MakeLTRB(5, 10, 20, 25);
643 IRect copy = rect;
644
645 EXPECT_EQ(rect, copy);
646 EXPECT_EQ(copy.GetLeft(), 5);
647 EXPECT_EQ(copy.GetTop(), 10);
648 EXPECT_EQ(copy.GetRight(), 20);
649 EXPECT_EQ(copy.GetBottom(), 25);
650 EXPECT_EQ(copy.GetX(), 5);
651 EXPECT_EQ(copy.GetY(), 10);
652 EXPECT_EQ(copy.GetWidth(), 15);
653 EXPECT_EQ(copy.GetHeight(), 15);
654 EXPECT_FALSE(copy.IsEmpty());
655 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::MakeLTRB().

## ◆ TEST() [237/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectCutOut |
| ) |  |

Definition at line 2791 of file rect_unittests.cc.

2791 {
2792 IRect cull_rect = IRect::MakeLTRB(20, 20, 40, 40);
2793
2794 auto check_empty_flips = [&cull_rect](const IRect& diff_rect,
2795 const std::string& label) {
2796 EXPECT_FALSE(diff_rect.IsEmpty());
2797 EXPECT_FALSE(cull_rect.IsEmpty());
2798
2799 // unflipped cull_rect vs flipped(empty) diff_rect
2800 // == cull_rect
2801 EXPECT_TRUE(cull_rect.Cutout(flip_lr(diff_rect)).has_value()) << label;
2802 EXPECT_EQ(cull_rect.Cutout(flip_lr(diff_rect)), cull_rect) << label;
2803 EXPECT_TRUE(cull_rect.Cutout(flip_tb(diff_rect)).has_value()) << label;
2804 EXPECT_EQ(cull_rect.Cutout(flip_tb(diff_rect)), cull_rect) << label;
2805 EXPECT_TRUE(cull_rect.Cutout(flip_lrtb(diff_rect)).has_value()) << label;
2806 EXPECT_EQ(cull_rect.Cutout(flip_lrtb(diff_rect)), cull_rect) << label;
2807
2808 // flipped(empty) cull_rect vs flipped(empty) diff_rect
2809 // == empty
2810 EXPECT_FALSE(flip_lr(cull_rect).Cutout(diff_rect).has_value()) << label;
2811 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(diff_rect), IRect()) << label;
2812 EXPECT_FALSE(flip_tb(cull_rect).Cutout(diff_rect).has_value()) << label;
2813 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(diff_rect), IRect()) << label;
2814 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(diff_rect).has_value()) << label;
2815 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(diff_rect), IRect()) << label;
2816
2817 // flipped(empty) cull_rect vs unflipped diff_rect
2818 // == empty
2819 EXPECT_FALSE(flip_lr(cull_rect).Cutout(flip_lr(diff_rect)).has_value())
2820 << label;
2821 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(flip_lr(diff_rect)), IRect())
2822 << label;
2823 EXPECT_FALSE(flip_tb(cull_rect).Cutout(flip_tb(diff_rect)).has_value())
2824 << label;
2825 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(flip_tb(diff_rect)), IRect())
2826 << label;
2827 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(flip_lrtb(diff_rect)).has_value())
2828 << label;
2829 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(flip_lrtb(diff_rect)), IRect())
2830 << label;
2831 };
2832
2833 auto non_reducing = [&cull_rect, &check_empty_flips](
2834 const IRect& diff_rect, const std::string& label) {
2835 EXPECT_EQ(cull_rect.Cutout(diff_rect), cull_rect) << label;
2836 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), cull_rect) << label;
2837 check_empty_flips(diff_rect, label);
2838 };
2839
2840 auto reducing = [&cull_rect, &check_empty_flips](const IRect& diff_rect,
2841 const IRect& result_rect,
2842 const std::string& label) {
2843 EXPECT_TRUE(!result_rect.IsEmpty());
2844 EXPECT_EQ(cull_rect.Cutout(diff_rect), result_rect) << label;
2845 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), result_rect) << label;
2846 check_empty_flips(diff_rect, label);
2847 };
2848
2849 auto emptying = [&cull_rect, &check_empty_flips](const IRect& diff_rect,
2850 const std::string& label) {
2851 EXPECT_FALSE(cull_rect.Cutout(diff_rect).has_value()) << label;
2852 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), IRect()) << label;
2853 check_empty_flips(diff_rect, label);
2854 };
2855
2856 // Skim the corners and edge
2857 non_reducing(IRect::MakeLTRB(10, 10, 20, 20), "outside UL corner");
2858 non_reducing(IRect::MakeLTRB(20, 10, 40, 20), "Above");
2859 non_reducing(IRect::MakeLTRB(40, 10, 50, 20), "outside UR corner");
2860 non_reducing(IRect::MakeLTRB(40, 20, 50, 40), "Right");
2861 non_reducing(IRect::MakeLTRB(40, 40, 50, 50), "outside LR corner");
2862 non_reducing(IRect::MakeLTRB(20, 40, 40, 50), "Below");
2863 non_reducing(IRect::MakeLTRB(10, 40, 20, 50), "outside LR corner");
2864 non_reducing(IRect::MakeLTRB(10, 20, 20, 40), "Left");
2865
2866 // Overlap corners
2867 non_reducing(IRect::MakeLTRB(15, 15, 25, 25), "covering UL corner");
2868 non_reducing(IRect::MakeLTRB(35, 15, 45, 25), "covering UR corner");
2869 non_reducing(IRect::MakeLTRB(35, 35, 45, 45), "covering LR corner");
2870 non_reducing(IRect::MakeLTRB(15, 35, 25, 45), "covering LL corner");
2871
2872 // Overlap edges, but not across an entire side
2873 non_reducing(IRect::MakeLTRB(20, 15, 39, 25), "Top edge left-biased");
2874 non_reducing(IRect::MakeLTRB(21, 15, 40, 25), "Top edge, right biased");
2875 non_reducing(IRect::MakeLTRB(35, 20, 45, 39), "Right edge, top-biased");
2876 non_reducing(IRect::MakeLTRB(35, 21, 45, 40), "Right edge, bottom-biased");
2877 non_reducing(IRect::MakeLTRB(20, 35, 39, 45), "Bottom edge, left-biased");
2878 non_reducing(IRect::MakeLTRB(21, 35, 40, 45), "Bottom edge, right-biased");
2879 non_reducing(IRect::MakeLTRB(15, 20, 25, 39), "Left edge, top-biased");
2880 non_reducing(IRect::MakeLTRB(15, 21, 25, 40), "Left edge, bottom-biased");
2881
2882 // Slice all the way through the middle
2883 non_reducing(IRect::MakeLTRB(25, 15, 35, 45), "Vertical interior slice");
2884 non_reducing(IRect::MakeLTRB(15, 25, 45, 35), "Horizontal interior slice");
2885
2886 // Slice off each edge
2887 reducing(IRect::MakeLTRB(20, 15, 40, 25), //
2888 IRect::MakeLTRB(20, 25, 40, 40), //
2889 "Slice off top");
2890 reducing(IRect::MakeLTRB(35, 20, 45, 40), //
2891 IRect::MakeLTRB(20, 20, 35, 40), //
2892 "Slice off right");
2893 reducing(IRect::MakeLTRB(20, 35, 40, 45), //
2894 IRect::MakeLTRB(20, 20, 40, 35), //
2895 "Slice off bottom");
2896 reducing(IRect::MakeLTRB(15, 20, 25, 40), //
2897 IRect::MakeLTRB(25, 20, 40, 40), //
2898 "Slice off left");
2899
2900 // cull rect contains diff rect
2901 non_reducing(IRect::MakeLTRB(21, 21, 39, 39), "Contained, non-covering");
2902
2903 // cull rect equals diff rect
2904 emptying(cull_rect, "Perfectly covering");
2905
2906 // diff rect contains cull rect
2907 emptying(IRect::MakeLTRB(15, 15, 45, 45), "Smothering");
2908 }

References impeller::TRect< T >::Cutout(), impeller::TRect< T >::CutoutOrEmpty(), flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::MakeLTRB().

## ◆ TEST() [238/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectDefaultConstructor |
| ) |  |

Definition at line 59 of file rect_unittests.cc.

59 {
60 IRect rect = IRect();
61
62 EXPECT_EQ(rect.GetLeft(), 0);
63 EXPECT_EQ(rect.GetTop(), 0);
64 EXPECT_EQ(rect.GetRight(), 0);
65 EXPECT_EQ(rect.GetBottom(), 0);
66 EXPECT_EQ(rect.GetX(), 0);
67 EXPECT_EQ(rect.GetY(), 0);
68 EXPECT_EQ(rect.GetWidth(), 0);
69 EXPECT_EQ(rect.GetHeight(), 0);
70 EXPECT_TRUE(rect.IsEmpty());
71 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), and impeller::TRect< T >::IsEmpty().

## ◆ TEST() [239/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectDoesNotIntersectEmpty |
| ) |  |

Definition at line 794 of file rect_unittests.cc.

794 {
795 IRect rect = IRect::MakeLTRB(50, 50, 100, 100);
796
797 auto test = [&rect](int64_t l, int64_t t, int64_t r, int64_t b,
798 const std::string& label) {
799 EXPECT_FALSE(rect.IntersectsWithRect(IRect::MakeLTRB(l, b, r, t)))
800 << label << " with Top/Bottom swapped";
801 EXPECT_FALSE(rect.IntersectsWithRect(IRect::MakeLTRB(r, b, l, t)))
802 << label << " with Left/Right swapped";
803 EXPECT_FALSE(rect.IntersectsWithRect(IRect::MakeLTRB(r, t, l, b)))
804 << label << " with all sides swapped";
805 };
806
807 test(20, 20, 30, 30, "Above and Left");
808 test(70, 20, 80, 30, "Above");
809 test(120, 20, 130, 30, "Above and Right");
810 test(120, 70, 130, 80, "Right");
811 test(120, 120, 130, 130, "Below and Right");
812 test(70, 120, 80, 130, "Below");
813 test(20, 120, 30, 130, "Below and Left");
814 test(20, 70, 30, 80, "Left");
815
816 test(70, 70, 80, 80, "Inside");
817
818 test(40, 70, 60, 80, "Straddling Left");
819 test(70, 40, 80, 60, "Straddling Top");
820 test(90, 70, 110, 80, "Straddling Right");
821 test(70, 90, 80, 110, "Straddling Bottom");
822 }

References impeller::saturated::b, impeller::TRect< T >::IntersectsWithRect(), and impeller::TRect< T >::MakeLTRB().

## ◆ TEST() [240/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectEmptyDeclaration |
| ) |  |

Definition at line 29 of file rect_unittests.cc.

29 {
30 IRect rect;
31
32 EXPECT_EQ(rect.GetLeft(), 0);
33 EXPECT_EQ(rect.GetTop(), 0);
34 EXPECT_EQ(rect.GetRight(), 0);
35 EXPECT_EQ(rect.GetBottom(), 0);
36 EXPECT_EQ(rect.GetX(), 0);
37 EXPECT_EQ(rect.GetY(), 0);
38 EXPECT_EQ(rect.GetWidth(), 0);
39 EXPECT_EQ(rect.GetHeight(), 0);
40 EXPECT_TRUE(rect.IsEmpty());
41 // EXPECT_TRUE(rect.IsFinite()); // should fail to compile
42 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), and impeller::TRect< T >::IsEmpty().

## ◆ TEST() [241/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectExpand |
| ) |  |

Definition at line 1238 of file rect_unittests.cc.

1238 {
1239 auto rect = IRect::MakeLTRB(100, 100, 200, 200);
1240
1241 // Expand(T amount)
1242 EXPECT_EQ(rect.Expand(10), IRect::MakeLTRB(90, 90, 210, 210));
1243 EXPECT_EQ(rect.Expand(-10), IRect::MakeLTRB(110, 110, 190, 190));
1244
1245 // Expand(amount, amount)
1246 EXPECT_EQ(rect.Expand(10, 10), IRect::MakeLTRB(90, 90, 210, 210));
1247 EXPECT_EQ(rect.Expand(10, -10), IRect::MakeLTRB(90, 110, 210, 190));
1248 EXPECT_EQ(rect.Expand(-10, 10), IRect::MakeLTRB(110, 90, 190, 210));
1249 EXPECT_EQ(rect.Expand(-10, -10), IRect::MakeLTRB(110, 110, 190, 190));
1250
1251 // Expand(amount, amount, amount, amount)
1252 EXPECT_EQ(rect.Expand(10, 20, 30, 40), IRect::MakeLTRB(90, 80, 230, 240));
1253 EXPECT_EQ(rect.Expand(-10, 20, 30, 40), IRect::MakeLTRB(110, 80, 230, 240));
1254 EXPECT_EQ(rect.Expand(10, -20, 30, 40), IRect::MakeLTRB(90, 120, 230, 240));
1255 EXPECT_EQ(rect.Expand(10, 20, -30, 40), IRect::MakeLTRB(90, 80, 170, 240));
1256 EXPECT_EQ(rect.Expand(10, 20, 30, -40), IRect::MakeLTRB(90, 80, 230, 160));
1257
1258 // Expand(IPoint amount)
1259 EXPECT_EQ(rect.Expand(IPoint{10, 10}), IRect::MakeLTRB(90, 90, 210, 210));
1260 EXPECT_EQ(rect.Expand(IPoint{10, -10}), IRect::MakeLTRB(90, 110, 210, 190));
1261 EXPECT_EQ(rect.Expand(IPoint{-10, 10}), IRect::MakeLTRB(110, 90, 190, 210));
1262 EXPECT_EQ(rect.Expand(IPoint{-10, -10}), IRect::MakeLTRB(110, 110, 190, 190));
1263
1264 // Expand(ISize amount)
1265 EXPECT_EQ(rect.Expand(ISize{10, 10}), IRect::MakeLTRB(90, 90, 210, 210));
1266 EXPECT_EQ(rect.Expand(ISize{10, -10}), IRect::MakeLTRB(90, 110, 210, 190));
1267 EXPECT_EQ(rect.Expand(ISize{-10, 10}), IRect::MakeLTRB(110, 90, 190, 210));
1268 EXPECT_EQ(rect.Expand(ISize{-10, -10}), IRect::MakeLTRB(110, 110, 190, 190));
1269 }

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

## ◆ TEST() [242/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectFromIRect |
| ) |  |

Definition at line 616 of file rect_unittests.cc.

616 {
617 EXPECT_EQ(IRect(IRect::MakeXYWH(2, 3, 7, 15)), //
618 IRect::MakeXYWH(2, 3, 7, 15));
619 EXPECT_EQ(IRect(IRect::MakeLTRB(2, 3, 7, 15)), //
620 IRect::MakeLTRB(2, 3, 7, 15));
621 }

References impeller::TRect< T >::MakeLTRB(), and impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [243/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectGetNormalizingTransform |
| ) |  |

Definition at line 1077 of file rect_unittests.cc.

1077 {
1078 {
1079 // Checks for expected matrix values
1080
1081 auto r = IRect::MakeXYWH(100, 200, 200, 400);
1082
1083 EXPECT_EQ(r.GetNormalizingTransform(),
1084 Matrix::MakeScale({0.005, 0.0025, 1.0}) *
1085 Matrix::MakeTranslation({-100, -200}));
1086 }
1087
1088 {
1089 // Checks for expected transform of points relative to the rect
1090
1091 auto r = IRect::MakeLTRB(300, 500, 400, 700);
1092 auto m = r.GetNormalizingTransform();
1093
1094 // The 4 corners of the rect => (0, 0) to (1, 1)
1095 EXPECT_EQ(m * Point(300, 500), Point(0, 0));
1096 EXPECT_EQ(m * Point(400, 500), Point(1, 0));
1097 EXPECT_EQ(m * Point(400, 700), Point(1, 1));
1098 EXPECT_EQ(m * Point(300, 700), Point(0, 1));
1099
1100 // The center => (0.5, 0.5)
1101 EXPECT_EQ(m * Point(350, 600), Point(0.5, 0.5));
1102
1103 // Outside the 4 corners => (-1, -1) to (2, 2)
1104 EXPECT_EQ(m * Point(200, 300), Point(-1, -1));
1105 EXPECT_EQ(m * Point(500, 300), Point(2, -1));
1106 EXPECT_EQ(m * Point(500, 900), Point(2, 2));
1107 EXPECT_EQ(m * Point(200, 900), Point(-1, 2));
1108 }
1109
1110 {
1111 // Checks for behavior with empty rects
1112
1113 auto zero = Matrix::MakeScale({0.0, 0.0, 1.0});
1114
1115 // Empty for width and/or height == 0
1116 EXPECT_EQ(IRect::MakeXYWH(10, 10, 0, 10).GetNormalizingTransform(), zero);
1117 EXPECT_EQ(IRect::MakeXYWH(10, 10, 10, 0).GetNormalizingTransform(), zero);
1118 EXPECT_EQ(IRect::MakeXYWH(10, 10, 0, 0).GetNormalizingTransform(), zero);
1119
1120 // Empty for width and/or height < 0
1121 EXPECT_EQ(IRect::MakeXYWH(10, 10, -1, 10).GetNormalizingTransform(), zero);
1122 EXPECT_EQ(IRect::MakeXYWH(10, 10, 10, -1).GetNormalizingTransform(), zero);
1123 EXPECT_EQ(IRect::MakeXYWH(10, 10, -1, -1).GetNormalizingTransform(), zero);
1124 }
1125 }

References impeller::TRect< T >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [244/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectIntersection |
| ) |  |

Definition at line 1751 of file rect_unittests.cc.

1751 {
1752 auto check_empty_flips = [](const IRect& a, const IRect& b,
1753 const std::string& label) {
1754 ASSERT_FALSE(a.IsEmpty());
1755 // b is allowed to be empty
1756
1757 // unflipped a vs flipped (empty) b yields a
1758 EXPECT_FALSE(a.Intersection(flip_lr(b)).has_value()) << label;
1759 EXPECT_FALSE(a.Intersection(flip_tb(b)).has_value()) << label;
1760 EXPECT_FALSE(a.Intersection(flip_lrtb(b)).has_value()) << label;
1761
1762 // flipped (empty) a vs unflipped b yields b
1763 EXPECT_FALSE(flip_lr(a).Intersection(b).has_value()) << label;
1764 EXPECT_FALSE(flip_tb(a).Intersection(b).has_value()) << label;
1765 EXPECT_FALSE(flip_lrtb(a).Intersection(b).has_value()) << label;
1766
1767 // flipped (empty) a vs flipped (empty) b yields empty
1768 EXPECT_FALSE(flip_lr(a).Intersection(flip_lr(b)).has_value()) << label;
1769 EXPECT_FALSE(flip_tb(a).Intersection(flip_tb(b)).has_value()) << label;
1770 EXPECT_FALSE(flip_lrtb(a).Intersection(flip_lrtb(b)).has_value()) << label;
1771 };
1772
1773 auto test_non_empty = [&check_empty_flips](const IRect& a, const IRect& b,
1774 const IRect& result) {
1775 ASSERT_FALSE(a.IsEmpty()) << a;
1776 // b is allowed to be empty
1777
1778 std::stringstream stream;
1779 stream << a << " union " << b;
1780 auto label = stream.str();
1781
1782 EXPECT_TRUE(a.Intersection(b).has_value()) << label;
1783 EXPECT_TRUE(b.Intersection(a).has_value()) << label;
1784 EXPECT_EQ(a.Intersection(b), result) << label;
1785 EXPECT_EQ(b.Intersection(a), result) << label;
1786 check_empty_flips(a, b, label);
1787 };
1788
1789 auto test_empty = [&check_empty_flips](const IRect& a, const IRect& b) {
1790 ASSERT_FALSE(a.IsEmpty()) << a;
1791 // b is allowed to be empty
1792
1793 std::stringstream stream;
1794 stream << a << " union " << b;
1795 auto label = stream.str();
1796
1797 EXPECT_FALSE(a.Intersection(b).has_value()) << label;
1798 EXPECT_FALSE(b.Intersection(a).has_value()) << label;
1799 check_empty_flips(a, b, label);
1800 };
1801
1802 {
1803 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1804 auto b = IRect::MakeXYWH(0, 0, 0, 0);
1805
1806 test_empty(a, b);
1807 }
1808
1809 {
1810 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1811 auto b = IRect::MakeXYWH(10, 10, 0, 0);
1812
1813 test_empty(a, b);
1814 }
1815
1816 {
1817 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1818 auto b = IRect::MakeXYWH(10, 10, 100, 100);
1819 auto expected = IRect::MakeXYWH(10, 10, 90, 90);
1820
1821 test_non_empty(a, b, expected);
1822 }
1823
1824 {
1825 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1826 auto b = IRect::MakeXYWH(100, 100, 100, 100);
1827
1828 test_empty(a, b);
1829 }
1830
1831 {
1832 auto a = IRect::MakeMaximum();
1833 auto b = IRect::MakeXYWH(10, 10, 300, 300);
1834
1835 test_non_empty(a, b, b);
1836 }
1837
1838 {
1839 auto a = IRect::MakeMaximum();
1840 auto b = IRect::MakeMaximum();
1841
1842 test_non_empty(a, b, IRect::MakeMaximum());
1843 }
1844 }

References impeller::saturated::b, flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::Intersection(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::MakeMaximum(), and impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [245/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectIntersectsWithRect |
| ) |  |

Definition at line 2016 of file rect_unittests.cc.

2016 {
2017 auto check_empty_flips = [](const IRect& a, const IRect& b,
2018 const std::string& label) {
2019 ASSERT_FALSE(a.IsEmpty());
2020 // b is allowed to be empty
2021
2022 // unflipped a vs flipped (empty) b yields a
2023 EXPECT_FALSE(a.IntersectsWithRect(flip_lr(b))) << label;
2024 EXPECT_FALSE(a.IntersectsWithRect(flip_tb(b))) << label;
2025 EXPECT_FALSE(a.IntersectsWithRect(flip_lrtb(b))) << label;
2026
2027 // flipped (empty) a vs unflipped b yields b
2028 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(b)) << label;
2029 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(b)) << label;
2030 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(b)) << label;
2031
2032 // flipped (empty) a vs flipped (empty) b yields empty
2033 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(flip_lr(b))) << label;
2034 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(flip_tb(b))) << label;
2035 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(flip_lrtb(b))) << label;
2036 };
2037
2038 auto test_non_empty = [&check_empty_flips](const IRect& a, const IRect& b) {
2039 ASSERT_FALSE(a.IsEmpty()) << a;
2040 // b is allowed to be empty
2041
2042 std::stringstream stream;
2043 stream << a << " union " << b;
2044 auto label = stream.str();
2045
2046 EXPECT_TRUE(a.IntersectsWithRect(b)) << label;
2047 EXPECT_TRUE(b.IntersectsWithRect(a)) << label;
2048 check_empty_flips(a, b, label);
2049 };
2050
2051 auto test_empty = [&check_empty_flips](const IRect& a, const IRect& b) {
2052 ASSERT_FALSE(a.IsEmpty()) << a;
2053 // b is allowed to be empty
2054
2055 std::stringstream stream;
2056 stream << a << " union " << b;
2057 auto label = stream.str();
2058
2059 EXPECT_FALSE(a.IntersectsWithRect(b)) << label;
2060 EXPECT_FALSE(b.IntersectsWithRect(a)) << label;
2061 check_empty_flips(a, b, label);
2062 };
2063
2064 {
2065 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2066 auto b = IRect::MakeXYWH(0, 0, 0, 0);
2067
2068 test_empty(a, b);
2069 }
2070
2071 {
2072 auto a = IRect::MakeXYWH(100, 100, 100, 100);
2073 auto b = IRect::MakeXYWH(10, 10, 0, 0);
2074
2075 test_empty(a, b);
2076 }
2077
2078 {
2079 auto a = IRect::MakeXYWH(0, 0, 100, 100);
2080 auto b = IRect::MakeXYWH(10, 10, 100, 100);
2081
2082 test_non_empty(a, b);
2083 }
2084
2085 {
2086 auto a = IRect::MakeXYWH(0, 0, 100, 100);
2087 auto b = IRect::MakeXYWH(100, 100, 100, 100);
2088
2089 test_empty(a, b);
2090 }
2091
2092 {
2093 auto a = IRect::MakeMaximum();
2094 auto b = IRect::MakeXYWH(10, 10, 100, 100);
2095
2096 test_non_empty(a, b);
2097 }
2098
2099 {
2100 auto a = IRect::MakeMaximum();
2101 auto b = IRect::MakeMaximum();
2102
2103 test_non_empty(a, b);
2104 }
2105 }

References impeller::saturated::b, flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IntersectsWithRect(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::MakeMaximum(), and impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [246/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectMakeMaximum |
| ) |  |

Definition at line 593 of file rect_unittests.cc.

593 {
594 IRect rect = IRect::MakeMaximum();
595 auto min = std::numeric_limits<int64_t>::min();
596 auto max = std::numeric_limits<int64_t>::max();
597
598 EXPECT_EQ(rect.GetLeft(), min);
599 EXPECT_EQ(rect.GetTop(), min);
600 EXPECT_EQ(rect.GetRight(), max);
601 EXPECT_EQ(rect.GetBottom(), max);
602 EXPECT_EQ(rect.GetX(), min);
603 EXPECT_EQ(rect.GetY(), min);
604 EXPECT_EQ(rect.GetWidth(), max);
605 EXPECT_EQ(rect.GetHeight(), max);
606 EXPECT_FALSE(rect.IsEmpty());
607 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::MakeMaximum().

## ◆ TEST() [247/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectOriginSizeXYWHGetters |
| ) |  |

Definition at line 683 of file rect_unittests.cc.

683 {
684 {
685 IRect r = IRect::MakeOriginSize({10, 20}, {50, 40});
686 EXPECT_EQ(r.GetOrigin(), IPoint(10, 20));
687 EXPECT_EQ(r.GetSize(), ISize(50, 40));
688 EXPECT_EQ(r.GetX(), 10);
689 EXPECT_EQ(r.GetY(), 20);
690 EXPECT_EQ(r.GetWidth(), 50);
691 EXPECT_EQ(r.GetHeight(), 40);
692 auto expected_array = std::array<int64_t, 4>{10, 20, 50, 40};
693 EXPECT_EQ(r.GetXYWH(), expected_array);
694 }
695
696 {
697 IRect r = IRect::MakeLTRB(10, 20, 50, 40);
698 EXPECT_EQ(r.GetOrigin(), IPoint(10, 20));
699 EXPECT_EQ(r.GetSize(), ISize(40, 20));
700 EXPECT_EQ(r.GetX(), 10);
701 EXPECT_EQ(r.GetY(), 20);
702 EXPECT_EQ(r.GetWidth(), 40);
703 EXPECT_EQ(r.GetHeight(), 20);
704 auto expected_array = std::array<int64_t, 4>{10, 20, 40, 20};
705 EXPECT_EQ(r.GetXYWH(), expected_array);
706 }
707 }

References impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetOrigin(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetXYWH(), impeller::TRect< T >::GetY(), impeller::TRect< T >::MakeLTRB(), and impeller::TRect< T >::MakeOriginSize().

## ◆ TEST() [248/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectOverflowLTRB |
| ) |  |

Definition at line 478 of file rect_unittests.cc.

478 {
479 auto min = std::numeric_limits<int64_t>::min();
480 auto max = std::numeric_limits<int64_t>::max();
481
482 // 4 cases
483 // negative l, r near max takes width past max
484 // positive l, r near min takes width below min
485 // negative t, b near max takes width past max
486 // positive t, b near min takes width below min
487
488 {
489 IRect rect = IRect::MakeLTRB(-10, 10, max - 5, 26);
490
491 EXPECT_EQ(rect.GetLeft(), -10);
492 EXPECT_EQ(rect.GetTop(), 10);
493 EXPECT_EQ(rect.GetRight(), max - 5);
494 EXPECT_EQ(rect.GetBottom(), 26);
495 EXPECT_EQ(rect.GetX(), -10);
496 EXPECT_EQ(rect.GetY(), 10);
497 EXPECT_EQ(rect.GetWidth(), max);
498 EXPECT_EQ(rect.GetHeight(), 16);
499 EXPECT_FALSE(rect.IsEmpty());
500 }
501
502 {
503 IRect rect = IRect::MakeLTRB(10, 10, min + 5, 26);
504
505 EXPECT_EQ(rect.GetLeft(), 10);
506 EXPECT_EQ(rect.GetTop(), 10);
507 EXPECT_EQ(rect.GetRight(), min + 5);
508 EXPECT_EQ(rect.GetBottom(), 26);
509 EXPECT_EQ(rect.GetX(), 10);
510 EXPECT_EQ(rect.GetY(), 10);
511 EXPECT_EQ(rect.GetWidth(), min);
512 EXPECT_EQ(rect.GetHeight(), 16);
513 EXPECT_TRUE(rect.IsEmpty());
514 }
515
516 {
517 IRect rect = IRect::MakeLTRB(5, -10, 15, max - 5);
518
519 EXPECT_EQ(rect.GetLeft(), 5);
520 EXPECT_EQ(rect.GetTop(), -10);
521 EXPECT_EQ(rect.GetRight(), 15);
522 EXPECT_EQ(rect.GetBottom(), max - 5);
523 EXPECT_EQ(rect.GetX(), 5);
524 EXPECT_EQ(rect.GetY(), -10);
525 EXPECT_EQ(rect.GetWidth(), 10);
526 EXPECT_EQ(rect.GetHeight(), max);
527 EXPECT_FALSE(rect.IsEmpty());
528 }
529
530 {
531 IRect rect = IRect::MakeLTRB(5, 10, 15, min + 5);
532
533 EXPECT_EQ(rect.GetLeft(), 5);
534 EXPECT_EQ(rect.GetTop(), 10);
535 EXPECT_EQ(rect.GetRight(), 15);
536 EXPECT_EQ(rect.GetBottom(), min + 5);
537 EXPECT_EQ(rect.GetX(), 5);
538 EXPECT_EQ(rect.GetY(), 10);
539 EXPECT_EQ(rect.GetWidth(), 10);
540 EXPECT_EQ(rect.GetHeight(), min);
541 EXPECT_TRUE(rect.IsEmpty());
542 }
543 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::MakeLTRB().

## ◆ TEST() [249/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectOverflowXYWH |
| ) |  |

Definition at line 272 of file rect_unittests.cc.

272 {
273 auto min = std::numeric_limits<int64_t>::min();
274 auto max = std::numeric_limits<int64_t>::max();
275
276 // 4 cases
277 // x near max, positive w takes it past max
278 // x near min, negative w takes it below min
279 // y near max, positive h takes it past max
280 // y near min, negative h takes it below min
281
282 {
283 IRect rect = IRect::MakeXYWH(max - 5, 10, 10, 16);
284
285 EXPECT_EQ(rect.GetLeft(), max - 5);
286 EXPECT_EQ(rect.GetTop(), 10);
287 EXPECT_EQ(rect.GetRight(), max);
288 EXPECT_EQ(rect.GetBottom(), 26);
289 EXPECT_EQ(rect.GetX(), max - 5);
290 EXPECT_EQ(rect.GetY(), 10);
291 EXPECT_EQ(rect.GetWidth(), 5);
292 EXPECT_EQ(rect.GetHeight(), 16);
293 EXPECT_FALSE(rect.IsEmpty());
294 }
295
296 {
297 IRect rect = IRect::MakeXYWH(min + 5, 10, -10, 16);
298
299 EXPECT_EQ(rect.GetLeft(), min + 5);
300 EXPECT_EQ(rect.GetTop(), 10);
301 EXPECT_EQ(rect.GetRight(), min);
302 EXPECT_EQ(rect.GetBottom(), 26);
303 EXPECT_EQ(rect.GetX(), min + 5);
304 EXPECT_EQ(rect.GetY(), 10);
305 EXPECT_EQ(rect.GetWidth(), -5);
306 EXPECT_EQ(rect.GetHeight(), 16);
307 EXPECT_TRUE(rect.IsEmpty());
308 }
309
310 {
311 IRect rect = IRect::MakeXYWH(5, max - 10, 10, 16);
312
313 EXPECT_EQ(rect.GetLeft(), 5);
314 EXPECT_EQ(rect.GetTop(), max - 10);
315 EXPECT_EQ(rect.GetRight(), 15);
316 EXPECT_EQ(rect.GetBottom(), max);
317 EXPECT_EQ(rect.GetX(), 5);
318 EXPECT_EQ(rect.GetY(), max - 10);
319 EXPECT_EQ(rect.GetWidth(), 10);
320 EXPECT_EQ(rect.GetHeight(), 10);
321 EXPECT_FALSE(rect.IsEmpty());
322 }
323
324 {
325 IRect rect = IRect::MakeXYWH(5, min + 10, 10, -16);
326
327 EXPECT_EQ(rect.GetLeft(), 5);
328 EXPECT_EQ(rect.GetTop(), min + 10);
329 EXPECT_EQ(rect.GetRight(), 15);
330 EXPECT_EQ(rect.GetBottom(), min);
331 EXPECT_EQ(rect.GetX(), 5);
332 EXPECT_EQ(rect.GetY(), min + 10);
333 EXPECT_EQ(rect.GetWidth(), 10);
334 EXPECT_EQ(rect.GetHeight(), -10);
335 EXPECT_TRUE(rect.IsEmpty());
336 }
337 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [250/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectRound |
| ) |  |

Definition at line 3049 of file rect_unittests.cc.

3049 {
3050 {
3051 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
3052 auto ir = IRect::MakeLTRB(-100, -200, 300, 400);
3053 EXPECT_EQ(IRect::Round(r), ir);
3054 }
3055 {
3056 auto r = Rect::MakeLTRB(-100.4, -200.4, 300.4, 400.4);
3057 auto ir = IRect::MakeLTRB(-100, -200, 300, 400);
3058 EXPECT_EQ(IRect::Round(r), ir);
3059 }
3060 {
3061 auto r = Rect::MakeLTRB(-100.5, -200.5, 300.5, 400.5);
3062 auto ir = IRect::MakeLTRB(-101, -201, 301, 401);
3063 EXPECT_EQ(IRect::Round(r), ir);
3064 }
3065 }

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

## ◆ TEST() [251/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectRoundOut |
| ) |  |

Definition at line 3021 of file rect_unittests.cc.

3021 {
3022 {
3023 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
3024 auto ir = IRect::MakeLTRB(-100, -200, 300, 400);
3025 EXPECT_EQ(IRect::RoundOut(r), ir);
3026 }
3027 {
3028 auto r = Rect::MakeLTRB(-100.1, -200.1, 300.1, 400.1);
3029 auto ir = IRect::MakeLTRB(-101, -201, 301, 401);
3030 EXPECT_EQ(IRect::RoundOut(r), ir);
3031 }
3032 }

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

## ◆ TEST() [252/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectScale |
| ) |  |

Definition at line 929 of file rect_unittests.cc.

929 {
930 auto test1 = [](IRect rect, int64_t scale) {
931 IRect expected = IRect::MakeXYWH(rect.GetX() * scale, //
932 rect.GetY() * scale, //
933 rect.GetWidth() * scale, //
934 rect.GetHeight() * scale);
935
936 EXPECT_EQ(rect.Scale(scale), expected) //
937 << rect << " * " << scale;
938 EXPECT_EQ(rect.Scale(scale, scale), expected) //
939 << rect << " * " << scale;
940 EXPECT_EQ(rect.Scale(IPoint(scale, scale)), expected) //
941 << rect << " * " << scale;
942 EXPECT_EQ(rect.Scale(ISize(scale, scale)), expected) //
943 << rect << " * " << scale;
944 };
945
946 auto test2 = [&test1](IRect rect, int64_t scale_x, int64_t scale_y) {
947 IRect expected = IRect::MakeXYWH(rect.GetX() * scale_x, //
948 rect.GetY() * scale_y, //
949 rect.GetWidth() * scale_x, //
950 rect.GetHeight() * scale_y);
951
952 EXPECT_EQ(rect.Scale(scale_x, scale_y), expected) //
953 << rect << " * " << scale_x << ", " << scale_y;
954 EXPECT_EQ(rect.Scale(IPoint(scale_x, scale_y)), expected) //
955 << rect << " * " << scale_x << ", " << scale_y;
956 EXPECT_EQ(rect.Scale(ISize(scale_x, scale_y)), expected) //
957 << rect << " * " << scale_x << ", " << scale_y;
958
959 test1(rect, scale_x);
960 test1(rect, scale_y);
961 };
962
963 test2(IRect::MakeLTRB(10, 15, 100, 150), 2, 3);
964 test2(IRect::MakeLTRB(10, 15, 100, 150), 3, 2);
965 test2(IRect::MakeLTRB(10, 15, -100, 150), 2, 3);
966 test2(IRect::MakeLTRB(10, 15, 100, -150), 2, 3);
967 test2(IRect::MakeLTRB(10, 15, 100, 150), -2, 3);
968 test2(IRect::MakeLTRB(10, 15, 100, 150), 2, -3);
969 }

References impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::MakeLTRB(), impeller::TRect< T >::MakeXYWH(), impeller::TRect< T >::Scale(), and scale.

## ◆ TEST() [253/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectSimpleLTRB |
| ) |  |

Definition at line 89 of file rect_unittests.cc.

89 {
90 IRect rect = IRect::MakeLTRB(5, 10, 20, 25);
91
92 EXPECT_EQ(rect.GetLeft(), 5);
93 EXPECT_EQ(rect.GetTop(), 10);
94 EXPECT_EQ(rect.GetRight(), 20);
95 EXPECT_EQ(rect.GetBottom(), 25);
96 EXPECT_EQ(rect.GetX(), 5);
97 EXPECT_EQ(rect.GetY(), 10);
98 EXPECT_EQ(rect.GetWidth(), 15);
99 EXPECT_EQ(rect.GetHeight(), 15);
100 EXPECT_FALSE(rect.IsEmpty());
101 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::MakeLTRB().

## ◆ TEST() [254/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectSimpleXYWH |
| ) |  |

Definition at line 119 of file rect_unittests.cc.

119 {
120 IRect rect = IRect::MakeXYWH(5, 10, 15, 16);
121
122 EXPECT_EQ(rect.GetLeft(), 5);
123 EXPECT_EQ(rect.GetTop(), 10);
124 EXPECT_EQ(rect.GetRight(), 20);
125 EXPECT_EQ(rect.GetBottom(), 26);
126 EXPECT_EQ(rect.GetX(), 5);
127 EXPECT_EQ(rect.GetY(), 10);
128 EXPECT_EQ(rect.GetWidth(), 15);
129 EXPECT_EQ(rect.GetHeight(), 16);
130 EXPECT_FALSE(rect.IsEmpty());
131 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [255/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectUnion |
| ) |  |

Definition at line 1456 of file rect_unittests.cc.

1456 {
1457 auto check_empty_flips = [](const IRect& a, const IRect& b,
1458 const std::string& label) {
1459 ASSERT_FALSE(a.IsEmpty());
1460 // b is allowed to be empty
1461
1462 // unflipped a vs flipped (empty) b yields a
1463 EXPECT_EQ(a.Union(flip_lr(b)), a) << label;
1464 EXPECT_EQ(a.Union(flip_tb(b)), a) << label;
1465 EXPECT_EQ(a.Union(flip_lrtb(b)), a) << label;
1466
1467 // flipped (empty) a vs unflipped b yields b
1468 EXPECT_EQ(flip_lr(a).Union(b), b) << label;
1469 EXPECT_EQ(flip_tb(a).Union(b), b) << label;
1470 EXPECT_EQ(flip_lrtb(a).Union(b), b) << label;
1471
1472 // flipped (empty) a vs flipped (empty) b yields empty
1473 EXPECT_TRUE(flip_lr(a).Union(flip_lr(b)).IsEmpty()) << label;
1474 EXPECT_TRUE(flip_tb(a).Union(flip_tb(b)).IsEmpty()) << label;
1475 EXPECT_TRUE(flip_lrtb(a).Union(flip_lrtb(b)).IsEmpty()) << label;
1476 };
1477
1478 auto test = [&check_empty_flips](const IRect& a, const IRect& b,
1479 const IRect& result) {
1480 ASSERT_FALSE(a.IsEmpty()) << a;
1481 // b is allowed to be empty
1482
1483 std::stringstream stream;
1484 stream << a << " union " << b;
1485 auto label = stream.str();
1486
1487 EXPECT_EQ(a.Union(b), result) << label;
1488 EXPECT_EQ(b.Union(a), result) << label;
1489 check_empty_flips(a, b, label);
1490 };
1491
1492 {
1493 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1494 auto b = IRect::MakeXYWH(0, 0, 0, 0);
1495 auto expected = IRect::MakeXYWH(100, 100, 100, 100);
1496 test(a, b, expected);
1497 }
1498
1499 {
1500 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1501 auto b = IRect::MakeXYWH(0, 0, 1, 1);
1502 auto expected = IRect::MakeXYWH(0, 0, 200, 200);
1503 test(a, b, expected);
1504 }
1505
1506 {
1507 auto a = IRect::MakeXYWH(100, 100, 100, 100);
1508 auto b = IRect::MakeXYWH(10, 10, 1, 1);
1509 auto expected = IRect::MakeXYWH(10, 10, 190, 190);
1510 test(a, b, expected);
1511 }
1512
1513 {
1514 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1515 auto b = IRect::MakeXYWH(10, 10, 100, 100);
1516 auto expected = IRect::MakeXYWH(0, 0, 110, 110);
1517 test(a, b, expected);
1518 }
1519
1520 {
1521 auto a = IRect::MakeXYWH(0, 0, 100, 100);
1522 auto b = IRect::MakeXYWH(100, 100, 100, 100);
1523 auto expected = IRect::MakeXYWH(0, 0, 200, 200);
1524 test(a, b, expected);
1525 }
1526 }

References impeller::saturated::b, flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::MakeXYWH(), and impeller::TRect< T >::Union().

## ◆ TEST() [256/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IRectXYWHIsEmpty |
| ) |  |

Definition at line 1151 of file rect_unittests.cc.

1151 {
1152 // Non-empty
1153 EXPECT_FALSE(IRect::MakeXYWH(1, 2, 10, 7).IsEmpty());
1154
1155 // Empty both width and height both 0 or negative, in all combinations
1156 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, 0).IsEmpty());
1157 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, -1).IsEmpty());
1158 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, 0).IsEmpty());
1159 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, -1).IsEmpty());
1160
1161 // Empty for 0 or negative width or height (but not both at the same time)
1162 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 10, 0).IsEmpty());
1163 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 10, -1).IsEmpty());
1164 EXPECT_TRUE(IRect::MakeXYWH(1, 2, 0, 7).IsEmpty());
1165 EXPECT_TRUE(IRect::MakeXYWH(1, 2, -1, 7).IsEmpty());
1166 }

References impeller::TRect< T >::MakeXYWH().

## ◆ TEST() [257/360]

impeller::testing::TEST | ( | RectTest | ,
|  | IsSquare |
| ) |  |

Definition at line 1182 of file rect_unittests.cc.

1182 {
1183 EXPECT_TRUE(Rect::MakeXYWH(10, 30, 20, 20).IsSquare());
1184 EXPECT_FALSE(Rect::MakeXYWH(10, 30, 20, 19).IsSquare());
1185 EXPECT_FALSE(Rect::MakeXYWH(10, 30, 19, 20).IsSquare());
1186 EXPECT_TRUE(Rect::MakeMaximum().IsSquare());
1187
1188 EXPECT_TRUE(IRect::MakeXYWH(10, 30, 20, 20).IsSquare());
1189 EXPECT_FALSE(IRect::MakeXYWH(10, 30, 20, 19).IsSquare());
1190 EXPECT_FALSE(IRect::MakeXYWH(10, 30, 19, 20).IsSquare());
1191 EXPECT_TRUE(IRect::MakeMaximum().IsSquare());
1192 }

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

## ◆ TEST() [258/360]

impeller::testing::TEST | ( | RectTest | ,
|  | MakePointBoundsQuad |
| ) |  |

Definition at line 1168 of file rect_unittests.cc.

1168 {
1169 Quad quad = {
1170 Point(10, 10),
1171 Point(20, 10),
1172 Point(10, 20),
1173 Point(20, 20),
1174 };
1175 std::optional<Rect> bounds = Rect::MakePointBounds(quad);
1176 EXPECT_TRUE(bounds.has_value());
1177 if (bounds.has_value()) {
1178 EXPECT_TRUE(RectNear(bounds.value(), Rect::MakeLTRB(10, 10, 20, 20)));
1179 }
1180 }

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

## ◆ TEST() [259/360]

impeller::testing::TEST | ( | RectTest | ,
|  | OptIRectIntersection |
| ) |  |

Definition at line 1846 of file rect_unittests.cc.

1846 {
1847 auto a = IRect::MakeLTRB(0, 0, 110, 110);
1848 auto b = IRect::MakeLTRB(100, 100, 200, 200);
1849 auto c = IRect::MakeLTRB(100, 0, 200, 110);
1850
1851 // NullOpt, NullOpt
1852 EXPECT_FALSE(IRect::Intersection(std::nullopt, std::nullopt).has_value());
1853 EXPECT_EQ(IRect::Intersection(std::nullopt, std::nullopt), std::nullopt);
1854
1855 auto test1 = [](const IRect& r) {
1856 // Rect, NullOpt
1857 EXPECT_TRUE(IRect::Intersection(r, std::nullopt).has_value());
1858 EXPECT_EQ(IRect::Intersection(r, std::nullopt).value(), r);
1859
1860 // OptRect, NullOpt
1861 EXPECT_TRUE(
1862 IRect::Intersection(std::optional(r), std::nullopt).has_value());
1863 EXPECT_EQ(IRect::Intersection(std::optional(r), std::nullopt).value(), r);
1864
1865 // NullOpt, Rect
1866 EXPECT_TRUE(IRect::Intersection(std::nullopt, r).has_value());
1867 EXPECT_EQ(IRect::Intersection(std::nullopt, r).value(), r);
1868
1869 // NullOpt, OptRect
1870 EXPECT_TRUE(
1871 IRect::Intersection(std::nullopt, std::optional(r)).has_value());
1872 EXPECT_EQ(IRect::Intersection(std::nullopt, std::optional(r)).value(), r);
1873 };
1874
1875 test1(a);
1876 test1(b);
1877 test1(c);
1878
1879 auto test2 = [](const IRect& a, const IRect& b, const IRect& i) {
1880 ASSERT_EQ(a.Intersection(b), i);
1881
1882 // Rect, OptRect
1883 EXPECT_TRUE(IRect::Intersection(a, std::optional(b)).has_value());
1884 EXPECT_EQ(IRect::Intersection(a, std::optional(b)).value(), i);
1885
1886 // OptRect, Rect
1887 EXPECT_TRUE(IRect::Intersection(std::optional(a), b).has_value());
1888 EXPECT_EQ(IRect::Intersection(std::optional(a), b).value(), i);
1889
1890 // OptRect, OptRect
1891 EXPECT_TRUE(
1892 IRect::Intersection(std::optional(a), std::optional(b)).has_value());
1893 EXPECT_EQ(IRect::Intersection(std::optional(a), std::optional(b)).value(),
1894 i);
1895 };
1896
1897 test2(a, b, IRect::MakeLTRB(100, 100, 110, 110));
1898 test2(a, c, IRect::MakeLTRB(100, 0, 110, 110));
1899 test2(b, c, IRect::MakeLTRB(100, 100, 200, 110));
1900 }

References impeller::saturated::b, impeller::TRect< T >::Intersection(), and impeller::TRect< T >::MakeLTRB().

## ◆ TEST() [260/360]

impeller::testing::TEST | ( | RectTest | ,
|  | OptIRectUnion |
| ) |  |

Definition at line 1528 of file rect_unittests.cc.

1528 {
1529 auto a = IRect::MakeLTRB(0, 0, 100, 100);
1530 auto b = IRect::MakeLTRB(100, 100, 200, 200);
1531 auto c = IRect::MakeLTRB(100, 0, 200, 100);
1532
1533 // NullOpt, NullOpt
1534 EXPECT_FALSE(IRect::Union(std::nullopt, std::nullopt).has_value());
1535 EXPECT_EQ(IRect::Union(std::nullopt, std::nullopt), std::nullopt);
1536
1537 auto test1 = [](const IRect& r) {
1538 // Rect, NullOpt
1539 EXPECT_TRUE(IRect::Union(r, std::nullopt).has_value());
1540 EXPECT_EQ(IRect::Union(r, std::nullopt).value(), r);
1541
1542 // OptRect, NullOpt
1543 EXPECT_TRUE(IRect::Union(std::optional(r), std::nullopt).has_value());
1544 EXPECT_EQ(IRect::Union(std::optional(r), std::nullopt).value(), r);
1545
1546 // NullOpt, Rect
1547 EXPECT_TRUE(IRect::Union(std::nullopt, r).has_value());
1548 EXPECT_EQ(IRect::Union(std::nullopt, r).value(), r);
1549
1550 // NullOpt, OptRect
1551 EXPECT_TRUE(IRect::Union(std::nullopt, std::optional(r)).has_value());
1552 EXPECT_EQ(IRect::Union(std::nullopt, std::optional(r)).value(), r);
1553 };
1554
1555 test1(a);
1556 test1(b);
1557 test1(c);
1558
1559 auto test2 = [](const IRect& a, const IRect& b, const IRect& u) {
1560 ASSERT_EQ(a.Union(b), u);
1561
1562 // Rect, OptRect
1563 EXPECT_TRUE(IRect::Union(a, std::optional(b)).has_value());
1564 EXPECT_EQ(IRect::Union(a, std::optional(b)).value(), u);
1565
1566 // OptRect, Rect
1567 EXPECT_TRUE(IRect::Union(std::optional(a), b).has_value());
1568 EXPECT_EQ(IRect::Union(std::optional(a), b).value(), u);
1569
1570 // OptRect, OptRect
1571 EXPECT_TRUE(IRect::Union(std::optional(a), std::optional(b)).has_value());
1572 EXPECT_EQ(IRect::Union(std::optional(a), std::optional(b)).value(), u);
1573 };
1574
1575 test2(a, b, IRect::MakeLTRB(0, 0, 200, 200));
1576 test2(a, c, IRect::MakeLTRB(0, 0, 200, 100));
1577 test2(b, c, IRect::MakeLTRB(100, 0, 200, 200));
1578 }

References impeller::saturated::b, impeller::TRect< T >::MakeLTRB(), and impeller::TRect< T >::Union().

## ◆ TEST() [261/360]

impeller::testing::TEST | ( | RectTest | ,
|  | OptRectIntersection |
| ) |  |

Definition at line 1697 of file rect_unittests.cc.

1697 {
1698 auto a = Rect::MakeLTRB(0, 0, 110, 110);
1699 auto b = Rect::MakeLTRB(100, 100, 200, 200);
1700 auto c = Rect::MakeLTRB(100, 0, 200, 110);
1701
1702 // NullOpt, NullOpt
1703 EXPECT_FALSE(Rect::Intersection(std::nullopt, std::nullopt).has_value());
1704 EXPECT_EQ(Rect::Intersection(std::nullopt, std::nullopt), std::nullopt);
1705
1706 auto test1 = [](const Rect& r) {
1707 // Rect, NullOpt
1708 EXPECT_TRUE(Rect::Intersection(r, std::nullopt).has_value());
1709 EXPECT_EQ(Rect::Intersection(r, std::nullopt).value(), r);
1710
1711 // OptRect, NullOpt
1712 EXPECT_TRUE(Rect::Intersection(std::optional(r), std::nullopt).has_value());
1713 EXPECT_EQ(Rect::Intersection(std::optional(r), std::nullopt).value(), r);
1714
1715 // NullOpt, Rect
1716 EXPECT_TRUE(Rect::Intersection(std::nullopt, r).has_value());
1717 EXPECT_EQ(Rect::Intersection(std::nullopt, r).value(), r);
1718
1719 // NullOpt, OptRect
1720 EXPECT_TRUE(Rect::Intersection(std::nullopt, std::optional(r)).has_value());
1721 EXPECT_EQ(Rect::Intersection(std::nullopt, std::optional(r)).value(), r);
1722 };
1723
1724 test1(a);
1725 test1(b);
1726 test1(c);
1727
1728 auto test2 = [](const Rect& a, const Rect& b, const Rect& i) {
1729 ASSERT_EQ(a.Intersection(b), i);
1730
1731 // Rect, OptRect
1732 EXPECT_TRUE(Rect::Intersection(a, std::optional(b)).has_value());
1733 EXPECT_EQ(Rect::Intersection(a, std::optional(b)).value(), i);
1734
1735 // OptRect, Rect
1736 EXPECT_TRUE(Rect::Intersection(std::optional(a), b).has_value());
1737 EXPECT_EQ(Rect::Intersection(std::optional(a), b).value(), i);
1738
1739 // OptRect, OptRect
1740 EXPECT_TRUE(
1741 Rect::Intersection(std::optional(a), std::optional(b)).has_value());
1742 EXPECT_EQ(Rect::Intersection(std::optional(a), std::optional(b)).value(),
1743 i);
1744 };
1745
1746 test2(a, b, Rect::MakeLTRB(100, 100, 110, 110));
1747 test2(a, c, Rect::MakeLTRB(100, 0, 110, 110));
1748 test2(b, c, Rect::MakeLTRB(100, 100, 200, 110));
1749 }

References impeller::saturated::b, impeller::TRect< T >::Intersection(), impeller::TRect< Scalar >::Intersection(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [262/360]

impeller::testing::TEST | ( | RectTest | ,
|  | OptRectUnion |
| ) |  |

Definition at line 1404 of file rect_unittests.cc.

1404 {
1405 auto a = Rect::MakeLTRB(0, 0, 100, 100);
1406 auto b = Rect::MakeLTRB(100, 100, 200, 200);
1407 auto c = Rect::MakeLTRB(100, 0, 200, 100);
1408
1409 // NullOpt, NullOpt
1410 EXPECT_FALSE(Rect::Union(std::nullopt, std::nullopt).has_value());
1411 EXPECT_EQ(Rect::Union(std::nullopt, std::nullopt), std::nullopt);
1412
1413 auto test1 = [](const Rect& r) {
1414 // Rect, NullOpt
1415 EXPECT_TRUE(Rect::Union(r, std::nullopt).has_value());
1416 EXPECT_EQ(Rect::Union(r, std::nullopt).value(), r);
1417
1418 // OptRect, NullOpt
1419 EXPECT_TRUE(Rect::Union(std::optional(r), std::nullopt).has_value());
1420 EXPECT_EQ(Rect::Union(std::optional(r), std::nullopt).value(), r);
1421
1422 // NullOpt, Rect
1423 EXPECT_TRUE(Rect::Union(std::nullopt, r).has_value());
1424 EXPECT_EQ(Rect::Union(std::nullopt, r).value(), r);
1425
1426 // NullOpt, OptRect
1427 EXPECT_TRUE(Rect::Union(std::nullopt, std::optional(r)).has_value());
1428 EXPECT_EQ(Rect::Union(std::nullopt, std::optional(r)).value(), r);
1429 };
1430
1431 test1(a);
1432 test1(b);
1433 test1(c);
1434
1435 auto test2 = [](const Rect& a, const Rect& b, const Rect& u) {
1436 ASSERT_EQ(a.Union(b), u);
1437
1438 // Rect, OptRect
1439 EXPECT_TRUE(Rect::Union(a, std::optional(b)).has_value());
1440 EXPECT_EQ(Rect::Union(a, std::optional(b)).value(), u);
1441
1442 // OptRect, Rect
1443 EXPECT_TRUE(Rect::Union(std::optional(a), b).has_value());
1444 EXPECT_EQ(Rect::Union(std::optional(a), b).value(), u);
1445
1446 // OptRect, OptRect
1447 EXPECT_TRUE(Rect::Union(std::optional(a), std::optional(b)).has_value());
1448 EXPECT_EQ(Rect::Union(std::optional(a), std::optional(b)).value(), u);
1449 };
1450
1451 test2(a, b, Rect::MakeLTRB(0, 0, 200, 200));
1452 test2(a, c, Rect::MakeLTRB(0, 0, 200, 100));
1453 test2(b, c, Rect::MakeLTRB(100, 0, 200, 200));
1454 }

References impeller::saturated::b, impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::Union(), and impeller::TRect< T >::Union().

## ◆ TEST() [263/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectArea |
| ) |  |

Definition at line 971 of file rect_unittests.cc.

971 {
972 EXPECT_EQ(Rect::MakeXYWH(0, 0, 100, 200).Area(), 20000);
973 EXPECT_EQ(Rect::MakeXYWH(10, 20, 100, 200).Area(), 20000);
974 EXPECT_EQ(Rect::MakeXYWH(0, 0, 200, 100).Area(), 20000);
975 EXPECT_EQ(Rect::MakeXYWH(10, 20, 200, 100).Area(), 20000);
976 EXPECT_EQ(Rect::MakeXYWH(0, 0, 100, 100).Area(), 10000);
977 EXPECT_EQ(Rect::MakeXYWH(10, 20, 100, 100).Area(), 10000);
978 }

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

## ◆ TEST() [264/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectContainsInclusivePoint |
| ) |  |

Definition at line 2262 of file rect_unittests.cc.

2262 {
2263 auto check_nans = [](const Rect& rect, const Point& point,
2264 const std::string& label) {
2265 ASSERT_TRUE(rect.IsFinite()) << label;
2266 ASSERT_TRUE(point.IsFinite()) << label;
2267
2268 for (int i = 1; i < 16; i++) {
2269 EXPECT_FALSE(swap_nan(rect, i).ContainsInclusive(point))
2270 << label << ", index = " << i;
2271 for (int j = 1; j < 4; j++) {
2272 EXPECT_FALSE(swap_nan(rect, i).ContainsInclusive(swap_nan(point, j)))
2273 << label << ", indices = " << i << ", " << j;
2274 }
2275 }
2276 };
2277
2278 auto check_empty_flips = [](const Rect& rect, const Point& point,
2279 const std::string& label) {
2280 ASSERT_FALSE(rect.IsEmpty());
2281
2282 EXPECT_FALSE(flip_lr(rect).ContainsInclusive(point)) << label;
2283 EXPECT_FALSE(flip_tb(rect).ContainsInclusive(point)) << label;
2284 EXPECT_FALSE(flip_lrtb(rect).ContainsInclusive(point)) << label;
2285 };
2286
2287 auto test_inside = [&check_nans, &check_empty_flips](const Rect& rect,
2288 const Point& point) {
2289 ASSERT_FALSE(rect.IsEmpty()) << rect;
2290
2291 std::stringstream stream;
2292 stream << rect << " contains " << point;
2293 auto label = stream.str();
2294
2295 EXPECT_TRUE(rect.ContainsInclusive(point)) << label;
2296 check_empty_flips(rect, point, label);
2297 check_nans(rect, point, label);
2298 };
2299
2300 auto test_outside = [&check_nans, &check_empty_flips](const Rect& rect,
2301 const Point& point) {
2302 ASSERT_FALSE(rect.IsEmpty()) << rect;
2303
2304 std::stringstream stream;
2305 stream << rect << " contains " << point;
2306 auto label = stream.str();
2307
2308 EXPECT_FALSE(rect.ContainsInclusive(point)) << label;
2309 check_empty_flips(rect, point, label);
2310 check_nans(rect, point, label);
2311 };
2312
2313 {
2314 // Origin is inclusive
2315 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2316 auto p = Point(100, 100);
2317
2318 test_inside(r, p);
2319 }
2320 {
2321 // Size is inclusive
2322 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2323 auto p = Point(200, 200);
2324
2325 test_inside(r, p);
2326 }
2327 {
2328 // Size + epsilon is exclusive
2329 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2330 auto p = Point(200 + kEhCloseEnough, 200 + kEhCloseEnough);
2331
2332 test_outside(r, p);
2333 }
2334 {
2335 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2336 auto p = Point(99, 99);
2337
2338 test_outside(r, p);
2339 }
2340 {
2341 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2342 auto p = Point(199, 199);
2343
2344 test_inside(r, p);
2345 }
2346
2347 {
2348 auto r = Rect::MakeMaximum();
2349 auto p = Point(199, 199);
2350
2351 test_inside(r, p);
2352 }
2353 }

References flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), impeller::kEhCloseEnough, impeller::TRect< Scalar >::MakeMaximum(), impeller::TRect< Scalar >::MakeXYWH(), and swap_nan().

## ◆ TEST() [265/360]

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

Definition at line 2107 of file rect_unittests.cc.

2107 {
2108 auto check_nans = [](const Rect& rect, const Point& point,
2109 const std::string& label) {
2110 ASSERT_TRUE(rect.IsFinite()) << label;
2111 ASSERT_TRUE(point.IsFinite()) << label;
2112
2113 for (int i = 1; i < 16; i++) {
2114 EXPECT_FALSE(swap_nan(rect, i).Contains(point))
2115 << label << ", index = " << i;
2116 for (int j = 1; j < 4; j++) {
2117 EXPECT_FALSE(swap_nan(rect, i).Contains(swap_nan(point, j)))
2118 << label << ", indices = " << i << ", " << j;
2119 }
2120 }
2121 };
2122
2123 auto check_empty_flips = [](const Rect& rect, const Point& point,
2124 const std::string& label) {
2125 ASSERT_FALSE(rect.IsEmpty());
2126
2127 EXPECT_FALSE(flip_lr(rect).Contains(point)) << label;
2128 EXPECT_FALSE(flip_tb(rect).Contains(point)) << label;
2129 EXPECT_FALSE(flip_lrtb(rect).Contains(point)) << label;
2130 };
2131
2132 auto test_inside = [&check_nans, &check_empty_flips](const Rect& rect,
2133 const Point& point) {
2134 ASSERT_FALSE(rect.IsEmpty()) << rect;
2135
2136 std::stringstream stream;
2137 stream << rect << " contains " << point;
2138 auto label = stream.str();
2139
2140 EXPECT_TRUE(rect.Contains(point)) << label;
2141 check_empty_flips(rect, point, label);
2142 check_nans(rect, point, label);
2143 };
2144
2145 auto test_outside = [&check_nans, &check_empty_flips](const Rect& rect,
2146 const Point& point) {
2147 ASSERT_FALSE(rect.IsEmpty()) << rect;
2148
2149 std::stringstream stream;
2150 stream << rect << " contains " << point;
2151 auto label = stream.str();
2152
2153 EXPECT_FALSE(rect.Contains(point)) << label;
2154 check_empty_flips(rect, point, label);
2155 check_nans(rect, point, label);
2156 };
2157
2158 {
2159 // Origin is inclusive
2160 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2161 auto p = Point(100, 100);
2162
2163 test_inside(r, p);
2164 }
2165 {
2166 // Size is exclusive
2167 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2168 auto p = Point(200, 200);
2169
2170 test_outside(r, p);
2171 }
2172 {
2173 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2174 auto p = Point(99, 99);
2175
2176 test_outside(r, p);
2177 }
2178 {
2179 auto r = Rect::MakeXYWH(100, 100, 100, 100);
2180 auto p = Point(199, 199);
2181
2182 test_inside(r, p);
2183 }
2184
2185 {
2186 auto r = Rect::MakeMaximum();
2187 auto p = Point(199, 199);
2188
2189 test_inside(r, p);
2190 }
2191 }

References flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), impeller::TRect< Scalar >::MakeMaximum(), impeller::TRect< Scalar >::MakeXYWH(), and swap_nan().

## ◆ TEST() [266/360]

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

Definition at line 2431 of file rect_unittests.cc.

2431 {
2432 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
2433 ASSERT_TRUE(a.IsFinite()) << label;
2434 ASSERT_TRUE(b.IsFinite()) << label;
2435 ASSERT_FALSE(a.IsEmpty());
2436
2437 for (int i = 1; i < 16; i++) {
2438 // NaN in a produces false
2439 EXPECT_FALSE(swap_nan(a, i).Contains(b)) << label << ", index = " << i;
2440 // NaN in b produces false
2441 EXPECT_TRUE(a.Contains(swap_nan(b, i))) << label << ", index = " << i;
2442 // NaN in both is false
2443 for (int j = 1; j < 16; j++) {
2444 EXPECT_FALSE(swap_nan(a, i).Contains(swap_nan(b, j)))
2445 << label << ", indices = " << i << ", " << j;
2446 }
2447 }
2448 };
2449
2450 auto check_empty_flips = [](const Rect& a, const Rect& b,
2451 const std::string& label) {
2452 ASSERT_FALSE(a.IsEmpty());
2453 // test b rects are allowed to have 0 w/h, but not be backwards
2454 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2455
2456 // unflipped a vs flipped (empty) b yields false
2457 EXPECT_TRUE(a.Contains(flip_lr(b))) << label;
2458 EXPECT_TRUE(a.Contains(flip_tb(b))) << label;
2459 EXPECT_TRUE(a.Contains(flip_lrtb(b))) << label;
2460
2461 // flipped (empty) a vs unflipped b yields false
2462 EXPECT_FALSE(flip_lr(a).Contains(b)) << label;
2463 EXPECT_FALSE(flip_tb(a).Contains(b)) << label;
2464 EXPECT_FALSE(flip_lrtb(a).Contains(b)) << label;
2465
2466 // flipped (empty) a vs flipped (empty) b yields empty
2467 EXPECT_FALSE(flip_lr(a).Contains(flip_lr(b))) << label;
2468 EXPECT_FALSE(flip_tb(a).Contains(flip_tb(b))) << label;
2469 EXPECT_FALSE(flip_lrtb(a).Contains(flip_lrtb(b))) << label;
2470 };
2471
2472 auto test_inside = [&check_nans, &check_empty_flips](const Rect& a,
2473 const Rect& b) {
2474 ASSERT_FALSE(a.IsEmpty()) << a;
2475 // test b rects are allowed to have 0 w/h, but not be backwards
2476 ASSERT_FALSE(b.GetLeft() > b.GetRight() || b.GetTop() > b.GetBottom());
2477
2478 std::stringstream stream;
2479 stream << a << " contains " << b;
2480 auto label = stream.str();
2481
2482 EXPECT_TRUE(a.Contains(b)) << label;
2483 check_empty_flips(a, b, label);
2484 check_nans(a, b, label);
2485 };
2486
2487 auto test_not_inside = [&check_nans, &check_empty_flips](const Rect& a,
2488 const Rect& b) {
2489 ASSERT_FALSE(a.IsEmpty()) << a;
2490 // If b was empty, it would be contained and should not be tested with
2491 // this function - use |test_inside| instead.
2492 ASSERT_FALSE(b.IsEmpty()) << b;
2493
2494 std::stringstream stream;
2495 stream << a << " contains " << b;
2496 auto label = stream.str();
2497
2498 EXPECT_FALSE(a.Contains(b)) << label;
2499 check_empty_flips(a, b, label);
2500 check_nans(a, b, label);
2501 };
2502
2503 {
2504 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2505
2506 test_inside(a, a);
2507 }
2508 {
2509 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2510 auto b = Rect::MakeXYWH(0, 0, 0, 0);
2511
2512 test_inside(a, b);
2513 }
2514 {
2515 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2516 auto b = Rect::MakeXYWH(150, 150, 20, 20);
2517
2518 test_inside(a, b);
2519 }
2520 {
2521 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2522 auto b = Rect::MakeXYWH(150, 150, 100, 100);
2523
2524 test_not_inside(a, b);
2525 }
2526 {
2527 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2528 auto b = Rect::MakeXYWH(50, 50, 100, 100);
2529
2530 test_not_inside(a, b);
2531 }
2532 {
2533 auto a = Rect::MakeXYWH(100, 100, 100, 100);
2534 auto b = Rect::MakeXYWH(0, 0, 300, 300);
2535
2536 test_not_inside(a, b);
2537 }
2538 {
2539 auto a = Rect::MakeMaximum();
2540 auto b = Rect::MakeXYWH(0, 0, 300, 300);
2541
2542 test_inside(a, b);
2543 }
2544 }

References impeller::saturated::b, impeller::TRect< T >::Contains(), flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), impeller::TRect< Scalar >::MakeMaximum(), impeller::TRect< Scalar >::MakeXYWH(), and swap_nan().

## ◆ TEST() [267/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectCopy |
| ) |  |

Definition at line 623 of file rect_unittests.cc.

623 {
624 // Using fractional-power-of-2 friendly values for equality tests
625 Rect rect = Rect::MakeLTRB(5.125f, 10.25f, 20.625f, 25.375f);
626 Rect copy = rect;
627
628 EXPECT_EQ(rect, copy);
629 EXPECT_EQ(copy.GetLeft(), 5.125f);
630 EXPECT_EQ(copy.GetTop(), 10.25f);
631 EXPECT_EQ(copy.GetRight(), 20.625f);
632 EXPECT_EQ(copy.GetBottom(), 25.375f);
633 EXPECT_EQ(copy.GetX(), 5.125f);
634 EXPECT_EQ(copy.GetY(), 10.25f);
635 EXPECT_EQ(copy.GetWidth(), 15.5f);
636 EXPECT_EQ(copy.GetHeight(), 15.125f);
637 EXPECT_FALSE(copy.IsEmpty());
638 EXPECT_TRUE(copy.IsFinite());
639 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [268/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectCutOut |
| ) |  |

Definition at line 2639 of file rect_unittests.cc.

2639 {
2640 Rect cull_rect = Rect::MakeLTRB(20, 20, 40, 40);
2641
2642 auto check_nans = [&cull_rect](const Rect& diff_rect,
2643 const std::string& label) {
2644 EXPECT_TRUE(cull_rect.IsFinite()) << label;
2645 EXPECT_TRUE(diff_rect.IsFinite()) << label;
2646
2647 for (int i = 1; i < 16; i++) {
2648 // NaN in cull_rect produces empty
2649 EXPECT_FALSE(swap_nan(cull_rect, i).Cutout(diff_rect).has_value())
2650 << label << ", index " << i;
2651 EXPECT_EQ(swap_nan(cull_rect, i).CutoutOrEmpty(diff_rect), Rect())
2652 << label << ", index " << i;
2653
2654 // NaN in diff_rect is nop
2655 EXPECT_TRUE(cull_rect.Cutout(swap_nan(diff_rect, i)).has_value())
2656 << label << ", index " << i;
2657 EXPECT_EQ(cull_rect.CutoutOrEmpty(swap_nan(diff_rect, i)), cull_rect)
2658 << label << ", index " << i;
2659
2660 for (int j = 1; j < 16; j++) {
2661 // NaN in both is also empty
2662 EXPECT_FALSE(
2663 swap_nan(cull_rect, i).Cutout(swap_nan(diff_rect, j)).has_value())
2664 << label << ", indices " << i << ", " << j;
2665 EXPECT_EQ(swap_nan(cull_rect, i).CutoutOrEmpty(swap_nan(diff_rect, j)),
2666 Rect())
2667 << label << ", indices " << i << ", " << j;
2668 }
2669 }
2670 };
2671
2672 auto check_empty_flips = [&cull_rect](const Rect& diff_rect,
2673 const std::string& label) {
2674 EXPECT_FALSE(cull_rect.IsEmpty()) << label;
2675 EXPECT_FALSE(diff_rect.IsEmpty()) << label;
2676
2677 // unflipped cull_rect vs flipped(empty) diff_rect
2678 // == cull_rect
2679 EXPECT_TRUE(cull_rect.Cutout(flip_lr(diff_rect)).has_value()) << label;
2680 EXPECT_EQ(cull_rect.Cutout(flip_lr(diff_rect)), cull_rect) << label;
2681 EXPECT_TRUE(cull_rect.Cutout(flip_tb(diff_rect)).has_value()) << label;
2682 EXPECT_EQ(cull_rect.Cutout(flip_tb(diff_rect)), cull_rect) << label;
2683 EXPECT_TRUE(cull_rect.Cutout(flip_lrtb(diff_rect)).has_value()) << label;
2684 EXPECT_EQ(cull_rect.Cutout(flip_lrtb(diff_rect)), cull_rect) << label;
2685
2686 // flipped(empty) cull_rect vs unflipped diff_rect
2687 // == empty
2688 EXPECT_FALSE(flip_lr(cull_rect).Cutout(diff_rect).has_value()) << label;
2689 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(diff_rect), Rect()) << label;
2690 EXPECT_FALSE(flip_tb(cull_rect).Cutout(diff_rect).has_value()) << label;
2691 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(diff_rect), Rect()) << label;
2692 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(diff_rect).has_value()) << label;
2693 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(diff_rect), Rect()) << label;
2694
2695 // flipped(empty) cull_rect vs flipped(empty) diff_rect
2696 // == empty
2697 EXPECT_FALSE(flip_lr(cull_rect).Cutout(flip_lr(diff_rect)).has_value())
2698 << label;
2699 EXPECT_EQ(flip_lr(cull_rect).CutoutOrEmpty(flip_lr(diff_rect)), Rect())
2700 << label;
2701 EXPECT_FALSE(flip_tb(cull_rect).Cutout(flip_tb(diff_rect)).has_value())
2702 << label;
2703 EXPECT_EQ(flip_tb(cull_rect).CutoutOrEmpty(flip_tb(diff_rect)), Rect())
2704 << label;
2705 EXPECT_FALSE(flip_lrtb(cull_rect).Cutout(flip_lrtb(diff_rect)).has_value())
2706 << label;
2707 EXPECT_EQ(flip_lrtb(cull_rect).CutoutOrEmpty(flip_lrtb(diff_rect)), Rect())
2708 << label;
2709 };
2710
2711 auto non_reducing = [&cull_rect, &check_empty_flips, &check_nans](
2712 const Rect& diff_rect, const std::string& label) {
2713 EXPECT_EQ(cull_rect.Cutout(diff_rect), cull_rect) << label;
2714 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), cull_rect) << label;
2715 check_empty_flips(diff_rect, label);
2716 check_nans(diff_rect, label);
2717 };
2718
2719 auto reducing = [&cull_rect, &check_empty_flips, &check_nans](
2720 const Rect& diff_rect, const Rect& result_rect,
2721 const std::string& label) {
2722 EXPECT_TRUE(!result_rect.IsEmpty());
2723 EXPECT_EQ(cull_rect.Cutout(diff_rect), result_rect) << label;
2724 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), result_rect) << label;
2725 check_empty_flips(diff_rect, label);
2726 check_nans(diff_rect, label);
2727 };
2728
2729 auto emptying = [&cull_rect, &check_empty_flips, &check_nans](
2730 const Rect& diff_rect, const std::string& label) {
2731 EXPECT_FALSE(cull_rect.Cutout(diff_rect).has_value()) << label;
2732 EXPECT_EQ(cull_rect.CutoutOrEmpty(diff_rect), Rect()) << label;
2733 check_empty_flips(diff_rect, label);
2734 check_nans(diff_rect, label);
2735 };
2736
2737 // Skim the corners and edge
2738 non_reducing(Rect::MakeLTRB(10, 10, 20, 20), "outside UL corner");
2739 non_reducing(Rect::MakeLTRB(20, 10, 40, 20), "Above");
2740 non_reducing(Rect::MakeLTRB(40, 10, 50, 20), "outside UR corner");
2741 non_reducing(Rect::MakeLTRB(40, 20, 50, 40), "Right");
2742 non_reducing(Rect::MakeLTRB(40, 40, 50, 50), "outside LR corner");
2743 non_reducing(Rect::MakeLTRB(20, 40, 40, 50), "Below");
2744 non_reducing(Rect::MakeLTRB(10, 40, 20, 50), "outside LR corner");
2745 non_reducing(Rect::MakeLTRB(10, 20, 20, 40), "Left");
2746
2747 // Overlap corners
2748 non_reducing(Rect::MakeLTRB(15, 15, 25, 25), "covering UL corner");
2749 non_reducing(Rect::MakeLTRB(35, 15, 45, 25), "covering UR corner");
2750 non_reducing(Rect::MakeLTRB(35, 35, 45, 45), "covering LR corner");
2751 non_reducing(Rect::MakeLTRB(15, 35, 25, 45), "covering LL corner");
2752
2753 // Overlap edges, but not across an entire side
2754 non_reducing(Rect::MakeLTRB(20, 15, 39, 25), "Top edge left-biased");
2755 non_reducing(Rect::MakeLTRB(21, 15, 40, 25), "Top edge, right biased");
2756 non_reducing(Rect::MakeLTRB(35, 20, 45, 39), "Right edge, top-biased");
2757 non_reducing(Rect::MakeLTRB(35, 21, 45, 40), "Right edge, bottom-biased");
2758 non_reducing(Rect::MakeLTRB(20, 35, 39, 45), "Bottom edge, left-biased");
2759 non_reducing(Rect::MakeLTRB(21, 35, 40, 45), "Bottom edge, right-biased");
2760 non_reducing(Rect::MakeLTRB(15, 20, 25, 39), "Left edge, top-biased");
2761 non_reducing(Rect::MakeLTRB(15, 21, 25, 40), "Left edge, bottom-biased");
2762
2763 // Slice all the way through the middle
2764 non_reducing(Rect::MakeLTRB(25, 15, 35, 45), "Vertical interior slice");
2765 non_reducing(Rect::MakeLTRB(15, 25, 45, 35), "Horizontal interior slice");
2766
2767 // Slice off each edge
2768 reducing(Rect::MakeLTRB(20, 15, 40, 25), //
2769 Rect::MakeLTRB(20, 25, 40, 40), //
2770 "Slice off top");
2771 reducing(Rect::MakeLTRB(35, 20, 45, 40), //
2772 Rect::MakeLTRB(20, 20, 35, 40), //
2773 "Slice off right");
2774 reducing(Rect::MakeLTRB(20, 35, 40, 45), //
2775 Rect::MakeLTRB(20, 20, 40, 35), //
2776 "Slice off bottom");
2777 reducing(Rect::MakeLTRB(15, 20, 25, 40), //
2778 Rect::MakeLTRB(25, 20, 40, 40), //
2779 "Slice off left");
2780
2781 // cull rect contains diff rect
2782 non_reducing(Rect::MakeLTRB(21, 21, 39, 39), "Contained, non-covering");
2783
2784 // cull rect equals diff rect
2785 emptying(cull_rect, "Perfectly covering");
2786
2787 // diff rect contains cull rect
2788 emptying(Rect::MakeLTRB(15, 15, 45, 45), "Smothering");
2789 }

References impeller::TRect< T >::Cutout(), impeller::TRect< T >::CutoutOrEmpty(), flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), impeller::TRect< Scalar >::MakeLTRB(), and swap_nan().

## ◆ TEST() [269/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectDefaultConstructor |
| ) |  |

Definition at line 44 of file rect_unittests.cc.

44 {
45 Rect rect = Rect();
46
47 EXPECT_EQ(rect.GetLeft(), 0.0f);
48 EXPECT_EQ(rect.GetTop(), 0.0f);
49 EXPECT_EQ(rect.GetRight(), 0.0f);
50 EXPECT_EQ(rect.GetBottom(), 0.0f);
51 EXPECT_EQ(rect.GetX(), 0.0f);
52 EXPECT_EQ(rect.GetY(), 0.0f);
53 EXPECT_EQ(rect.GetWidth(), 0.0f);
54 EXPECT_EQ(rect.GetHeight(), 0.0f);
55 EXPECT_TRUE(rect.IsEmpty());
56 EXPECT_TRUE(rect.IsFinite());
57 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::IsFinite().

## ◆ TEST() [270/360]

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

Definition at line 2981 of file rect_unittests.cc.

2981 {
2982 auto r = Rect::MakeLTRB(1, 2, 3, 4);
2983
2984 EXPECT_EQ(r.GetLeft(), 1);
2985 EXPECT_EQ(r.GetTop(), 2);
2986 EXPECT_EQ(r.GetRight(), 3);
2987 EXPECT_EQ(r.GetBottom(), 4);
2988
2989 EXPECT_POINT_NEAR(r.GetLeftTop(), Point(1, 2));
2990 EXPECT_POINT_NEAR(r.GetRightTop(), Point(3, 2));
2991 EXPECT_POINT_NEAR(r.GetLeftBottom(), Point(1, 4));
2992 EXPECT_POINT_NEAR(r.GetRightBottom(), Point(3, 4));
2993 }

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

## ◆ TEST() [271/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectDoesNotIntersectEmpty |
| ) |  |

Definition at line 764 of file rect_unittests.cc.

764 {
765 Rect rect = Rect::MakeLTRB(50, 50, 100, 100);
766
767 auto test = [&rect](Scalar l, Scalar t, Scalar r, Scalar b,
768 const std::string& label) {
769 EXPECT_FALSE(rect.IntersectsWithRect(Rect::MakeLTRB(l, b, r, t)))
770 << label << " with Top/Bottom swapped";
771 EXPECT_FALSE(rect.IntersectsWithRect(Rect::MakeLTRB(r, b, l, t)))
772 << label << " with Left/Right swapped";
773 EXPECT_FALSE(rect.IntersectsWithRect(Rect::MakeLTRB(r, t, l, b)))
774 << label << " with all sides swapped";
775 };
776
777 test(20, 20, 30, 30, "Above and Left");
778 test(70, 20, 80, 30, "Above");
779 test(120, 20, 130, 30, "Above and Right");
780 test(120, 70, 130, 80, "Right");
781 test(120, 120, 130, 130, "Below and Right");
782 test(70, 120, 80, 130, "Below");
783 test(20, 120, 30, 130, "Below and Left");
784 test(20, 70, 30, 80, "Left");
785
786 test(70, 70, 80, 80, "Inside");
787
788 test(40, 70, 60, 80, "Straddling Left");
789 test(70, 40, 80, 60, "Straddling Top");
790 test(90, 70, 110, 80, "Straddling Right");
791 test(70, 90, 80, 110, "Straddling Bottom");
792 }

References impeller::saturated::b, impeller::TRect< T >::IntersectsWithRect(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [272/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectEmptyDeclaration |
| ) |  |

Definition at line 14 of file rect_unittests.cc.

14 {
15 Rect rect;
16
17 EXPECT_EQ(rect.GetLeft(), 0.0f);
18 EXPECT_EQ(rect.GetTop(), 0.0f);
19 EXPECT_EQ(rect.GetRight(), 0.0f);
20 EXPECT_EQ(rect.GetBottom(), 0.0f);
21 EXPECT_EQ(rect.GetX(), 0.0f);
22 EXPECT_EQ(rect.GetY(), 0.0f);
23 EXPECT_EQ(rect.GetWidth(), 0.0f);
24 EXPECT_EQ(rect.GetHeight(), 0.0f);
25 EXPECT_TRUE(rect.IsEmpty());
26 EXPECT_TRUE(rect.IsFinite());
27 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), and impeller::TRect< T >::IsFinite().

## ◆ TEST() [273/360]

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

Definition at line 1205 of file rect_unittests.cc.

1205 {
1206 auto rect = Rect::MakeLTRB(100, 100, 200, 200);
1207
1208 // Expand(T amount)
1209 EXPECT_EQ(rect.Expand(10), Rect::MakeLTRB(90, 90, 210, 210));
1210 EXPECT_EQ(rect.Expand(-10), Rect::MakeLTRB(110, 110, 190, 190));
1211
1212 // Expand(amount, amount)
1213 EXPECT_EQ(rect.Expand(10, 10), Rect::MakeLTRB(90, 90, 210, 210));
1214 EXPECT_EQ(rect.Expand(10, -10), Rect::MakeLTRB(90, 110, 210, 190));
1215 EXPECT_EQ(rect.Expand(-10, 10), Rect::MakeLTRB(110, 90, 190, 210));
1216 EXPECT_EQ(rect.Expand(-10, -10), Rect::MakeLTRB(110, 110, 190, 190));
1217
1218 // Expand(amount, amount, amount, amount)
1219 EXPECT_EQ(rect.Expand(10, 20, 30, 40), Rect::MakeLTRB(90, 80, 230, 240));
1220 EXPECT_EQ(rect.Expand(-10, 20, 30, 40), Rect::MakeLTRB(110, 80, 230, 240));
1221 EXPECT_EQ(rect.Expand(10, -20, 30, 40), Rect::MakeLTRB(90, 120, 230, 240));
1222 EXPECT_EQ(rect.Expand(10, 20, -30, 40), Rect::MakeLTRB(90, 80, 170, 240));
1223 EXPECT_EQ(rect.Expand(10, 20, 30, -40), Rect::MakeLTRB(90, 80, 230, 160));
1224
1225 // Expand(Point amount)
1226 EXPECT_EQ(rect.Expand(Point{10, 10}), Rect::MakeLTRB(90, 90, 210, 210));
1227 EXPECT_EQ(rect.Expand(Point{10, -10}), Rect::MakeLTRB(90, 110, 210, 190));
1228 EXPECT_EQ(rect.Expand(Point{-10, 10}), Rect::MakeLTRB(110, 90, 190, 210));
1229 EXPECT_EQ(rect.Expand(Point{-10, -10}), Rect::MakeLTRB(110, 110, 190, 190));
1230
1231 // Expand(Size amount)
1232 EXPECT_EQ(rect.Expand(Size{10, 10}), Rect::MakeLTRB(90, 90, 210, 210));
1233 EXPECT_EQ(rect.Expand(Size{10, -10}), Rect::MakeLTRB(90, 110, 210, 190));
1234 EXPECT_EQ(rect.Expand(Size{-10, 10}), Rect::MakeLTRB(110, 90, 190, 210));
1235 EXPECT_EQ(rect.Expand(Size{-10, -10}), Rect::MakeLTRB(110, 110, 190, 190));
1236 }

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

## ◆ TEST() [274/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectFromRect |
| ) |  |

Definition at line 609 of file rect_unittests.cc.

609 {
610 EXPECT_EQ(Rect(Rect::MakeXYWH(2, 3, 7, 15)),
611 Rect::MakeXYWH(2.0, 3.0, 7.0, 15.0));
612 EXPECT_EQ(Rect(Rect::MakeLTRB(2, 3, 7, 15)),
613 Rect::MakeLTRB(2.0, 3.0, 7.0, 15.0));
614 }

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

## ◆ TEST() [275/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectGetNormalizingTransform |
| ) |  |

Definition at line 989 of file rect_unittests.cc.

989 {
990 {
991 // Checks for expected matrix values
992
993 auto r = Rect::MakeXYWH(100, 200, 200, 400);
994
995 EXPECT_EQ(r.GetNormalizingTransform(),
996 Matrix::MakeScale({0.005, 0.0025, 1.0}) *
997 Matrix::MakeTranslation({-100, -200}));
998 }
999
1000 {
1001 // Checks for expected transform of points relative to the rect
1002
1003 auto r = Rect::MakeLTRB(300, 500, 400, 700);
1004 auto m = r.GetNormalizingTransform();
1005
1006 // The 4 corners of the rect => (0, 0) to (1, 1)
1007 EXPECT_EQ(m * Point(300, 500), Point(0, 0));
1008 EXPECT_EQ(m * Point(400, 500), Point(1, 0));
1009 EXPECT_EQ(m * Point(400, 700), Point(1, 1));
1010 EXPECT_EQ(m * Point(300, 700), Point(0, 1));
1011
1012 // The center => (0.5, 0.5)
1013 EXPECT_EQ(m * Point(350, 600), Point(0.5, 0.5));
1014
1015 // Outside the 4 corners => (-1, -1) to (2, 2)
1016 EXPECT_EQ(m * Point(200, 300), Point(-1, -1));
1017 EXPECT_EQ(m * Point(500, 300), Point(2, -1));
1018 EXPECT_EQ(m * Point(500, 900), Point(2, 2));
1019 EXPECT_EQ(m * Point(200, 900), Point(-1, 2));
1020 }
1021
1022 {
1023 // Checks for behavior with empty rects
1024
1025 auto zero = Matrix::MakeScale({0.0, 0.0, 1.0});
1026
1027 // Empty for width and/or height == 0
1028 EXPECT_EQ(Rect::MakeXYWH(10, 10, 0, 10).GetNormalizingTransform(), zero);
1029 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, 0).GetNormalizingTransform(), zero);
1030 EXPECT_EQ(Rect::MakeXYWH(10, 10, 0, 0).GetNormalizingTransform(), zero);
1031
1032 // Empty for width and/or height < 0
1033 EXPECT_EQ(Rect::MakeXYWH(10, 10, -1, 10).GetNormalizingTransform(), zero);
1034 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, -1).GetNormalizingTransform(), zero);
1035 EXPECT_EQ(Rect::MakeXYWH(10, 10, -1, -1).GetNormalizingTransform(), zero);
1036 }
1037
1038 {
1039 // Checks for behavior with non-finite rects
1040
1041 auto z = Matrix::MakeScale({0.0, 0.0, 1.0});
1042 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
1043 auto inf = std::numeric_limits<Scalar>::infinity();
1044
1045 // Non-finite for width and/or height == nan
1046 EXPECT_EQ(Rect::MakeXYWH(10, 10, nan, 10).GetNormalizingTransform(), z);
1047 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, nan).GetNormalizingTransform(), z);
1048 EXPECT_EQ(Rect::MakeXYWH(10, 10, nan, nan).GetNormalizingTransform(), z);
1049
1050 // Non-finite for width and/or height == inf
1051 EXPECT_EQ(Rect::MakeXYWH(10, 10, inf, 10).GetNormalizingTransform(), z);
1052 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, inf).GetNormalizingTransform(), z);
1053 EXPECT_EQ(Rect::MakeXYWH(10, 10, inf, inf).GetNormalizingTransform(), z);
1054
1055 // Non-finite for width and/or height == -inf
1056 EXPECT_EQ(Rect::MakeXYWH(10, 10, -inf, 10).GetNormalizingTransform(), z);
1057 EXPECT_EQ(Rect::MakeXYWH(10, 10, 10, -inf).GetNormalizingTransform(), z);
1058 EXPECT_EQ(Rect::MakeXYWH(10, 10, -inf, -inf).GetNormalizingTransform(), z);
1059
1060 // Non-finite for origin X and/or Y == nan
1061 EXPECT_EQ(Rect::MakeXYWH(nan, 10, 10, 10).GetNormalizingTransform(), z);
1062 EXPECT_EQ(Rect::MakeXYWH(10, nan, 10, 10).GetNormalizingTransform(), z);
1063 EXPECT_EQ(Rect::MakeXYWH(nan, nan, 10, 10).GetNormalizingTransform(), z);
1064
1065 // Non-finite for origin X and/or Y == inf
1066 EXPECT_EQ(Rect::MakeXYWH(inf, 10, 10, 10).GetNormalizingTransform(), z);
1067 EXPECT_EQ(Rect::MakeXYWH(10, inf, 10, 10).GetNormalizingTransform(), z);
1068 EXPECT_EQ(Rect::MakeXYWH(inf, inf, 10, 10).GetNormalizingTransform(), z);
1069
1070 // Non-finite for origin X and/or Y == -inf
1071 EXPECT_EQ(Rect::MakeXYWH(-inf, 10, 10, 10).GetNormalizingTransform(), z);
1072 EXPECT_EQ(Rect::MakeXYWH(10, -inf, 10, 10).GetNormalizingTransform(), z);
1073 EXPECT_EQ(Rect::MakeXYWH(-inf, -inf, 10, 10).GetNormalizingTransform(), z);
1074 }
1075 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [276/360]

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

Definition at line 2910 of file rect_unittests.cc.

2910 {
2911 {
2912 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
2913 auto points = r.GetPoints();
2914 EXPECT_POINT_NEAR(points[0], Point(100, 200));
2915 EXPECT_POINT_NEAR(points[1], Point(400, 200));
2916 EXPECT_POINT_NEAR(points[2], Point(100, 600));
2917 EXPECT_POINT_NEAR(points[3], Point(400, 600));
2918 }
2919
2920 {
2921 Rect r = Rect::MakeMaximum();
2922 auto points = r.GetPoints();
2923 EXPECT_EQ(points[0], Point(std::numeric_limits<float>::lowest(),
2924 std::numeric_limits<float>::lowest()));
2925 EXPECT_EQ(points[1], Point(std::numeric_limits<float>::max(),
2926 std::numeric_limits<float>::lowest()));
2927 EXPECT_EQ(points[2], Point(std::numeric_limits<float>::lowest(),
2928 std::numeric_limits<float>::max()));
2929 EXPECT_EQ(points[3], Point(std::numeric_limits<float>::max(),
2930 std::numeric_limits<float>::max()));
2931 }
2932 }

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

## ◆ TEST() [277/360]

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

Definition at line 2967 of file rect_unittests.cc.

2967 {
2968 {
2969 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
2970 auto actual = r.GetPositive();
2971 EXPECT_RECT_NEAR(r, actual);
2972 }
2973 {
2974 Rect r = Rect::MakeXYWH(100, 200, -100, -100);
2975 auto actual = r.GetPositive();
2976 Rect expected = Rect::MakeXYWH(0, 100, 100, 100);
2977 EXPECT_RECT_NEAR(expected, actual);
2978 }
2979 }

References EXPECT_RECT_NEAR, impeller::TRect< T >::GetPositive(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [278/360]

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

Definition at line 2941 of file rect_unittests.cc.

2941 {
2942 Rect r = Rect::MakeXYWH(100, 200, 300, 400);
2943 auto points = r.GetTransformedPoints(Matrix::MakeTranslation({10, 20}));
2944 EXPECT_POINT_NEAR(points[0], Point(110, 220));
2945 EXPECT_POINT_NEAR(points[1], Point(410, 220));
2946 EXPECT_POINT_NEAR(points[2], Point(110, 620));
2947 EXPECT_POINT_NEAR(points[3], Point(410, 620));
2948 }

References EXPECT_POINT_NEAR, impeller::TRect< T >::GetTransformedPoints(), impeller::Matrix::MakeTranslation(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [279/360]

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

Definition at line 1580 of file rect_unittests.cc.

1580 {
1581 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
1582 ASSERT_TRUE(a.IsFinite()) << label;
1583 ASSERT_TRUE(b.IsFinite()) << label;
1584
1585 for (int i = 1; i < 16; i++) {
1586 // NaN in a produces empty
1587 EXPECT_FALSE(swap_nan(a, i).Intersection(b).has_value())
1588 << label << ", index = " << i;
1589 // NaN in b produces empty
1590 EXPECT_FALSE(a.Intersection(swap_nan(b, i)).has_value())
1591 << label << ", index = " << i;
1592 // NaN in both is empty
1593 for (int j = 1; j < 16; j++) {
1594 EXPECT_FALSE(swap_nan(a, i).Intersection(swap_nan(b, j)).has_value())
1595 << label << ", indices = " << i << ", " << j;
1596 }
1597 }
1598 };
1599
1600 auto check_empty_flips = [](const Rect& a, const Rect& b,
1601 const std::string& label) {
1602 ASSERT_FALSE(a.IsEmpty());
1603 // b is allowed to be empty
1604
1605 // unflipped a vs flipped (empty) b yields a
1606 EXPECT_FALSE(a.Intersection(flip_lr(b)).has_value()) << label;
1607 EXPECT_FALSE(a.Intersection(flip_tb(b)).has_value()) << label;
1608 EXPECT_FALSE(a.Intersection(flip_lrtb(b)).has_value()) << label;
1609
1610 // flipped (empty) a vs unflipped b yields b
1611 EXPECT_FALSE(flip_lr(a).Intersection(b).has_value()) << label;
1612 EXPECT_FALSE(flip_tb(a).Intersection(b).has_value()) << label;
1613 EXPECT_FALSE(flip_lrtb(a).Intersection(b).has_value()) << label;
1614
1615 // flipped (empty) a vs flipped (empty) b yields empty
1616 EXPECT_FALSE(flip_lr(a).Intersection(flip_lr(b)).has_value()) << label;
1617 EXPECT_FALSE(flip_tb(a).Intersection(flip_tb(b)).has_value()) << label;
1618 EXPECT_FALSE(flip_lrtb(a).Intersection(flip_lrtb(b)).has_value()) << label;
1619 };
1620
1621 auto test_non_empty = [&check_nans, &check_empty_flips](
1622 const Rect& a, const Rect& b, const Rect& result) {
1623 ASSERT_FALSE(a.IsEmpty()) << a;
1624 // b is allowed to be empty
1625
1626 std::stringstream stream;
1627 stream << a << " union " << b;
1628 auto label = stream.str();
1629
1630 EXPECT_TRUE(a.Intersection(b).has_value()) << label;
1631 EXPECT_TRUE(b.Intersection(a).has_value()) << label;
1632 EXPECT_EQ(a.Intersection(b), result) << label;
1633 EXPECT_EQ(b.Intersection(a), result) << label;
1634 check_empty_flips(a, b, label);
1635 check_nans(a, b, label);
1636 };
1637
1638 auto test_empty = [&check_nans, &check_empty_flips](const Rect& a,
1639 const Rect& b) {
1640 ASSERT_FALSE(a.IsEmpty()) << a;
1641 // b is allowed to be empty
1642
1643 std::stringstream stream;
1644 stream << a << " union " << b;
1645 auto label = stream.str();
1646
1647 EXPECT_FALSE(a.Intersection(b).has_value()) << label;
1648 EXPECT_FALSE(b.Intersection(a).has_value()) << label;
1649 check_empty_flips(a, b, label);
1650 check_nans(a, b, label);
1651 };
1652
1653 {
1654 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1655 auto b = Rect::MakeXYWH(0, 0, 0, 0);
1656
1657 test_empty(a, b);
1658 }
1659
1660 {
1661 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1662 auto b = Rect::MakeXYWH(10, 10, 0, 0);
1663
1664 test_empty(a, b);
1665 }
1666
1667 {
1668 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1669 auto b = Rect::MakeXYWH(10, 10, 100, 100);
1670 auto expected = Rect::MakeXYWH(10, 10, 90, 90);
1671
1672 test_non_empty(a, b, expected);
1673 }
1674
1675 {
1676 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1677 auto b = Rect::MakeXYWH(100, 100, 100, 100);
1678
1679 test_empty(a, b);
1680 }
1681
1682 {
1683 auto a = Rect::MakeMaximum();
1684 auto b = Rect::MakeXYWH(10, 10, 300, 300);
1685
1686 test_non_empty(a, b, b);
1687 }
1688
1689 {
1690 auto a = Rect::MakeMaximum();
1691 auto b = Rect::MakeMaximum();
1692
1693 test_non_empty(a, b, Rect::MakeMaximum());
1694 }
1695 }

References impeller::saturated::b, flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::Intersection(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), impeller::TRect< Scalar >::MakeMaximum(), impeller::TRect< Scalar >::MakeXYWH(), and swap_nan().

## ◆ TEST() [280/360]

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

Definition at line 1902 of file rect_unittests.cc.

1902 {
1903 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
1904 ASSERT_TRUE(a.IsFinite()) << label;
1905 ASSERT_TRUE(b.IsFinite()) << label;
1906
1907 for (int i = 1; i < 16; i++) {
1908 // NaN in a produces b
1909 EXPECT_FALSE(swap_nan(a, i).IntersectsWithRect(b))
1910 << label << ", index = " << i;
1911 // NaN in b produces a
1912 EXPECT_FALSE(a.IntersectsWithRect(swap_nan(b, i)))
1913 << label << ", index = " << i;
1914 // NaN in both is empty
1915 for (int j = 1; j < 16; j++) {
1916 EXPECT_FALSE(swap_nan(a, i).IntersectsWithRect(swap_nan(b, j)))
1917 << label << ", indices = " << i << ", " << j;
1918 }
1919 }
1920 };
1921
1922 auto check_empty_flips = [](const Rect& a, const Rect& b,
1923 const std::string& label) {
1924 ASSERT_FALSE(a.IsEmpty());
1925 // b is allowed to be empty
1926
1927 // unflipped a vs flipped (empty) b yields a
1928 EXPECT_FALSE(a.IntersectsWithRect(flip_lr(b))) << label;
1929 EXPECT_FALSE(a.IntersectsWithRect(flip_tb(b))) << label;
1930 EXPECT_FALSE(a.IntersectsWithRect(flip_lrtb(b))) << label;
1931
1932 // flipped (empty) a vs unflipped b yields b
1933 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(b)) << label;
1934 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(b)) << label;
1935 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(b)) << label;
1936
1937 // flipped (empty) a vs flipped (empty) b yields empty
1938 EXPECT_FALSE(flip_lr(a).IntersectsWithRect(flip_lr(b))) << label;
1939 EXPECT_FALSE(flip_tb(a).IntersectsWithRect(flip_tb(b))) << label;
1940 EXPECT_FALSE(flip_lrtb(a).IntersectsWithRect(flip_lrtb(b))) << label;
1941 };
1942
1943 auto test_non_empty = [&check_nans, &check_empty_flips](const Rect& a,
1944 const Rect& b) {
1945 ASSERT_FALSE(a.IsEmpty()) << a;
1946 // b is allowed to be empty
1947
1948 std::stringstream stream;
1949 stream << a << " union " << b;
1950 auto label = stream.str();
1951
1952 EXPECT_TRUE(a.IntersectsWithRect(b)) << label;
1953 EXPECT_TRUE(b.IntersectsWithRect(a)) << label;
1954 check_empty_flips(a, b, label);
1955 check_nans(a, b, label);
1956 };
1957
1958 auto test_empty = [&check_nans, &check_empty_flips](const Rect& a,
1959 const Rect& b) {
1960 ASSERT_FALSE(a.IsEmpty()) << a;
1961 // b is allowed to be empty
1962
1963 std::stringstream stream;
1964 stream << a << " union " << b;
1965 auto label = stream.str();
1966
1967 EXPECT_FALSE(a.IntersectsWithRect(b)) << label;
1968 EXPECT_FALSE(b.IntersectsWithRect(a)) << label;
1969 check_empty_flips(a, b, label);
1970 check_nans(a, b, label);
1971 };
1972
1973 {
1974 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1975 auto b = Rect::MakeXYWH(0, 0, 0, 0);
1976
1977 test_empty(a, b);
1978 }
1979
1980 {
1981 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1982 auto b = Rect::MakeXYWH(10, 10, 0, 0);
1983
1984 test_empty(a, b);
1985 }
1986
1987 {
1988 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1989 auto b = Rect::MakeXYWH(10, 10, 100, 100);
1990
1991 test_non_empty(a, b);
1992 }
1993
1994 {
1995 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1996 auto b = Rect::MakeXYWH(100, 100, 100, 100);
1997
1998 test_empty(a, b);
1999 }
2000
2001 {
2002 auto a = Rect::MakeMaximum();
2003 auto b = Rect::MakeXYWH(10, 10, 100, 100);
2004
2005 test_non_empty(a, b);
2006 }
2007
2008 {
2009 auto a = Rect::MakeMaximum();
2010 auto b = Rect::MakeMaximum();
2011
2012 test_non_empty(a, b);
2013 }
2014 }

References impeller::saturated::b, flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IntersectsWithRect(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), impeller::TRect< Scalar >::MakeMaximum(), impeller::TRect< Scalar >::MakeXYWH(), and swap_nan().

## ◆ TEST() [281/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectMakeMaximum |
| ) |  |

Definition at line 575 of file rect_unittests.cc.

575 {
576 Rect rect = Rect::MakeMaximum();
577 auto inf = std::numeric_limits<Scalar>::infinity();
578 auto min = std::numeric_limits<Scalar>::lowest();
579 auto max = std::numeric_limits<Scalar>::max();
580
581 EXPECT_EQ(rect.GetLeft(), min);
582 EXPECT_EQ(rect.GetTop(), min);
583 EXPECT_EQ(rect.GetRight(), max);
584 EXPECT_EQ(rect.GetBottom(), max);
585 EXPECT_EQ(rect.GetX(), min);
586 EXPECT_EQ(rect.GetY(), min);
587 EXPECT_EQ(rect.GetWidth(), inf);
588 EXPECT_EQ(rect.GetHeight(), inf);
589 EXPECT_FALSE(rect.IsEmpty());
590 EXPECT_TRUE(rect.IsFinite());
591 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), and impeller::TRect< Scalar >::MakeMaximum().

## ◆ TEST() [282/360]

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

Definition at line 2950 of file rect_unittests.cc.

2950 {
2951 {
2952 std::vector<Point> points{{1, 5}, {4, -1}, {0, 6}};
2953 auto r = Rect::MakePointBounds(points.begin(), points.end());
2954 auto expected = Rect::MakeXYWH(0, -1, 4, 7);
2955 EXPECT_TRUE(r.has_value());
2956 if (r.has_value()) {
2957 EXPECT_RECT_NEAR(r.value(), expected);
2958 }
2959 }
2960 {
2961 std::vector<Point> points;
2962 std::optional<Rect> r = Rect::MakePointBounds(points.begin(), points.end());
2963 EXPECT_FALSE(r.has_value());
2964 }
2965 }

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

## ◆ TEST() [283/360]

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

Definition at line 545 of file rect_unittests.cc.

545 {
546 {
547 Size s(100, 200);
548 Rect r = Rect::MakeSize(s);
549 Rect expected = Rect::MakeLTRB(0, 0, 100, 200);
550 EXPECT_RECT_NEAR(r, expected);
551 }
552
553 {
554 ISize s(100, 200);
555 Rect r = Rect::MakeSize(s);
556 Rect expected = Rect::MakeLTRB(0, 0, 100, 200);
557 EXPECT_RECT_NEAR(r, expected);
558 }
559
560 {
561 Size s(100, 200);
562 IRect r = IRect::MakeSize(s);
563 IRect expected = IRect::MakeLTRB(0, 0, 100, 200);
564 EXPECT_EQ(r, expected);
565 }
566
567 {
568 ISize s(100, 200);
569 IRect r = IRect::MakeSize(s);
570 IRect expected = IRect::MakeLTRB(0, 0, 100, 200);
571 EXPECT_EQ(r, expected);
572 }
573 }

References EXPECT_RECT_NEAR, impeller::TRect< T >::MakeLTRB(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< T >::MakeSize(), and impeller::TRect< Scalar >::MakeSize().

## ◆ TEST() [284/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectOriginSizeXYWHGetters |
| ) |  |

Definition at line 657 of file rect_unittests.cc.

657 {
658 {
659 Rect r = Rect::MakeOriginSize({10, 20}, {50, 40});
660 EXPECT_EQ(r.GetOrigin(), Point(10, 20));
661 EXPECT_EQ(r.GetSize(), Size(50, 40));
662 EXPECT_EQ(r.GetX(), 10);
663 EXPECT_EQ(r.GetY(), 20);
664 EXPECT_EQ(r.GetWidth(), 50);
665 EXPECT_EQ(r.GetHeight(), 40);
666 auto expected_array = std::array<Scalar, 4>{10, 20, 50, 40};
667 EXPECT_EQ(r.GetXYWH(), expected_array);
668 }
669
670 {
671 Rect r = Rect::MakeLTRB(10, 20, 50, 40);
672 EXPECT_EQ(r.GetOrigin(), Point(10, 20));
673 EXPECT_EQ(r.GetSize(), Size(40, 20));
674 EXPECT_EQ(r.GetX(), 10);
675 EXPECT_EQ(r.GetY(), 20);
676 EXPECT_EQ(r.GetWidth(), 40);
677 EXPECT_EQ(r.GetHeight(), 20);
678 auto expected_array = std::array<Scalar, 4>{10, 20, 40, 20};
679 EXPECT_EQ(r.GetXYWH(), expected_array);
680 }
681 }

References impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetOrigin(), impeller::TRect< T >::GetSize(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetXYWH(), impeller::TRect< T >::GetY(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeOriginSize().

## ◆ TEST() [285/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectOverflowLTRB |
| ) |  |

Definition at line 339 of file rect_unittests.cc.

339 {
340 auto min = std::numeric_limits<Scalar>::lowest();
341 auto max = std::numeric_limits<Scalar>::max();
342 auto inf = std::numeric_limits<Scalar>::infinity();
343
344 // 8 cases:
345 // finite negative X, max W
346 // ~min X, ~max W
347 // finite negative Y, max H
348 // ~min Y, ~max H
349 // finite positive X, min W
350 // ~min X, ~min W
351 // finite positive Y, min H
352 // ~min Y, ~min H
353
354 // a small finite value subtracted from a max value will remain max
355 // a very large finite value (like min) subtracted from max will go to inf
356
357 {
358 Rect rect = Rect::MakeLTRB(-5.0f, 10.0f, max, 25.0f);
359
360 EXPECT_EQ(rect.GetLeft(), -5.0f);
361 EXPECT_EQ(rect.GetTop(), 10.0f);
362 EXPECT_EQ(rect.GetRight(), max);
363 EXPECT_EQ(rect.GetBottom(), 25.0f);
364 EXPECT_EQ(rect.GetX(), -5.0f);
365 EXPECT_EQ(rect.GetY(), 10.0f);
366 EXPECT_EQ(rect.GetWidth(), max);
367 EXPECT_EQ(rect.GetHeight(), 15.0f);
368 EXPECT_FALSE(rect.IsEmpty());
369 EXPECT_TRUE(rect.IsFinite());
370 }
371
372 {
373 Rect rect = Rect::MakeLTRB(min + 5.0f, 10.0f, max - 5.0f, 25.0f);
374
375 EXPECT_EQ(rect.GetLeft(), min + 5.0f);
376 EXPECT_EQ(rect.GetTop(), 10.0f);
377 EXPECT_EQ(rect.GetRight(), max - 5.0f);
378 EXPECT_EQ(rect.GetBottom(), 25.0f);
379 EXPECT_EQ(rect.GetX(), min + 5.0f);
380 EXPECT_EQ(rect.GetY(), 10.0f);
381 EXPECT_EQ(rect.GetWidth(), inf);
382 EXPECT_EQ(rect.GetHeight(), 15.0f);
383 EXPECT_FALSE(rect.IsEmpty());
384 EXPECT_TRUE(rect.IsFinite());
385 }
386
387 {
388 Rect rect = Rect::MakeLTRB(5.0f, -10.0f, 20.0f, max);
389
390 EXPECT_EQ(rect.GetLeft(), 5.0f);
391 EXPECT_EQ(rect.GetTop(), -10.0f);
392 EXPECT_EQ(rect.GetRight(), 20.0f);
393 EXPECT_EQ(rect.GetBottom(), max);
394 EXPECT_EQ(rect.GetX(), 5.0f);
395 EXPECT_EQ(rect.GetY(), -10.0f);
396 EXPECT_EQ(rect.GetWidth(), 15.0f);
397 EXPECT_EQ(rect.GetHeight(), max);
398 EXPECT_FALSE(rect.IsEmpty());
399 EXPECT_TRUE(rect.IsFinite());
400 }
401
402 {
403 Rect rect = Rect::MakeLTRB(5.0f, min + 10.0f, 20.0f, max - 15.0f);
404
405 EXPECT_EQ(rect.GetLeft(), 5.0f);
406 EXPECT_EQ(rect.GetTop(), min + 10.0f);
407 EXPECT_EQ(rect.GetRight(), 20.0f);
408 EXPECT_EQ(rect.GetBottom(), max - 15.0f);
409 EXPECT_EQ(rect.GetX(), 5.0f);
410 EXPECT_EQ(rect.GetY(), min + 10.0f);
411 EXPECT_EQ(rect.GetWidth(), 15.0f);
412 EXPECT_EQ(rect.GetHeight(), inf);
413 EXPECT_FALSE(rect.IsEmpty());
414 EXPECT_TRUE(rect.IsFinite());
415 }
416
417 {
418 Rect rect = Rect::MakeLTRB(5.0f, 10.0f, min, 25.0f);
419
420 EXPECT_EQ(rect.GetLeft(), 5.0f);
421 EXPECT_EQ(rect.GetTop(), 10.0f);
422 EXPECT_EQ(rect.GetRight(), min);
423 EXPECT_EQ(rect.GetBottom(), 25.0f);
424 EXPECT_EQ(rect.GetX(), 5.0f);
425 EXPECT_EQ(rect.GetY(), 10.0f);
426 EXPECT_EQ(rect.GetWidth(), min);
427 EXPECT_EQ(rect.GetHeight(), 15.0f);
428 EXPECT_TRUE(rect.IsEmpty());
429 EXPECT_TRUE(rect.IsFinite());
430 }
431
432 {
433 Rect rect = Rect::MakeLTRB(max - 5.0f, 10.0f, min + 10.0f, 25.0f);
434
435 EXPECT_EQ(rect.GetLeft(), max - 5.0f);
436 EXPECT_EQ(rect.GetTop(), 10.0f);
437 EXPECT_EQ(rect.GetRight(), min + 10.0f);
438 EXPECT_EQ(rect.GetBottom(), 25.0f);
439 EXPECT_EQ(rect.GetX(), max - 5.0f);
440 EXPECT_EQ(rect.GetY(), 10.0f);
441 EXPECT_EQ(rect.GetWidth(), -inf);
442 EXPECT_EQ(rect.GetHeight(), 15.0f);
443 EXPECT_TRUE(rect.IsEmpty());
444 EXPECT_TRUE(rect.IsFinite());
445 }
446
447 {
448 Rect rect = Rect::MakeLTRB(5.0f, 10.0f, 20.0f, min);
449
450 EXPECT_EQ(rect.GetLeft(), 5.0f);
451 EXPECT_EQ(rect.GetTop(), 10.0f);
452 EXPECT_EQ(rect.GetRight(), 20.0f);
453 EXPECT_EQ(rect.GetBottom(), min);
454 EXPECT_EQ(rect.GetX(), 5.0f);
455 EXPECT_EQ(rect.GetY(), 10.0f);
456 EXPECT_EQ(rect.GetWidth(), 15.0f);
457 EXPECT_EQ(rect.GetHeight(), min);
458 EXPECT_TRUE(rect.IsEmpty());
459 EXPECT_TRUE(rect.IsFinite());
460 }
461
462 {
463 Rect rect = Rect::MakeLTRB(5.0f, max - 5.0f, 20.0f, min + 10.0f);
464
465 EXPECT_EQ(rect.GetLeft(), 5.0f);
466 EXPECT_EQ(rect.GetTop(), max - 5.0f);
467 EXPECT_EQ(rect.GetRight(), 20.0f);
468 EXPECT_EQ(rect.GetBottom(), min + 10.0f);
469 EXPECT_EQ(rect.GetX(), 5.0f);
470 EXPECT_EQ(rect.GetY(), max - 5.0f);
471 EXPECT_EQ(rect.GetWidth(), 15.0f);
472 EXPECT_EQ(rect.GetHeight(), -inf);
473 EXPECT_TRUE(rect.IsEmpty());
474 EXPECT_TRUE(rect.IsFinite());
475 }
476 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [286/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectOverflowXYWH |
| ) |  |

Definition at line 133 of file rect_unittests.cc.

133 {
134 auto min = std::numeric_limits<Scalar>::lowest();
135 auto max = std::numeric_limits<Scalar>::max();
136 auto inf = std::numeric_limits<Scalar>::infinity();
137
138 // 8 cases:
139 // finite X, max W
140 // max X, max W
141 // finite Y, max H
142 // max Y, max H
143 // finite X, min W
144 // min X, min W
145 // finite Y, min H
146 // min Y, min H
147
148 // a small finite value added to a max value will remain max
149 // a very large finite value (like max) added to max will go to infinity
150
151 {
152 Rect rect = Rect::MakeXYWH(5.0, 10.0f, max, 15.0f);
153
154 EXPECT_EQ(rect.GetLeft(), 5.0f);
155 EXPECT_EQ(rect.GetTop(), 10.0f);
156 EXPECT_EQ(rect.GetRight(), max);
157 EXPECT_EQ(rect.GetBottom(), 25.0f);
158 EXPECT_EQ(rect.GetX(), 5.0f);
159 EXPECT_EQ(rect.GetY(), 10.0f);
160 EXPECT_EQ(rect.GetWidth(), max);
161 EXPECT_EQ(rect.GetHeight(), 15.0f);
162 EXPECT_FALSE(rect.IsEmpty());
163 EXPECT_TRUE(rect.IsFinite());
164 }
165
166 {
167 Rect rect = Rect::MakeXYWH(max, 10.0f, max, 15.0f);
168
169 EXPECT_EQ(rect.GetLeft(), max);
170 EXPECT_EQ(rect.GetTop(), 10.0f);
171 EXPECT_EQ(rect.GetRight(), inf);
172 EXPECT_EQ(rect.GetBottom(), 25.0f);
173 EXPECT_EQ(rect.GetX(), max);
174 EXPECT_EQ(rect.GetY(), 10.0f);
175 EXPECT_EQ(rect.GetWidth(), inf);
176 EXPECT_EQ(rect.GetHeight(), 15.0f);
177 EXPECT_FALSE(rect.IsEmpty());
178 EXPECT_FALSE(rect.IsFinite());
179 }
180
181 {
182 Rect rect = Rect::MakeXYWH(5.0f, 10.0f, 20.0f, max);
183
184 EXPECT_EQ(rect.GetLeft(), 5.0f);
185 EXPECT_EQ(rect.GetTop(), 10.0f);
186 EXPECT_EQ(rect.GetRight(), 25.0f);
187 EXPECT_EQ(rect.GetBottom(), max);
188 EXPECT_EQ(rect.GetX(), 5.0f);
189 EXPECT_EQ(rect.GetY(), 10.0f);
190 EXPECT_EQ(rect.GetWidth(), 20.0f);
191 EXPECT_EQ(rect.GetHeight(), max);
192 EXPECT_FALSE(rect.IsEmpty());
193 EXPECT_TRUE(rect.IsFinite());
194 }
195
196 {
197 Rect rect = Rect::MakeXYWH(5.0f, max, 20.0f, max);
198
199 EXPECT_EQ(rect.GetLeft(), 5.0f);
200 EXPECT_EQ(rect.GetTop(), max);
201 EXPECT_EQ(rect.GetRight(), 25.0f);
202 EXPECT_EQ(rect.GetBottom(), inf);
203 EXPECT_EQ(rect.GetX(), 5.0f);
204 EXPECT_EQ(rect.GetY(), max);
205 EXPECT_EQ(rect.GetWidth(), 20.0f);
206 EXPECT_EQ(rect.GetHeight(), inf);
207 EXPECT_FALSE(rect.IsEmpty());
208 EXPECT_FALSE(rect.IsFinite());
209 }
210
211 {
212 Rect rect = Rect::MakeXYWH(5.0, 10.0f, min, 15.0f);
213
214 EXPECT_EQ(rect.GetLeft(), 5.0f);
215 EXPECT_EQ(rect.GetTop(), 10.0f);
216 EXPECT_EQ(rect.GetRight(), min);
217 EXPECT_EQ(rect.GetBottom(), 25.0f);
218 EXPECT_EQ(rect.GetX(), 5.0f);
219 EXPECT_EQ(rect.GetY(), 10.0f);
220 EXPECT_EQ(rect.GetWidth(), min);
221 EXPECT_EQ(rect.GetHeight(), 15.0f);
222 EXPECT_TRUE(rect.IsEmpty());
223 EXPECT_TRUE(rect.IsFinite());
224 }
225
226 {
227 Rect rect = Rect::MakeXYWH(min, 10.0f, min, 15.0f);
228
229 EXPECT_EQ(rect.GetLeft(), min);
230 EXPECT_EQ(rect.GetTop(), 10.0f);
231 EXPECT_EQ(rect.GetRight(), -inf);
232 EXPECT_EQ(rect.GetBottom(), 25.0f);
233 EXPECT_EQ(rect.GetX(), min);
234 EXPECT_EQ(rect.GetY(), 10.0f);
235 EXPECT_EQ(rect.GetWidth(), -inf);
236 EXPECT_EQ(rect.GetHeight(), 15.0f);
237 EXPECT_TRUE(rect.IsEmpty());
238 EXPECT_FALSE(rect.IsFinite());
239 }
240
241 {
242 Rect rect = Rect::MakeXYWH(5.0f, 10.0f, 20.0f, min);
243
244 EXPECT_EQ(rect.GetLeft(), 5.0f);
245 EXPECT_EQ(rect.GetTop(), 10.0f);
246 EXPECT_EQ(rect.GetRight(), 25.0f);
247 EXPECT_EQ(rect.GetBottom(), min);
248 EXPECT_EQ(rect.GetX(), 5.0f);
249 EXPECT_EQ(rect.GetY(), 10.0f);
250 EXPECT_EQ(rect.GetWidth(), 20.0f);
251 EXPECT_EQ(rect.GetHeight(), min);
252 EXPECT_TRUE(rect.IsEmpty());
253 EXPECT_TRUE(rect.IsFinite());
254 }
255
256 {
257 Rect rect = Rect::MakeXYWH(5.0f, min, 20.0f, min);
258
259 EXPECT_EQ(rect.GetLeft(), 5.0f);
260 EXPECT_EQ(rect.GetTop(), min);
261 EXPECT_EQ(rect.GetRight(), 25.0f);
262 EXPECT_EQ(rect.GetBottom(), -inf);
263 EXPECT_EQ(rect.GetX(), 5.0f);
264 EXPECT_EQ(rect.GetY(), min);
265 EXPECT_EQ(rect.GetWidth(), 20.0f);
266 EXPECT_EQ(rect.GetHeight(), -inf);
267 EXPECT_TRUE(rect.IsEmpty());
268 EXPECT_FALSE(rect.IsFinite());
269 }
270 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [287/360]

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

Definition at line 2995 of file rect_unittests.cc.

2995 {
2996 {
2997 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
2998 auto actual = r.Project(r);
2999 auto expected = Rect::MakeLTRB(0, 0, 1, 1);
3000 EXPECT_RECT_NEAR(expected, actual);
3001 }
3002 {
3003 auto r = Rect::MakeLTRB(-100, -100, 100, 100);
3004 auto actual = r.Project(Rect::MakeLTRB(0, 0, 100, 100));
3005 auto expected = Rect::MakeLTRB(0.5, 0.5, 1, 1);
3006 EXPECT_RECT_NEAR(expected, actual);
3007 }
3008 }

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

## ◆ TEST() [288/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectRound |
| ) |  |

Definition at line 3034 of file rect_unittests.cc.

3034 {
3035 {
3036 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
3037 EXPECT_EQ(Rect::Round(r), r);
3038 }
3039 {
3040 auto r = Rect::MakeLTRB(-100.4, -200.4, 300.4, 400.4);
3041 EXPECT_EQ(Rect::Round(r), Rect::MakeLTRB(-100, -200, 300, 400));
3042 }
3043 {
3044 auto r = Rect::MakeLTRB(-100.5, -200.5, 300.5, 400.5);
3045 EXPECT_EQ(Rect::Round(r), Rect::MakeLTRB(-101, -201, 301, 401));
3046 }
3047 }

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

## ◆ TEST() [289/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectRoundOut |
| ) |  |

Definition at line 3010 of file rect_unittests.cc.

3010 {
3011 {
3012 auto r = Rect::MakeLTRB(-100, -200, 300, 400);
3013 EXPECT_EQ(Rect::RoundOut(r), r);
3014 }
3015 {
3016 auto r = Rect::MakeLTRB(-100.1, -200.1, 300.1, 400.1);
3017 EXPECT_EQ(Rect::RoundOut(r), Rect::MakeLTRB(-101, -201, 301, 401));
3018 }
3019 }

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

## ◆ TEST() [290/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectRoundOutEmpty |
| ) |  |

Definition at line 709 of file rect_unittests.cc.

709 {
710 Rect rect;
711
712 EXPECT_EQ(Rect::RoundOut(rect), Rect());
713
714 EXPECT_EQ(IRect::RoundOut(rect), IRect());
715 }

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

## ◆ TEST() [291/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectRoundOutSimple |
| ) |  |

Definition at line 717 of file rect_unittests.cc.

717 {
718 Rect rect = Rect::MakeLTRB(5.125f, 10.75f, 20.625f, 25.375f);
719
720 EXPECT_EQ(Rect::RoundOut(rect), Rect::MakeLTRB(5.0f, 10.0f, 21.0f, 26.0f));
721
722 EXPECT_EQ(IRect::RoundOut(rect), IRect::MakeLTRB(5, 10, 21, 26));
723 }

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

## ◆ TEST() [292/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectRoundOutToIRectHuge |
| ) |  |

Definition at line 725 of file rect_unittests.cc.

725 {
726 auto test = [](int corners) {
727 EXPECT_TRUE(corners >= 0 && corners <= 0xf);
728 Scalar l, t, r, b;
729 int64_t il, it, ir, ib;
730 l = il = 50;
731 t = it = 50;
732 r = ir = 80;
733 b = ib = 80;
734 if ((corners & (1 << 0)) != 0) {
735 l = -1E20;
736 il = std::numeric_limits<int64_t>::min();
737 }
738 if ((corners & (1 << 1)) != 0) {
739 t = -1E20;
740 it = std::numeric_limits<int64_t>::min();
741 }
742 if ((corners & (1 << 2)) != 0) {
743 r = +1E20;
744 ir = std::numeric_limits<int64_t>::max();
745 }
746 if ((corners & (1 << 3)) != 0) {
747 b = +1E20;
748 ib = std::numeric_limits<int64_t>::max();
749 }
750
751 Rect rect = Rect::MakeLTRB(l, t, r, b);
752 IRect irect = IRect::RoundOut(rect);
753 EXPECT_EQ(irect.GetLeft(), il) << corners;
754 EXPECT_EQ(irect.GetTop(), it) << corners;
755 EXPECT_EQ(irect.GetRight(), ir) << corners;
756 EXPECT_EQ(irect.GetBottom(), ib) << corners;
757 };
758
759 for (int corners = 0; corners <= 15; corners++) {
760 test(corners);
761 }
762 }

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

## ◆ TEST() [293/360]

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

Definition at line 884 of file rect_unittests.cc.

884 {
885 auto test1 = [](Rect rect, Scalar scale) {
886 Rect expected = Rect::MakeXYWH(rect.GetX() * scale, //
887 rect.GetY() * scale, //
888 rect.GetWidth() * scale, //
889 rect.GetHeight() * scale);
890
891 EXPECT_RECT_NEAR(rect.Scale(scale), expected) //
892 << rect << " * " << scale;
893 EXPECT_RECT_NEAR(rect.Scale(scale, scale), expected) //
894 << rect << " * " << scale;
895 EXPECT_RECT_NEAR(rect.Scale(Point(scale, scale)), expected) //
896 << rect << " * " << scale;
897 EXPECT_RECT_NEAR(rect.Scale(Size(scale, scale)), expected) //
898 << rect << " * " << scale;
899 };
900
901 auto test2 = [&test1](Rect rect, Scalar scale_x, Scalar scale_y) {
902 Rect expected = Rect::MakeXYWH(rect.GetX() * scale_x, //
903 rect.GetY() * scale_y, //
904 rect.GetWidth() * scale_x, //
905 rect.GetHeight() * scale_y);
906
907 EXPECT_RECT_NEAR(rect.Scale(scale_x, scale_y), expected) //
908 << rect << " * " << scale_x << ", " << scale_y;
909 EXPECT_RECT_NEAR(rect.Scale(Point(scale_x, scale_y)), expected) //
910 << rect << " * " << scale_x << ", " << scale_y;
911 EXPECT_RECT_NEAR(rect.Scale(Size(scale_x, scale_y)), expected) //
912 << rect << " * " << scale_x << ", " << scale_y;
913
914 test1(rect, scale_x);
915 test1(rect, scale_y);
916 };
917
918 test2(Rect::MakeLTRB(10, 15, 100, 150), 1.0, 0.0);
919 test2(Rect::MakeLTRB(10, 15, 100, 150), 0.0, 1.0);
920 test2(Rect::MakeLTRB(10, 15, 100, 150), 0.0, 0.0);
921 test2(Rect::MakeLTRB(10, 15, 100, 150), 2.5, 3.5);
922 test2(Rect::MakeLTRB(10, 15, 100, 150), 3.5, 2.5);
923 test2(Rect::MakeLTRB(10, 15, -100, 150), 2.5, 3.5);
924 test2(Rect::MakeLTRB(10, 15, 100, -150), 2.5, 3.5);
925 test2(Rect::MakeLTRB(10, 15, 100, 150), -2.5, 3.5);
926 test2(Rect::MakeLTRB(10, 15, 100, 150), 2.5, -3.5);
927 }

References EXPECT_RECT_NEAR, impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeXYWH(), impeller::TRect< T >::Scale(), and scale.

## ◆ TEST() [294/360]

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

Definition at line 2934 of file rect_unittests.cc.

2934 {
2935 auto r = Rect::MakeLTRB(0, 0, 100, 100);
2936
2937 EXPECT_EQ(r.Shift(Point(10, 5)), Rect::MakeLTRB(10, 5, 110, 105));
2938 EXPECT_EQ(r.Shift(Point(-10, -5)), Rect::MakeLTRB(-10, -5, 90, 95));
2939 }

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

## ◆ TEST() [295/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectSimpleLTRB |
| ) |  |

Definition at line 73 of file rect_unittests.cc.

73 {
74 // Using fractional-power-of-2 friendly values for equality tests
75 Rect rect = Rect::MakeLTRB(5.125f, 10.25f, 20.625f, 25.375f);
76
77 EXPECT_EQ(rect.GetLeft(), 5.125f);
78 EXPECT_EQ(rect.GetTop(), 10.25f);
79 EXPECT_EQ(rect.GetRight(), 20.625f);
80 EXPECT_EQ(rect.GetBottom(), 25.375f);
81 EXPECT_EQ(rect.GetX(), 5.125f);
82 EXPECT_EQ(rect.GetY(), 10.25f);
83 EXPECT_EQ(rect.GetWidth(), 15.5f);
84 EXPECT_EQ(rect.GetHeight(), 15.125f);
85 EXPECT_FALSE(rect.IsEmpty());
86 EXPECT_TRUE(rect.IsFinite());
87 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST() [296/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectSimpleXYWH |
| ) |  |

Definition at line 103 of file rect_unittests.cc.

103 {
104 // Using fractional-power-of-2 friendly values for equality tests
105 Rect rect = Rect::MakeXYWH(5.125f, 10.25f, 15.5f, 15.125f);
106
107 EXPECT_EQ(rect.GetLeft(), 5.125f);
108 EXPECT_EQ(rect.GetTop(), 10.25f);
109 EXPECT_EQ(rect.GetRight(), 20.625f);
110 EXPECT_EQ(rect.GetBottom(), 25.375f);
111 EXPECT_EQ(rect.GetX(), 5.125f);
112 EXPECT_EQ(rect.GetY(), 10.25f);
113 EXPECT_EQ(rect.GetWidth(), 15.5f);
114 EXPECT_EQ(rect.GetHeight(), 15.125f);
115 EXPECT_FALSE(rect.IsEmpty());
116 EXPECT_TRUE(rect.IsFinite());
117 }

References impeller::TRect< T >::GetBottom(), impeller::TRect< T >::GetHeight(), impeller::TRect< T >::GetLeft(), impeller::TRect< T >::GetRight(), impeller::TRect< T >::GetTop(), impeller::TRect< T >::GetWidth(), impeller::TRect< T >::GetX(), impeller::TRect< T >::GetY(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST() [297/360]

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

Definition at line 1313 of file rect_unittests.cc.

1313 {
1314 auto check_nans = [](const Rect& a, const Rect& b, const std::string& label) {
1315 ASSERT_TRUE(a.IsFinite()) << label;
1316 ASSERT_TRUE(b.IsFinite()) << label;
1317 ASSERT_FALSE(a.Union(b).IsEmpty());
1318
1319 for (int i = 1; i < 16; i++) {
1320 // NaN in a produces b
1321 EXPECT_EQ(swap_nan(a, i).Union(b), b) << label << ", index = " << i;
1322 // NaN in b produces a
1323 EXPECT_EQ(a.Union(swap_nan(b, i)), a) << label << ", index = " << i;
1324 // NaN in both is empty
1325 for (int j = 1; j < 16; j++) {
1326 EXPECT_TRUE(swap_nan(a, i).Union(swap_nan(b, j)).IsEmpty())
1327 << label << ", indices = " << i << ", " << j;
1328 }
1329 }
1330 };
1331
1332 auto check_empty_flips = [](const Rect& a, const Rect& b,
1333 const std::string& label) {
1334 ASSERT_FALSE(a.IsEmpty());
1335 // b is allowed to be empty
1336
1337 // unflipped a vs flipped (empty) b yields a
1338 EXPECT_EQ(a.Union(flip_lr(b)), a) << label;
1339 EXPECT_EQ(a.Union(flip_tb(b)), a) << label;
1340 EXPECT_EQ(a.Union(flip_lrtb(b)), a) << label;
1341
1342 // flipped (empty) a vs unflipped b yields b
1343 EXPECT_EQ(flip_lr(a).Union(b), b) << label;
1344 EXPECT_EQ(flip_tb(a).Union(b), b) << label;
1345 EXPECT_EQ(flip_lrtb(a).Union(b), b) << label;
1346
1347 // flipped (empty) a vs flipped (empty) b yields empty
1348 EXPECT_TRUE(flip_lr(a).Union(flip_lr(b)).IsEmpty()) << label;
1349 EXPECT_TRUE(flip_tb(a).Union(flip_tb(b)).IsEmpty()) << label;
1350 EXPECT_TRUE(flip_lrtb(a).Union(flip_lrtb(b)).IsEmpty()) << label;
1351 };
1352
1353 auto test = [&check_nans, &check_empty_flips](const Rect& a, const Rect& b,
1354 const Rect& result) {
1355 ASSERT_FALSE(a.IsEmpty()) << a;
1356 // b is allowed to be empty
1357
1358 std::stringstream stream;
1359 stream << a << " union " << b;
1360 auto label = stream.str();
1361
1362 EXPECT_EQ(a.Union(b), result) << label;
1363 EXPECT_EQ(b.Union(a), result) << label;
1364 check_empty_flips(a, b, label);
1365 check_nans(a, b, label);
1366 };
1367
1368 {
1369 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1370 auto b = Rect::MakeXYWH(0, 0, 0, 0);
1371 auto expected = Rect::MakeXYWH(100, 100, 100, 100);
1372 test(a, b, expected);
1373 }
1374
1375 {
1376 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1377 auto b = Rect::MakeXYWH(0, 0, 1, 1);
1378 auto expected = Rect::MakeXYWH(0, 0, 200, 200);
1379 test(a, b, expected);
1380 }
1381
1382 {
1383 auto a = Rect::MakeXYWH(100, 100, 100, 100);
1384 auto b = Rect::MakeXYWH(10, 10, 1, 1);
1385 auto expected = Rect::MakeXYWH(10, 10, 190, 190);
1386 test(a, b, expected);
1387 }
1388
1389 {
1390 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1391 auto b = Rect::MakeXYWH(10, 10, 100, 100);
1392 auto expected = Rect::MakeXYWH(0, 0, 110, 110);
1393 test(a, b, expected);
1394 }
1395
1396 {
1397 auto a = Rect::MakeXYWH(0, 0, 100, 100);
1398 auto b = Rect::MakeXYWH(100, 100, 100, 100);
1399 auto expected = Rect::MakeXYWH(0, 0, 200, 200);
1400 test(a, b, expected);
1401 }
1402 }

References impeller::saturated::b, flip_lr(), flip_lrtb(), flip_tb(), impeller::TRect< T >::IsEmpty(), impeller::TRect< T >::IsFinite(), impeller::TRect< Scalar >::MakeXYWH(), swap_nan(), and impeller::TRect< T >::Union().

## ◆ TEST() [298/360]

impeller::testing::TEST | ( | RectTest | ,
|  | RectXYWHIsEmpty |
| ) |  |

Definition at line 1127 of file rect_unittests.cc.

1127 {
1128 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
1129
1130 // Non-empty
1131 EXPECT_FALSE(Rect::MakeXYWH(1.5, 2.3, 10.5, 7.2).IsEmpty());
1132
1133 // Empty both width and height both 0 or negative, in all combinations
1134 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, 0.0).IsEmpty());
1135 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, -1.0).IsEmpty());
1136 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, -1.0).IsEmpty());
1137 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, 0.0).IsEmpty());
1138
1139 // Empty for 0 or negative width or height (but not both at the same time)
1140 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, 0.0).IsEmpty());
1141 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, -1.0).IsEmpty());
1142 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 0.0, 7.2).IsEmpty());
1143 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, -1.0, 7.2).IsEmpty());
1144
1145 // Empty for NaN in width or height or both
1146 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, 10.5, nan).IsEmpty());
1147 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, nan, 7.2).IsEmpty());
1148 EXPECT_TRUE(Rect::MakeXYWH(1.5, 2.3, nan, nan).IsEmpty());
1149 }

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

## ◆ TEST() [299/360]

impeller::testing::TEST | ( | RectTest | ,
|  | TransformAndClipBounds |
| ) |  |

Definition at line 3067 of file rect_unittests.cc.

3067 {
3068 {
3069 // This matrix should clip no corners.
3070 auto matrix = impeller::Matrix::MakeColumn(
3071 // clang-format off
3072 2.0f, 0.0f, 0.0f, 0.0f,
3073 0.0f, 4.0f, 0.0f, 0.0f,
3074 0.0f, 0.0f, 1.0f, 0.0f,
3075 0.0f, 0.0f, 0.0f, 8.0f
3076 // clang-format on
3077 );
3078 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3079 // None of these should have a W<0
3080 EXPECT_EQ(matrix.TransformHomogenous(src.GetLeftTop()),
3081 Vector3(200.0f, 400.0f, 8.0f));
3082 EXPECT_EQ(matrix.TransformHomogenous(src.GetRightTop()),
3083 Vector3(400.0f, 400.0f, 8.0f));
3084 EXPECT_EQ(matrix.TransformHomogenous(src.GetLeftBottom()),
3085 Vector3(200.0f, 800.0f, 8.0f));
3086 EXPECT_EQ(matrix.TransformHomogenous(src.GetRightBottom()),
3087 Vector3(400.0f, 800.0f, 8.0f));
3088
3089 Rect expect = Rect::MakeLTRB(25.0f, 50.0f, 50.0f, 100.0f);
3090 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3091 EXPECT_EQ(src.TransformAndClipBounds(matrix), expect);
3092 }
3093
3094 {
3095 // This matrix should clip one corner.
3096 auto matrix = impeller::Matrix::MakeColumn(
3097 // clang-format off
3098 2.0f, 0.0f, 0.0f, -0.01f,
3099 0.0f, 2.0f, 0.0f, -0.006f,
3100 0.0f, 0.0f, 1.0f, 0.0f,
3101 0.0f, 0.0f, 0.0f, 3.0f
3102 // clang-format on
3103 );
3104 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3105 // Exactly one of these should have a W<0
3106 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3107 Vector3(200.0f, 200.0f, 1.4f));
3108 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3109 Vector3(400.0f, 200.0f, 0.4f));
3110 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3111 Vector3(200.0f, 400.0f, 0.8f));
3112 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3113 Vector3(400.0f, 400.0f, -0.2f));
3114
3115 Rect expect = Rect::MakeLTRB(142.85715f, 142.85715f, 6553600.f, 6553600.f);
3116 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3117 EXPECT_RECT_NEAR(src.TransformAndClipBounds(matrix), expect);
3118 }
3119
3120 {
3121 // This matrix should clip two corners.
3122 auto matrix = impeller::Matrix::MakeColumn(
3123 // clang-format off
3124 2.0f, 0.0f, 0.0f, -.015f,
3125 0.0f, 2.0f, 0.0f, -.006f,
3126 0.0f, 0.0f, 1.0f, 0.0f,
3127 0.0f, 0.0f, 0.0f, 3.0f
3128 // clang-format on
3129 );
3130 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3131 // Exactly two of these should have a W<0
3132 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3133 Vector3(200.0f, 200.0f, 0.9f));
3134 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3135 Vector3(400.0f, 200.0f, -0.6f));
3136 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3137 Vector3(200.0f, 400.0f, 0.3f));
3138 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3139 Vector3(400.0f, 400.0f, -1.2f));
3140
3141 Rect expect = Rect::MakeLTRB(222.2222f, 222.2222f, 5898373.f, 6553600.f);
3142 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3143 EXPECT_RECT_NEAR(src.TransformAndClipBounds(matrix), expect);
3144 }
3145
3146 {
3147 // This matrix should clip three corners.
3148 auto matrix = impeller::Matrix::MakeColumn(
3149 // clang-format off
3150 2.0f, 0.0f, 0.0f, -.02f,
3151 0.0f, 2.0f, 0.0f, -.006f,
3152 0.0f, 0.0f, 1.0f, 0.0f,
3153 0.0f, 0.0f, 0.0f, 3.0f
3154 // clang-format on
3155 );
3156 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3157 // Exactly three of these should have a W<0
3158 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3159 Vector3(200.0f, 200.0f, 0.4f));
3160 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3161 Vector3(400.0f, 200.0f, -1.6f));
3162 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3163 Vector3(200.0f, 400.0f, -0.2f));
3164 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3165 Vector3(400.0f, 400.0f, -2.2f));
3166
3167 Rect expect = Rect::MakeLTRB(499.99988f, 499.99988f, 5898340.f, 4369400.f);
3168 EXPECT_FALSE(src.TransformAndClipBounds(matrix).IsEmpty());
3169 EXPECT_RECT_NEAR(src.TransformAndClipBounds(matrix), expect);
3170 }
3171
3172 {
3173 // This matrix should clip all four corners.
3174 auto matrix = impeller::Matrix::MakeColumn(
3175 // clang-format off
3176 2.0f, 0.0f, 0.0f, -.025f,
3177 0.0f, 2.0f, 0.0f, -.006f,
3178 0.0f, 0.0f, 1.0f, 0.0f,
3179 0.0f, 0.0f, 0.0f, 3.0f
3180 // clang-format on
3181 );
3182 Rect src = Rect::MakeLTRB(100.0f, 100.0f, 200.0f, 200.0f);
3183 // All of these should have a W<0
3184 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftTop()),
3185 Vector3(200.0f, 200.0f, -0.1f));
3186 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightTop()),
3187 Vector3(400.0f, 200.0f, -2.6f));
3188 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetLeftBottom()),
3189 Vector3(200.0f, 400.0f, -0.7f));
3190 EXPECT_VECTOR3_NEAR(matrix.TransformHomogenous(src.GetRightBottom()),
3191 Vector3(400.0f, 400.0f, -3.2f));
3192
3193 EXPECT_TRUE(src.TransformAndClipBounds(matrix).IsEmpty());
3194 }
3195 }

References EXPECT_RECT_NEAR, EXPECT_VECTOR3_NEAR, impeller::TRect< T >::GetLeftBottom(), impeller::TRect< T >::GetLeftTop(), impeller::TRect< T >::GetRightBottom(), impeller::TRect< T >::GetRightTop(), impeller::TRect< T >::IsEmpty(), impeller::Matrix::MakeColumn(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< T >::TransformAndClipBounds().

## ◆ TEST() [300/360]

impeller::testing::TEST | ( | RenderPassBuilder | ,
|  | CreatesMSAAResolveWithCorrectStore |
| ) |  |

Definition at line 102 of file render_pass_builder_vk_unittests.cc.

102 {
103 RenderPassBuilderVK builder = RenderPassBuilderVK();
104 auto const context = MockVulkanContextBuilder().Build();
105
106 // Create an MSAA color attachment.
107 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
108 SampleCount::kCount4, LoadAction::kClear,
109 StoreAction::kMultisampleResolve);
110
111 auto render_pass = builder.Build(context->GetDevice());
112
113 EXPECT_TRUE(!!render_pass);
114
115 auto maybe_color = builder.GetColorAttachments().find(0u);
116 ASSERT_NE(maybe_color, builder.GetColorAttachments().end());
117 auto color = maybe_color->second;
118
119 // MSAA Texture.
120 EXPECT_EQ(color.initialLayout, vk::ImageLayout::eGeneral);
121 EXPECT_EQ(color.finalLayout, vk::ImageLayout::eGeneral);
122 EXPECT_EQ(color.loadOp, vk::AttachmentLoadOp::eClear);
123 EXPECT_EQ(color.storeOp, vk::AttachmentStoreOp::eDontCare);
124
125 auto maybe_resolve = builder.GetResolves().find(0u);
126 ASSERT_NE(maybe_resolve, builder.GetResolves().end());
127 auto resolve = maybe_resolve->second;
128
129 // MSAA Resolve Texture.
130 EXPECT_EQ(resolve.initialLayout, vk::ImageLayout::eGeneral);
131 EXPECT_EQ(resolve.finalLayout, vk::ImageLayout::eGeneral);
132 EXPECT_EQ(resolve.loadOp, vk::AttachmentLoadOp::eClear);
133 EXPECT_EQ(resolve.storeOp, vk::AttachmentStoreOp::eStore);
134 }

References impeller::RenderPassBuilderVK::Build(), color, impeller::RenderPassBuilderVK::GetColorAttachments(), impeller::RenderPassBuilderVK::GetResolves(), impeller::kClear, impeller::kCount4, impeller::kMultisampleResolve, impeller::kR8G8B8A8UNormInt, and impeller::RenderPassBuilderVK::SetColorAttachment().

## ◆ TEST() [301/360]

impeller::testing::TEST | ( | RenderPassBuilder | ,
|  | CreatesRenderPassWithCombinedDepthStencil |
| ) |  |

Definition at line 30 of file render_pass_builder_vk_unittests.cc.

30 {
31 RenderPassBuilderVK builder = RenderPassBuilderVK();
32 auto const context = MockVulkanContextBuilder().Build();
33
34 // Create a single color attachment with a transient depth stencil.
35 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
36 SampleCount::kCount1, LoadAction::kClear,
37 StoreAction::kStore);
38 builder.SetDepthStencilAttachment(PixelFormat::kD24UnormS8Uint,
39 SampleCount::kCount1, LoadAction::kDontCare,
40 StoreAction::kDontCare);
41
42 auto render_pass = builder.Build(context->GetDevice());
43
44 EXPECT_TRUE(!!render_pass);
45
46 auto maybe_color = builder.GetColorAttachments().find(0u);
47 ASSERT_NE(maybe_color, builder.GetColorAttachments().end());
48 auto color = maybe_color->second;
49
50 EXPECT_EQ(color.initialLayout, vk::ImageLayout::eGeneral);
51 EXPECT_EQ(color.finalLayout, vk::ImageLayout::eGeneral);
52 EXPECT_EQ(color.loadOp, vk::AttachmentLoadOp::eClear);
53 EXPECT_EQ(color.storeOp, vk::AttachmentStoreOp::eStore);
54
55 auto maybe_depth_stencil = builder.GetDepthStencil();
56 ASSERT_TRUE(maybe_depth_stencil.has_value());
57 if (!maybe_depth_stencil.has_value()) {
58 return;
59 }
60 auto depth_stencil = maybe_depth_stencil.value();
61
62 EXPECT_EQ(depth_stencil.initialLayout, vk::ImageLayout::eUndefined);
63 EXPECT_EQ(depth_stencil.finalLayout,
64 vk::ImageLayout::eDepthStencilAttachmentOptimal);
65 EXPECT_EQ(depth_stencil.loadOp, vk::AttachmentLoadOp::eDontCare);
66 EXPECT_EQ(depth_stencil.storeOp, vk::AttachmentStoreOp::eDontCare);
67 EXPECT_EQ(depth_stencil.stencilLoadOp, vk::AttachmentLoadOp::eDontCare);
68 EXPECT_EQ(depth_stencil.stencilStoreOp, vk::AttachmentStoreOp::eDontCare);
69 }

References impeller::RenderPassBuilderVK::Build(), color, impeller::RenderPassBuilderVK::GetColorAttachments(), impeller::RenderPassBuilderVK::GetDepthStencil(), impeller::kClear, impeller::kCount1, impeller::kD24UnormS8Uint, impeller::kDontCare, impeller::kR8G8B8A8UNormInt, impeller::kStore, impeller::RenderPassBuilderVK::SetColorAttachment(), and impeller::RenderPassBuilderVK::SetDepthStencilAttachment().

## ◆ TEST() [302/360]

impeller::testing::TEST | ( | RenderPassBuilder | ,
|  | CreatesRenderPassWithNoDepthStencil |
| ) |  |

Definition at line 15 of file render_pass_builder_vk_unittests.cc.

15 {
16 RenderPassBuilderVK builder = RenderPassBuilderVK();
17 auto const context = MockVulkanContextBuilder().Build();
18
19 // Create a single color attachment with a transient depth stencil.
20 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
21 SampleCount::kCount1, LoadAction::kClear,
22 StoreAction::kStore);
23
24 auto render_pass = builder.Build(context->GetDevice());
25
26 EXPECT_TRUE(!!render_pass);
27 EXPECT_FALSE(builder.GetDepthStencil().has_value());
28 }

References impeller::RenderPassBuilderVK::Build(), impeller::RenderPassBuilderVK::GetDepthStencil(), impeller::kClear, impeller::kCount1, impeller::kR8G8B8A8UNormInt, impeller::kStore, and impeller::RenderPassBuilderVK::SetColorAttachment().

## ◆ TEST() [303/360]

impeller::testing::TEST | ( | RenderPassBuilder | ,
|  | CreatesRenderPassWithOnlyStencil |
| ) |  |

Definition at line 71 of file render_pass_builder_vk_unittests.cc.

71 {
72 RenderPassBuilderVK builder = RenderPassBuilderVK();
73 auto const context = MockVulkanContextBuilder().Build();
74
75 // Create a single color attachment with a transient depth stencil.
76 builder.SetColorAttachment(0, PixelFormat::kR8G8B8A8UNormInt,
77 SampleCount::kCount1, LoadAction::kClear,
78 StoreAction::kStore);
79 builder.SetStencilAttachment(PixelFormat::kS8UInt, SampleCount::kCount1,
80 LoadAction::kDontCare, StoreAction::kDontCare);
81
82 auto render_pass = builder.Build(context->GetDevice());
83
84 EXPECT_TRUE(!!render_pass);
85
86 auto maybe_depth_stencil = builder.GetDepthStencil();
87 ASSERT_TRUE(maybe_depth_stencil.has_value());
88 if (!maybe_depth_stencil.has_value()) {
89 return;
90 }
91 auto depth_stencil = maybe_depth_stencil.value();
92
93 EXPECT_EQ(depth_stencil.initialLayout, vk::ImageLayout::eUndefined);
94 EXPECT_EQ(depth_stencil.finalLayout,
95 vk::ImageLayout::eDepthStencilAttachmentOptimal);
96 EXPECT_EQ(depth_stencil.loadOp, vk::AttachmentLoadOp::eDontCare);
97 EXPECT_EQ(depth_stencil.storeOp, vk::AttachmentStoreOp::eDontCare);
98 EXPECT_EQ(depth_stencil.stencilLoadOp, vk::AttachmentLoadOp::eDontCare);
99 EXPECT_EQ(depth_stencil.stencilStoreOp, vk::AttachmentStoreOp::eDontCare);
100 }

References impeller::RenderPassBuilderVK::Build(), impeller::RenderPassBuilderVK::GetDepthStencil(), impeller::kClear, impeller::kCount1, impeller::kDontCare, impeller::kR8G8B8A8UNormInt, impeller::kS8UInt, impeller::kStore, impeller::RenderPassBuilderVK::SetColorAttachment(), and impeller::RenderPassBuilderVK::SetStencilAttachment().

## ◆ TEST() [304/360]

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

Definition at line 18 of file resource_manager_vk_unittests.cc.

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

References impeller::saturated::b, and impeller::ResourceManagerVK::Create().

## ◆ TEST() [305/360]

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

Definition at line 58 of file resource_manager_vk_unittests.cc.

58 {
59 // In a typical app, there is a single ResourceManagerVK per app, shared b/w
60 // threads.
61 //
62 // This test ensures that the ResourceManagerVK is thread-safe.
63 std::weak_ptr<ResourceManagerVK> manager;
64
65 {
66 auto const manager = ResourceManagerVK::Create();
67
68 // Spawn two threads, and have them both put resources into the manager.
69 struct MockResource {};
70
71 std::thread thread1([&manager]() {
72 UniqueResourceVKT<MockResource>(manager, MockResource{});
73 });
74
75 std::thread thread2([&manager]() {
76 UniqueResourceVKT<MockResource>(manager, MockResource{});
77 });
78
79 thread1.join();
80 thread2.join();
81 }
82
83 // The thread should have terminated.
84 EXPECT_EQ(manager.lock(), nullptr);
85 }

References impeller::ResourceManagerVK::Create().

## ◆ TEST() [306/360]

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

Definition at line 24 of file resource_manager_vk_unittests.cc.

24 {
25 auto const manager = ResourceManagerVK::Create();
26
27 auto waiter = fml::AutoResetWaitableEvent();
28 auto dead = false;
29 auto rattle = fml::ScopedCleanupClosure([&waiter]() { waiter.Signal(); });
30
31 // Not killed immediately.
32 EXPECT_FALSE(waiter.IsSignaledForTest());
33
34 {
35 auto resource = UniqueResourceVKT<fml::ScopedCleanupClosure>(
36 manager, std::move(rattle));
37 }
38
39 waiter.Wait();
40 }

References impeller::ResourceManagerVK::Create().

## ◆ TEST() [307/360]

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

Definition at line 43 of file resource_manager_vk_unittests.cc.

43 {
44 // Originally, this shared_ptr was never destroyed, and the thread never
45 // terminated. This test ensures that the thread terminates when the
46 // ResourceManagerVK is out of scope.
47 std::weak_ptr<ResourceManagerVK> manager;
48
49 {
50 auto shared = ResourceManagerVK::Create();
51 manager = shared;
52 }
53
54 // The thread should have terminated.
55 EXPECT_EQ(manager.lock(), nullptr);
56 }

References impeller::ResourceManagerVK::Create().

## ◆ TEST() [308/360]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | CastingFiniteDoubleToFloatStaysFinite |
| ) |  |

Definition at line 981 of file saturated_math_unittests.cc.

981 {
982 const double d_max = std::numeric_limits<double>::max();
983 const float f_max = std::numeric_limits<float>::max();
984
985 {
986 const float result = saturated::Cast<double, float>(d_max);
987 EXPECT_EQ(result, f_max);
988 }
989
990 {
991 const float result = saturated::Cast<double, float>(-d_max);
992 EXPECT_EQ(result, -f_max);
993 }
994 }

## ◆ TEST() [309/360]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | CastingInfiniteDoubleToFloatStaysInfinite |
| ) |  |

Definition at line 996 of file saturated_math_unittests.cc.

996 {
997 const double d_inf = std::numeric_limits<double>::infinity();
998 const float f_max = std::numeric_limits<float>::infinity();
999
1000 {
1001 const float result = saturated::Cast<double, float>(d_inf);
1002 EXPECT_EQ(result, f_max);
1003 }
1004
1005 {
1006 const float result = saturated::Cast<double, float>(-d_inf);
1007 EXPECT_EQ(result, -f_max);
1008 }
1009 }

## ◆ TEST() [310/360]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | CastingInfiniteScalarToSignedIntProducesLimit |
| ) |  |

Definition at line 1066 of file saturated_math_unittests.cc.

1066 {
1067 // larger than even any [u]int64_t;
1068 const Scalar inf = std::numeric_limits<Scalar>::infinity();
1069
1070 {
1071 const auto result = saturated::Cast<Scalar, int8_t>(inf);
1072 EXPECT_EQ(result, int8_t(0x7F));
1073 }
1074 {
1075 const auto result = saturated::Cast<Scalar, int8_t>(-inf);
1076 EXPECT_EQ(result, int8_t(0x80));
1077 }
1078
1079 {
1080 const auto result = saturated::Cast<Scalar, int16_t>(inf);
1081 EXPECT_EQ(result, int16_t(0x7FFF));
1082 }
1083 {
1084 const auto result = saturated::Cast<Scalar, int16_t>(-inf);
1085 EXPECT_EQ(result, int16_t(0x8000));
1086 }
1087
1088 {
1089 const auto result = saturated::Cast<Scalar, int32_t>(inf);
1090 EXPECT_EQ(result, int32_t(0x7FFFFFFF));
1091 }
1092 {
1093 const auto result = saturated::Cast<Scalar, int32_t>(-inf);
1094 EXPECT_EQ(result, int32_t(0x80000000));
1095 }
1096
1097 {
1098 const auto result = saturated::Cast<Scalar, int64_t>(inf);
1099 EXPECT_EQ(result, int64_t(0x7FFFFFFFFFFFFFFF));
1100 }
1101 {
1102 const auto result = saturated::Cast<Scalar, int64_t>(-inf);
1103 EXPECT_EQ(result, int64_t(0x8000000000000000));
1104 }
1105 }

## ◆ TEST() [311/360]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | CastingLargeScalarToSignedIntProducesLimit |
| ) |  |

Definition at line 1025 of file saturated_math_unittests.cc.

1025 {
1026 // larger than even any [u]int64_t;
1027 const Scalar large = 1e20f;
1028
1029 {
1030 const auto result = saturated::Cast<Scalar, int8_t>(large);
1031 EXPECT_EQ(result, int8_t(0x7F));
1032 }
1033 {
1034 const auto result = saturated::Cast<Scalar, int8_t>(-large);
1035 EXPECT_EQ(result, int8_t(0x80));
1036 }
1037
1038 {
1039 const auto result = saturated::Cast<Scalar, int16_t>(large);
1040 EXPECT_EQ(result, int16_t(0x7FFF));
1041 }
1042 {
1043 const auto result = saturated::Cast<Scalar, int16_t>(-large);
1044 EXPECT_EQ(result, int16_t(0x8000));
1045 }
1046
1047 {
1048 const auto result = saturated::Cast<Scalar, int32_t>(large);
1049 EXPECT_EQ(result, int32_t(0x7FFFFFFF));
1050 }
1051 {
1052 const auto result = saturated::Cast<Scalar, int32_t>(-large);
1053 EXPECT_EQ(result, int32_t(0x80000000));
1054 }
1055
1056 {
1057 const auto result = saturated::Cast<Scalar, int64_t>(large);
1058 EXPECT_EQ(result, int64_t(0x7FFFFFFFFFFFFFFF));
1059 }
1060 {
1061 const auto result = saturated::Cast<Scalar, int64_t>(-large);
1062 EXPECT_EQ(result, int64_t(0x8000000000000000));
1063 }
1064 }

## ◆ TEST() [312/360]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | CastingNaNDoubleToFloatStaysNaN |
| ) |  |

Definition at line 1011 of file saturated_math_unittests.cc.

1011 {
1012 const double d_nan = std::numeric_limits<double>::quiet_NaN();
1013
1014 {
1015 const float result = saturated::Cast<double, float>(d_nan);
1016 EXPECT_TRUE(std::isnan(result));
1017 }
1018
1019 {
1020 const float result = saturated::Cast<double, float>(-d_nan);
1021 EXPECT_TRUE(std::isnan(result));
1022 }
1023 }

## ◆ TEST() [313/360]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | CastingNaNScalarToSignedIntProducesZero |
| ) |  |

Definition at line 1107 of file saturated_math_unittests.cc.

1107 {
1108 // larger than even any [u]int64_t;
1109 const Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
1110
1111 {
1112 const auto result = saturated::Cast<Scalar, int8_t>(nan);
1113 EXPECT_EQ(result, int8_t(0));
1114 }
1115
1116 {
1117 const auto result = saturated::Cast<Scalar, int16_t>(nan);
1118 EXPECT_EQ(result, int16_t(0));
1119 }
1120
1121 {
1122 const auto result = saturated::Cast<Scalar, int32_t>(nan);
1123 EXPECT_EQ(result, int32_t(0));
1124 }
1125
1126 {
1127 const auto result = saturated::Cast<Scalar, int64_t>(nan);
1128 EXPECT_EQ(result, int64_t(0));
1129 }
1130 }

## ◆ TEST() [314/360]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ExplicitAddOfFloatingPoint |
| ) |  |

Definition at line 136 of file saturated_math_unittests.cc.

136 {
137 {
138 const float inf = std::numeric_limits<float>::infinity();
139 const float max = std::numeric_limits<float>::max();
140 const float big = max * 0.5f;
141
142 EXPECT_EQ(saturated::Add<float>(big, big), max);
143 EXPECT_EQ(saturated::Add<float>(max, big), inf);
144 EXPECT_EQ(saturated::Add<float>(big, max), inf);
145 EXPECT_EQ(saturated::Add<float>(max, max), inf);
146 EXPECT_EQ(saturated::Add<float>(max, inf), inf);
147 EXPECT_EQ(saturated::Add<float>(inf, max), inf);
148 EXPECT_EQ(saturated::Add<float>(inf, inf), inf);
149
150 EXPECT_EQ(saturated::Add<float>(-big, -big), -max);
151 EXPECT_EQ(saturated::Add<float>(-max, -big), -inf);
152 EXPECT_EQ(saturated::Add<float>(-big, -max), -inf);
153 EXPECT_EQ(saturated::Add<float>(-max, -max), -inf);
154 EXPECT_EQ(saturated::Add<float>(-max, -inf), -inf);
155 EXPECT_EQ(saturated::Add<float>(-inf, -max), -inf);
156 EXPECT_EQ(saturated::Add<float>(-inf, -inf), -inf);
157
158 EXPECT_EQ(saturated::Add<float>(big, -big), 0.0f);
159 EXPECT_EQ(saturated::Add<float>(max, -big), big);
160 EXPECT_EQ(saturated::Add<float>(big, -max), -big);
161 EXPECT_EQ(saturated::Add<float>(max, -max), 0.0f);
162 EXPECT_EQ(saturated::Add<float>(max, -inf), -inf);
163 EXPECT_EQ(saturated::Add<float>(inf, -max), inf);
164 EXPECT_TRUE(std::isnan(saturated::Add<float>(inf, -inf)));
165
166 EXPECT_EQ(saturated::Add<float>(-big, big), 0.0f);
167 EXPECT_EQ(saturated::Add<float>(-max, big), -big);
168 EXPECT_EQ(saturated::Add<float>(-big, max), big);
169 EXPECT_EQ(saturated::Add<float>(-max, max), 0.0f);
170 EXPECT_EQ(saturated::Add<float>(-max, inf), inf);
171 EXPECT_EQ(saturated::Add<float>(-inf, max), -inf);
172 EXPECT_TRUE(std::isnan(saturated::Add<float>(-inf, inf)));
173 }
174 {
175 const double inf = std::numeric_limits<double>::infinity();
176 const double max = std::numeric_limits<double>::max();
177 const double big = max * 0.5f;
178
179 EXPECT_EQ(saturated::Add<double>(big, big), max);
180 EXPECT_EQ(saturated::Add<double>(max, big), inf);
181 EXPECT_EQ(saturated::Add<double>(big, max), inf);
182 EXPECT_EQ(saturated::Add<double>(max, max), inf);
183 EXPECT_EQ(saturated::Add<double>(max, inf), inf);
184 EXPECT_EQ(saturated::Add<double>(inf, max), inf);
185 EXPECT_EQ(saturated::Add<double>(inf, inf), inf);
186
187 EXPECT_EQ(saturated::Add<double>(-big, -big), -max);
188 EXPECT_EQ(saturated::Add<double>(-max, -big), -inf);
189 EXPECT_EQ(saturated::Add<double>(-big, -max), -inf);
190 EXPECT_EQ(saturated::Add<double>(-max, -max), -inf);
191 EXPECT_EQ(saturated::Add<double>(-max, -inf), -inf);
192 EXPECT_EQ(saturated::Add<double>(-inf, -max), -inf);
193 EXPECT_EQ(saturated::Add<double>(-inf, -inf), -inf);
194
195 EXPECT_EQ(saturated::Add<double>(big, -big), 0.0f);
196 EXPECT_EQ(saturated::Add<double>(max, -big), big);
197 EXPECT_EQ(saturated::Add<double>(big, -max), -big);
198 EXPECT_EQ(saturated::Add<double>(max, -max), 0.0f);
199 EXPECT_EQ(saturated::Add<double>(max, -inf), -inf);
200 EXPECT_EQ(saturated::Add<double>(inf, -max), inf);
201 EXPECT_TRUE(std::isnan(saturated::Add<double>(inf, -inf)));
202
203 EXPECT_EQ(saturated::Add<double>(-big, big), 0.0f);
204 EXPECT_EQ(saturated::Add<double>(-max, big), -big);
205 EXPECT_EQ(saturated::Add<double>(-big, max), big);
206 EXPECT_EQ(saturated::Add<double>(-max, max), 0.0f);
207 EXPECT_EQ(saturated::Add<double>(-max, inf), inf);
208 EXPECT_EQ(saturated::Add<double>(-inf, max), -inf);
209 EXPECT_TRUE(std::isnan(saturated::Add<double>(-inf, inf)));
210 }
211 {
212 const Scalar inf = std::numeric_limits<Scalar>::infinity();
213 const Scalar max = std::numeric_limits<Scalar>::max();
214 const Scalar big = max * 0.5f;
215
216 EXPECT_EQ(saturated::Add<Scalar>(big, big), max);
217 EXPECT_EQ(saturated::Add<Scalar>(max, big), inf);
218 EXPECT_EQ(saturated::Add<Scalar>(big, max), inf);
219 EXPECT_EQ(saturated::Add<Scalar>(max, max), inf);
220 EXPECT_EQ(saturated::Add<Scalar>(max, inf), inf);
221 EXPECT_EQ(saturated::Add<Scalar>(inf, max), inf);
222 EXPECT_EQ(saturated::Add<Scalar>(inf, inf), inf);
223
224 EXPECT_EQ(saturated::Add<Scalar>(-big, -big), -max);
225 EXPECT_EQ(saturated::Add<Scalar>(-max, -big), -inf);
226 EXPECT_EQ(saturated::Add<Scalar>(-big, -max), -inf);
227 EXPECT_EQ(saturated::Add<Scalar>(-max, -max), -inf);
228 EXPECT_EQ(saturated::Add<Scalar>(-max, -inf), -inf);
229 EXPECT_EQ(saturated::Add<Scalar>(-inf, -max), -inf);
230 EXPECT_EQ(saturated::Add<Scalar>(-inf, -inf), -inf);
231
232 EXPECT_EQ(saturated::Add<Scalar>(big, -big), 0.0f);
233 EXPECT_EQ(saturated::Add<Scalar>(max, -big), big);
234 EXPECT_EQ(saturated::Add<Scalar>(big, -max), -big);
235 EXPECT_EQ(saturated::Add<Scalar>(max, -max), 0.0f);
236 EXPECT_EQ(saturated::Add<Scalar>(max, -inf), -inf);
237 EXPECT_EQ(saturated::Add<Scalar>(inf, -max), inf);
238 EXPECT_TRUE(std::isnan(saturated::Add<Scalar>(inf, -inf)));
239
240 EXPECT_EQ(saturated::Add<Scalar>(-big, big), 0.0f);
241 EXPECT_EQ(saturated::Add<Scalar>(-max, big), -big);
242 EXPECT_EQ(saturated::Add<Scalar>(-big, max), big);
243 EXPECT_EQ(saturated::Add<Scalar>(-max, max), 0.0f);
244 EXPECT_EQ(saturated::Add<Scalar>(-max, inf), inf);
245 EXPECT_EQ(saturated::Add<Scalar>(-inf, max), -inf);
246 EXPECT_TRUE(std::isnan(saturated::Add<Scalar>(-inf, inf)));
247 }
248 }

## ◆ TEST() [315/360]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ExplicitAddOfSignedInts |
| ) |  |

Definition at line 12 of file saturated_math_unittests.cc.

12 {
13 {
14 EXPECT_EQ(saturated::Add<int8_t>(0x79, 5), int8_t(0x7E));
15 EXPECT_EQ(saturated::Add<int8_t>(0x7A, 5), int8_t(0x7F));
16 EXPECT_EQ(saturated::Add<int8_t>(0x7B, 5), int8_t(0x7F));
17 }
18 {
19 EXPECT_EQ(saturated::Add<int8_t>(0x86, -5), int8_t(0x81));
20 EXPECT_EQ(saturated::Add<int8_t>(0x85, -5), int8_t(0x80));
21 EXPECT_EQ(saturated::Add<int8_t>(0x84, -5), int8_t(0x80));
22 }
23 {
24 EXPECT_EQ(saturated::Add<int16_t>(0x7FF9, 5), int16_t(0x7FFE));
25 EXPECT_EQ(saturated::Add<int16_t>(0x7FFA, 5), int16_t(0x7FFF));
26 EXPECT_EQ(saturated::Add<int16_t>(0x7FFB, 5), int16_t(0x7FFF));
27 }
28 {
29 EXPECT_EQ(saturated::Add<int16_t>(0x8006, -5), int16_t(0x8001));
30 EXPECT_EQ(saturated::Add<int16_t>(0x8005, -5), int16_t(0x8000));
31 EXPECT_EQ(saturated::Add<int16_t>(0x8004, -5), int16_t(0x8000));
32 }
33 {
34 EXPECT_EQ(saturated::Add<int32_t>(0x7FFFFFF9, 5), int32_t(0x7FFFFFFE));
35 EXPECT_EQ(saturated::Add<int32_t>(0x7FFFFFFA, 5), int32_t(0x7FFFFFFF));
36 EXPECT_EQ(saturated::Add<int32_t>(0x7FFFFFFB, 5), int32_t(0x7FFFFFFF));
37 }
38 {
39 EXPECT_EQ(saturated::Add<int32_t>(0x80000006, -5), int32_t(0x80000001));
40 EXPECT_EQ(saturated::Add<int32_t>(0x80000005, -5), int32_t(0x80000000));
41 EXPECT_EQ(saturated::Add<int32_t>(0x80000004, -5), int32_t(0x80000000));
42 }
43 {
44 EXPECT_EQ(saturated::Add<int64_t>(0x7FFFFFFFFFFFFFF9, 5),
45 int64_t(0x7FFFFFFFFFFFFFFE));
46 EXPECT_EQ(saturated::Add<int64_t>(0x7FFFFFFFFFFFFFFA, 5),
47 int64_t(0x7FFFFFFFFFFFFFFF));
48 EXPECT_EQ(saturated::Add<int64_t>(0x7FFFFFFFFFFFFFFB, 5),
49 int64_t(0x7FFFFFFFFFFFFFFF));
50 }
51 {
52 EXPECT_EQ(saturated::Add<int64_t>(0x8000000000000006, -5),
53 int64_t(0x8000000000000001));
54 EXPECT_EQ(saturated::Add<int64_t>(0x8000000000000005, -5),
55 int64_t(0x8000000000000000));
56 EXPECT_EQ(saturated::Add<int64_t>(0x8000000000000004, -5),
57 int64_t(0x8000000000000000));
58 }
59 }

## ◆ TEST() [316/360]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ExplicitAverageScalarOfFloatingPoint |
| ) |  |

Definition at line 828 of file saturated_math_unittests.cc.

828 {
829 const Scalar s_inf = std::numeric_limits<Scalar>::infinity();
830 const Scalar s_max = std::numeric_limits<Scalar>::max();
831 const Scalar s_big = s_max * 0.5f;
832
833 {
834 const float inf = std::numeric_limits<Scalar>::infinity();
835 const float max = std::numeric_limits<float>::max();
836 const float big = max * 0.5f;
837
838 EXPECT_EQ(saturated::AverageScalar<float>(big, big), s_big);
839 EXPECT_EQ(saturated::AverageScalar<float>(max, max), s_max);
840 EXPECT_EQ(saturated::AverageScalar<float>(big, -big), 0.0f);
841 EXPECT_EQ(saturated::AverageScalar<float>(max, -max), 0.0f);
842 EXPECT_EQ(saturated::AverageScalar<float>(-big, big), 0.0f);
843 EXPECT_EQ(saturated::AverageScalar<float>(-max, max), 0.0f);
844 EXPECT_EQ(saturated::AverageScalar<float>(-big, -big), -s_big);
845 EXPECT_EQ(saturated::AverageScalar<float>(-max, -max), -s_max);
846
847 EXPECT_EQ(saturated::AverageScalar<float>(inf, inf), s_inf);
848 EXPECT_EQ(saturated::AverageScalar<float>(-inf, -inf), -s_inf);
849 EXPECT_TRUE(std::isnan(saturated::AverageScalar<float>(-inf, inf)));
850 EXPECT_TRUE(std::isnan(saturated::AverageScalar<float>(inf, -inf)));
851 }
852 {
853 const double inf = std::numeric_limits<Scalar>::infinity();
854 const double max = std::numeric_limits<double>::max();
855 const double big = max * 0.5;
856
857 // Most of the averages below using the double constants will
858 // overflow the Scalar return value and result in infinity,
859 // so we also test with some Scalar constants (promoted to double)
860 // to verify that they don't overflow in the double template
861 EXPECT_EQ(saturated::AverageScalar<double>(s_big, s_big), s_big);
862 EXPECT_EQ(saturated::AverageScalar<double>(s_max, s_max), s_max);
863 EXPECT_EQ(saturated::AverageScalar<double>(-s_big, -s_big), -s_big);
864 EXPECT_EQ(saturated::AverageScalar<double>(-s_max, -s_max), -s_max);
865
866 // And now testing continues with the double constants which
867 // mostly overflow
868 EXPECT_EQ(saturated::AverageScalar<double>(big, big), s_inf);
869 EXPECT_EQ(saturated::AverageScalar<double>(max, max), s_inf);
870 EXPECT_EQ(saturated::AverageScalar<double>(big, -big), 0.0f);
871 EXPECT_EQ(saturated::AverageScalar<double>(max, -max), 0.0f);
872 EXPECT_EQ(saturated::AverageScalar<double>(-big, big), 0.0f);
873 EXPECT_EQ(saturated::AverageScalar<double>(-max, max), 0.0f);
874 EXPECT_EQ(saturated::AverageScalar<double>(-big, -big), -s_inf);
875 EXPECT_EQ(saturated::AverageScalar<double>(-max, -max), -s_inf);
876
877 EXPECT_EQ(saturated::AverageScalar<double>(inf, inf), s_inf);
878 EXPECT_EQ(saturated::AverageScalar<double>(-inf, -inf), -s_inf);
879 EXPECT_TRUE(std::isnan(saturated::AverageScalar<double>(-inf, inf)));
880 EXPECT_TRUE(std::isnan(saturated::AverageScalar<double>(inf, -inf)));
881 }
882 {
883 const Scalar inf = std::numeric_limits<Scalar>::infinity();
884 const Scalar max = std::numeric_limits<Scalar>::max();
885 const Scalar big = max * 0.5f;
886
887 EXPECT_EQ(saturated::AverageScalar<Scalar>(big, big), s_big);
888 EXPECT_EQ(saturated::AverageScalar<Scalar>(max, max), s_max);
889 EXPECT_EQ(saturated::AverageScalar<Scalar>(big, -big), 0.0f);
890 EXPECT_EQ(saturated::AverageScalar<Scalar>(max, -max), 0.0f);
891 EXPECT_EQ(saturated::AverageScalar<Scalar>(-big, big), 0.0f);
892 EXPECT_EQ(saturated::AverageScalar<Scalar>(-max, max), 0.0f);
893 EXPECT_EQ(saturated::AverageScalar<Scalar>(-big, -big), -s_big);
894 EXPECT_EQ(saturated::AverageScalar<Scalar>(-max, -max), -s_max);
895
896 EXPECT_EQ(saturated::AverageScalar<Scalar>(inf, inf), s_inf);
897 EXPECT_EQ(saturated::AverageScalar<Scalar>(-inf, -inf), -s_inf);
898 EXPECT_TRUE(std::isnan(saturated::AverageScalar<Scalar>(-inf, s_inf)));
899 EXPECT_TRUE(std::isnan(saturated::AverageScalar<Scalar>(inf, -s_inf)));
900 }
901 }

## ◆ TEST() [317/360]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ExplicitAverageScalarOfSignedInts |
| ) |  |

Definition at line 716 of file saturated_math_unittests.cc.

716 {
717 // For each type try:
718 //
719 // - near the limits, averaging to 0
720 // - at the limits, averaging to 0 or 0.5 depending on precision
721 // - both large enough for the sum to overflow
722 // - both negative enough for the sum to underflow
723 {
724 EXPECT_EQ(saturated::AverageScalar<int8_t>(0x81, 0x7F), -0.0f);
725 EXPECT_EQ(saturated::AverageScalar<int8_t>(0x80, 0x7F), -0.5f);
726 EXPECT_EQ(saturated::AverageScalar<int8_t>(0x70, 0x75), 114.5f);
727 EXPECT_EQ(saturated::AverageScalar<int8_t>(0x85, 0x8A), -120.5f);
728 }
729 {
730 EXPECT_EQ(saturated::AverageScalar<int16_t>(0x8001, 0x7FFF), -0.0f);
731 EXPECT_EQ(saturated::AverageScalar<int16_t>(0x8000, 0x7FFF), -0.5f);
732 EXPECT_EQ(saturated::AverageScalar<int16_t>(0x7000, 0x7005), 28674.5f);
733 EXPECT_EQ(saturated::AverageScalar<int16_t>(0x8005, 0x800A), -32760.5f);
734 }
735 {
736 EXPECT_EQ(saturated::AverageScalar<int32_t>(0x80000001, 0x7FFFFFFF), -0.0f);
737 EXPECT_EQ(saturated::AverageScalar<int32_t>(0x80000000, 0x7FFFFFFF), -0.5f);
738 EXPECT_EQ(saturated::AverageScalar<int32_t>(0x70000000, 0x70000005),
739 1879048195.5f);
740 EXPECT_EQ(saturated::AverageScalar<int32_t>(0x80000005, 0x8000000A),
741 -2147483655.5f);
742 }
743 {
744 EXPECT_EQ(saturated::AverageScalar<int64_t>(0x8000000000000001,
745 0x7FFFFFFFFFFFFFFF),
746 0.0f);
747 // 64-bit integers overflow the ability of a Scalar (float) to
748 // represent discrete integers and so the two numbers we are
749 // averaging here will look like the same number with different
750 // signs and the answer will be "0"
751 EXPECT_EQ(saturated::AverageScalar<int64_t>(0x8000000000000000,
752 0x7FFFFFFFFFFFFFFF),
753 0.0f);
754 EXPECT_NEAR(saturated::AverageScalar<int64_t>(0x7000000000000000,
755 0x7000000000000005),
756 8.07045053e+18, 1e18);
757 EXPECT_NEAR(saturated::AverageScalar<int64_t>(0x8000000000000005,
758 0x800000000000000A),
759 -9.223372e+18, 1e18);
760 }
761 }

## ◆ TEST() [318/360]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ExplicitSubOfFloatingPoint |
| ) |  |

Definition at line 488 of file saturated_math_unittests.cc.

488 {
489 {
490 const float inf = std::numeric_limits<float>::infinity();
491 const float max = std::numeric_limits<float>::max();
492 const float big = max * 0.5f;
493
494 EXPECT_EQ(saturated::Sub<float>(big, big), 0.0f);
495 EXPECT_EQ(saturated::Sub<float>(max, big), big);
496 EXPECT_EQ(saturated::Sub<float>(big, max), -big);
497 EXPECT_EQ(saturated::Sub<float>(max, max), 0.0f);
498 EXPECT_EQ(saturated::Sub<float>(max, inf), -inf);
499 EXPECT_EQ(saturated::Sub<float>(inf, max), inf);
500 EXPECT_TRUE(std::isnan(saturated::Sub<float>(inf, inf)));
501
502 EXPECT_EQ(saturated::Sub<float>(-big, -big), 0.0f);
503 EXPECT_EQ(saturated::Sub<float>(-max, -big), -big);
504 EXPECT_EQ(saturated::Sub<float>(-big, -max), big);
505 EXPECT_EQ(saturated::Sub<float>(-max, -max), 0.0f);
506 EXPECT_EQ(saturated::Sub<float>(-max, -inf), inf);
507 EXPECT_EQ(saturated::Sub<float>(-inf, -max), -inf);
508 EXPECT_TRUE(std::isnan(saturated::Sub<float>(-inf, -inf)));
509
510 EXPECT_EQ(saturated::Sub<float>(big, -big), max);
511 EXPECT_EQ(saturated::Sub<float>(max, -big), inf);
512 EXPECT_EQ(saturated::Sub<float>(big, -max), inf);
513 EXPECT_EQ(saturated::Sub<float>(max, -max), inf);
514 EXPECT_EQ(saturated::Sub<float>(max, -inf), inf);
515 EXPECT_EQ(saturated::Sub<float>(inf, -max), inf);
516 EXPECT_EQ(saturated::Sub<float>(inf, -inf), inf);
517
518 EXPECT_EQ(saturated::Sub<float>(-big, big), -max);
519 EXPECT_EQ(saturated::Sub<float>(-max, big), -inf);
520 EXPECT_EQ(saturated::Sub<float>(-big, max), -inf);
521 EXPECT_EQ(saturated::Sub<float>(-max, max), -inf);
522 EXPECT_EQ(saturated::Sub<float>(-max, inf), -inf);
523 EXPECT_EQ(saturated::Sub<float>(-inf, max), -inf);
524 EXPECT_EQ(saturated::Sub<float>(-inf, inf), -inf);
525 }
526 {
527 const double inf = std::numeric_limits<double>::infinity();
528 const double max = std::numeric_limits<double>::max();
529 const double big = max * 0.5f;
530
531 EXPECT_EQ(saturated::Sub<double>(big, big), 0.0f);
532 EXPECT_EQ(saturated::Sub<double>(max, big), big);
533 EXPECT_EQ(saturated::Sub<double>(big, max), -big);
534 EXPECT_EQ(saturated::Sub<double>(max, max), 0.0f);
535 EXPECT_EQ(saturated::Sub<double>(max, inf), -inf);
536 EXPECT_EQ(saturated::Sub<double>(inf, max), inf);
537 EXPECT_TRUE(std::isnan(saturated::Sub<double>(inf, inf)));
538
539 EXPECT_EQ(saturated::Sub<double>(-big, -big), 0.0f);
540 EXPECT_EQ(saturated::Sub<double>(-max, -big), -big);
541 EXPECT_EQ(saturated::Sub<double>(-big, -max), big);
542 EXPECT_EQ(saturated::Sub<double>(-max, -max), 0.0f);
543 EXPECT_EQ(saturated::Sub<double>(-max, -inf), inf);
544 EXPECT_EQ(saturated::Sub<double>(-inf, -max), -inf);
545 EXPECT_TRUE(std::isnan(saturated::Sub<double>(-inf, -inf)));
546
547 EXPECT_EQ(saturated::Sub<double>(big, -big), max);
548 EXPECT_EQ(saturated::Sub<double>(max, -big), inf);
549 EXPECT_EQ(saturated::Sub<double>(big, -max), inf);
550 EXPECT_EQ(saturated::Sub<double>(max, -max), inf);
551 EXPECT_EQ(saturated::Sub<double>(max, -inf), inf);
552 EXPECT_EQ(saturated::Sub<double>(inf, -max), inf);
553 EXPECT_EQ(saturated::Sub<double>(inf, -inf), inf);
554
555 EXPECT_EQ(saturated::Sub<double>(-big, big), -max);
556 EXPECT_EQ(saturated::Sub<double>(-max, big), -inf);
557 EXPECT_EQ(saturated::Sub<double>(-big, max), -inf);
558 EXPECT_EQ(saturated::Sub<double>(-max, max), -inf);
559 EXPECT_EQ(saturated::Sub<double>(-max, inf), -inf);
560 EXPECT_EQ(saturated::Sub<double>(-inf, max), -inf);
561 EXPECT_EQ(saturated::Sub<double>(-inf, inf), -inf);
562 }
563 {
564 const Scalar inf = std::numeric_limits<Scalar>::infinity();
565 const Scalar max = std::numeric_limits<Scalar>::max();
566 const Scalar big = max * 0.5f;
567
568 EXPECT_EQ(saturated::Sub<Scalar>(big, big), 0.0f);
569 EXPECT_EQ(saturated::Sub<Scalar>(max, big), big);
570 EXPECT_EQ(saturated::Sub<Scalar>(big, max), -big);
571 EXPECT_EQ(saturated::Sub<Scalar>(max, max), 0.0f);
572 EXPECT_EQ(saturated::Sub<Scalar>(max, inf), -inf);
573 EXPECT_EQ(saturated::Sub<Scalar>(inf, max), inf);
574 EXPECT_TRUE(std::isnan(saturated::Sub<Scalar>(inf, inf)));
575
576 EXPECT_EQ(saturated::Sub<Scalar>(-big, -big), 0.0f);
577 EXPECT_EQ(saturated::Sub<Scalar>(-max, -big), -big);
578 EXPECT_EQ(saturated::Sub<Scalar>(-big, -max), big);
579 EXPECT_EQ(saturated::Sub<Scalar>(-max, -max), 0.0f);
580 EXPECT_EQ(saturated::Sub<Scalar>(-max, -inf), inf);
581 EXPECT_EQ(saturated::Sub<Scalar>(-inf, -max), -inf);
582 EXPECT_TRUE(std::isnan(saturated::Sub<Scalar>(-inf, -inf)));
583
584 EXPECT_EQ(saturated::Sub<Scalar>(big, -big), max);
585 EXPECT_EQ(saturated::Sub<Scalar>(max, -big), inf);
586 EXPECT_EQ(saturated::Sub<Scalar>(big, -max), inf);
587 EXPECT_EQ(saturated::Sub<Scalar>(max, -max), inf);
588 EXPECT_EQ(saturated::Sub<Scalar>(max, -inf), inf);
589 EXPECT_EQ(saturated::Sub<Scalar>(inf, -max), inf);
590 EXPECT_EQ(saturated::Sub<Scalar>(inf, -inf), inf);
591
592 EXPECT_EQ(saturated::Sub<Scalar>(-big, big), -max);
593 EXPECT_EQ(saturated::Sub<Scalar>(-max, big), -inf);
594 EXPECT_EQ(saturated::Sub<Scalar>(-big, max), -inf);
595 EXPECT_EQ(saturated::Sub<Scalar>(-max, max), -inf);
596 EXPECT_EQ(saturated::Sub<Scalar>(-max, inf), -inf);
597 EXPECT_EQ(saturated::Sub<Scalar>(-inf, max), -inf);
598 EXPECT_EQ(saturated::Sub<Scalar>(-inf, inf), -inf);
599 }
600 }

## ◆ TEST() [319/360]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ExplicitSubOfSignedInts |
| ) |  |

Definition at line 364 of file saturated_math_unittests.cc.

364 {
365 {
366 EXPECT_EQ(saturated::Sub<int8_t>(0x79, -5), int8_t(0x7E));
367 EXPECT_EQ(saturated::Sub<int8_t>(0x7A, -5), int8_t(0x7F));
368 EXPECT_EQ(saturated::Sub<int8_t>(0x7B, -5), int8_t(0x7F));
369 }
370 {
371 EXPECT_EQ(saturated::Sub<int8_t>(0x86, 5), int8_t(0x81));
372 EXPECT_EQ(saturated::Sub<int8_t>(0x85, 5), int8_t(0x80));
373 EXPECT_EQ(saturated::Sub<int8_t>(0x84, 5), int8_t(0x80));
374 }
375 {
376 EXPECT_EQ(saturated::Sub<int16_t>(0x7FF9, -5), int16_t(0x7FFE));
377 EXPECT_EQ(saturated::Sub<int16_t>(0x7FFA, -5), int16_t(0x7FFF));
378 EXPECT_EQ(saturated::Sub<int16_t>(0x7FFB, -5), int16_t(0x7FFF));
379 }
380 {
381 EXPECT_EQ(saturated::Sub<int16_t>(0x8006, 5), int16_t(0x8001));
382 EXPECT_EQ(saturated::Sub<int16_t>(0x8005, 5), int16_t(0x8000));
383 EXPECT_EQ(saturated::Sub<int16_t>(0x8004, 5), int16_t(0x8000));
384 }
385 {
386 EXPECT_EQ(saturated::Sub<int32_t>(0x7FFFFFF9, -5), int32_t(0x7FFFFFFE));
387 EXPECT_EQ(saturated::Sub<int32_t>(0x7FFFFFFA, -5), int32_t(0x7FFFFFFF));
388 EXPECT_EQ(saturated::Sub<int32_t>(0x7FFFFFFB, -5), int32_t(0x7FFFFFFF));
389 }
390 {
391 EXPECT_EQ(saturated::Sub<int32_t>(0x80000006, 5), int32_t(0x80000001));
392 EXPECT_EQ(saturated::Sub<int32_t>(0x80000005, 5), int32_t(0x80000000));
393 EXPECT_EQ(saturated::Sub<int32_t>(0x80000004, 5), int32_t(0x80000000));
394 }
395 {
396 EXPECT_EQ(saturated::Sub<int64_t>(0x7FFFFFFFFFFFFFF9, -5),
397 int64_t(0x7FFFFFFFFFFFFFFE));
398 EXPECT_EQ(saturated::Sub<int64_t>(0x7FFFFFFFFFFFFFFA, -5),
399 int64_t(0x7FFFFFFFFFFFFFFF));
400 EXPECT_EQ(saturated::Sub<int64_t>(0x7FFFFFFFFFFFFFFB, -5),
401 int64_t(0x7FFFFFFFFFFFFFFF));
402 }
403 {
404 EXPECT_EQ(saturated::Sub<int64_t>(0x8000000000000006, 5),
405 int64_t(0x8000000000000001));
406 EXPECT_EQ(saturated::Sub<int64_t>(0x8000000000000005, 5),
407 int64_t(0x8000000000000000));
408 EXPECT_EQ(saturated::Sub<int64_t>(0x8000000000000004, 5),
409 int64_t(0x8000000000000000));
410 }
411 }

## ◆ TEST() [320/360]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ImplicitAddOfFloatingPoint |
| ) |  |

Definition at line 250 of file saturated_math_unittests.cc.

250 {
251 {
252 const float inf = std::numeric_limits<float>::infinity();
253 const float max = std::numeric_limits<float>::max();
254 const float big = max * 0.5f;
255
256 EXPECT_EQ(saturated::Add(big, big), max);
257 EXPECT_EQ(saturated::Add(max, big), inf);
258 EXPECT_EQ(saturated::Add(big, max), inf);
259 EXPECT_EQ(saturated::Add(max, max), inf);
260 EXPECT_EQ(saturated::Add(max, inf), inf);
261 EXPECT_EQ(saturated::Add(inf, max), inf);
262 EXPECT_EQ(saturated::Add(inf, inf), inf);
263
264 EXPECT_EQ(saturated::Add(-big, -big), -max);
265 EXPECT_EQ(saturated::Add(-max, -big), -inf);
266 EXPECT_EQ(saturated::Add(-big, -max), -inf);
267 EXPECT_EQ(saturated::Add(-max, -max), -inf);
268 EXPECT_EQ(saturated::Add(-max, -inf), -inf);
269 EXPECT_EQ(saturated::Add(-inf, -max), -inf);
270 EXPECT_EQ(saturated::Add(-inf, -inf), -inf);
271
272 EXPECT_EQ(saturated::Add(big, -big), 0.0f);
273 EXPECT_EQ(saturated::Add(max, -big), big);
274 EXPECT_EQ(saturated::Add(big, -max), -big);
275 EXPECT_EQ(saturated::Add(max, -max), 0.0f);
276 EXPECT_EQ(saturated::Add(max, -inf), -inf);
277 EXPECT_EQ(saturated::Add(inf, -max), inf);
278 EXPECT_TRUE(std::isnan(saturated::Add(inf, -inf)));
279
280 EXPECT_EQ(saturated::Add(-big, big), 0.0f);
281 EXPECT_EQ(saturated::Add(-max, big), -big);
282 EXPECT_EQ(saturated::Add(-big, max), big);
283 EXPECT_EQ(saturated::Add(-max, max), 0.0f);
284 EXPECT_EQ(saturated::Add(-max, inf), inf);
285 EXPECT_EQ(saturated::Add(-inf, max), -inf);
286 EXPECT_TRUE(std::isnan(saturated::Add(-inf, inf)));
287 }
288 {
289 const double inf = std::numeric_limits<double>::infinity();
290 const double max = std::numeric_limits<double>::max();
291 const double big = max * 0.5f;
292
293 EXPECT_EQ(saturated::Add(big, big), max);
294 EXPECT_EQ(saturated::Add(max, big), inf);
295 EXPECT_EQ(saturated::Add(big, max), inf);
296 EXPECT_EQ(saturated::Add(max, max), inf);
297 EXPECT_EQ(saturated::Add(max, inf), inf);
298 EXPECT_EQ(saturated::Add(inf, max), inf);
299 EXPECT_EQ(saturated::Add(inf, inf), inf);
300
301 EXPECT_EQ(saturated::Add(-big, -big), -max);
302 EXPECT_EQ(saturated::Add(-max, -big), -inf);
303 EXPECT_EQ(saturated::Add(-big, -max), -inf);
304 EXPECT_EQ(saturated::Add(-max, -max), -inf);
305 EXPECT_EQ(saturated::Add(-max, -inf), -inf);
306 EXPECT_EQ(saturated::Add(-inf, -max), -inf);
307 EXPECT_EQ(saturated::Add(-inf, -inf), -inf);
308
309 EXPECT_EQ(saturated::Add(big, -big), 0.0f);
310 EXPECT_EQ(saturated::Add(max, -big), big);
311 EXPECT_EQ(saturated::Add(big, -max), -big);
312 EXPECT_EQ(saturated::Add(max, -max), 0.0f);
313 EXPECT_EQ(saturated::Add(max, -inf), -inf);
314 EXPECT_EQ(saturated::Add(inf, -max), inf);
315 EXPECT_TRUE(std::isnan(saturated::Add(inf, -inf)));
316
317 EXPECT_EQ(saturated::Add(-big, big), 0.0f);
318 EXPECT_EQ(saturated::Add(-max, big), -big);
319 EXPECT_EQ(saturated::Add(-big, max), big);
320 EXPECT_EQ(saturated::Add(-max, max), 0.0f);
321 EXPECT_EQ(saturated::Add(-max, inf), inf);
322 EXPECT_EQ(saturated::Add(-inf, max), -inf);
323 EXPECT_TRUE(std::isnan(saturated::Add(-inf, inf)));
324 }
325 {
326 const Scalar inf = std::numeric_limits<Scalar>::infinity();
327 const Scalar max = std::numeric_limits<Scalar>::max();
328 const Scalar big = max * 0.5f;
329
330 EXPECT_EQ(saturated::Add(big, big), max);
331 EXPECT_EQ(saturated::Add(max, big), inf);
332 EXPECT_EQ(saturated::Add(big, max), inf);
333 EXPECT_EQ(saturated::Add(max, max), inf);
334 EXPECT_EQ(saturated::Add(max, inf), inf);
335 EXPECT_EQ(saturated::Add(inf, max), inf);
336 EXPECT_EQ(saturated::Add(inf, inf), inf);
337
338 EXPECT_EQ(saturated::Add(-big, -big), -max);
339 EXPECT_EQ(saturated::Add(-max, -big), -inf);
340 EXPECT_EQ(saturated::Add(-big, -max), -inf);
341 EXPECT_EQ(saturated::Add(-max, -max), -inf);
342 EXPECT_EQ(saturated::Add(-max, -inf), -inf);
343 EXPECT_EQ(saturated::Add(-inf, -max), -inf);
344 EXPECT_EQ(saturated::Add(-inf, -inf), -inf);
345
346 EXPECT_EQ(saturated::Add(big, -big), 0.0f);
347 EXPECT_EQ(saturated::Add(max, -big), big);
348 EXPECT_EQ(saturated::Add(big, -max), -big);
349 EXPECT_EQ(saturated::Add(max, -max), 0.0f);
350 EXPECT_EQ(saturated::Add(max, -inf), -inf);
351 EXPECT_EQ(saturated::Add(inf, -max), inf);
352 EXPECT_TRUE(std::isnan(saturated::Add(inf, -inf)));
353
354 EXPECT_EQ(saturated::Add(-big, big), 0.0f);
355 EXPECT_EQ(saturated::Add(-max, big), -big);
356 EXPECT_EQ(saturated::Add(-big, max), big);
357 EXPECT_EQ(saturated::Add(-max, max), 0.0f);
358 EXPECT_EQ(saturated::Add(-max, inf), inf);
359 EXPECT_EQ(saturated::Add(-inf, max), -inf);
360 EXPECT_TRUE(std::isnan(saturated::Add(-inf, inf)));
361 }
362 }

## ◆ TEST() [321/360]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ImplicitAddOfSignedInts |
| ) |  |

Definition at line 61 of file saturated_math_unittests.cc.

61 {
62 {
63 int8_t a = 0x79;
64 int8_t b = 5;
65 EXPECT_EQ(saturated::Add(a, b), int8_t(0x7E));
66 a = 0x7A;
67 EXPECT_EQ(saturated::Add(a, b), int8_t(0x7F));
68 a = 0x7B;
69 EXPECT_EQ(saturated::Add(a, b), int8_t(0x7F));
70 }
71 {
72 int8_t a = 0x86;
73 int8_t b = -5;
74 EXPECT_EQ(saturated::Add(a, b), int8_t(0x81));
75 a = 0x85;
76 EXPECT_EQ(saturated::Add(a, b), int8_t(0x80));
77 a = 0x84;
78 EXPECT_EQ(saturated::Add(a, b), int8_t(0x80));
79 }
80 {
81 int16_t a = 0x7FF9;
82 int16_t b = 5;
83 EXPECT_EQ(saturated::Add(a, b), int16_t(0x7FFE));
84 a = 0x7FFA;
85 EXPECT_EQ(saturated::Add(a, b), int16_t(0x7FFF));
86 a = 0x7FFB;
87 EXPECT_EQ(saturated::Add(a, b), int16_t(0x7FFF));
88 }
89 {
90 int16_t a = 0x8006;
91 int16_t b = -5;
92 EXPECT_EQ(saturated::Add(a, b), int16_t(0x8001));
93 a = 0x8005;
94 EXPECT_EQ(saturated::Add(a, b), int16_t(0x8000));
95 a = 0x8004;
96 EXPECT_EQ(saturated::Add(a, b), int16_t(0x8000));
97 }
98 {
99 int32_t a = 0x7FFFFFF9;
100 int32_t b = 5;
101 EXPECT_EQ(saturated::Add(a, b), int32_t(0x7FFFFFFE));
102 a = 0x7FFFFFFA;
103 EXPECT_EQ(saturated::Add(a, b), int32_t(0x7FFFFFFF));
104 a = 0x7FFFFFFB;
105 EXPECT_EQ(saturated::Add(a, b), int32_t(0x7FFFFFFF));
106 }
107 {
108 int32_t a = 0x80000006;
109 int32_t b = -5;
110 EXPECT_EQ(saturated::Add(a, b), int32_t(0x80000001));
111 a = 0x80000005;
112 EXPECT_EQ(saturated::Add(a, b), int32_t(0x80000000));
113 a = 0x80000004;
114 EXPECT_EQ(saturated::Add(a, b), int32_t(0x80000000));
115 }
116 {
117 int64_t a = 0x7FFFFFFFFFFFFFF9;
118 int64_t b = 5;
119 EXPECT_EQ(saturated::Add(a, b), int64_t(0x7FFFFFFFFFFFFFFE));
120 a = 0x7FFFFFFFFFFFFFFA;
121 EXPECT_EQ(saturated::Add(a, b), int64_t(0x7FFFFFFFFFFFFFFF));
122 a = 0x7FFFFFFFFFFFFFFB;
123 EXPECT_EQ(saturated::Add(a, b), int64_t(0x7FFFFFFFFFFFFFFF));
124 }
125 {
126 int64_t a = 0x8000000000000006;
127 int64_t b = -5;
128 EXPECT_EQ(saturated::Add(a, b), int64_t(0x8000000000000001));
129 a = 0x8000000000000005;
130 EXPECT_EQ(saturated::Add(a, b), int64_t(0x8000000000000000));
131 a = 0x8000000000000004;
132 EXPECT_EQ(saturated::Add(a, b), int64_t(0x8000000000000000));
133 }
134 }

References impeller::saturated::b.

## ◆ TEST() [322/360]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ImplicitAverageScalarOfFloatingPoint |
| ) |  |

Definition at line 903 of file saturated_math_unittests.cc.

903 {
904 // All return values are Scalar regardless of the operand types
905 // so these constants are used as the expected answers.
906 const Scalar s_inf = std::numeric_limits<Scalar>::infinity();
907 const Scalar s_max = std::numeric_limits<Scalar>::max();
908 const Scalar s_big = s_max * 0.5f;
909
910 {
911 const float inf = std::numeric_limits<float>::infinity();
912 const float max = std::numeric_limits<float>::max();
913 const float big = max * 0.5f;
914
915 EXPECT_EQ(saturated::AverageScalar(big, big), s_big);
916 EXPECT_EQ(saturated::AverageScalar(max, max), s_max);
917 EXPECT_EQ(saturated::AverageScalar(big, -big), 0.0f);
918 EXPECT_EQ(saturated::AverageScalar(max, -max), 0.0f);
919 EXPECT_EQ(saturated::AverageScalar(-big, big), 0.0f);
920 EXPECT_EQ(saturated::AverageScalar(-max, max), 0.0f);
921 EXPECT_EQ(saturated::AverageScalar(-big, -big), -s_big);
922 EXPECT_EQ(saturated::AverageScalar(-max, -max), -s_max);
923
924 EXPECT_EQ(saturated::AverageScalar(inf, inf), s_inf);
925 EXPECT_EQ(saturated::AverageScalar(-inf, -inf), -s_inf);
926 EXPECT_TRUE(std::isnan(saturated::AverageScalar(-inf, inf)));
927 EXPECT_TRUE(std::isnan(saturated::AverageScalar(inf, -inf)));
928 }
929 {
930 const double inf = std::numeric_limits<double>::infinity();
931 const double max = std::numeric_limits<double>::max();
932 const double big = max * 0.5;
933
934 // The s_constants converted to double. We should get finite results
935 // from finding the averages of these values, but we'll get a lot of
936 // overflow to infinity when testing the large double constants.
937 const double d_s_max = s_max;
938 const double d_s_big = s_big;
939 EXPECT_EQ(saturated::AverageScalar(d_s_big, d_s_big), s_big);
940 EXPECT_EQ(saturated::AverageScalar(d_s_max, d_s_max), s_max);
941 EXPECT_EQ(saturated::AverageScalar(-d_s_big, -d_s_big), -s_big);
942 EXPECT_EQ(saturated::AverageScalar(-d_s_max, -d_s_max), -s_max);
943
944 // And now testing continues with the double constants which
945 // mostly overflow
946 EXPECT_EQ(saturated::AverageScalar(big, big), s_inf);
947 EXPECT_EQ(saturated::AverageScalar(max, max), s_inf);
948 EXPECT_EQ(saturated::AverageScalar(big, -big), 0.0f);
949 EXPECT_EQ(saturated::AverageScalar(max, -max), 0.0f);
950 EXPECT_EQ(saturated::AverageScalar(-big, big), 0.0f);
951 EXPECT_EQ(saturated::AverageScalar(-max, max), 0.0f);
952 EXPECT_EQ(saturated::AverageScalar(-big, -big), -s_inf);
953 EXPECT_EQ(saturated::AverageScalar(-max, -max), -s_inf);
954
955 EXPECT_EQ(saturated::AverageScalar(inf, inf), s_inf);
956 EXPECT_EQ(saturated::AverageScalar(-inf, -inf), -s_inf);
957 EXPECT_TRUE(std::isnan(saturated::AverageScalar(-inf, inf)));
958 EXPECT_TRUE(std::isnan(saturated::AverageScalar(inf, -inf)));
959 }
960 {
961 const Scalar inf = std::numeric_limits<Scalar>::infinity();
962 const Scalar max = std::numeric_limits<Scalar>::max();
963 const Scalar big = max * 0.5f;
964
965 EXPECT_EQ(saturated::AverageScalar(big, big), s_big);
966 EXPECT_EQ(saturated::AverageScalar(max, max), s_max);
967 EXPECT_EQ(saturated::AverageScalar(big, -big), 0.0f);
968 EXPECT_EQ(saturated::AverageScalar(max, -max), 0.0f);
969 EXPECT_EQ(saturated::AverageScalar(-big, big), 0.0f);
970 EXPECT_EQ(saturated::AverageScalar(-max, max), 0.0f);
971 EXPECT_EQ(saturated::AverageScalar(-big, -big), -s_big);
972 EXPECT_EQ(saturated::AverageScalar(-max, -max), -s_max);
973
974 EXPECT_EQ(saturated::AverageScalar(inf, inf), s_inf);
975 EXPECT_EQ(saturated::AverageScalar(-inf, -inf), -s_inf);
976 EXPECT_TRUE(std::isnan(saturated::AverageScalar(-inf, s_inf)));
977 EXPECT_TRUE(std::isnan(saturated::AverageScalar(inf, -s_inf)));
978 }
979 }

## ◆ TEST() [323/360]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ImplicitAverageScalarOfSignedInts |
| ) |  |

Definition at line 763 of file saturated_math_unittests.cc.

763 {
764 // For each type try:
765 //
766 // - near the limits, averaging to 0
767 // - at the limits, averaging to 0 or 0.5 depending on precision
768 // - both large enough for the sum to overflow
769 // - both negative enough for the sum to underflow
770 {
771 int8_t a = 0x81;
772 int8_t b = 0x7f;
773 EXPECT_EQ(saturated::AverageScalar(a, b), -0.0f);
774 a = 0x80;
775 EXPECT_EQ(saturated::AverageScalar(a, b), -0.5f);
776 a = 0x70;
777 b = 0x75;
778 EXPECT_EQ(saturated::AverageScalar(a, b), 114.5f);
779 a = 0x85;
780 b = 0x8A;
781 EXPECT_EQ(saturated::AverageScalar(a, b), -120.5f);
782 }
783 {
784 int16_t a = 0x8001;
785 int16_t b = 0x7FFF;
786 EXPECT_EQ(saturated::AverageScalar(a, b), -0.0f);
787 a = 0x8000;
788 EXPECT_EQ(saturated::AverageScalar(a, b), -0.5f);
789 a = 0x7000;
790 b = 0x7005;
791 EXPECT_EQ(saturated::AverageScalar(a, b), 28674.5f);
792 a = 0x8005;
793 b = 0x800A;
794 EXPECT_EQ(saturated::AverageScalar(a, b), -32760.5f);
795 }
796 {
797 int32_t a = 0x80000001;
798 int32_t b = 0x7FFFFFFF;
799 EXPECT_EQ(saturated::AverageScalar(a, b), -0.0f);
800 a = 0x80000000;
801 EXPECT_EQ(saturated::AverageScalar(a, b), -0.5f);
802 a = 0x70000000;
803 b = 0x70000005;
804 EXPECT_EQ(saturated::AverageScalar(a, b), 1879048195.5f);
805 a = 0x80000005;
806 b = 0x8000000A;
807 EXPECT_EQ(saturated::AverageScalar(a, b), -2147483655.5f);
808 }
809 {
810 int64_t a = 0x8000000000000001;
811 int64_t b = 0x7FFFFFFFFFFFFFFF;
812 EXPECT_EQ(saturated::AverageScalar(a, b), 0.0f);
813 // 64-bit integers overflow the ability of a Scalar (float) to
814 // represent discrete integers and so the two numbers we are
815 // averaging here will look like the same number with different
816 // signs and the answer will be "0"
817 a = 0x8000000000000000;
818 EXPECT_EQ(saturated::AverageScalar<int64_t>(a, b), 0.0f);
819 a = 0x7000000000000000;
820 b = 0x7000000000000005;
821 EXPECT_NEAR(saturated::AverageScalar<int64_t>(a, b), 8.0704505e+18, 1e18);
822 a = 0x8000000000000005;
823 b = 0x800000000000000A;
824 EXPECT_NEAR(saturated::AverageScalar<int64_t>(a, b), -9.223372e+18, 1e18);
825 }
826 }

References impeller::saturated::b.

## ◆ TEST() [324/360]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ImplicitSubOfFloatingPoint |
| ) |  |

Definition at line 602 of file saturated_math_unittests.cc.

602 {
603 {
604 const float inf = std::numeric_limits<float>::infinity();
605 const float max = std::numeric_limits<float>::max();
606 const float big = max * 0.5f;
607
608 EXPECT_EQ(saturated::Sub(big, big), 0.0f);
609 EXPECT_EQ(saturated::Sub(max, big), big);
610 EXPECT_EQ(saturated::Sub(big, max), -big);
611 EXPECT_EQ(saturated::Sub(max, max), 0.0f);
612 EXPECT_EQ(saturated::Sub(max, inf), -inf);
613 EXPECT_EQ(saturated::Sub(inf, max), inf);
614 EXPECT_TRUE(std::isnan(saturated::Sub(inf, inf)));
615
616 EXPECT_EQ(saturated::Sub(-big, -big), 0.0f);
617 EXPECT_EQ(saturated::Sub(-max, -big), -big);
618 EXPECT_EQ(saturated::Sub(-big, -max), big);
619 EXPECT_EQ(saturated::Sub(-max, -max), 0.0f);
620 EXPECT_EQ(saturated::Sub(-max, -inf), inf);
621 EXPECT_EQ(saturated::Sub(-inf, -max), -inf);
622 EXPECT_TRUE(std::isnan(saturated::Sub(-inf, -inf)));
623
624 EXPECT_EQ(saturated::Sub(big, -big), max);
625 EXPECT_EQ(saturated::Sub(max, -big), inf);
626 EXPECT_EQ(saturated::Sub(big, -max), inf);
627 EXPECT_EQ(saturated::Sub(max, -max), inf);
628 EXPECT_EQ(saturated::Sub(max, -inf), inf);
629 EXPECT_EQ(saturated::Sub(inf, -max), inf);
630 EXPECT_EQ(saturated::Sub(inf, -inf), inf);
631
632 EXPECT_EQ(saturated::Sub(-big, big), -max);
633 EXPECT_EQ(saturated::Sub(-max, big), -inf);
634 EXPECT_EQ(saturated::Sub(-big, max), -inf);
635 EXPECT_EQ(saturated::Sub(-max, max), -inf);
636 EXPECT_EQ(saturated::Sub(-max, inf), -inf);
637 EXPECT_EQ(saturated::Sub(-inf, max), -inf);
638 EXPECT_EQ(saturated::Sub(-inf, inf), -inf);
639 }
640 {
641 const double inf = std::numeric_limits<double>::infinity();
642 const double max = std::numeric_limits<double>::max();
643 const double big = max * 0.5f;
644
645 EXPECT_EQ(saturated::Sub(big, big), 0.0f);
646 EXPECT_EQ(saturated::Sub(max, big), big);
647 EXPECT_EQ(saturated::Sub(big, max), -big);
648 EXPECT_EQ(saturated::Sub(max, max), 0.0f);
649 EXPECT_EQ(saturated::Sub(max, inf), -inf);
650 EXPECT_EQ(saturated::Sub(inf, max), inf);
651 EXPECT_TRUE(std::isnan(saturated::Sub(inf, inf)));
652
653 EXPECT_EQ(saturated::Sub(-big, -big), 0.0f);
654 EXPECT_EQ(saturated::Sub(-max, -big), -big);
655 EXPECT_EQ(saturated::Sub(-big, -max), big);
656 EXPECT_EQ(saturated::Sub(-max, -max), 0.0f);
657 EXPECT_EQ(saturated::Sub(-max, -inf), inf);
658 EXPECT_EQ(saturated::Sub(-inf, -max), -inf);
659 EXPECT_TRUE(std::isnan(saturated::Sub(-inf, -inf)));
660
661 EXPECT_EQ(saturated::Sub(big, -big), max);
662 EXPECT_EQ(saturated::Sub(max, -big), inf);
663 EXPECT_EQ(saturated::Sub(big, -max), inf);
664 EXPECT_EQ(saturated::Sub(max, -max), inf);
665 EXPECT_EQ(saturated::Sub(max, -inf), inf);
666 EXPECT_EQ(saturated::Sub(inf, -max), inf);
667 EXPECT_EQ(saturated::Sub(inf, -inf), inf);
668
669 EXPECT_EQ(saturated::Sub(-big, big), -max);
670 EXPECT_EQ(saturated::Sub(-max, big), -inf);
671 EXPECT_EQ(saturated::Sub(-big, max), -inf);
672 EXPECT_EQ(saturated::Sub(-max, max), -inf);
673 EXPECT_EQ(saturated::Sub(-max, inf), -inf);
674 EXPECT_EQ(saturated::Sub(-inf, max), -inf);
675 EXPECT_EQ(saturated::Sub(-inf, inf), -inf);
676 }
677 {
678 const Scalar inf = std::numeric_limits<Scalar>::infinity();
679 const Scalar max = std::numeric_limits<Scalar>::max();
680 const Scalar big = max * 0.5f;
681
682 EXPECT_EQ(saturated::Sub(big, big), 0.0f);
683 EXPECT_EQ(saturated::Sub(max, big), big);
684 EXPECT_EQ(saturated::Sub(big, max), -big);
685 EXPECT_EQ(saturated::Sub(max, max), 0.0f);
686 EXPECT_EQ(saturated::Sub(max, inf), -inf);
687 EXPECT_EQ(saturated::Sub(inf, max), inf);
688 EXPECT_TRUE(std::isnan(saturated::Sub(inf, inf)));
689
690 EXPECT_EQ(saturated::Sub(-big, -big), 0.0f);
691 EXPECT_EQ(saturated::Sub(-max, -big), -big);
692 EXPECT_EQ(saturated::Sub(-big, -max), big);
693 EXPECT_EQ(saturated::Sub(-max, -max), 0.0f);
694 EXPECT_EQ(saturated::Sub(-max, -inf), inf);
695 EXPECT_EQ(saturated::Sub(-inf, -max), -inf);
696 EXPECT_TRUE(std::isnan(saturated::Sub(-inf, -inf)));
697
698 EXPECT_EQ(saturated::Sub(big, -big), max);
699 EXPECT_EQ(saturated::Sub(max, -big), inf);
700 EXPECT_EQ(saturated::Sub(big, -max), inf);
701 EXPECT_EQ(saturated::Sub(max, -max), inf);
702 EXPECT_EQ(saturated::Sub(max, -inf), inf);
703 EXPECT_EQ(saturated::Sub(inf, -max), inf);
704 EXPECT_EQ(saturated::Sub(inf, -inf), inf);
705
706 EXPECT_EQ(saturated::Sub(-big, big), -max);
707 EXPECT_EQ(saturated::Sub(-max, big), -inf);
708 EXPECT_EQ(saturated::Sub(-big, max), -inf);
709 EXPECT_EQ(saturated::Sub(-max, max), -inf);
710 EXPECT_EQ(saturated::Sub(-max, inf), -inf);
711 EXPECT_EQ(saturated::Sub(-inf, max), -inf);
712 EXPECT_EQ(saturated::Sub(-inf, inf), -inf);
713 }
714 }

## ◆ TEST() [325/360]

impeller::testing::TEST | ( | SaturatedMath | ,
|  | ImplicitSubOfSignedInts |
| ) |  |

Definition at line 413 of file saturated_math_unittests.cc.

413 {
414 {
415 int8_t a = 0x79;
416 int8_t b = -5;
417 EXPECT_EQ(saturated::Sub(a, b), int8_t(0x7E));
418 a = 0x7A;
419 EXPECT_EQ(saturated::Sub(a, b), int8_t(0x7F));
420 a = 0x7B;
421 EXPECT_EQ(saturated::Sub(a, b), int8_t(0x7F));
422 }
423 {
424 int8_t a = 0x86;
425 int8_t b = 5;
426 EXPECT_EQ(saturated::Sub(a, b), int8_t(0x81));
427 a = 0x85;
428 EXPECT_EQ(saturated::Sub(a, b), int8_t(0x80));
429 a = 0x84;
430 EXPECT_EQ(saturated::Sub(a, b), int8_t(0x80));
431 }
432 {
433 int16_t a = 0x7FF9;
434 int16_t b = -5;
435 EXPECT_EQ(saturated::Sub(a, b), int16_t(0x7FFE));
436 a = 0x7FFA;
437 EXPECT_EQ(saturated::Sub(a, b), int16_t(0x7FFF));
438 a = 0x7FFB;
439 EXPECT_EQ(saturated::Sub(a, b), int16_t(0x7FFF));
440 }
441 {
442 int16_t a = 0x8006;
443 int16_t b = 5;
444 EXPECT_EQ(saturated::Sub(a, b), int16_t(0x8001));
445 a = 0x8005;
446 EXPECT_EQ(saturated::Sub(a, b), int16_t(0x8000));
447 a = 0x8004;
448 EXPECT_EQ(saturated::Sub(a, b), int16_t(0x8000));
449 }
450 {
451 int32_t a = 0x7FFFFFF9;
452 int32_t b = -5;
453 EXPECT_EQ(saturated::Sub(a, b), int32_t(0x7FFFFFFE));
454 a = 0x7FFFFFFA;
455 EXPECT_EQ(saturated::Sub(a, b), int32_t(0x7FFFFFFF));
456 a = 0x7FFFFFFB;
457 EXPECT_EQ(saturated::Sub(a, b), int32_t(0x7FFFFFFF));
458 }
459 {
460 int32_t a = 0x80000006;
461 int32_t b = 5;
462 EXPECT_EQ(saturated::Sub(a, b), int32_t(0x80000001));
463 a = 0x80000005;
464 EXPECT_EQ(saturated::Sub(a, b), int32_t(0x80000000));
465 a = 0x80000004;
466 EXPECT_EQ(saturated::Sub(a, b), int32_t(0x80000000));
467 }
468 {
469 int64_t a = 0x7FFFFFFFFFFFFFF9;
470 int64_t b = -5;
471 EXPECT_EQ(saturated::Sub(a, b), int64_t(0x7FFFFFFFFFFFFFFE));
472 a = 0x7FFFFFFFFFFFFFFA;
473 EXPECT_EQ(saturated::Sub(a, b), int64_t(0x7FFFFFFFFFFFFFFF));
474 a = 0x7FFFFFFFFFFFFFFB;
475 EXPECT_EQ(saturated::Sub(a, b), int64_t(0x7FFFFFFFFFFFFFFF));
476 }
477 {
478 int64_t a = 0x8000000000000006;
479 int64_t b = 5;
480 EXPECT_EQ(saturated::Sub(a, b), int64_t(0x8000000000000001));
481 a = 0x8000000000000005;
482 EXPECT_EQ(saturated::Sub(a, b), int64_t(0x8000000000000000));
483 a = 0x8000000000000004;
484 EXPECT_EQ(saturated::Sub(a, b), int64_t(0x8000000000000000));
485 }
486 }

References impeller::saturated::b.

## ◆ TEST() [326/360]

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

Definition at line 28 of file shader_archive_unittests.cc.

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

References impeller::ShaderArchiveWriter::AddShader(), impeller::ShaderArchiveWriter::CreateMapping(), CreateMappingFromString(), CreateStringFromMapping(), impeller::ShaderArchive::GetMapping(), impeller::ShaderArchive::GetShaderCount(), impeller::ShaderArchive::IsValid(), impeller::kFragment, and impeller::kVertex.

## ◆ TEST() [327/360]

impeller::testing::TEST | ( | SizeTest | ,
|  | ISizeIsEmpty |
| ) |  |

Definition at line 36 of file size_unittests.cc.

36 {
37 // Non-empty
38 EXPECT_FALSE(ISize(10, 7).IsEmpty());
39
40 // Empty both width and height both 0 or negative, in all combinations
41 EXPECT_TRUE(ISize(0, 0).IsEmpty());
42 EXPECT_TRUE(ISize(-1, -1).IsEmpty());
43 EXPECT_TRUE(ISize(-1, 0).IsEmpty());
44 EXPECT_TRUE(ISize(0, -1).IsEmpty());
45
46 // Empty for 0 or negative width or height (but not both at the same time)
47 EXPECT_TRUE(ISize(10, 0).IsEmpty());
48 EXPECT_TRUE(ISize(10, -1).IsEmpty());
49 EXPECT_TRUE(ISize(0, 7).IsEmpty());
50 EXPECT_TRUE(ISize(-1, 7).IsEmpty());
51 }

## ◆ TEST() [328/360]

impeller::testing::TEST | ( | SizeTest | ,
|  | IsSquare |
| ) |  |

Definition at line 53 of file size_unittests.cc.

53 {
54 EXPECT_TRUE(Size(20, 20).IsSquare());
55 EXPECT_FALSE(Size(20, 19).IsSquare());
56 EXPECT_FALSE(Size(19, 20).IsSquare());
57
58 EXPECT_TRUE(ISize(20, 20).IsSquare());
59 EXPECT_FALSE(ISize(20, 19).IsSquare());
60 EXPECT_FALSE(ISize(19, 20).IsSquare());
61 }

## ◆ TEST() [329/360]

impeller::testing::TEST | ( | SizeTest | ,
|  | MaxDimension |
| ) |  |

Definition at line 63 of file size_unittests.cc.

63 {
64 EXPECT_EQ(Size(20, 20).MaxDimension(), 20);
65 EXPECT_EQ(Size(20, 19).MaxDimension(), 20);
66 EXPECT_EQ(Size(19, 20).MaxDimension(), 20);
67 EXPECT_EQ(Size(20, 21).MaxDimension(), 21);
68 EXPECT_EQ(Size(21, 20).MaxDimension(), 21);
69
70 EXPECT_EQ(ISize(20, 20).MaxDimension(), 20);
71 EXPECT_EQ(ISize(20, 19).MaxDimension(), 20);
72 EXPECT_EQ(ISize(19, 20).MaxDimension(), 20);
73 EXPECT_EQ(ISize(20, 21).MaxDimension(), 21);
74 EXPECT_EQ(ISize(21, 20).MaxDimension(), 21);
75 }

## ◆ TEST() [330/360]

impeller::testing::TEST | ( | SizeTest | ,
|  | NegationOperator |
| ) |  |

Definition at line 77 of file size_unittests.cc.

77 {
78 EXPECT_EQ(-Size(10, 20), Size(-10, -20));
79 EXPECT_EQ(-Size(-10, 20), Size(10, -20));
80 EXPECT_EQ(-Size(10, -20), Size(-10, 20));
81 EXPECT_EQ(-Size(-10, -20), Size(10, 20));
82 }

## ◆ TEST() [331/360]

impeller::testing::TEST | ( | SizeTest | ,
|  | SizeIsEmpty |
| ) |  |

Definition at line 12 of file size_unittests.cc.

12 {
13 auto nan = std::numeric_limits<Scalar>::quiet_NaN();
14
15 // Non-empty
16 EXPECT_FALSE(Size(10.5, 7.2).IsEmpty());
17
18 // Empty both width and height both 0 or negative, in all combinations
19 EXPECT_TRUE(Size(0.0, 0.0).IsEmpty());
20 EXPECT_TRUE(Size(-1.0, -1.0).IsEmpty());
21 EXPECT_TRUE(Size(-1.0, 0.0).IsEmpty());
22 EXPECT_TRUE(Size(0.0, -1.0).IsEmpty());
23
24 // Empty for 0 or negative width or height (but not both at the same time)
25 EXPECT_TRUE(Size(10.5, 0.0).IsEmpty());
26 EXPECT_TRUE(Size(10.5, -1.0).IsEmpty());
27 EXPECT_TRUE(Size(0.0, 7.2).IsEmpty());
28 EXPECT_TRUE(Size(-1.0, 7.2).IsEmpty());
29
30 // Empty for NaN in width or height or both
31 EXPECT_TRUE(Size(10.5, nan).IsEmpty());
32 EXPECT_TRUE(Size(nan, 7.2).IsEmpty());
33 EXPECT_TRUE(Size(nan, nan).IsEmpty());
34 }

## ◆ TEST() [332/360]

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

Definition at line 151 of file skia_conversions_unittests.cc.

151 {
152 std::vector<flutter::DlColor> colors = {
153 flutter::DlColor::kBlue(), flutter::DlColor::kGreen(),
154 flutter::DlColor::kGreen(), flutter::DlColor::kRed()};
155 std::vector<float> stops = {0.0, 0.5, 0.4, 1.0};
156 const auto gradient =
157 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
158 SkPoint::Make(1.0, 1.0), //
159 4, //
160 colors.data(), //
161 stops.data(), //
162 flutter::DlTileMode::kClamp, //
163 nullptr //
164 );
165
166 std::vector<Color> converted_colors;
167 std::vector<Scalar> converted_stops;
168 skia_conversions::ConvertStops(gradient.get(), converted_colors,
169 converted_stops);
170
171 // Value is clamped to 0.5
172 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
173 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
174 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 0.5f));
175 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[3], 1.0f));
176 }

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

## ◆ TEST() [333/360]

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

Definition at line 73 of file skia_conversions_unittests.cc.

73 {
74 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
75 flutter::DlColor::kRed()};
76 std::vector<float> stops = {0.5, 1.0};
77 const auto gradient =
78 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
79 SkPoint::Make(1.0, 1.0), //
80 2, //
81 colors.data(), //
82 stops.data(), //
83 flutter::DlTileMode::kClamp, //
84 nullptr //
85 );
86
87 std::vector<Color> converted_colors;
88 std::vector<Scalar> converted_stops;
89 skia_conversions::ConvertStops(gradient.get(), converted_colors,
90 converted_stops);
91
92 // First color is inserted as blue.
93 ASSERT_TRUE(ScalarNearlyEqual(converted_colors[0].blue, 1.0f));
94 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
95 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
96 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
97 }

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

## ◆ TEST() [334/360]

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

Definition at line 99 of file skia_conversions_unittests.cc.

99 {
100 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
101 flutter::DlColor::kRed()};
102 std::vector<float> stops = {0.0, .5};
103 const auto gradient =
104 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
105 SkPoint::Make(1.0, 1.0), //
106 2, //
107 colors.data(), //
108 stops.data(), //
109 flutter::DlTileMode::kClamp, //
110 nullptr //
111 );
112
113 std::vector<Color> converted_colors;
114 std::vector<Scalar> converted_stops;
115 skia_conversions::ConvertStops(gradient.get(), converted_colors,
116 converted_stops);
117
118 // Last color is inserted as red.
119 ASSERT_TRUE(ScalarNearlyEqual(converted_colors[2].red, 1.0f));
120 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
121 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
122 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
123 }

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

## ◆ TEST() [335/360]

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

Definition at line 47 of file skia_conversions_unittests.cc.

47 {
48 // Typical gradient.
49 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
50 flutter::DlColor::kRed(),
51 flutter::DlColor::kGreen()};
52 std::vector<float> stops = {0.0, 0.5, 1.0};
53 const auto gradient =
54 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
55 SkPoint::Make(1.0, 1.0), //
56 3, //
57 colors.data(), //
58 stops.data(), //
59 flutter::DlTileMode::kClamp, //
60 nullptr //
61 );
62
63 std::vector<Color> converted_colors;
64 std::vector<Scalar> converted_stops;
65 skia_conversions::ConvertStops(gradient.get(), converted_colors,
66 converted_stops);
67
68 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
69 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
70 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
71 }

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

## ◆ TEST() [336/360]

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

Definition at line 125 of file skia_conversions_unittests.cc.

125 {
126 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
127 flutter::DlColor::kGreen(),
128 flutter::DlColor::kRed()};
129 std::vector<float> stops = {0.0, 100, 1.0};
130 const auto gradient =
131 flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
132 SkPoint::Make(1.0, 1.0), //
133 3, //
134 colors.data(), //
135 stops.data(), //
136 flutter::DlTileMode::kClamp, //
137 nullptr //
138 );
139
140 std::vector<Color> converted_colors;
141 std::vector<Scalar> converted_stops;
142 skia_conversions::ConvertStops(gradient.get(), converted_colors,
143 converted_stops);
144
145 // Value is clamped to 1.0
146 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
147 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 1.0f));
148 ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
149 }

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

## ◆ TEST() [337/360]

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

Definition at line 178 of file skia_conversions_unittests.cc.

178 {
179 EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(
180 SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 10)));
181 EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(
182 SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 9.999)));
183 EXPECT_FALSE(skia_conversions::IsNearlySimpleRRect(
184 SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 9)));
185 }

References impeller::skia_conversions::IsNearlySimpleRRect().

## ◆ TEST() [338/360]

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

Definition at line 15 of file skia_conversions_unittests.cc.

15 {
16 for (int x = -100; x < 100; x += 4) {
17 for (int y = -100; y < 100; y += 4) {
18 EXPECT_EQ(skia_conversions::ToPoint(SkPoint::Make(x * 0.25f, y * 0.25f)),
19 Point(x * 0.25f, y * 0.25f));
20 }
21 }
22 }

References impeller::skia_conversions::ToPoint().

## ◆ TEST() [339/360]

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

Definition at line 24 of file skia_conversions_unittests.cc.

24 {
25 for (int x = -100; x < 100; x += 4) {
26 for (int y = -100; y < 100; y += 4) {
27 EXPECT_EQ(skia_conversions::ToSize(SkPoint::Make(x * 0.25f, y * 0.25f)),
28 Size(x * 0.25f, y * 0.25f));
29 }
30 }
31 }

References impeller::skia_conversions::ToSize().

## ◆ TEST() [340/360]

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

Definition at line 33 of file skia_conversions_unittests.cc.

33 {
34 // Create a color with alpha, red, green, and blue values that are all
35 // trivially divisible by 255 so that we can test the conversion results in
36 // correct scalar values.
37 // AARRGGBB
38 const flutter::DlColor color = flutter::DlColor(0x8040C020);
39 auto converted_color = skia_conversions::ToColor(color);
40
41 ASSERT_TRUE(ScalarNearlyEqual(converted_color.alpha, 0x80 * (1.0f / 255)));
42 ASSERT_TRUE(ScalarNearlyEqual(converted_color.red, 0x40 * (1.0f / 255)));
43 ASSERT_TRUE(ScalarNearlyEqual(converted_color.green, 0xC0 * (1.0f / 255)));
44 ASSERT_TRUE(ScalarNearlyEqual(converted_color.blue, 0x20 * (1.0f / 255)));
45 }

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

## ◆ TEST() [341/360]

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

Definition at line 86 of file base_unittests.cc.

86 {
87 ASSERT_EQ(SPrintF("%sx%d", "Hello", 12), "Hellox12");
88 ASSERT_EQ(SPrintF(""), "");
89 ASSERT_EQ(SPrintF("Hello"), "Hello");
90 ASSERT_EQ(SPrintF("%sx%.2f", "Hello", 12.122222), "Hellox12.12");
91 }

References impeller::SPrintF().

## ◆ TEST() [342/360]

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

Definition at line 515 of file tessellator_unittests.cc.

515 {
516 auto tessellator = std::make_shared<Tessellator>();
517 PathBuilder builder;
518 builder.AddLine({0, 0}, {100, 100});
519 auto path = builder.TakePath();
520
521 auto polyline = tessellator->CreateTempPolyline(path, 0.1);
522 EXPECT_DEBUG_DEATH(tessellator->CreateTempPolyline(path, 0.1),
523 "point_buffer_");
524 }

References impeller::PathBuilder::AddLine(), polyline, and impeller::PathBuilder::TakePath().

## ◆ TEST() [343/360]

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

Definition at line 139 of file tessellator_unittests.cc.

139 {
140 auto tessellator = std::make_shared<Tessellator>();
141
142 auto test = [&tessellator](const Matrix& transform, Scalar radius) {
143 auto generator = tessellator->FilledCircle(transform, {}, radius);
144 size_t quadrant_divisions = generator.GetVertexCount() / 4;
145
146 // Confirm the approximation error is within the currently accepted
147 // |kCircleTolerance| value advertised by |CircleTessellator|.
148 // (With an additional 1% tolerance for floating point rounding.)
149 double angle = kPiOver2 / quadrant_divisions;
150 Point first = {radius, 0};
151 Point next = {static_cast<Scalar>(cos(angle) * radius),
152 static_cast<Scalar>(sin(angle) * radius)};
153 Point midpoint = (first + next) * 0.5;
154 EXPECT_GE(midpoint.GetLength(),
155 radius - Tessellator::kCircleTolerance * 1.01)
156 << ", transform = " << transform << ", radius = " << radius
157 << ", divisions = " << quadrant_divisions;
158 };
159
160 test({}, 0.0);
161 test({}, 0.9);
162 test({}, 1.0);
163 test({}, 1.9);
164 test(Matrix::MakeScale(Vector2(2.0, 2.0)), 0.95);
165 test({}, 2.0);
166 test(Matrix::MakeScale(Vector2(2.0, 2.0)), 1.0);
167 test({}, 11.9);
168 test({}, 12.0);
169 test({}, 35.9);
170 for (int i = 36; i < 10000; i += 4) {
171 test({}, i);
172 }
173 }

References impeller::TPoint< T >::GetLength(), impeller::Tessellator::kCircleTolerance, impeller::kPiOver2, impeller::Matrix::MakeScale(), and transform.

## ◆ TEST() [344/360]

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

Definition at line 499 of file tessellator_unittests.cc.

499 {
500 // This path is not technically empty (it has a size in one dimension),
501 // but is otherwise completely flat.
502 PathBuilder builder;
503 builder.MoveTo({0, 0});
504 builder.MoveTo({10, 10}, /*relative=*/true);
505
506 std::vector<Point> points;
507 std::vector<uint16_t> indices;
508 Tessellator::TessellateConvexInternal(builder.TakePath(), points, indices,
509 3.0);
510
511 EXPECT_TRUE(points.empty());
512 }

References impeller::PathBuilder::MoveTo(), impeller::PathBuilder::TakePath(), and impeller::Tessellator::TessellateConvexInternal().

## ◆ TEST() [345/360]

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

Definition at line 175 of file tessellator_unittests.cc.

175 {
176 auto tessellator = std::make_shared<Tessellator>();
177
178 auto test = [&tessellator](const Matrix& transform, const Point& center,
179 Scalar radius) {
180 auto generator = tessellator->FilledCircle(transform, center, radius);
181 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
182
183 auto vertex_count = generator.GetVertexCount();
184 auto vertices = std::vector<Point>();
185 generator.GenerateVertices([&vertices](const Point& p) { //
186 vertices.push_back(p);
187 });
188 EXPECT_EQ(vertices.size(), vertex_count);
189 ASSERT_EQ(vertex_count % 4, 0u);
190
191 auto quadrant_count = vertex_count / 4;
192 for (size_t i = 0; i < quadrant_count; i++) {
193 double angle = kPiOver2 * i / (quadrant_count - 1);
194 double degrees = angle * 180.0 / kPi;
195 double rsin = sin(angle) * radius;
196 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
197 double rcos = (i == quadrant_count - 1) ? 0.0f : cos(angle) * radius;
198 EXPECT_POINT_NEAR(vertices[i * 2],
199 Point(center.x - rcos, center.y + rsin))
200 << "vertex " << i << ", angle = " << degrees << std::endl;
201 EXPECT_POINT_NEAR(vertices[i * 2 + 1],
202 Point(center.x - rcos, center.y - rsin))
203 << "vertex " << i << ", angle = " << degrees << std::endl;
204 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1],
205 Point(center.x + rcos, center.y - rsin))
206 << "vertex " << i << ", angle = " << degrees << std::endl;
207 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2],
208 Point(center.x + rcos, center.y + rsin))
209 << "vertex " << i << ", angle = " << degrees << std::endl;
210 }
211 };
212
213 test({}, {}, 2.0);
214 test({}, {10, 10}, 2.0);
215 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {}, 2.0);
216 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {}, 1000.0);
217 }

References EXPECT_POINT_NEAR, impeller::kPi, impeller::kPiOver2, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), and transform.

## ◆ TEST() [346/360]

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

Definition at line 364 of file tessellator_unittests.cc.

364 {
365 auto tessellator = std::make_shared<Tessellator>();
366
367 auto test = [&tessellator](const Matrix& transform, const Rect& bounds) {
368 auto center = bounds.GetCenter();
369 auto half_size = bounds.GetSize() * 0.5f;
370
371 auto generator = tessellator->FilledEllipse(transform, bounds);
372 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
373
374 auto vertex_count = generator.GetVertexCount();
375 auto vertices = std::vector<Point>();
376 generator.GenerateVertices([&vertices](const Point& p) { //
377 vertices.push_back(p);
378 });
379 EXPECT_EQ(vertices.size(), vertex_count);
380 ASSERT_EQ(vertex_count % 4, 0u);
381
382 auto quadrant_count = vertex_count / 4;
383 for (size_t i = 0; i < quadrant_count; i++) {
384 double angle = kPiOver2 * i / (quadrant_count - 1);
385 double degrees = angle * 180.0 / kPi;
386 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
387 double rcos =
388 (i == quadrant_count - 1) ? 0.0f : cos(angle) * half_size.width;
389 double rsin = sin(angle) * half_size.height;
390 EXPECT_POINT_NEAR(vertices[i * 2],
391 Point(center.x - rcos, center.y + rsin))
392 << "vertex " << i << ", angle = " << degrees << ", " //
393 << "bounds = " << bounds << std::endl;
394 EXPECT_POINT_NEAR(vertices[i * 2 + 1],
395 Point(center.x - rcos, center.y - rsin))
396 << "vertex " << i << ", angle = " << degrees << ", " //
397 << "bounds = " << bounds << std::endl;
398 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1],
399 Point(center.x + rcos, center.y - rsin))
400 << "vertex " << i << ", angle = " << degrees << ", " //
401 << "bounds = " << bounds << std::endl;
402 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2],
403 Point(center.x + rcos, center.y + rsin))
404 << "vertex " << i << ", angle = " << degrees << ", " //
405 << "bounds = " << bounds << std::endl;
406 }
407 };
408
409 // Square bounds should actually use the circle generator, but its
410 // results should match the same math as the ellipse generator.
411 test({}, Rect::MakeXYWH(0, 0, 2, 2));
412
413 test({}, Rect::MakeXYWH(0, 0, 2, 3));
414 test({}, Rect::MakeXYWH(0, 0, 3, 2));
415 test({}, Rect::MakeXYWH(5, 10, 2, 3));
416 test({}, Rect::MakeXYWH(16, 7, 3, 2));
417 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 3, 2));
418 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 2, 3));
419 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
420 Rect::MakeXYWH(5000, 10000, 3000, 2000));
421 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
422 Rect::MakeXYWH(5000, 10000, 2000, 3000));
423 }

References EXPECT_POINT_NEAR, impeller::kPi, impeller::kPiOver2, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), and transform.

## ◆ TEST() [347/360]

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

Definition at line 425 of file tessellator_unittests.cc.

425 {
426 auto tessellator = std::make_shared<Tessellator>();
427
428 auto test = [&tessellator](const Matrix& transform, const Rect& bounds,
429 const Size& radii) {
430 FML_DCHECK(radii.width * 2 <= bounds.GetWidth()) << radii << bounds;
431 FML_DCHECK(radii.height * 2 <= bounds.GetHeight()) << radii << bounds;
432
433 Scalar middle_left = bounds.GetX() + radii.width;
434 Scalar middle_top = bounds.GetY() + radii.height;
435 Scalar middle_right = bounds.GetX() + bounds.GetWidth() - radii.width;
436 Scalar middle_bottom = bounds.GetY() + bounds.GetHeight() - radii.height;
437
438 auto generator = tessellator->FilledRoundRect(transform, bounds, radii);
439 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
440
441 auto vertex_count = generator.GetVertexCount();
442 auto vertices = std::vector<Point>();
443 generator.GenerateVertices([&vertices](const Point& p) { //
444 vertices.push_back(p);
445 });
446 EXPECT_EQ(vertices.size(), vertex_count);
447 ASSERT_EQ(vertex_count % 4, 0u);
448
449 auto quadrant_count = vertex_count / 4;
450 for (size_t i = 0; i < quadrant_count; i++) {
451 double angle = kPiOver2 * i / (quadrant_count - 1);
452 double degrees = angle * 180.0 / kPi;
453 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
454 double rcos = (i == quadrant_count - 1) ? 0.0f : cos(angle) * radii.width;
455 double rsin = sin(angle) * radii.height;
456 EXPECT_POINT_NEAR(vertices[i * 2],
457 Point(middle_left - rcos, middle_bottom + rsin))
458 << "vertex " << i << ", angle = " << degrees << ", " //
459 << "bounds = " << bounds << std::endl;
460 EXPECT_POINT_NEAR(vertices[i * 2 + 1],
461 Point(middle_left - rcos, middle_top - rsin))
462 << "vertex " << i << ", angle = " << degrees << ", " //
463 << "bounds = " << bounds << std::endl;
464 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1],
465 Point(middle_right + rcos, middle_top - rsin))
466 << "vertex " << i << ", angle = " << degrees << ", " //
467 << "bounds = " << bounds << std::endl;
468 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2],
469 Point(middle_right + rcos, middle_bottom + rsin))
470 << "vertex " << i << ", angle = " << degrees << ", " //
471 << "bounds = " << bounds << std::endl;
472 }
473 };
474
475 // Both radii spanning the bounds should actually use the circle/ellipse
476 // generator, but their results should match the same math as the round
477 // rect generator.
478 test({}, Rect::MakeXYWH(0, 0, 20, 20), {10, 10});
479
480 // One radius spanning the bounds, but not the other will not match the
481 // round rect math if the generator transfers to circle/ellipse
482 test({}, Rect::MakeXYWH(0, 0, 20, 20), {10, 5});
483 test({}, Rect::MakeXYWH(0, 0, 20, 20), {5, 10});
484
485 test({}, Rect::MakeXYWH(0, 0, 20, 30), {2, 2});
486 test({}, Rect::MakeXYWH(0, 0, 30, 20), {2, 2});
487 test({}, Rect::MakeXYWH(5, 10, 20, 30), {2, 3});
488 test({}, Rect::MakeXYWH(16, 7, 30, 20), {2, 3});
489 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 30, 20),
490 {2, 3});
491 test(Matrix::MakeScale({500.0, 500.0, 0.0}), Rect::MakeXYWH(5, 10, 20, 30),
492 {2, 3});
493 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
494 Rect::MakeXYWH(5000, 10000, 3000, 2000), {50, 70});
495 test(Matrix::MakeScale({0.002, 0.002, 0.0}),
496 Rect::MakeXYWH(5000, 10000, 2000, 3000), {50, 70});
497 }

References EXPECT_POINT_NEAR, impeller::kPi, impeller::kPiOver2, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), and transform.

## ◆ TEST() [348/360]

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

Definition at line 291 of file tessellator_unittests.cc.

291 {
292 auto tessellator = std::make_shared<Tessellator>();
293
294 auto test = [&tessellator](const Matrix& transform, const Point& p0,
295 const Point& p1, Scalar radius) {
296 auto generator = tessellator->RoundCapLine(transform, p0, p1, radius);
297 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
298
299 auto vertex_count = generator.GetVertexCount();
300 auto vertices = std::vector<Point>();
301 generator.GenerateVertices([&vertices](const Point& p) { //
302 vertices.push_back(p);
303 });
304 EXPECT_EQ(vertices.size(), vertex_count);
305 ASSERT_EQ(vertex_count % 4, 0u);
306
307 Point along = p1 - p0;
308 Scalar length = along.GetLength();
309 if (length > 0) {
310 along *= radius / length;
311 } else {
312 along = {radius, 0};
313 }
314 Point across = {-along.y, along.x};
315
316 auto quadrant_count = vertex_count / 4;
317 for (size_t i = 0; i < quadrant_count; i++) {
318 double angle = kPiOver2 * i / (quadrant_count - 1);
319 double degrees = angle * 180.0 / kPi;
320 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
321 Point relative_along =
322 along * ((i == quadrant_count - 1) ? 0.0f : cos(angle));
323 Point relative_across = across * sin(angle);
324 EXPECT_POINT_NEAR(vertices[i * 2], //
325 p0 - relative_along + relative_across)
326 << "vertex " << i << ", angle = " << degrees << ", " //
327 << "line = " << p0 << " => " << p1 << ", " //
328 << "radius = " << radius << std::endl;
329 EXPECT_POINT_NEAR(vertices[i * 2 + 1], //
330 p0 - relative_along - relative_across)
331 << "vertex " << i << ", angle = " << degrees << ", " //
332 << "line = " << p0 << " => " << p1 << ", " //
333 << "radius = " << radius << std::endl;
334 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1], //
335 p1 + relative_along - relative_across)
336 << "vertex " << i << ", angle = " << degrees << ", " //
337 << "line = " << p0 << " => " << p1 << ", " //
338 << "radius = " << radius << std::endl;
339 EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2], //
340 p1 + relative_along + relative_across)
341 << "vertex " << i << ", angle = " << degrees << ", " //
342 << "line = " << p0 << " => " << p1 << ", " //
343 << "radius = " << radius << std::endl;
344 }
345 };
346
347 // Empty line should actually use the circle generator, but its
348 // results should match the same math as the round cap generator.
349 test({}, {0, 0}, {0, 0}, 10);
350
351 test({}, {0, 0}, {10, 0}, 2);
352 test({}, {10, 0}, {0, 0}, 2);
353 test({}, {0, 0}, {10, 10}, 2);
354
355 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {0, 0}, {10, 0}, 2);
356 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {10, 0}, {0, 0}, 2);
357 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {0, 0}, {10, 10}, 2);
358
359 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {0, 0}, {10, 0}, 2);
360 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {10, 0}, {0, 0}, 2);
361 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {0, 0}, {10, 10}, 2);
362 }

References EXPECT_POINT_NEAR, impeller::TPoint< T >::GetLength(), impeller::kPi, impeller::kPiOver2, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), transform, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST() [349/360]

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

Definition at line 219 of file tessellator_unittests.cc.

219 {
220 auto tessellator = std::make_shared<Tessellator>();
221
222 auto test = [&tessellator](const Matrix& transform, const Point& center,
223 Scalar radius, Scalar half_width) {
224 ASSERT_GT(radius, half_width);
225 auto generator =
226 tessellator->StrokedCircle(transform, center, radius, half_width);
227 EXPECT_EQ(generator.GetTriangleType(), PrimitiveType::kTriangleStrip);
228
229 auto vertex_count = generator.GetVertexCount();
230 auto vertices = std::vector<Point>();
231 generator.GenerateVertices([&vertices](const Point& p) { //
232 vertices.push_back(p);
233 });
234 EXPECT_EQ(vertices.size(), vertex_count);
235 ASSERT_EQ(vertex_count % 4, 0u);
236
237 auto quadrant_count = vertex_count / 8;
238
239 // Test outer points first
240 for (size_t i = 0; i < quadrant_count; i++) {
241 double angle = kPiOver2 * i / (quadrant_count - 1);
242 double degrees = angle * 180.0 / kPi;
243 double rsin = sin(angle) * (radius + half_width);
244 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
245 double rcos =
246 (i == quadrant_count - 1) ? 0.0f : cos(angle) * (radius + half_width);
247 EXPECT_POINT_NEAR(vertices[i * 2],
248 Point(center.x - rcos, center.y - rsin))
249 << "vertex " << i << ", angle = " << degrees << std::endl;
250 EXPECT_POINT_NEAR(vertices[quadrant_count * 2 + i * 2],
251 Point(center.x + rsin, center.y - rcos))
252 << "vertex " << i << ", angle = " << degrees << std::endl;
253 EXPECT_POINT_NEAR(vertices[quadrant_count * 4 + i * 2],
254 Point(center.x + rcos, center.y + rsin))
255 << "vertex " << i << ", angle = " << degrees << std::endl;
256 EXPECT_POINT_NEAR(vertices[quadrant_count * 6 + i * 2],
257 Point(center.x - rsin, center.y + rcos))
258 << "vertex " << i << ", angle = " << degrees << std::endl;
259 }
260
261 // Then test innerer points
262 for (size_t i = 0; i < quadrant_count; i++) {
263 double angle = kPiOver2 * i / (quadrant_count - 1);
264 double degrees = angle * 180.0 / kPi;
265 double rsin = sin(angle) * (radius - half_width);
266 // Note that cos(radians(90 degrees)) isn't exactly 0.0 like it should be
267 double rcos =
268 (i == quadrant_count - 1) ? 0.0f : cos(angle) * (radius - half_width);
269 EXPECT_POINT_NEAR(vertices[i * 2 + 1],
270 Point(center.x - rcos, center.y - rsin))
271 << "vertex " << i << ", angle = " << degrees << std::endl;
272 EXPECT_POINT_NEAR(vertices[quadrant_count * 2 + i * 2 + 1],
273 Point(center.x + rsin, center.y - rcos))
274 << "vertex " << i << ", angle = " << degrees << std::endl;
275 EXPECT_POINT_NEAR(vertices[quadrant_count * 4 + i * 2 + 1],
276 Point(center.x + rcos, center.y + rsin))
277 << "vertex " << i << ", angle = " << degrees << std::endl;
278 EXPECT_POINT_NEAR(vertices[quadrant_count * 6 + i * 2 + 1],
279 Point(center.x - rsin, center.y + rcos))
280 << "vertex " << i << ", angle = " << degrees << std::endl;
281 }
282 };
283
284 test({}, {}, 2.0, 1.0);
285 test({}, {}, 2.0, 0.5);
286 test({}, {10, 10}, 2.0, 1.0);
287 test(Matrix::MakeScale({500.0, 500.0, 0.0}), {}, 2.0, 1.0);
288 test(Matrix::MakeScale({0.002, 0.002, 0.0}), {}, 1000.0, 10.0);
289 }

References EXPECT_POINT_NEAR, impeller::kPi, impeller::kPiOver2, impeller::kTriangleStrip, impeller::Matrix::MakeScale(), and transform.

## ◆ TEST() [350/360]

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

Definition at line 84 of file tessellator_unittests.cc.

84 {
85 {
86 std::vector<Point> points;
87 std::vector<uint16_t> indices;
88 // Sanity check simple rectangle.
89 Tessellator::TessellateConvexInternal(
90 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 10, 10)).TakePath(), points,
91 indices, 1.0);
92
93 // Note: the origin point is repeated but not referenced in the indices
94 // below
95 std::vector<Point> expected = {{0, 0}, {10, 0}, {10, 10}, {0, 10}, {0, 0}};
96 std::vector<uint16_t> expected_indices = {0, 1, 3, 2};
97 EXPECT_EQ(points, expected);
98 EXPECT_EQ(indices, expected_indices);
99 }
100
101 {
102 std::vector<Point> points;
103 std::vector<uint16_t> indices;
104 Tessellator::TessellateConvexInternal(
105 PathBuilder{}
106 .AddRect(Rect::MakeLTRB(0, 0, 10, 10))
107 .AddRect(Rect::MakeLTRB(20, 20, 30, 30))
108 .TakePath(),
109 points, indices, 1.0);
110
111 std::vector<Point> expected = {{0, 0}, {10, 0}, {10, 10}, {0, 10},
112 {0, 0}, {20, 20}, {30, 20}, {30, 30},
113 {20, 30}, {20, 20}};
114 std::vector<uint16_t> expected_indices = {0, 1, 3, 2, 2, 5, 5, 6, 8, 7};
115 EXPECT_EQ(points, expected);
116 EXPECT_EQ(indices, expected_indices);
117 }
118 }

References impeller::PathBuilder::AddRect(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::Tessellator::TessellateConvexInternal().

## ◆ TEST() [351/360]

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

Definition at line 121 of file tessellator_unittests.cc.

121 {
122 std::vector<Point> points;
123 std::vector<uint16_t> indices;
124
125 // Create a rectangle that lacks an explicit close.
126 Path path = PathBuilder{}
127 .LineTo({100, 0})
128 .LineTo({100, 100})
129 .LineTo({0, 100})
130 .TakePath();
131 Tessellator::TessellateConvexInternal(path, points, indices, 1.0);
132
133 std::vector<Point> expected = {{0, 0}, {100, 0}, {100, 100}, {0, 100}};
134 std::vector<uint16_t> expected_indices = {0, 1, 3, 2};
135 EXPECT_EQ(points, expected);
136 EXPECT_EQ(indices, expected_indices);
137 }

References impeller::LineTo(), impeller::PathBuilder::LineTo(), and impeller::Tessellator::TessellateConvexInternal().

## ◆ TEST() [352/360]

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

Definition at line 17 of file tessellator_unittests.cc.

17 {
18 // Zero points.
19 {
20 TessellatorLibtess t;
21 auto path = PathBuilder{}.TakePath(FillType::kOdd);
22 TessellatorLibtess::Result result = t.Tessellate(
23 path, 1.0f,
24 [](const float* vertices, size_t vertices_count,
25 const uint16_t* indices, size_t indices_count) { return true; });
26
27 ASSERT_EQ(result, TessellatorLibtess::Result::kInputError);
28 }
29
30 // One point.
31 {
32 TessellatorLibtess t;
33 auto path = PathBuilder{}.LineTo({0, 0}).TakePath(FillType::kOdd);
34 TessellatorLibtess::Result result = t.Tessellate(
35 path, 1.0f,
36 [](const float* vertices, size_t vertices_count,
37 const uint16_t* indices, size_t indices_count) { return true; });
38
39 ASSERT_EQ(result, TessellatorLibtess::Result::kSuccess);
40 }
41
42 // Two points.
43 {
44 TessellatorLibtess t;
45 auto path = PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath(FillType::kOdd);
46 TessellatorLibtess::Result result = t.Tessellate(
47 path, 1.0f,
48 [](const float* vertices, size_t vertices_count,
49 const uint16_t* indices, size_t indices_count) { return true; });
50
51 ASSERT_EQ(result, TessellatorLibtess::Result::kSuccess);
52 }
53
54 // Many points.
55 {
56 TessellatorLibtess t;
57 PathBuilder builder;
58 for (int i = 0; i < 1000; i++) {
59 auto coord = i * 1.0f;
60 builder.AddLine({coord, coord}, {coord + 1, coord + 1});
61 }
62 auto path = builder.TakePath(FillType::kOdd);
63 TessellatorLibtess::Result result = t.Tessellate(
64 path, 1.0f,
65 [](const float* vertices, size_t vertices_count,
66 const uint16_t* indices, size_t indices_count) { return true; });
67
68 ASSERT_EQ(result, TessellatorLibtess::Result::kSuccess);
69 }
70
71 // Closure fails.
72 {
73 TessellatorLibtess t;
74 auto path = PathBuilder{}.AddLine({0, 0}, {0, 1}).TakePath(FillType::kOdd);
75 TessellatorLibtess::Result result = t.Tessellate(
76 path, 1.0f,
77 [](const float* vertices, size_t vertices_count,
78 const uint16_t* indices, size_t indices_count) { return false; });
79
80 ASSERT_EQ(result, TessellatorLibtess::Result::kInputError);
81 }
82 }

References impeller::PathBuilder::AddLine(), impeller::TessellatorLibtess::kInputError, impeller::kOdd, impeller::TessellatorLibtess::kSuccess, impeller::PathBuilder::LineTo(), impeller::PathBuilder::TakePath(), and impeller::TessellatorLibtess::Tessellate().

## ◆ TEST() [353/360]

impeller::testing::TEST | ( | TextureMTL | ,
|  | CreateFromDrawable |
| ) |  |

Definition at line 21 of file texture_mtl_unittests.mm.

21 {
22 auto device = MTLCreateSystemDefaultDevice();
23 auto layer = [[CAMetalLayer alloc] init];
24 layer.device = device;
25 layer.drawableSize = CGSize{100, 100};
26 layer.pixelFormat = ToMTLPixelFormat(PixelFormat::kB8G8R8A8UNormInt);
27
28 TextureDescriptor desc;
29 desc.size = {100, 100};
30 desc.format = PixelFormat::kB8G8R8A8UNormInt;
31 auto drawable_future = GetDrawableDeferred(layer);
32 auto drawable_texture =
33 CreateTextureFromDrawableFuture(desc, drawable_future);
34
35 ASSERT_TRUE(drawable_texture->IsValid());
36 EXPECT_TRUE(drawable_texture->IsDrawable());
37
38 // Spawn a thread and acquire the drawable in the thread.
39 auto thread = std::thread([&drawable_texture]() {
40 // Force the drawable to be acquired.
41 drawable_texture->GetMTLTexture();
42 });
43 thread.join();
44 // Block until drawable is acquired.
45 EXPECT_TRUE(drawable_future.get() != nil);
46 // Drawable is cached.
47 EXPECT_TRUE(drawable_texture->GetMTLTexture() != nil);
48 // Once more for good measure.
49 EXPECT_TRUE(drawable_texture->GetMTLTexture() != nil);
50 }

References impeller::CreateTextureFromDrawableFuture(), impeller::TextureDescriptor::format, impeller::GetDrawableDeferred(), impeller::kB8G8R8A8UNormInt, impeller::TextureDescriptor::size, and impeller::ToMTLPixelFormat().

## ◆ TEST() [354/360]

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

Definition at line 36 of file base_unittests.cc.

36 {
37 Foo f = {};
38
39 // f.a = 100; <--- Static analysis error.
40 f.mtx.Lock();
41 f.a = 100;
42 f.mtx.Unlock();
43 }

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

## ◆ TEST() [355/360]

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

Definition at line 45 of file base_unittests.cc.

45 {
46 Foo f = {};
47
48 // f.a = 100; <--- Static analysis error.
49 auto a = Lock(f.mtx);
50 f.a = 100;
51 }

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

## ◆ TEST() [356/360]

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

Definition at line 53 of file base_unittests.cc.

53 {
54 RWFoo f = {};
55
56 // f.a = 100; <--- Static analysis error.
57 f.mtx.LockWriter();
58 f.a = 100;
59 f.mtx.UnlockWriter();
60 // int b = f.a; <--- Static analysis error.
61 f.mtx.LockReader();
62 int b = f.a; // NOLINT(clang-analyzer-deadcode.DeadStores)
63 FML_ALLOW_UNUSED_LOCAL(b);
64 f.mtx.UnlockReader();
65 }

References impeller::saturated::b, and impeller::testing::RWFoo::mtx.

## ◆ TEST() [357/360]

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

Definition at line 67 of file base_unittests.cc.

67 {
68 RWFoo f = {};
69
70 // f.a = 100; <--- Static analysis error.
71 {
72 auto write_lock = WriterLock{f.mtx};
73 f.a = 100;
74 }
75
76 // int b = f.a; <--- Static analysis error.
77 {
78 auto read_lock = ReaderLock(f.mtx);
79 int b = f.a; // NOLINT(clang-analyzer-deadcode.DeadStores)
80 FML_ALLOW_UNUSED_LOCAL(b);
81 }
82
83 // f.mtx.UnlockReader(); <--- Static analysis error.
84 }

References impeller::saturated::b, and impeller::testing::RWFoo::mtx.

## ◆ TEST() [358/360]

impeller::testing::TEST | ( | TrigTest | ,
|  | MultiplyByScalarRadius |
| ) |  |

Definition at line 65 of file trig_unittests.cc.

65 {
66 for (int i = 0; i <= 360; i++) {
67 for (int i = 1; i <= 10; i++) {
68 Scalar radius = i * 5.0f;
69 EXPECT_EQ(Trig(Degrees(i)) * radius,
70 Point(radius * std::cos(i * kPi / 180),
71 radius * std::sin(i * kPi / 180)))
72 << "at " << i << " degrees and radius " << radius;
73 }
74 }
75 }

References impeller::kPi.

## ◆ TEST() [359/360]

impeller::testing::TEST | ( | TrigTest | ,
|  | TrigAngles |
| ) |  |

Definition at line 15 of file trig_unittests.cc.

15 {
16 {
17 Trig trig(Degrees(0.0));
18 EXPECT_EQ(trig.cos, 1.0);
19 EXPECT_EQ(trig.sin, 0.0);
20 }
21
22 {
23 Trig trig(Radians(0.0));
24 EXPECT_EQ(trig.cos, 1.0);
25 EXPECT_EQ(trig.sin, 0.0);
26 }
27
28 {
29 Trig trig(Degrees(30.0));
30 EXPECT_NEAR(trig.cos, sqrt(0.75), kEhCloseEnough);
31 EXPECT_NEAR(trig.sin, 0.5, kEhCloseEnough);
32 }
33
34 {
35 Trig trig(Radians(kPi / 6.0));
36 EXPECT_NEAR(trig.cos, sqrt(0.75), kEhCloseEnough);
37 EXPECT_NEAR(trig.sin, 0.5, kEhCloseEnough);
38 }
39
40 {
41 Trig trig(Degrees(60.0));
42 EXPECT_NEAR(trig.cos, 0.5, kEhCloseEnough);
43 EXPECT_NEAR(trig.sin, sqrt(0.75), kEhCloseEnough);
44 }
45
46 {
47 Trig trig(Radians(kPi / 3.0));
48 EXPECT_NEAR(trig.cos, 0.5, kEhCloseEnough);
49 EXPECT_NEAR(trig.sin, sqrt(0.75), kEhCloseEnough);
50 }
51
52 {
53 Trig trig(Degrees(90.0));
54 EXPECT_NEAR(trig.cos, 0.0, kEhCloseEnough);
55 EXPECT_NEAR(trig.sin, 1.0, kEhCloseEnough);
56 }
57
58 {
59 Trig trig(Radians(kPi / 2.0));
60 EXPECT_NEAR(trig.cos, 0.0, kEhCloseEnough);
61 EXPECT_NEAR(trig.sin, 1.0, kEhCloseEnough);
62 }
63 }

References impeller::Trig::cos, impeller::kEhCloseEnough, impeller::kPi, and impeller::Trig::sin.

## ◆ TEST() [360/360]

impeller::testing::TEST | ( | TypographerTest | ,
|  | RectanglePackerFillsRows |
| ) |  |

Definition at line 398 of file typographer_unittests.cc.

398 {
399 auto skyline = RectanglePacker::Factory(257, 256);
400
401 // Fill up the first row.
402 IPoint16 loc;
403 for (auto i = 0u; i < 16; i++) {
404 skyline->AddRect(16, 16, &loc);
405 }
406 // Last rectangle still in first row.
407 EXPECT_EQ(loc.x(), 256 - 16);
408 EXPECT_EQ(loc.y(), 0);
409
410 // Fill up second row.
411 for (auto i = 0u; i < 16; i++) {
412 skyline->AddRect(16, 16, &loc);
413 }
414
415 EXPECT_EQ(loc.x(), 256 - 16);
416 EXPECT_EQ(loc.y(), 16);
417 }

References impeller::RectanglePacker::Factory(), impeller::IPoint16::x(), and impeller::IPoint16::y().

## ◆ TEST_F()

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

Definition at line 72 of file golden_tests.cc.

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

References impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::Paint::kFill, impeller::ColorSource::MakeConicalGradient(), impeller::testing::Screenshotter::MakeScreenshot(), impeller::TRect< Scalar >::MakeXYWH(), and paint.

## ◆ TEST_P() [1/456]

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

Definition at line 371 of file aiks_path_unittests.cc.

371 {
372 Canvas canvas;
373 canvas.Scale(GetContentScale());
374
375 Paint paint;
376 paint.color = Color::Red();
377 std::vector<Color> colors = {Color{1.0, 0.0, 0.0, 1.0},
378 Color{0.0, 0.0, 0.0, 1.0}};
379 std::vector<Scalar> stops = {0.0, 1.0};
380 paint.color_source = ColorSource::MakeSweepGradient(
381 {100, 100}, Degrees(45), Degrees(135), std::move(colors),
382 std::move(stops), Entity::TileMode::kMirror, {});
383 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
384 .style = FilterContents::BlurStyle::kNormal,
385 .sigma = Sigma(20),
386 };
387
388 PathBuilder builder;
389 builder.AddArc(Rect::MakeXYWH(10, 10, 100, 100), Degrees(0), Degrees(0),
390 false);
391 canvas.DrawPath(builder.TakePath(), paint);
392
393 // Check that this empty picture can be created without crashing.
394 canvas.EndRecordingAsPicture();
395 }

References impeller::PathBuilder::AddArc(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kMirror, impeller::FilterContents::kNormal, impeller::ColorSource::MakeSweepGradient(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Color::Red(), impeller::Canvas::Scale(), impeller::Paint::MaskBlurDescriptor::style, and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [2/456]

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

Definition at line 157 of file aiks_blend_unittests.cc.

157 {
158 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
159 PixelFormat::kB10G10R10A10XR);
160 auto texture = CreateTextureForFixture("airplane.jpg",
161 /*enable_mipmapping=*/true);
162
163 Canvas canvas;
164 canvas.Scale(GetContentScale());
165 canvas.DrawPaint({.color = Color(0.1, 0.2, 0.1, 1.0)});
166 canvas.SaveLayer({
167 .color_filter =
168 ColorFilter::MakeBlend(BlendMode::kPlus, Color(Vector4{1, 0, 0, 1})),
169 });
170 Paint paint;
171 paint.color = Color::Red();
172 canvas.DrawRect(Rect::MakeXYWH(100, 100, 400, 400), paint);
173 paint.color = Color::White();
174 canvas.DrawImageRect(
175 std::make_shared<Image>(texture), Rect::MakeSize(texture->GetSize()),
176 Rect::MakeXYWH(100, 100, 400, 400).Expand(-100, -100), paint);
177 canvas.Restore();
178 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
179 }

References impeller::Canvas::DrawImageRect(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< T >::Expand(), impeller::kB10G10R10A10XR, impeller::kPlus, impeller::ColorFilter::MakeBlend(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), and impeller::Color::White().

## ◆ TEST_P() [3/456]

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

Definition at line 134 of file aiks_blend_unittests.cc.

134 {
135 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
136 PixelFormat::kB10G10R10A10XR);
137 auto texture = CreateTextureForFixture("airplane.jpg",
138 /*enable_mipmapping=*/true);
139
140 Canvas canvas;
141 canvas.Scale(GetContentScale());
142 canvas.DrawPaint({.color = Color(0.9, 1.0, 0.9, 1.0)});
143 canvas.SaveLayer({});
144 Paint paint;
145 paint.blend_mode = BlendMode::kPlus;
146 paint.color = Color::Red();
147 canvas.DrawRect(Rect::MakeXYWH(100, 100, 400, 400), paint);
148 paint.color = Color::White();
149 canvas.DrawImageRect(
150 std::make_shared<Image>(texture), Rect::MakeSize(texture->GetSize()),
151 Rect::MakeXYWH(100, 100, 400, 400).Expand(-100, -100), paint);
152 canvas.Restore();
153 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
154 }

References impeller::Canvas::DrawImageRect(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< T >::Expand(), impeller::kB10G10R10A10XR, impeller::kPlus, impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), and impeller::Color::White().

## ◆ TEST_P() [4/456]

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

Definition at line 43 of file aiks_blend_unittests.cc.

43 {
44 Canvas canvas;
45 Paint paint;
46
47 paint.color = Color::Red();
48 canvas.DrawPaint(paint);
49
50 paint.blend_mode = BlendMode::kSourceOver;
51 canvas.SaveLayer(paint);
52
53 paint.color = Color::White();
54 canvas.DrawRect(Rect::MakeXYWH(100, 100, 400, 400), paint);
55
56 paint.blend_mode = BlendMode::kSource;
57 canvas.SaveLayer(paint);
58
59 paint.color = Color::Blue();
60 canvas.DrawRect(Rect::MakeXYWH(200, 200, 200, 200), paint);
61
62 canvas.Restore();
63 canvas.Restore();
64
65 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
66 }

References impeller::Color::Blue(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSource, impeller::kSourceOver, impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::White().

## ◆ TEST_P() [5/456]

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

Definition at line 201 of file aiks_blur_unittests.cc.

201 {
202 Scalar sigma = 47.6;
203 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
204 if (AiksTest::ImGuiBegin("Controls", nullptr,
205 ImGuiWindowFlags_AlwaysAutoResize)) {
206 ImGui::SliderFloat("Sigma", &sigma, 0, 50);
207 ImGui::End();
208 }
209 Canvas canvas;
210 canvas.Scale(GetContentScale());
211 canvas.DrawPaint({});
212 Paint blur = {
213 .color = Color::Green(),
214 .mask_blur_descriptor =
215 Paint::MaskBlurDescriptor{
216 .style = FilterContents::BlurStyle::kNormal,
217 .sigma = Sigma(sigma),
218 },
219 };
220 canvas.DrawRect(Rect::MakeXYWH(300, 300, 200, 200), blur);
221 return canvas.EndRecordingAsPicture();
222 };
223
224 ASSERT_TRUE(OpenPlaygroundHere(callback));
225 }

References impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::AiksPlayground::ImGuiBegin(), impeller::FilterContents::kNormal, impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Scale(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [6/456]

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

Definition at line 227 of file aiks_blur_unittests.cc.

227 {
228 Canvas canvas;
229 canvas.Scale(GetContentScale());
230
231 auto paint_lines = [&canvas](Scalar dx, Scalar dy, Paint paint) {
232 auto draw_line = [&canvas, &paint](Point a, Point b) {
233 canvas.DrawPath(PathBuilder{}.AddLine(a, b).TakePath(), paint);
234 };
235 paint.stroke_width = 5;
236 paint.style = Paint::Style::kStroke;
237 draw_line(Point(dx + 100, dy + 100), Point(dx + 200, dy + 200));
238 draw_line(Point(dx + 100, dy + 200), Point(dx + 200, dy + 100));
239 draw_line(Point(dx + 150, dy + 100), Point(dx + 200, dy + 150));
240 draw_line(Point(dx + 100, dy + 150), Point(dx + 150, dy + 200));
241 };
242
243 AiksContext renderer(GetContext(), nullptr);
244 Canvas recorder_canvas;
245 for (int x = 0; x < 5; ++x) {
246 for (int y = 0; y < 5; ++y) {
247 Rect rect = Rect::MakeXYWH(x * 20, y * 20, 20, 20);
248 Paint paint{.color =
249 ((x + y) & 1) == 0 ? Color::Yellow() : Color::Blue()};
250 recorder_canvas.DrawRect(rect, paint);
251 }
252 }
253 Picture picture = recorder_canvas.EndRecordingAsPicture();
254 std::shared_ptr<Texture> texture =
255 picture.ToImage(renderer, ISize{100, 100})->GetTexture();
256
257 ColorSource image_source = ColorSource::MakeImage(
258 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {}, {});
259 std::shared_ptr<ImageFilter> blur_filter = ImageFilter::MakeBlur(
260 Sigma(5), Sigma(5), FilterContents::BlurStyle::kNormal,
261 Entity::TileMode::kDecal);
262 canvas.DrawRect(Rect::MakeLTRB(0, 0, 300, 600),
263 Paint{.color = Color::DarkGreen()});
264 canvas.DrawRect(Rect::MakeLTRB(100, 100, 200, 200),
265 Paint{.color_source = image_source});
266 canvas.DrawRect(Rect::MakeLTRB(300, 0, 600, 600),
267 Paint{.color = Color::Red()});
268 canvas.DrawRect(
269 Rect::MakeLTRB(400, 100, 500, 200),
270 Paint{.color_source = image_source, .image_filter = blur_filter});
271 paint_lines(0, 300, Paint{.color_source = image_source});
272 paint_lines(300, 300,
273 Paint{.color_source = image_source, .image_filter = blur_filter});
274 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
275 }

References impeller::PathBuilder::AddLine(), impeller::saturated::b, impeller::Color::Blue(), impeller::Paint::color, impeller::Paint::color_source, impeller::Color::DarkGreen(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::Entity::kRepeat, impeller::Paint::kStroke, impeller::ImageFilter::MakeBlur(), impeller::ColorSource::MakeImage(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Color::Red(), impeller::Canvas::Scale(), impeller::PathBuilder::TakePath(), impeller::Picture::ToImage(), and impeller::Color::Yellow().

## ◆ TEST_P() [7/456]

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

Definition at line 153 of file aiks_dl_vertices_unittests.cc.

153 {
154 constexpr Scalar hexagon_radius = 125;
155 auto hex_start = Point(200.0, -hexagon_radius + 200.0);
156 auto center_to_flat = 1.73 / 2 * hexagon_radius;
157
158 // clang-format off
159 std::vector<SkPoint> vertices = {
160 SkPoint::Make(hex_start.x, hex_start.y),
161 SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 0.5 * hexagon_radius),
162 SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
163 SkPoint::Make(hex_start.x + center_to_flat, hex_start.y + 1.5 * hexagon_radius),
164 SkPoint::Make(hex_start.x, hex_start.y + 2 * hexagon_radius),
165 SkPoint::Make(hex_start.x, hex_start.y + 2 * hexagon_radius),
166 SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 1.5 * hexagon_radius),
167 SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 1.5 * hexagon_radius),
168 SkPoint::Make(hex_start.x - center_to_flat, hex_start.y + 0.5 * hexagon_radius)
169 };
170 // clang-format on
171 auto paint = flutter::DlPaint(flutter::DlColor::kDarkGrey());
172 auto dl_vertices = flutter::DlVertices::Make(
173 flutter::DlVertexMode::kTriangleFan, vertices.size(), vertices.data(),
174 nullptr, nullptr);
175 flutter::DisplayListBuilder builder;
176 builder.DrawVertices(dl_vertices, flutter::DlBlendMode::kSrcOver, paint);
177 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
178 }

References paint.

## ◆ TEST_P() [8/456]

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

Definition at line 142 of file aiks_path_unittests.cc.

142 {
143 Canvas canvas;
144
145 // Starting at (50, 50), draw lines from:
146 // 1. (50, height)
147 // 2. (width, height)
148 // 3. (width, 50)
149 PathBuilder builder;
150 builder.MoveTo({50, 50});
151 builder.LineTo({50, 100});
152 builder.LineTo({100, 100});
153 builder.LineTo({100, 50});
154
155 Paint paint;
156 paint.color = Color::Red();
157 paint.style = Paint::Style::kStroke;
158 paint.stroke_width = 10;
159
160 canvas.DrawPath(builder.TakePath(), paint);
161
162 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
163 }

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

## ◆ TEST_P() [9/456]

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

Definition at line 165 of file aiks_path_unittests.cc.

165 {
166 Canvas canvas;
167
168 // Draw a stroked path that is explicitly closed to verify
169 // It doesn't become a rectangle.
170 PathBuilder builder;
171 builder.MoveTo({50, 50});
172 builder.LineTo({520, 120});
173 builder.LineTo({300, 310});
174 builder.LineTo({100, 50});
175 builder.Close();
176
177 Paint paint;
178 paint.color = Color::Red();
179 paint.style = Paint::Style::kStroke;
180 paint.stroke_width = 10;
181
182 canvas.DrawPath(builder.TakePath(), paint);
183
184 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
185 }

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

## ◆ TEST_P() [10/456]

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

Definition at line 351 of file aiks_path_unittests.cc.

351 {
352 PathBuilder builder = {};
353 for (auto i = 0; i < 10; i++) {
354 if (i % 2 == 0) {
355 builder.AddCircle(Point(100 + 50 * i, 100 + 50 * i), 100);
356 } else {
357 builder.MoveTo({100.f + 50.f * i - 100, 100.f + 50.f * i});
358 builder.LineTo({100.f + 50.f * i, 100.f + 50.f * i - 100});
359 builder.LineTo({100.f + 50.f * i - 100, 100.f + 50.f * i - 100});
360 builder.Close();
361 }
362 }
363 builder.SetConvexity(Convexity::kConvex);
364
365 Canvas canvas;
366 canvas.DrawPath(builder.TakePath(), {.color = Color::Red().WithAlpha(0.4)});
367
368 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
369 }

References impeller::PathBuilder::AddCircle(), impeller::PathBuilder::Close(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::kConvex, impeller::PathBuilder::LineTo(), impeller::PathBuilder::MoveTo(), impeller::PathBuilder::SetConvexity(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [11/456]

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

Definition at line 855 of file aiks_unittests.cc.

855 {
856 Canvas canvas;
857 canvas.Scale(Vector2(0.2, 0.2));
858 canvas.DrawPaint({.color = Color::MediumTurquoise()});
859 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
860 }

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

## ◆ TEST_P() [12/456]

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

Definition at line 862 of file aiks_unittests.cc.

862 {
863 Canvas canvas;
864 canvas.Scale(Vector2(0.2, 0.2));
865 canvas.DrawPaint({.color = Color::MediumTurquoise()});
866 canvas.DrawPaint({.color = Color::Color::OrangeRed().WithAlpha(0.5)});
867 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
868 }

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

## ◆ TEST_P() [13/456]

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

Definition at line 524 of file aiks_blend_unittests.cc.

524 {
525 auto modes = GetBlendModeSelection();
526
527 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
528 static Color background = Color::MediumTurquoise();
529 static Color foreground = Color::Color::OrangeRed().WithAlpha(0.5);
530 static int current_blend_index = 3;
531
532 if (AiksTest::ImGuiBegin("Controls", nullptr,
533 ImGuiWindowFlags_AlwaysAutoResize)) {
534 ImGui::ColorEdit4("Background", reinterpret_cast<float*>(&background));
535 ImGui::ColorEdit4("Foreground", reinterpret_cast<float*>(&foreground));
536 ImGui::ListBox("Blend mode", &current_blend_index,
537 modes.blend_mode_names.data(),
538 modes.blend_mode_names.size());
539 ImGui::End();
540 }
541
542 Canvas canvas;
543 canvas.Scale(Vector2(0.2, 0.2));
544 canvas.DrawPaint({.color = background});
545 canvas.DrawPaint(
546 {.color = foreground,
547 .blend_mode = static_cast<BlendMode>(current_blend_index)});
548 return canvas.EndRecordingAsPicture();
549 };
550 ASSERT_TRUE(OpenPlaygroundHere(callback));
551 }

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

## ◆ TEST_P() [14/456]

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

Definition at line 68 of file aiks_blend_unittests.cc.

68 {
69 Canvas canvas;
70 canvas.Scale(Vector2(0.2, 0.2));
71 canvas.DrawPaint({.color = Color::MediumTurquoise()});
72 canvas.DrawPaint({.color = Color::Color::OrangeRed().WithAlpha(0.5),
73 .blend_mode = BlendMode::kHue});
74 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
75 }

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

## ◆ TEST_P() [15/456]

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

Definition at line 2705 of file aiks_unittests.cc.

2705 {
2706 // Avoiding `GetSecondsElapsed()` to reduce risk of golden flakiness.
2707 int time = 0;
2708 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
2709 Canvas canvas;
2710
2711 canvas.Save();
2712 {
2713 canvas.Translate({300, 300});
2714
2715 // 1. Draw/restore a clip before drawing the image, which will get drawn
2716 // to the depth buffer behind the image.
2717 canvas.Save();
2718 {
2719 canvas.DrawPaint({.color = Color::Green()});
2720 canvas.ClipRect(Rect::MakeLTRB(-180, -180, 180, 180),
2721 Entity::ClipOperation::kDifference);
2722 canvas.DrawPaint({.color = Color::Black()});
2723 }
2724 canvas.Restore(); // Restore rectangle difference clip.
2725
2726 canvas.Save();
2727 {
2728 // 2. Draw an oval clip that applies to the image, which will get drawn
2729 // in front of the image on the depth buffer.
2730 canvas.ClipOval(Rect::MakeLTRB(-200, -200, 200, 200));
2731
2732 // 3. Draw the rotating image with a perspective transform.
2733 canvas.Transform(
2734 Matrix(1.0, 0.0, 0.0, 0.0, //
2735 0.0, 1.0, 0.0, 0.0, //
2736 0.0, 0.0, 1.0, 0.003, //
2737 0.0, 0.0, 0.0, 1.0) * //
2738 Matrix::MakeRotationY({Radians{-1.0f + (time++ / 60.0f)}}));
2739 auto image =
2740 std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2741 canvas.DrawImage(image, -Point(image->GetSize()) / 2, {});
2742 }
2743 canvas.Restore(); // Restore oval intersect clip.
2744
2745 // 4. Draw a semi-translucent blue circle atop all previous draws.
2746 canvas.DrawCircle({}, 230, {.color = Color::Blue().WithAlpha(0.4)});
2747 }
2748 canvas.Restore(); // Restore translation.
2749
2750 return canvas.EndRecordingAsPicture();
2751 };
2752 ASSERT_TRUE(OpenPlaygroundHere(callback));
2753 }

References impeller::Color::Black(), impeller::Color::Blue(), impeller::Canvas::ClipOval(), impeller::Canvas::ClipRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawImage(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Entity::kDifference, impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeRotationY(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::Transform(), impeller::Canvas::Translate(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [16/456]

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

Definition at line 2243 of file aiks_unittests.cc.

2243 {
2244 std::vector<Point> points = {
2245 {0, 0}, //
2246 {100, 100}, //
2247 {100, 0}, //
2248 {0, 100}, //
2249 {0, 0}, //
2250 {48, 48}, //
2251 {52, 52}, //
2252 };
2253 std::vector<PointStyle> caps = {
2254 PointStyle::kRound,
2255 PointStyle::kSquare,
2256 };
2257 Paint paint;
2258 paint.color = Color::Yellow().WithAlpha(0.5);
2259
2260 Paint background;
2261 background.color = Color::Black();
2262
2263 Canvas canvas;
2264 canvas.DrawPaint(background);
2265 canvas.Translate({200, 200});
2266 canvas.DrawPoints(points, 10, paint, PointStyle::kRound);
2267 canvas.Translate({150, 0});
2268 canvas.DrawPoints(points, 10, paint, PointStyle::kSquare);
2269
2270 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2271 }

References impeller::Color::Black(), impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPoints(), impeller::Canvas::EndRecordingAsPicture(), impeller::kRound, impeller::kSquare, paint, impeller::Canvas::Translate(), impeller::Color::WithAlpha(), and impeller::Color::Yellow().

## ◆ TEST_P() [17/456]

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

Definition at line 2273 of file aiks_unittests.cc.

2273 {
2274 auto texture = CreateTextureForFixture("table_mountain_nx.png",
2275 /*enable_mipmapping=*/true);
2276
2277 std::vector<Point> points = {
2278 {0, 0}, //
2279 {100, 100}, //
2280 {100, 0}, //
2281 {0, 100}, //
2282 {0, 0}, //
2283 {48, 48}, //
2284 {52, 52}, //
2285 };
2286 std::vector<PointStyle> caps = {
2287 PointStyle::kRound,
2288 PointStyle::kSquare,
2289 };
2290 Paint paint;
2291 paint.color_source = ColorSource::MakeImage(texture, Entity::TileMode::kClamp,
2292 Entity::TileMode::kClamp, {}, {});
2293
2294 Canvas canvas;
2295 canvas.Translate({200, 200});
2296 canvas.DrawPoints(points, 100, paint, PointStyle::kRound);
2297 canvas.Translate({150, 0});
2298 canvas.DrawPoints(points, 100, paint, PointStyle::kSquare);
2299
2300 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2301 }

References impeller::Entity::kClamp, impeller::kRound, impeller::kSquare, impeller::ColorSource::MakeImage(), paint, and impeller::Canvas::Translate().

## ◆ TEST_P() [18/456]

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

Definition at line 385 of file aiks_unittests.cc.

385 {
386 Canvas recorder_canvas;
387
388 Canvas canvas;
389 AiksContext renderer(GetContext(), nullptr);
390 Paint paint;
391 paint.color = Color::BlackTransparent();
392 canvas.DrawPaint(paint);
393 Picture picture = recorder_canvas.EndRecordingAsPicture();
394 auto image = picture.ToImage(renderer, ISize{1000, 1000});
395 if (image) {
396 canvas.DrawImage(image, Point(), Paint());
397 paint.color = Color{0.1, 0.1, 0.1, 0.2};
398 canvas.DrawRect(Rect::MakeSize(ISize{1000, 1000}), paint);
399 }
400
401 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
402 }

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

## ◆ TEST_P() [19/456]

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

Definition at line 445 of file aiks_unittests.cc.

445 {
446 Canvas canvas;
447
448 Paint red;
449 red.color = Color::Red();
450
451 canvas.DrawCircle({250, 250}, 125, red);
452
453 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
454 }

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

## ◆ TEST_P() [20/456]

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

Definition at line 468 of file aiks_unittests.cc.

468 {
469 Canvas canvas;
470
471 Paint red;
472 red.color = Color::Red();
473
474 Paint green;
475 green.color = Color::Green();
476
477 Paint blue;
478 blue.color = Color::Blue();
479
480 Paint save;
481 save.color = Color::Black();
482
483 canvas.SaveLayer(save, Rect::MakeXYWH(0, 0, 50, 50));
484
485 canvas.DrawRect(Rect::MakeXYWH(0, 0, 100, 100), red);
486 canvas.DrawRect(Rect::MakeXYWH(10, 10, 100, 100), green);
487 canvas.DrawRect(Rect::MakeXYWH(20, 20, 100, 100), blue);
488
489 canvas.Restore();
490
491 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
492 }

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

## ◆ TEST_P() [21/456]

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

Definition at line 494 of file aiks_unittests.cc.

495 {
496 Canvas canvas;
497
498 Paint red;
499 red.color = Color::Red();
500
501 Paint green;
502 green.color = Color::Green();
503
504 Paint blue;
505 blue.color = Color::Blue();
506
507 Paint save;
508 save.color = Color::Black().WithAlpha(0.5);
509
510 canvas.SaveLayer(save, Rect::MakeXYWH(0, 0, 100000, 100000));
511
512 canvas.DrawRect(Rect::MakeXYWH(0, 0, 100, 100), red);
513 canvas.DrawRect(Rect::MakeXYWH(10, 10, 100, 100), green);
514 canvas.DrawRect(Rect::MakeXYWH(20, 20, 100, 100), blue);
515
516 canvas.Restore();
517
518 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
519 }

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

## ◆ TEST_P() [22/456]

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

Definition at line 456 of file aiks_unittests.cc.

456 {
457 Canvas canvas;
458
459 Paint red;
460 red.color = Color::Red();
461
462 canvas.Skew(2, 5);
463 canvas.DrawRect(Rect::MakeXYWH(0, 0, 100, 100), red);
464
465 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
466 }

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

## ◆ TEST_P() [23/456]

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

Definition at line 359 of file aiks_unittests.cc.

359 {
360 Canvas recorder_canvas;
361 Paint paint;
362 paint.color = Color{0.9568, 0.2627, 0.2118, 1.0};
363 recorder_canvas.DrawRect(Rect::MakeXYWH(100.0, 100.0, 600, 600), paint);
364 paint.color = Color{0.1294, 0.5882, 0.9529, 1.0};
365 recorder_canvas.DrawRect(Rect::MakeXYWH(200.0, 200.0, 600, 600), paint);
366
367 Canvas canvas;
368 AiksContext renderer(GetContext(), nullptr);
369 paint.color = Color::BlackTransparent();
370 canvas.DrawPaint(paint);
371 Picture picture = recorder_canvas.EndRecordingAsPicture();
372 auto image = picture.ToImage(renderer, ISize{1000, 1000});
373 if (image) {
374 canvas.DrawImage(image, Point(), Paint());
375 paint.color = Color{0.1, 0.1, 0.1, 0.2};
376 canvas.DrawRect(Rect::MakeSize(ISize{1000, 1000}), paint);
377 }
378
379 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
380 }

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

## ◆ TEST_P() [24/456]

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

Definition at line 21 of file aiks_blend_unittests.cc.

21 {
22 Canvas canvas;
23
24 Rect layer_rect = Rect::MakeXYWH(0, 0, 500, 500);
25 canvas.ClipRect(layer_rect);
26
27 canvas.SaveLayer(
28 {
29 .color_filter = ColorFilter::MakeBlend(BlendMode::kDifference,
30 Color(0, 1, 0, 0.5)),
31 },
32 layer_rect);
33
34 Paint paint;
35 canvas.DrawPaint({.color = Color::Black()});
36 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300),
37 {.color = Color::White()});
38 canvas.Restore();
39
40 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
41 }

References impeller::Color::Black(), impeller::Canvas::ClipRect(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kDifference, impeller::ColorFilter::MakeBlend(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::White().

## ◆ TEST_P() [25/456]

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

Definition at line 102 of file aiks_blur_unittests.cc.

102 {
103 Canvas canvas;
104 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
105 canvas.DrawCircle({300, 200}, 100, {.color = Color::GreenYellow()});
106 canvas.DrawCircle({140, 170}, 75, {.color = Color::DarkMagenta()});
107 canvas.DrawCircle({180, 120}, 100, {.color = Color::OrangeRed()});
108 canvas.ClipRRect(Rect::MakeLTRB(75, 50, 375, 275), {20, 20});
109 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
110 ImageFilter::MakeBlur(Sigma(30.0), Sigma(30.0),
111 FilterContents::BlurStyle::kNormal,
112 Entity::TileMode::kClamp));
113 canvas.Restore();
114
115 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
116 }

References impeller::Canvas::ClipRRect(), impeller::Color::CornflowerBlue(), impeller::Color::DarkMagenta(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::GreenYellow(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSource, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Color::OrangeRed(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [26/456]

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

Definition at line 118 of file aiks_blur_unittests.cc.

118 {
119 Canvas canvas;
120 canvas.DrawCircle({400, 400}, 300, {.color = Color::Green()});
121 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
122 ImageFilter::MakeBlur(Sigma(999999), Sigma(999999),
123 FilterContents::BlurStyle::kNormal,
124 Entity::TileMode::kClamp));
125 canvas.Restore();
126
127 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
128 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSource, impeller::ImageFilter::MakeBlur(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [27/456]

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

Definition at line 78 of file aiks_blur_unittests.cc.

78 {
79 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
80 static PlaygroundPoint point_a(Point(50, 50), 30, Color::White());
81 static PlaygroundPoint point_b(Point(300, 200), 30, Color::White());
82 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
83
84 Canvas canvas;
85 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
86 canvas.DrawCircle({300, 200}, 100, {.color = Color::GreenYellow()});
87 canvas.DrawCircle({140, 170}, 75, {.color = Color::DarkMagenta()});
88 canvas.DrawCircle({180, 120}, 100, {.color = Color::OrangeRed()});
89 canvas.ClipRRect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), {20, 20});
90 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
91 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
92 FilterContents::BlurStyle::kNormal,
93 Entity::TileMode::kClamp));
94 canvas.Restore();
95
96 return canvas.EndRecordingAsPicture();
97 };
98
99 ASSERT_TRUE(OpenPlaygroundHere(callback));
100 }

References impeller::saturated::b, impeller::Canvas::ClipRRect(), impeller::Color::CornflowerBlue(), impeller::Color::DarkMagenta(), impeller::Canvas::DrawCircle(), impeller::DrawPlaygroundLine(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::GreenYellow(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSource, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Color::OrangeRed(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::White().

## ◆ TEST_P() [28/456]

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

Definition at line 2755 of file aiks_unittests.cc.

2755 {
2756 Canvas canvas;
2757 Paint paint;
2758
2759 canvas.Scale(GetContentScale());
2760
2761 // Draw something interesting in the background.
2762 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
2763 Color{0.1294, 0.5882, 0.9529, 1.0}};
2764 std::vector<Scalar> stops = {
2765 0.0,
2766 1.0,
2767 };
2768 paint.color_source = ColorSource::MakeLinearGradient(
2769 {0, 0}, {100, 100}, std::move(colors), std::move(stops),
2770 Entity::TileMode::kRepeat, {});
2771 canvas.DrawPaint(paint);
2772
2773 Rect clip_rect = Rect::MakeLTRB(50, 50, 400, 300);
2774
2775 // Draw a clipped SaveLayer, where the clip coverage and SaveLayer size are
2776 // the same.
2777 canvas.ClipRRect(clip_rect, Size(100, 100),
2778 Entity::ClipOperation::kIntersect);
2779 canvas.SaveLayer({}, clip_rect,
2780 ImageFilter::MakeFromColorFilter(*ColorFilter::MakeBlend(
2781 BlendMode::kExclusion, Color::Red())));
2782 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2783 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kExclusion, impeller::Entity::kIntersect, impeller::Entity::kRepeat, impeller::ColorFilter::MakeBlend(), impeller::ImageFilter::MakeFromColorFilter(), impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeLTRB(), paint, impeller::Color::Red(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Scale().

## ◆ TEST_P() [29/456]

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

Definition at line 130 of file aiks_blur_unittests.cc.

130 {
131 Canvas canvas;
132 canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
133 canvas.DrawCircle(
134 {400, 400}, 200,
135 {
136 .color = Color::Green(),
137 .image_filter = ImageFilter::MakeBlur(
138 Sigma(20.0), Sigma(20.0), FilterContents::BlurStyle::kNormal,
139 Entity::TileMode::kDecal),
140 });
141 canvas.Restore();
142
143 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
144 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeXYWH(), and impeller::Canvas::Restore().

## ◆ TEST_P() [30/456]

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

Definition at line 1469 of file aiks_unittests.cc.

1469 {
1470 Canvas canvas;
1471
1472 canvas.DrawPaint({.color = Color::White()});
1473
1474 // Draw a green circle on the screen.
1475 {
1476 // Increase the clip depth for the savelayer to contend with.
1477 canvas.ClipPath(PathBuilder{}.AddCircle({100, 100}, 50).TakePath());
1478
1479 canvas.SaveLayer({}, Rect::MakeXYWH(50, 50, 100, 100));
1480
1481 // Fill the layer with white.
1482 canvas.DrawRect(Rect::MakeSize(Size{400, 400}), {.color = Color::White()});
1483 // Fill the layer with green, but do so with a color blend that can't be
1484 // collapsed into the parent pass.
1485 // TODO(jonahwilliams): this blend mode was changed from color burn to
1486 // hardlight to work around https://github.com/flutter/flutter/issues/136554
1487 // .
1488 canvas.DrawRect(
1489 Rect::MakeSize(Size{400, 400}),
1490 {.color = Color::Green(), .blend_mode = BlendMode::kHardLight});
1491 }
1492
1493 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1494 }

References impeller::PathBuilder::AddCircle(), impeller::Canvas::ClipPath(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::kHardLight, impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::SaveLayer(), and impeller::Color::White().

## ◆ TEST_P() [31/456]

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

Definition at line 2181 of file aiks_unittests.cc.

2181 {
2182 auto runtime_stages =
2183 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2184
2185 auto runtime_stage =
2186 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2187 ASSERT_TRUE(runtime_stage);
2188 ASSERT_TRUE(runtime_stage->IsDirty());
2189
2190 struct FragUniforms {
2191 Vector2 iResolution;
2192 Scalar iTime;
2193 } frag_uniforms = {.iResolution = Vector2(400, 400), .iTime = 100.0};
2194 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2195 uniform_data->resize(sizeof(FragUniforms));
2196 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2197
2198 std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
2199
2200 Paint paint;
2201 paint.color_source = ColorSource::MakeRuntimeEffect(
2202 runtime_stage, uniform_data, texture_inputs);
2203
2204 Canvas canvas;
2205 canvas.Save();
2206 canvas.ClipRRect(Rect::MakeXYWH(0, 0, 400, 400), {10.0, 10.0},
2207 Entity::ClipOperation::kIntersect);
2208 canvas.DrawRect(Rect::MakeXYWH(0, 0, 400, 400), paint);
2209 canvas.Restore();
2210
2211 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2212 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kIntersect, impeller::ColorSource::MakeRuntimeEffect(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::PlaygroundBackendToRuntimeStageBackend(), impeller::Canvas::Restore(), and impeller::Canvas::Save().

## ◆ TEST_P() [32/456]

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

Definition at line 397 of file aiks_path_unittests.cc.

397 {
398 Canvas canvas;
399 Paint paint;
400 paint.color = Color::Fuchsia();
401 canvas.ClipPath(
402 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 500, 500)).TakePath());
403 canvas.DrawPath(PathBuilder{}.AddCircle({500, 500}, 250).TakePath(), paint);
404 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
405 }

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

## ◆ TEST_P() [33/456]

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

Definition at line 73 of file aiks_unittests.cc.

73 {
74 Canvas canvas;
75 Paint paint;
76 paint.color = Color::Blue();
77 canvas.DrawPath(PathBuilder{}
78 .AddRect(Rect::MakeXYWH(100.0, 100.0, 100.0, 100.0))
79 .TakePath(),
80 paint);
81 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
82 }

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

## ◆ TEST_P() [34/456]

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

Definition at line 106 of file aiks_unittests.cc.

106 {
107 Canvas canvas;
108 Paint paint;
109 paint.color = Color::Red();
110 paint.color_filter =
111 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow());
112 paint.invert_colors = true;
113
114 canvas.DrawRect(Rect::MakeLTRB(0, 0, 100, 100), paint);
115 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
116 }

References impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSourceOver, impeller::ColorFilter::MakeBlend(), impeller::TRect< Scalar >::MakeLTRB(), paint, impeller::Color::Red(), and impeller::Color::Yellow().

## ◆ TEST_P() [35/456]

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

Definition at line 118 of file aiks_unittests.cc.

118 {
119 Canvas canvas;
120 Paint paint;
121 paint.color = Color::Red();
122 paint.color_filter =
123 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow());
124 paint.invert_colors = true;
125
126 canvas.DrawPaint(paint);
127 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
128 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSourceOver, impeller::ColorFilter::MakeBlend(), paint, impeller::Color::Red(), and impeller::Color::Yellow().

## ◆ TEST_P() [36/456]

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

Definition at line 550 of file aiks_dl_gradient_unittests.cc.

550 {
551 Scalar size = 256;
552 DisplayListBuilder builder;
553 DlPaint paint;
554 paint.setColor(DlColor::kWhite());
555 builder.DrawRect(SkRect::MakeXYWH(0, 0, size * 3, size * 3), paint);
556 std::vector<DlColor> colors = {
557 DlColor(Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF).ToARGB()),
558 DlColor(Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF).ToARGB()),
559 DlColor(Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF).ToARGB()),
560 DlColor(Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF).ToARGB())};
561 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
562 std::array<std::tuple<SkPoint, float, SkPoint, float>, 8> array{
563 std::make_tuple(SkPoint::Make(size / 2.f, size / 2.f), 0.f,
564 SkPoint::Make(size / 2.f, size / 2.f), size / 2.f),
565 std::make_tuple(SkPoint::Make(size / 2.f, size / 2.f), size / 4.f,
566 SkPoint::Make(size / 2.f, size / 2.f), size / 2.f),
567 std::make_tuple(SkPoint::Make(size / 4.f, size / 4.f), 0.f,
568 SkPoint::Make(size / 2.f, size / 2.f), size / 2.f),
569 std::make_tuple(SkPoint::Make(size / 4.f, size / 4.f), size / 2.f,
570 SkPoint::Make(size / 2.f, size / 2.f), 0),
571 std::make_tuple(SkPoint::Make(size / 4.f, size / 4.f), size / 4.f,
572 SkPoint::Make(size / 2.f, size / 2.f), size / 2.f),
573 std::make_tuple(SkPoint::Make(size / 4.f, size / 4.f), size / 16.f,
574 SkPoint::Make(size / 2.f, size / 2.f), size / 8.f),
575 std::make_tuple(SkPoint::Make(size / 4.f, size / 4.f), size / 8.f,
576 SkPoint::Make(size / 2.f, size / 2.f), size / 16.f),
577 std::make_tuple(SkPoint::Make(size / 8.f, size / 8.f), size / 8.f,
578 SkPoint::Make(size / 2.f, size / 2.f), size / 8.f),
579 };
580 for (int i = 0; i < 8; i++) {
581 builder.Save();
582 builder.Translate((i % 3) * size, i / 3 * size);
583 paint.setColorSource(DlColorSource::MakeConical(
584 std::get<2>(array[i]), std::get<3>(array[i]), std::get<0>(array[i]),
585 std::get<1>(array[i]), stops.size(), colors.data(), stops.data(),
586 DlTileMode::kClamp));
587 builder.DrawRect(SkRect::MakeXYWH(0, 0, size, size), paint);
588 builder.Restore();
589 }
590 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
591 }

References paint.

## ◆ TEST_P() [37/456]

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

Definition at line 186 of file aiks_dl_gradient_unittests.cc.

186 {
187 CanRenderConicalGradientWithDithering(this);
188 }

References CanRenderConicalGradientWithDithering().

## ◆ TEST_P() [38/456]

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

Definition at line 31 of file aiks_path_unittests.cc.

31 {
32 Canvas canvas;
33 Paint paint;
34 paint.color = Color::Red();
35 paint.stroke_width = 25.0;
36 paint.style = Paint::Style::kStroke;
37 canvas.DrawPath(PathBuilder{}.AddCircle({500, 500}, 250).TakePath(), paint);
38 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
39 }

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

## ◆ TEST_P() [39/456]

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

Definition at line 2166 of file aiks_unittests.cc.

2166 {
2167 Canvas canvas;
2168
2169 canvas.DrawPaint({.color = Color::Red()});
2170 // Draw an empty savelayer with a destructive blend mode, which will replace
2171 // the entire red screen with fully transparent black, except for the green
2172 // circle drawn within the layer.
2173 canvas.SaveLayer({.blend_mode = BlendMode::kSource});
2174 canvas.DrawCircle({300, 300}, 100, {.color = Color::Green()});
2175 canvas.Restore();
2176
2177 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2178 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::kSource, impeller::Color::Red(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [40/456]

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

Definition at line 42 of file aiks_dl_clip_unittests.cc.

42 {
43 DisplayListBuilder builder;
44 builder.Translate(400, 400);
45
46 // Limit drawing to face circle with a clip.
47 builder.ClipPath(CreateCircle(0, 0, 200));
48 builder.Save();
49
50 // Cut away eyes/mouth using difference clips.
51 builder.ClipPath(CreateCircle(-100, -50, 30), DlCanvas::ClipOp::kDifference);
52 builder.ClipPath(CreateCircle(100, -50, 30), DlCanvas::ClipOp::kDifference);
53
54 SkPath path;
55 path.moveTo(-100, 50);
56 path.quadTo(0, 150, 100, 50);
57 builder.ClipPath(path, DlCanvas::ClipOp::kDifference);
58
59 // Draw a huge yellow rectangle to prove the clipping works.
60 DlPaint paint;
61 paint.setColor(DlColor::kYellow());
62 builder.DrawRect(SkRect::MakeXYWH(-1000, -1000, 2000, 2000), paint);
63
64 // Remove the difference clips and draw hair that partially covers the eyes.
65 builder.Restore();
66 paint.setColor(DlColor::kMaroon());
67 SkPath path_2;
68 path_2.moveTo(200, -200);
69 path_2.lineTo(-200, -200);
70 path_2.lineTo(-200, -40);
71 path_2.cubicTo({0, -40}, {0, -80}, {200, -80});
72
73 builder.DrawPath(path_2, paint);
74
75 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
76 }

References paint.

## ◆ TEST_P() [41/456]

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

Definition at line 113 of file aiks_path_unittests.cc.

113 {
114 Canvas canvas;
115
116 Paint paint;
117 paint.color = Color::Red();
118
119 PathBuilder builder;
120
121 PathBuilder::RoundingRadii radii;
122 radii.top_left = {50, 25};
123 radii.top_right = {25, 50};
124 radii.bottom_right = {50, 25};
125 radii.bottom_left = {25, 50};
126
127 builder.AddRoundedRect(Rect::MakeXYWH(100, 100, 200, 200), radii);
128 builder.AddCircle({200, 200}, 50);
129 auto path = builder.TakePath(FillType::kOdd);
130
131 canvas.DrawImage(
132 std::make_shared<Image>(CreateTextureForFixture("boston.jpg")), {10, 10},
133 Paint{});
134 canvas.DrawPath(path, paint);
135
136 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
137 }

References impeller::PathBuilder::AddCircle(), impeller::PathBuilder::AddRoundedRect(), impeller::PathBuilder::RoundingRadii::bottom_left, impeller::PathBuilder::RoundingRadii::bottom_right, impeller::Canvas::DrawImage(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::kOdd, impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Color::Red(), impeller::PathBuilder::TakePath(), impeller::PathBuilder::RoundingRadii::top_left, and impeller::PathBuilder::RoundingRadii::top_right.

## ◆ TEST_P() [42/456]

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

Definition at line 332 of file aiks_unittests.cc.

332 {
333 Canvas canvas;
334 Paint paint;
335
336 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
337 Color{0.1294, 0.5882, 0.9529, 1.0}};
338 std::vector<Scalar> stops = {
339 0.0,
340 1.0,
341 };
342
343 paint.color_source = ColorSource::MakeLinearGradient(
344 {0, 0}, {100, 100}, std::move(colors), std::move(stops),
345 Entity::TileMode::kRepeat, {});
346
347 canvas.Save();
348 canvas.Translate({100, 100, 0});
349 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), paint);
350 canvas.Restore();
351
352 canvas.Save();
353 canvas.Translate({100, 400, 0});
354 canvas.DrawCircle({100, 100}, 100, paint);
355 canvas.Restore();
356 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
357 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kRepeat, impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Canvas::Restore(), impeller::Canvas::Save(), and impeller::Canvas::Translate().

## ◆ TEST_P() [43/456]

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

Definition at line 747 of file aiks_unittests.cc.

747 {
748 Canvas canvas;
749 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
750
751 ASSERT_TRUE(RenderTextInCanvasSkia(
752 GetContext(), canvas, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture));
753 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
754 }

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

## ◆ TEST_P() [44/456]

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

Definition at line 769 of file aiks_unittests.cc.

769 {
770 Canvas canvas;
771 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
772
773 ASSERT_TRUE(RenderTextInCanvasSkia(
774 GetContext(), canvas, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture,
775 {.color = Color::Black().WithAlpha(0.5)}));
776 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
777 }

References impeller::Color::Black(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), kFontFixture, RenderTextInCanvasSkia(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [45/456]

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

Definition at line 756 of file aiks_unittests.cc.

756 {
757 Canvas canvas;
758 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
759
760 ASSERT_TRUE(RenderTextInCanvasSkia(
761 GetContext(), canvas, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture,
762 TextRenderOptions{.color = Color::Blue(),
763 .mask_blur_descriptor = Paint::MaskBlurDescriptor{
764 .style = FilterContents::BlurStyle::kNormal,
765 .sigma = Sigma(4)}}));
766 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
767 }

References impeller::Color::Blue(), impeller::testing::TextRenderOptions::color, impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), kFontFixture, impeller::FilterContents::kNormal, RenderTextInCanvasSkia(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [46/456]

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

Definition at line 57 of file aiks_blur_unittests.cc.

57 {
58 // This case triggers the ForegroundAdvancedBlend path. The color filter
59 // should apply to the color only, and respect the alpha mask.
60 Canvas canvas;
61 canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
62 canvas.DrawCircle({400, 400}, 200,
63 {
64 .color = Color::Grey(),
65 .color_filter = ColorFilter::MakeBlend(
66 BlendMode::kColor, Color::Green()),
67 .mask_blur_descriptor =
68 Paint::MaskBlurDescriptor{
69 .style = FilterContents::BlurStyle::kNormal,
70 .sigma = Radius(20),
71 },
72 });
73 canvas.Restore();
74
75 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
76 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Color::Grey(), impeller::kColor, impeller::FilterContents::kNormal, impeller::ColorFilter::MakeBlend(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [47/456]

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

Definition at line 36 of file aiks_blur_unittests.cc.

36 {
37 // This case triggers the ForegroundPorterDuffBlend path. The color filter
38 // should apply to the color only, and respect the alpha mask.
39 Canvas canvas;
40 canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
41 canvas.DrawCircle({400, 400}, 200,
42 {
43 .color = Color::White(),
44 .color_filter = ColorFilter::MakeBlend(
45 BlendMode::kSource, Color::Green()),
46 .mask_blur_descriptor =
47 Paint::MaskBlurDescriptor{
48 .style = FilterContents::BlurStyle::kNormal,
49 .sigma = Radius(20),
50 },
51 });
52 canvas.Restore();
53
54 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
55 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::FilterContents::kNormal, impeller::kSource, impeller::ColorFilter::MakeBlend(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), impeller::Paint::MaskBlurDescriptor::style, and impeller::Color::White().

## ◆ TEST_P() [48/456]

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

Definition at line 593 of file aiks_dl_gradient_unittests.cc.

593 {
594 std::vector<DlColor> colors = {
595 DlColor(Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF).ToARGB()),
596 DlColor(Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF).ToARGB()),
597 DlColor(Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF).ToARGB()),
598 DlColor(Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF).ToARGB())};
599 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
600
601 std::array<std::shared_ptr<DlColorSource>, 3> color_sources = {
602 DlColorSource::MakeLinear({0, 0}, {100, 100}, stops.size(), colors.data(),
603 stops.data(), DlTileMode::kDecal),
604 DlColorSource::MakeRadial({100, 100}, 100, stops.size(), colors.data(),
605 stops.data(), DlTileMode::kDecal),
606 DlColorSource::MakeSweep({100, 100}, 45, 135, stops.size(), colors.data(),
607 stops.data(), DlTileMode::kDecal),
608 };
609
610 DisplayListBuilder builder;
611 DlPaint paint;
612 paint.setColor(DlColor::kWhite());
613 builder.DrawRect(SkRect::MakeLTRB(0, 0, 605, 205), paint);
614 for (int i = 0; i < 3; i++) {
615 builder.Save();
616 builder.Translate(i * 200.0f, 0);
617 paint.setColorSource(color_sources[i]);
618 builder.DrawRect(SkRect::MakeLTRB(0, 0, 200, 200), paint);
619 builder.Restore();
620 }
621 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
622 }

References paint.

## ◆ TEST_P() [49/456]

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

Definition at line 35 of file aiks_dl_opacity_unittests.cc.

35 {
36 DisplayListBuilder builder;
37
38 DlPaint red;
39 red.setColor(DlColor::kRed());
40 DlPaint green;
41 green.setColor(DlColor::kGreen().modulateOpacity(0.5));
42 DlPaint blue;
43 blue.setColor(DlColor::kBlue());
44
45 DlPaint alpha;
46 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
47
48 builder.SaveLayer(nullptr, &alpha);
49 builder.DrawRect(SkRect::MakeXYWH(0, 0, 100, 100), red);
50 builder.DrawRect(SkRect::MakeXYWH(200, 200, 100, 100), green);
51 builder.DrawRect(SkRect::MakeXYWH(400, 400, 100, 100), blue);
52 builder.Restore();
53
54 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
55 }

## ◆ TEST_P() [50/456]

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

Definition at line 57 of file aiks_dl_opacity_unittests.cc.

57 {
58 DisplayListBuilder builder;
59
60 DlPaint red;
61 red.setColor(DlColor::kRed());
62
63 DlPaint alpha;
64 alpha.setColor(DlColor::kRed().modulateOpacity(0.7));
65
66 // Create a saveLayer that will forward its opacity to another
67 // saveLayer, to verify that we correctly distribute opacity.
68 SkRect bounds = SkRect::MakeLTRB(0, 0, 500, 500);
69 builder.SaveLayer(&bounds, &alpha);
70 builder.SaveLayer(&bounds, &alpha);
71 builder.DrawRect(SkRect::MakeXYWH(0, 0, 400, 400), red);
72 builder.DrawRect(SkRect::MakeXYWH(0, 0, 450, 450), red);
73 builder.Restore();
74 builder.Restore();
75
76 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
77 }

## ◆ TEST_P() [51/456]

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

Definition at line 84 of file aiks_unittests.cc.

84 {
85 Canvas canvas;
86 Paint paint;
87 auto image = std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
88 paint.color = Color::Red();
89 canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint);
90 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
91 }

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

## ◆ TEST_P() [52/456]

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

Definition at line 219 of file aiks_unittests.cc.

219 {
220 Canvas canvas;
221 Paint paint;
222 auto image = std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
223 Size image_half_size = Size(image->GetSize()) * 0.5;
224
225 // Render the bottom right quarter of the source image in a stretched rect.
226 auto source_rect = Rect::MakeSize(image_half_size);
227 source_rect = source_rect.Shift(Point(image_half_size));
228
229 canvas.DrawImageRect(image, source_rect, Rect::MakeXYWH(100, 100, 600, 600),
230 paint);
231 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
232 }

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

## ◆ TEST_P() [53/456]

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

Definition at line 93 of file aiks_unittests.cc.

93 {
94 Canvas canvas;
95 Paint paint;
96 auto image = std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
97 paint.color = Color::Red();
98 paint.color_filter =
99 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Yellow());
100 paint.invert_colors = true;
101
102 canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint);
103 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
104 }

References impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSourceOver, impeller::ColorFilter::MakeBlend(), impeller::TPoint< Scalar >::MakeXY(), paint, impeller::Color::Red(), and impeller::Color::Yellow().

## ◆ TEST_P() [54/456]

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

Definition at line 730 of file aiks_unittests.cc.

730 {
731 Canvas canvas;
732 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
733
734 ASSERT_TRUE(RenderTextInCanvasSkia(
735 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
736 "HomemadeApple.ttf"));
737 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
738 }

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

## ◆ TEST_P() [55/456]

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

Definition at line 67 of file aiks_dl_gradient_unittests.cc.

67 {
68 CanRenderLinearGradient(this, DlTileMode::kClamp);
69 }

## ◆ TEST_P() [56/456]

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

Definition at line 76 of file aiks_dl_gradient_unittests.cc.

76 {
77 CanRenderLinearGradient(this, DlTileMode::kDecal);
78 }

## ◆ TEST_P() [57/456]

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

Definition at line 80 of file aiks_dl_gradient_unittests.cc.

80 {
81 DisplayListBuilder builder;
82 Point scale = GetContentScale();
83 builder.Scale(scale.x, scale.y);
84 DlPaint paint;
85 builder.Translate(100.0f, 0);
86
87 std::vector<DlColor> colors = {
88 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
89 DlColor(Color{0.1294, 0.5882, 0.9529, 0.0}.ToARGB())};
90 std::vector<Scalar> stops = {0.0, 1.0};
91
92 paint.setColorSource(DlColorSource::MakeLinear(
93 {0, 0}, {200, 200}, 2, colors.data(), stops.data(), DlTileMode::kDecal));
94 // Overlay the gradient with 25% green. This should appear as the entire
95 // rectangle being drawn with 25% green, including the border area outside the
96 // decal gradient.
97 paint.setColorFilter(DlBlendColorFilter::Make(DlColor::kGreen().withAlpha(64),
98 DlBlendMode::kSrcOver));
99 paint.setColor(DlColor::kWhite());
100 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
101 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
102 }

References paint, scale, and impeller::Color::ToARGB().

## ◆ TEST_P() [58/456]

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

Definition at line 256 of file aiks_dl_gradient_unittests.cc.

256 {
257 CanRenderLinearGradientManyColors(this, DlTileMode::kClamp);
258 }

## ◆ TEST_P() [59/456]

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

Definition at line 265 of file aiks_dl_gradient_unittests.cc.

265 {
266 CanRenderLinearGradientManyColors(this, DlTileMode::kDecal);
267 }

## ◆ TEST_P() [60/456]

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

Definition at line 262 of file aiks_dl_gradient_unittests.cc.

262 {
263 CanRenderLinearGradientManyColors(this, DlTileMode::kMirror);
264 }

## ◆ TEST_P() [61/456]

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

Definition at line 259 of file aiks_dl_gradient_unittests.cc.

259 {
260 CanRenderLinearGradientManyColors(this, DlTileMode::kRepeat);
261 }

## ◆ TEST_P() [62/456]

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

Definition at line 300 of file aiks_dl_gradient_unittests.cc.

300 {
301 auto callback = [&]() -> sk_sp<DisplayList> {
302 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
303 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
304 DlTileMode::kMirror, DlTileMode::kDecal};
305
306 static int selected_tile_mode = 0;
307 static Matrix matrix;
308 if (AiksTest::ImGuiBegin("Controls", nullptr,
309 ImGuiWindowFlags_AlwaysAutoResize)) {
310 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
311 sizeof(tile_mode_names) / sizeof(char*));
312 std::string label = "##1";
313 for (int i = 0; i < 4; i++) {
314 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
315 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
316 label[2]++;
317 }
318 ImGui::End();
319 }
320
321 DisplayListBuilder builder;
322 DlPaint paint;
323 builder.Translate(100.0, 100.0);
324 auto tile_mode = tile_modes[selected_tile_mode];
325
326 std::vector<DlColor> colors = {
327 DlColor(Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}.ToARGB()),
328 DlColor(Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}.ToARGB()),
329 DlColor(Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
330 DlColor(Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}.ToARGB()),
331 DlColor(Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}.ToARGB()),
332 DlColor(Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
333 DlColor(Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}.ToARGB())};
334 std::vector<Scalar> stops = {
335 0.0, 2.0 / 62.0, 4.0 / 62.0, 8.0 / 62.0, 16.0 / 62.0, 32.0 / 62.0, 1.0,
336 };
337
338 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {200, 200},
339 stops.size(), colors.data(),
340 stops.data(), tile_mode));
341
342 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
343 return builder.Build();
344 };
345 ASSERT_TRUE(OpenPlaygroundHere(callback));
346 }

References paint, impeller::Color::ToARGB(), and impeller::Matrix::vec.

## ◆ TEST_P() [63/456]

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

Definition at line 348 of file aiks_dl_gradient_unittests.cc.

348 {
349 DisplayListBuilder builder;
350
351 std::vector<DlColor> colors = {
352 DlColor::kRed(), DlColor::kWhite(), DlColor::kRed(), DlColor::kWhite(),
353 DlColor::kRed(), DlColor::kWhite(), DlColor::kRed(), DlColor::kWhite(),
354 DlColor::kRed(), DlColor::kWhite(), DlColor::kRed()};
355 std::vector<Scalar> stops = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5,
356 0.6, 0.7, 0.8, 0.9, 1.0};
357
358 DlPaint paint;
359 paint.setColor(DlColor::kWhite());
360 paint.setColorSource(DlColorSource::MakeLinear(
361 {200, 200}, {400, 400}, stops.size(), colors.data(), stops.data(),
362 DlTileMode::kClamp));
363 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 20));
364
365 builder.DrawCircle({300, 300}, 200, paint);
366 builder.DrawRect(SkRect::MakeLTRB(100, 300, 500, 600), paint);
367
368 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
369 }

References paint.

## ◆ TEST_P() [64/456]

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

Definition at line 73 of file aiks_dl_gradient_unittests.cc.

73 {
74 CanRenderLinearGradient(this, DlTileMode::kMirror);
75 }

## ◆ TEST_P() [65/456]

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

Definition at line 70 of file aiks_dl_gradient_unittests.cc.

70 {
71 CanRenderLinearGradient(this, DlTileMode::kRepeat);
72 }

## ◆ TEST_P() [66/456]

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

Definition at line 296 of file aiks_dl_gradient_unittests.cc.

296 {
297 CanRenderLinearGradientWayManyColors(this, DlTileMode::kClamp);
298 }

## ◆ TEST_P() [67/456]

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

Definition at line 120 of file aiks_dl_gradient_unittests.cc.

120 {
121 CanRenderLinearGradientWithDithering(this);
122 }

References CanRenderLinearGradientWithDithering().

## ◆ TEST_P() [68/456]

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

Definition at line 215 of file aiks_dl_gradient_unittests.cc.

215 {
216 CanRenderLinearGradientWithOverlappingStops(this, DlTileMode::kClamp);
217 }

## ◆ TEST_P() [69/456]

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

Definition at line 23 of file aiks_blur_unittests.cc.

23 {
24 Canvas canvas;
25 canvas.DrawCircle({400, 400}, 300,
26 {.color = Color::Green(),
27 .mask_blur_descriptor = Paint::MaskBlurDescriptor{
28 .style = FilterContents::BlurStyle::kNormal,
29 .sigma = Sigma(99999),
30 }});
31 canvas.Restore();
32
33 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
34 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::FilterContents::kNormal, impeller::Canvas::Restore(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [70/456]

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

Definition at line 27 of file aiks_dl_clip_unittests.cc.

27 {
28 DisplayListBuilder builder;
29 DlPaint paint;
30 paint.setColor(DlColor::kFuchsia());
31
32 builder.Save();
33 builder.ClipPath(CreateCircle(200, 400, 300));
34 builder.Restore();
35 builder.ClipPath(CreateCircle(600, 400, 300));
36 builder.ClipPath(CreateCircle(400, 600, 300));
37 builder.DrawRect(SkRect::MakeXYWH(200, 200, 400, 400), paint);
38
39 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
40 }

References paint.

## ◆ TEST_P() [71/456]

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

Definition at line 407 of file aiks_path_unittests.cc.

407 {
408 Canvas canvas;
409
410 Paint paint;
411 paint.color = Color::Red();
412
413 PathBuilder::RoundingRadii radii;
414 radii.top_left = {50, 50};
415 radii.top_right = {50, 50};
416 radii.bottom_right = {50, 50};
417 radii.bottom_left = {50, 50};
418
419 const Scalar kTriangleHeight = 100;
420 canvas.Translate(Vector2(200, 200));
421 // Form a path similar to the Material drop slider value indicator. Both
422 // shapes should render identically side-by-side.
423 {
424 auto path =
425 PathBuilder{}
426 .MoveTo({0, kTriangleHeight})
427 .LineTo({-kTriangleHeight / 2.0f, 0})
428 .LineTo({kTriangleHeight / 2.0f, 0})
429 .Close()
430 .AddRoundedRect(
431 Rect::MakeXYWH(-kTriangleHeight / 2.0f, -kTriangleHeight / 2.0f,
432 kTriangleHeight, kTriangleHeight),
433 radii)
434 .TakePath();
435
436 canvas.DrawPath(path, paint);
437 }
438 canvas.Translate(Vector2(100, 0));
439 {
440 auto path =
441 PathBuilder{}
442 .MoveTo({0, kTriangleHeight})
443 .LineTo({-kTriangleHeight / 2.0f, 0})
444 .LineTo({0, -10})
445 .LineTo({kTriangleHeight / 2.0f, 0})
446 .Close()
447 .AddRoundedRect(
448 Rect::MakeXYWH(-kTriangleHeight / 2.0f, -kTriangleHeight / 2.0f,
449 kTriangleHeight, kTriangleHeight),
450 radii)
451 .TakePath();
452
453 canvas.DrawPath(path, paint);
454 }
455
456 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
457 }

References impeller::PathBuilder::RoundingRadii::bottom_left, impeller::PathBuilder::RoundingRadii::bottom_right, impeller::Close(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::LineTo(), impeller::TRect< Scalar >::MakeXYWH(), impeller::PathBuilder::MoveTo(), paint, impeller::Color::Red(), impeller::PathBuilder::RoundingRadii::top_left, impeller::PathBuilder::RoundingRadii::top_right, and impeller::Canvas::Translate().

## ◆ TEST_P() [72/456]

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

Definition at line 94 of file aiks_path_unittests.cc.

94 {
95 Canvas canvas;
96
97 Paint paint;
98 paint.color = Color::Red();
99 paint.style = Paint::Style::kStroke;
100 paint.stroke_cap = Cap::kRound;
101 paint.stroke_width = 50;
102
103 // Should draw a diagonal pill shape. If flat on either end, the stroke is
104 // rendering wrong.
105 PathBuilder builder;
106 builder.MoveTo({250, 250});
107 builder.QuadraticCurveTo({100, 100}, {250, 250});
108
109 canvas.DrawPath(builder.TakePath(), paint);
110 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
111 }

References impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::kRound, impeller::Paint::kStroke, impeller::PathBuilder::MoveTo(), paint, impeller::PathBuilder::QuadraticCurveTo(), impeller::Color::Red(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [73/456]

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

Definition at line 371 of file aiks_dl_gradient_unittests.cc.

371 {
372 auto callback = [&]() -> sk_sp<DisplayList> {
373 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
374 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
375 DlTileMode::kMirror, DlTileMode::kDecal};
376
377 static int selected_tile_mode = 0;
378 static Matrix matrix;
379 if (AiksTest::ImGuiBegin("Controls", nullptr,
380 ImGuiWindowFlags_AlwaysAutoResize)) {
381 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
382 sizeof(tile_mode_names) / sizeof(char*));
383 std::string label = "##1";
384 for (int i = 0; i < 4; i++) {
385 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
386 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
387 label[2]++;
388 }
389 ImGui::End();
390 }
391
392 DisplayListBuilder builder;
393 DlPaint paint;
394 builder.Translate(100.0, 100.0);
395 auto tile_mode = tile_modes[selected_tile_mode];
396
397 std::vector<DlColor> colors = {
398 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
399 DlColor(Color{0.1294, 0.5882, 0.9529, 1.0}.ToARGB())};
400 std::vector<Scalar> stops = {0.0, 1.0};
401
402 paint.setColorSource(DlColorSource::MakeRadial(
403 {100, 100}, 100, 2, colors.data(), stops.data(), tile_mode));
404
405 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
406 return builder.Build();
407 };
408 ASSERT_TRUE(OpenPlaygroundHere(callback));
409 }

References paint, impeller::Color::ToARGB(), and impeller::Matrix::vec.

## ◆ TEST_P() [74/456]

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

Definition at line 411 of file aiks_dl_gradient_unittests.cc.

411 {
412 auto callback = [&]() -> sk_sp<DisplayList> {
413 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
414 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
415 DlTileMode::kMirror, DlTileMode::kDecal};
416
417 static int selected_tile_mode = 0;
418 static Matrix matrix = {
419 1, 0, 0, 0, //
420 0, 1, 0, 0, //
421 0, 0, 1, 0, //
422 0, 0, 0, 1 //
423 };
424 if (AiksTest::ImGuiBegin("Controls", nullptr,
425 ImGuiWindowFlags_AlwaysAutoResize)) {
426 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
427 sizeof(tile_mode_names) / sizeof(char*));
428 std::string label = "##1";
429 for (int i = 0; i < 4; i++) {
430 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
431 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
432 label[2]++;
433 }
434 ImGui::End();
435 }
436
437 DisplayListBuilder builder;
438 DlPaint paint;
439 builder.Translate(100.0, 100.0);
440 auto tile_mode = tile_modes[selected_tile_mode];
441
442 std::vector<DlColor> colors = {
443 DlColor(Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}.ToARGB()),
444 DlColor(Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}.ToARGB()),
445 DlColor(Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
446 DlColor(Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}.ToARGB()),
447 DlColor(Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}.ToARGB()),
448 DlColor(Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
449 DlColor(Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}.ToARGB())};
450 std::vector<Scalar> stops = {
451 0.0,
452 (1.0 / 6.0) * 1,
453 (1.0 / 6.0) * 2,
454 (1.0 / 6.0) * 3,
455 (1.0 / 6.0) * 4,
456 (1.0 / 6.0) * 5,
457 1.0,
458 };
459
460 paint.setColorSource(DlColorSource::MakeRadial(
461 {100, 100}, 100, stops.size(), colors.data(), stops.data(), tile_mode));
462
463 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
464 return builder.Build();
465 };
466 ASSERT_TRUE(OpenPlaygroundHere(callback));
467 }

References paint, impeller::Color::ToARGB(), and impeller::Matrix::vec.

## ◆ TEST_P() [75/456]

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

Definition at line 140 of file aiks_dl_gradient_unittests.cc.

140 {
141 CanRenderRadialGradientWithDithering(this);
142 }

References CanRenderRadialGradientWithDithering().

## ◆ TEST_P() [76/456]

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

Definition at line 521 of file aiks_unittests.cc.

521 {
522 Canvas canvas;
523
524 Paint paint;
525 paint.color = Color::Red();
526
527 PathBuilder::RoundingRadii radii;
528 radii.top_left = {50, 25};
529 radii.top_right = {25, 50};
530 radii.bottom_right = {50, 25};
531 radii.bottom_left = {25, 50};
532
533 auto path = PathBuilder{}
534 .AddRoundedRect(Rect::MakeXYWH(100, 100, 500, 500), radii)
535 .TakePath();
536
537 canvas.DrawPath(path, paint);
538
539 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
540 }

References impeller::PathBuilder::AddRoundedRect(), impeller::PathBuilder::RoundingRadii::bottom_left, impeller::PathBuilder::RoundingRadii::bottom_right, impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Color::Red(), impeller::PathBuilder::TakePath(), impeller::PathBuilder::RoundingRadii::top_left, and impeller::PathBuilder::RoundingRadii::top_right.

## ◆ TEST_P() [77/456]

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

Definition at line 234 of file aiks_unittests.cc.

234 {
235 Canvas canvas;
236 canvas.Scale(GetContentScale());
237 Paint paint;
238
239 paint.color = Color::White();
240 canvas.DrawPaint(paint);
241
242 auto draw = [&canvas](const Paint& paint, Scalar x, Scalar y) {
243 canvas.Save();
244 canvas.Translate({x, y});
245 {
246 canvas.Save();
247 canvas.ClipRect(Rect::MakeLTRB(50, 50, 150, 150));
248 canvas.DrawPaint(paint);
249 canvas.Restore();
250 }
251 {
252 canvas.Save();
253 canvas.ClipOval(Rect::MakeLTRB(200, 50, 300, 150));
254 canvas.DrawPaint(paint);
255 canvas.Restore();
256 }
257 {
258 canvas.Save();
259 canvas.ClipRRect(Rect::MakeLTRB(50, 200, 150, 300), {20, 20});
260 canvas.DrawPaint(paint);
261 canvas.Restore();
262 }
263 {
264 canvas.Save();
265 canvas.ClipRRect(Rect::MakeLTRB(200, 230, 300, 270), {20, 20});
266 canvas.DrawPaint(paint);
267 canvas.Restore();
268 }
269 {
270 canvas.Save();
271 canvas.ClipRRect(Rect::MakeLTRB(230, 200, 270, 300), {20, 20});
272 canvas.DrawPaint(paint);
273 canvas.Restore();
274 }
275 canvas.Restore();
276 };
277
278 paint.color = Color::Blue();
279 draw(paint, 0, 0);
280
281 std::vector<Color> gradient_colors = {
282 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
283 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
284 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
285 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
286 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
287 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
288 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
289 std::vector<Scalar> stops = {
290 0.0,
291 (1.0 / 6.0) * 1,
292 (1.0 / 6.0) * 2,
293 (1.0 / 6.0) * 3,
294 (1.0 / 6.0) * 4,
295 (1.0 / 6.0) * 5,
296 1.0,
297 };
298 auto texture = CreateTextureForFixture("airplane.jpg",
299 /*enable_mipmapping=*/true);
300
301 paint.color_source = ColorSource::MakeRadialGradient(
302 {500, 600}, 75, std::move(gradient_colors), std::move(stops),
303 Entity::TileMode::kMirror, {});
304 draw(paint, 0, 300);
305
306 paint.color_source = ColorSource::MakeImage(
307 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
308 Matrix::MakeTranslation({0, 0}));
309 draw(paint, 300, 0);
310
311 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
312 }

References impeller::Color::Blue(), impeller::Canvas::ClipOval(), impeller::Canvas::ClipRect(), impeller::Canvas::ClipRRect(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::ColorSource::MakeImage(), impeller::TRect< Scalar >::MakeLTRB(), impeller::ColorSource::MakeRadialGradient(), impeller::Matrix::MakeTranslation(), paint, impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::Scale(), impeller::Canvas::Translate(), and impeller::Color::White().

## ◆ TEST_P() [78/456]

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

Definition at line 641 of file aiks_unittests.cc.

641 {
642 Canvas canvas;
643 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
644 ASSERT_TRUE(RenderTextInCanvasSkia(
645 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
646 "Roboto-Regular.ttf",
647 {
648 .stroke = true,
649 }));
650 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
651 }

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

## ◆ TEST_P() [79/456]

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

Definition at line 63 of file aiks_path_unittests.cc.

63 {
64 Canvas canvas;
65
66 Paint paint;
67 paint.color = Color::Red();
68 paint.style = Paint::Style::kStroke;
69 paint.stroke_width = 200;
70
71 Rect rect = Rect::MakeXYWH(100, 100, 200, 200);
72 PathBuilder builder;
73 builder.AddArc(rect, Degrees(0), Degrees(90), false);
74
75 canvas.DrawPath(builder.TakePath(), paint);
76 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
77 }

References impeller::PathBuilder::AddArc(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::kStroke, impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Color::Red(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [80/456]

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

Definition at line 79 of file aiks_path_unittests.cc.

79 {
80 Canvas canvas;
81
82 Paint paint;
83 paint.color = Color::Red();
84 paint.style = Paint::Style::kStroke;
85 paint.stroke_width = 20;
86
87 PathBuilder builder;
88 builder.AddCubicCurve({0, 200}, {50, 400}, {350, 0}, {400, 200});
89
90 canvas.DrawPath(builder.TakePath(), paint);
91 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
92 }

References impeller::PathBuilder::AddCubicCurve(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::kStroke, paint, impeller::Color::Red(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [81/456]

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

Definition at line 20 of file aiks_path_unittests.cc.

20 {
21 Canvas canvas;
22 Paint paint;
23 paint.color = Color::Red();
24 paint.stroke_width = 20.0;
25 paint.style = Paint::Style::kStroke;
26 canvas.DrawPath(PathBuilder{}.AddLine({200, 100}, {800, 100}).TakePath(),
27 paint);
28 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
29 }

References impeller::PathBuilder::AddLine(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::kStroke, paint, and impeller::Color::Red().

## ◆ TEST_P() [82/456]

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

Definition at line 490 of file aiks_dl_gradient_unittests.cc.

490 {
491 CanRenderSweepGradient(this, DlTileMode::kClamp);
492 }

## ◆ TEST_P() [83/456]

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

Definition at line 499 of file aiks_dl_gradient_unittests.cc.

499 {
500 CanRenderSweepGradient(this, DlTileMode::kDecal);
501 }

## ◆ TEST_P() [84/456]

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

Definition at line 537 of file aiks_dl_gradient_unittests.cc.

537 {
538 CanRenderSweepGradientManyColors(this, DlTileMode::kClamp);
539 }

## ◆ TEST_P() [85/456]

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

Definition at line 546 of file aiks_dl_gradient_unittests.cc.

546 {
547 CanRenderSweepGradientManyColors(this, DlTileMode::kDecal);
548 }

## ◆ TEST_P() [86/456]

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

Definition at line 543 of file aiks_dl_gradient_unittests.cc.

543 {
544 CanRenderSweepGradientManyColors(this, DlTileMode::kMirror);
545 }

## ◆ TEST_P() [87/456]

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

Definition at line 540 of file aiks_dl_gradient_unittests.cc.

540 {
541 CanRenderSweepGradientManyColors(this, DlTileMode::kRepeat);
542 }

## ◆ TEST_P() [88/456]

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

Definition at line 496 of file aiks_dl_gradient_unittests.cc.

496 {
497 CanRenderSweepGradient(this, DlTileMode::kMirror);
498 }

## ◆ TEST_P() [89/456]

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

Definition at line 493 of file aiks_dl_gradient_unittests.cc.

493 {
494 CanRenderSweepGradient(this, DlTileMode::kRepeat);
495 }

## ◆ TEST_P() [90/456]

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

Definition at line 163 of file aiks_dl_gradient_unittests.cc.

163 {
164 CanRenderSweepGradientWithDithering(this);
165 }

References CanRenderSweepGradientWithDithering().

## ◆ TEST_P() [91/456]

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

Definition at line 620 of file aiks_unittests.cc.

620 {
621 Canvas canvas;
622 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
623 ASSERT_TRUE(RenderTextInCanvasSkia(
624 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
625 "Roboto-Regular.ttf"));
626 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
627 }

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

## ◆ TEST_P() [92/456]

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

Definition at line 673 of file aiks_unittests.cc.

673 {
674 Canvas canvas;
675 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
676 ASSERT_TRUE(RenderTextInCanvasSTB(
677 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
678 "Roboto-Regular.ttf"));
679
680 SetTypographerContext(TypographerContextSTB::Make());
681 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
682 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::TypographerContextSTB::Make(), and RenderTextInCanvasSTB().

## ◆ TEST_P() [93/456]

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

Definition at line 663 of file aiks_unittests.cc.

663 {
664 Canvas canvas;
665 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
666 canvas.Scale({2.625, 2.625, 1});
667 ASSERT_TRUE(RenderTextInCanvasSkia(
668 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
669 "Roboto-Regular.ttf"));
670 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
671 }

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

## ◆ TEST_P() [94/456]

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

Definition at line 653 of file aiks_unittests.cc.

653 {
654 Canvas canvas;
655 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
656 canvas.Scale({0.5, 0.5, 1});
657 ASSERT_TRUE(RenderTextInCanvasSkia(
658 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
659 "Roboto-Regular.ttf"));
660 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
661 }

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

## ◆ TEST_P() [95/456]

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

Definition at line 629 of file aiks_unittests.cc.

629 {
630 Canvas canvas;
631 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
632
633 canvas.Translate({1000, 0, 0});
634 canvas.Scale({-1, 1, 1});
635 ASSERT_TRUE(RenderTextInCanvasSkia(
636 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
637 "Roboto-Regular.ttf"));
638 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
639 }

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

## ◆ TEST_P() [96/456]

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

Definition at line 779 of file aiks_unittests.cc.

779 {
780 Canvas canvas;
781 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
782
783 canvas.Translate({100, 100});
784 canvas.Scale(Vector2{0.5, 0.5});
785
786 // Blend the layer with the parent pass using kClear to expose the coverage.
787 canvas.SaveLayer({.blend_mode = BlendMode::kClear});
788 ASSERT_TRUE(RenderTextInCanvasSkia(
789 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
790 "Roboto-Regular.ttf"));
791 canvas.Restore();
792
793 // Render the text again over the cleared coverage rect.
794 ASSERT_TRUE(RenderTextInCanvasSkia(
795 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
796 "Roboto-Regular.ttf"));
797
798 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
799 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kClear, RenderTextInCanvasSkia(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [97/456]

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

Definition at line 801 of file aiks_unittests.cc.

801 {
802 Canvas canvas;
803 canvas.Translate({200, 150});
804
805 // Construct the text blob.
806 auto mapping = flutter::testing::OpenFixtureAsSkData("wtf.otf");
807 ASSERT_NE(mapping, nullptr);
808
809 Scalar font_size = 80;
810 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
811 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
812
813 Paint text_paint;
814 text_paint.color = Color::Blue().WithAlpha(0.8);
815
816 struct {
817 Point position;
818 const char* text;
819 } text[] = {{Point(0, 0), "0F0F0F0"},
820 {Point(1, 2), "789"},
821 {Point(1, 3), "456"},
822 {Point(1, 4), "123"},
823 {Point(0, 6), "0F0F0F0"}};
824 for (auto& t : text) {
825 canvas.Save();
826 canvas.Translate(t.position * Point(font_size * 2, font_size * 1.1));
827 {
828 auto blob = SkTextBlob::MakeFromString(t.text, sk_font);
829 ASSERT_NE(blob, nullptr);
830 auto frame = MakeTextFrameFromTextBlobSkia(blob);
831 canvas.DrawTextFrame(frame, Point(), text_paint);
832 }
833 canvas.Restore();
834 }
835
836 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
837 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawTextFrame(), impeller::Canvas::EndRecordingAsPicture(), font_size, impeller::MakeTextFrameFromTextBlobSkia(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::Translate(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [98/456]

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

Definition at line 2860 of file aiks_unittests.cc.

2860 {
2861 // Verifies that text scales are clamped to work around
2862 // https://github.com/flutter/flutter/issues/136112 .
2863
2864 Canvas canvas;
2865 Paint save_paint;
2866 canvas.SaveLayer(save_paint);
2867 canvas.Transform(Matrix(2000, 0, 0, 0, //
2868 0, 2000, 0, 0, //
2869 0, 0, -1, 9000, //
2870 0, 0, -1, 7000 //
2871 ));
2872
2873 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), canvas, "Hello world",
2874 "Roboto-Regular.ttf"));
2875 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2876 }

References impeller::Canvas::EndRecordingAsPicture(), RenderTextInCanvasSkia(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Transform().

## ◆ TEST_P() [99/456]

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

Definition at line 41 of file aiks_path_unittests.cc.

41 {
42 Canvas canvas;
43 Paint paint;
44 paint.color = Color::Red();
45 paint.stroke_width = 100.0;
46 paint.style = Paint::Style::kStroke;
47 canvas.DrawPath(PathBuilder{}.AddCircle({100, 100}, 50).TakePath(), paint);
48 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
49 }

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

## ◆ TEST_P() [100/456]

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

Definition at line 51 of file aiks_path_unittests.cc.

51 {
52 Canvas canvas;
53 Paint paint;
54 paint.color = Color::Red();
55 // Impeller doesn't support hairlines yet, but size this guarantees
56 // the smallest possible stroke width.
57 paint.stroke_width = 0.01;
58 paint.style = Paint::Style::kStroke;
59 canvas.DrawPath(PathBuilder{}.AddCircle({100, 100}, 50).TakePath(), paint);
60 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
61 }

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

## ◆ TEST_P() [101/456]

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

Definition at line 198 of file aiks_unittests.cc.

198 {
199 CanRenderTiledTexture(this, Entity::TileMode::kClamp);
200 }

References impeller::Entity::kClamp.

## ◆ TEST_P() [102/456]

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

Definition at line 214 of file aiks_unittests.cc.

214 {
215 CanRenderTiledTexture(this, Entity::TileMode::kClamp,
216 Matrix::MakeTranslation({172.f, 172.f, 0.f}));
217 }

References impeller::Entity::kClamp, and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [103/456]

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

Definition at line 210 of file aiks_unittests.cc.

210 {
211 CanRenderTiledTexture(this, Entity::TileMode::kDecal);
212 }

References impeller::Entity::kDecal.

## ◆ TEST_P() [104/456]

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

Definition at line 206 of file aiks_unittests.cc.

206 {
207 CanRenderTiledTexture(this, Entity::TileMode::kMirror);
208 }

References impeller::Entity::kMirror.

## ◆ TEST_P() [105/456]

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

Definition at line 202 of file aiks_unittests.cc.

202 {
203 CanRenderTiledTexture(this, Entity::TileMode::kRepeat);
204 }

References impeller::Entity::kRepeat.

## ◆ TEST_P() [106/456]

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 2120 of file aiks_unittests.cc.

2120 {
2121 Canvas canvas;
2122 canvas.DrawPaint({.color = Color::Red()});
2123
2124 // Draw two overlapping subpixel circles.
2125 canvas.SaveLayer({});
2126 canvas.DrawCircle({100, 100}, 0.1, {.color = Color::Yellow()});
2127 canvas.Restore();
2128 canvas.SaveLayer({});
2129 canvas.DrawCircle({100, 100}, 0.1, {.color = Color::Yellow()});
2130 canvas.Restore();
2131
2132 canvas.DrawPaint({.color = Color::Green()});
2133
2134 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2135 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::Yellow().

## ◆ TEST_P() [107/456]

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

Definition at line 78 of file aiks_dl_clip_unittests.cc.

78 {
79 DisplayListBuilder builder;
80
81 // Cover the whole canvas with red.
82 DlPaint paint;
83 paint.setColor(DlColor::kRed());
84 builder.DrawPaint(paint);
85
86 builder.Save();
87
88 // Append two clips, the second resulting in empty coverage.
89 builder.ClipRect(SkRect::MakeXYWH(100, 100, 100, 100));
90 builder.ClipRect(SkRect::MakeXYWH(300, 300, 100, 100));
91
92 // Restore to no clips.
93 builder.Restore();
94
95 // Replace the whole canvas with green.
96 paint.setColor(DlColor::kGreen());
97 builder.DrawPaint(paint);
98
99 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
100 }

References paint.

## ◆ TEST_P() [108/456]

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

Definition at line 314 of file aiks_unittests.cc.

314 {
315 Canvas canvas;
316
317 Paint red;
318 red.color = Color::Red();
319
320 Paint alpha;
321 alpha.color = Color::Red().WithAlpha(0.5);
322
323 canvas.SaveLayer(alpha);
324
325 canvas.DrawCircle({125, 125}, 125, red);
326
327 canvas.Restore();
328
329 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
330 }

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() [109/456]

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

Definition at line 57 of file aiks_unittests.cc.

57 {
58 Canvas canvas;
59 ASSERT_EQ(canvas.GetSaveCount(), 1u);
60 ASSERT_EQ(canvas.Restore(), false);
61
62 canvas.Translate(Size{100, 100});
63 canvas.Save();
64 ASSERT_EQ(canvas.GetSaveCount(), 2u);
65 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(),
66 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
67 ASSERT_TRUE(canvas.Restore());
68 ASSERT_EQ(canvas.GetSaveCount(), 1u);
69 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(),
70 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
71 }

References ASSERT_MATRIX_NEAR, impeller::Canvas::GetCurrentTransform(), impeller::Canvas::GetSaveCount(), impeller::Matrix::MakeTranslation(), impeller::Canvas::Restore(), impeller::Canvas::Save(), and impeller::Canvas::Translate().

## ◆ TEST_P() [110/456]

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

Definition at line 48 of file aiks_unittests.cc.

48 {
49 Canvas canvas;
50 Matrix identity;
51 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(), identity);
52 canvas.Translate(Size{100, 100});
53 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(),
54 Matrix::MakeTranslation({100.0, 100.0, 0.0}));
55 }

References ASSERT_MATRIX_NEAR, impeller::Canvas::GetCurrentTransform(), impeller::Matrix::MakeTranslation(), and impeller::Canvas::Translate().

## ◆ TEST_P() [111/456]

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

Definition at line 356 of file aiks_blend_unittests.cc.

356 {
357 Canvas canvas;
358 Paint white;
359 white.color = Color::Blue();
360 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600.0, 600.0), white);
361
362 Paint clear;
363 clear.blend_mode = BlendMode::kClear;
364
365 canvas.DrawCircle(Point::MakeXY(300.0, 300.0), 200.0, clear);
366 }

References impeller::Paint::blend_mode, impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawRect(), impeller::kClear, impeller::TPoint< Scalar >::MakeXY(), and impeller::TRect< Scalar >::MakeXYWH().

## ◆ TEST_P() [112/456]

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

Definition at line 183 of file aiks_blur_unittests.cc.

183 {
184 Canvas canvas;
185 Paint white;
186 white.color = Color::Blue();
187 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600.0, 600.0), white);
188
189 Paint clear;
190 clear.blend_mode = BlendMode::kClear;
191 clear.mask_blur_descriptor = Paint::MaskBlurDescriptor{
192 .style = FilterContents::BlurStyle::kNormal,
193 .sigma = Sigma(20),
194 };
195
196 canvas.DrawCircle(Point::MakeXY(300.0, 300.0), 200.0, clear);
197
198 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
199 }

References impeller::Paint::blend_mode, impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kClear, impeller::FilterContents::kNormal, impeller::TPoint< Scalar >::MakeXY(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Paint::mask_blur_descriptor, and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [113/456]

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

Definition at line 1745 of file aiks_unittests.cc.

1745 {
1746 Canvas canvas;
1747 canvas.SaveLayer({}, std::nullopt,
1748 ImageFilter::MakeBlur(Sigma(3), Sigma(3),
1749 FilterContents::BlurStyle::kNormal,
1750 Entity::TileMode::kClamp));
1751 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
1752 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
1753 .blend_mode = BlendMode::kSourceOver});
1754 canvas.Restore();
1755
1756 Picture picture = canvas.EndRecordingAsPicture();
1757
1758 std::optional<Color> actual_color;
1759 bool found_subpass = false;
1760 picture.pass->IterateAllElements([&](EntityPass::Element& element) -> bool {
1761 if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
1762 actual_color = subpass->get()->GetClearColor();
1763 found_subpass = true;
1764 }
1765 // Fail if the first element isn't a subpass.
1766 return true;
1767 });
1768
1769 EXPECT_TRUE(found_subpass);
1770 EXPECT_FALSE(actual_color.has_value());
1771 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSource, impeller::kSourceOver, impeller::ImageFilter::MakeBlur(), impeller::Picture::pass, impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [114/456]

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

Definition at line 2549 of file aiks_unittests.cc.

2549 {
2550 SetWindowSize({400, 400});
2551 Canvas canvas;
2552 canvas.Scale(GetContentScale());
2553 canvas.DrawRect(Rect::MakeLTRB(200, 200, 300, 300), {.color = Color::Red()});
2554 canvas.SaveLayer({
2555 .image_filter = std::make_shared<MatrixImageFilter>(
2556 Matrix::MakeScale({2, 2, 1}), SamplerDescriptor{}),
2557 });
2558 // Draw a rectangle that would fully cover the parent pass size, but not
2559 // the subpass that it is rendered in.
2560 canvas.DrawRect(Rect::MakeLTRB(0, 0, 400, 400), {.color = Color::Green()});
2561 // Draw a bigger rectangle to force the subpass to be bigger.
2562 canvas.DrawRect(Rect::MakeLTRB(0, 0, 800, 800), {.color = Color::Red()});
2563 canvas.Restore();
2564
2565 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2566 }

References impeller::Color::Green(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Color::Red(), and impeller::Canvas::Scale().

## ◆ TEST_P() [115/456]

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

Definition at line 168 of file aiks_blur_unittests.cc.

168 {
169 Canvas canvas;
170 canvas.Translate(Point(0, -400));
171 Paint paint;
172 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
173 .style = FilterContents::BlurStyle::kNormal,
174 .sigma = Radius{120 * 3},
175 };
176 paint.color = Color::Red();
177 PathBuilder builder{};
178 builder.AddRect(Rect::MakeLTRB(0, 0, 800, 800));
179 canvas.DrawPath(builder.TakePath(), paint);
180 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
181 }

References impeller::PathBuilder::AddRect(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::FilterContents::kNormal, impeller::TRect< Scalar >::MakeLTRB(), paint, impeller::Color::Red(), impeller::Paint::MaskBlurDescriptor::style, and impeller::Canvas::Translate().

## ◆ TEST_P() [116/456]

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

Definition at line 146 of file aiks_blur_unittests.cc.

146 {
147 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
148 static PlaygroundPoint playground_point(Point(400, 400), 20,
149 Color::Green());
150 auto point = DrawPlaygroundPoint(playground_point);
151
152 Canvas canvas;
153 canvas.Translate(point - Point(400, 400));
154 Paint paint;
155 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
156 .style = FilterContents::BlurStyle::kNormal,
157 .sigma = Radius{120 * 3},
158 };
159 paint.color = Color::Red();
160 PathBuilder builder{};
161 builder.AddRect(Rect::MakeLTRB(0, 0, 800, 800));
162 canvas.DrawPath(builder.TakePath(), paint);
163 return canvas.EndRecordingAsPicture();
164 };
165 ASSERT_TRUE(OpenPlaygroundHere(callback));
166 }

References impeller::PathBuilder::AddRect(), impeller::Canvas::DrawPath(), impeller::DrawPlaygroundPoint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::FilterContents::kNormal, impeller::TRect< Scalar >::MakeLTRB(), paint, impeller::Color::Red(), impeller::Paint::MaskBlurDescriptor::style, and impeller::Canvas::Translate().

## ◆ TEST_P() [117/456]

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

Definition at line 1721 of file aiks_unittests.cc.

1721 {
1722 Canvas canvas(Rect::MakeXYWH(0, 0, 100, 100));
1723 canvas.ClipRect(Rect::MakeXYWH(0, 0, 100, 100));
1724 canvas.ClipRect(Rect::MakeXYWH(-100, -100, 300, 300));
1725 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
1726 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
1727 .blend_mode = BlendMode::kSourceOver});
1728
1729 Picture picture = canvas.EndRecordingAsPicture();
1730 auto expected = Color::Red().Blend(Color::CornflowerBlue().WithAlpha(0.75),
1731 BlendMode::kSourceOver);
1732 ASSERT_EQ(picture.pass->GetClearColor(), expected);
1733
1734 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
1735 std::shared_ptr<Context> real_context = GetContext();
1736 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
1737 AiksContext renderer(mock_context, nullptr);
1738 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
1739
1740 ASSERT_EQ(spy->render_passes_.size(), 1llu);
1741 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
1742 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
1743 }

References impeller::Color::Blend(), impeller::Canvas::ClipRect(), impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSource, impeller::kSourceOver, impeller::TRect< Scalar >::MakeXYWH(), impeller::Picture::pass, impeller::Color::Red(), impeller::Picture::ToImage(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [118/456]

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

Definition at line 102 of file aiks_dl_clip_unittests.cc.

102 {
103 std::array<DlColor, 5> colors = {DlColor::kWhite(), DlColor::kBlack(),
104 DlColor::kSkyBlue(), DlColor::kRed(),
105 DlColor::kYellow()};
106 DisplayListBuilder builder;
107 DlPaint paint;
108
109 builder.Translate(300, 300);
110 for (int i = 0; i < 15; i++) {
111 builder.Scale(0.8, 0.8);
112
113 paint.setColor(colors[i % colors.size()]);
114 builder.ClipPath(CreateCircle(0, 0, 300));
115 builder.DrawRect(SkRect::MakeXYWH(-300, -300, 600, 600), paint);
116 }
117 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
118 }

References paint.

## ◆ TEST_P() [119/456]

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

Definition at line 1773 of file aiks_unittests.cc.

1773 {
1774 Canvas canvas;
1775 canvas.DrawPaint(
1776 {.color = Color::Yellow(), .blend_mode = BlendMode::kSource});
1777 canvas.SaveLayer({.blend_mode = BlendMode::kMultiply});
1778 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
1779 .blend_mode = BlendMode::kSourceOver});
1780
1781 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1782 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kMultiply, impeller::kSource, impeller::kSourceOver, impeller::Canvas::SaveLayer(), impeller::Color::WithAlpha(), and impeller::Color::Yellow().

## ◆ TEST_P() [120/456]

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

Definition at line 1784 of file aiks_unittests.cc.

1784 {
1785 // Bug: https://github.com/flutter/flutter/issues/131576
1786 Canvas canvas;
1787 canvas.DrawPaint(
1788 {.color = Color::Yellow(), .blend_mode = BlendMode::kSource});
1789 canvas.SaveLayer({}, {},
1790 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
1791 FilterContents::BlurStyle::kNormal,
1792 Entity::TileMode::kDecal));
1793 canvas.DrawPaint(
1794 {.color = Color::CornflowerBlue(), .blend_mode = BlendMode::kSourceOver});
1795
1796 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1797 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSource, impeller::kSourceOver, impeller::ImageFilter::MakeBlur(), impeller::Canvas::SaveLayer(), and impeller::Color::Yellow().

## ◆ TEST_P() [121/456]

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

Definition at line 1799 of file aiks_unittests.cc.

1799 {
1800 Canvas canvas;
1801
1802 canvas.SaveLayer({
1803 .color_filter =
1804 ColorFilter::MakeMatrix({.array =
1805 {
1806 -1.0, 0, 0, 1.0, 0, //
1807 0, -1.0, 0, 1.0, 0, //
1808 0, 0, -1.0, 1.0, 0, //
1809 1.0, 1.0, 1.0, 1.0, 0 //
1810 }}),
1811 });
1812
1813 canvas.Translate({500, 300, 0});
1814 canvas.Rotate(Radians(2 * kPi / 3));
1815 canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
1816
1817 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1818 }

References impeller::Color::Blue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kPi, impeller::ColorFilter::MakeMatrix(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Rotate(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Translate().

## ◆ TEST_P() [122/456]

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 205 of file aiks_blend_unittests.cc.

205 {
206 // Compare with https://fiddle.skia.org/c/@BlendModes
207
208 BlendModeSelection blend_modes = GetBlendModeSelection();
209
210 auto draw_color_wheel = [](Canvas& canvas) {
211 /// color_wheel_sampler: r=0 -> fuchsia, r=2pi/3 -> yellow, r=4pi/3 ->
212 /// cyan domain: r >= 0 (because modulo used is non euclidean)
213 auto color_wheel_sampler = [](Radians r) {
214 Scalar x = r.radians / k2Pi + 1;
215
216 // https://www.desmos.com/calculator/6nhjelyoaj
217 auto color_cycle = [](Scalar x) {
218 Scalar cycle = std::fmod(x, 6.0f);
219 return std::max(0.0f, std::min(1.0f, 2 - std::abs(2 - cycle)));
220 };
221 return Color(color_cycle(6 * x + 1), //
222 color_cycle(6 * x - 1), //
223 color_cycle(6 * x - 3), //
224 1);
225 };
226
227 Paint paint;
228 paint.blend_mode = BlendMode::kSourceOver;
229
230 // Draw a fancy color wheel for the backdrop.
231 // https://www.desmos.com/calculator/xw7kafthwd
232 const int max_dist = 900;
233 for (int i = 0; i <= 900; i++) {
234 Radians r(kPhi / k2Pi * i);
235 Scalar distance = r.radians / std::powf(4.12, 0.0026 * r.radians);
236 Scalar normalized_distance = static_cast<Scalar>(i) / max_dist;
237
238 paint.color =
239 color_wheel_sampler(r).WithAlpha(1.0f - normalized_distance);
240 Point position(distance * std::sin(r.radians),
241 -distance * std::cos(r.radians));
242
243 canvas.DrawCircle(position, 9 + normalized_distance * 3, paint);
244 }
245 };
246
247 std::shared_ptr<Image> color_wheel_image;
248 Matrix color_wheel_transform;
249
250 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
251 // UI state.
252 static bool cache_the_wheel = true;
253 static int current_blend_index = 3;
254 static float dst_alpha = 1;
255 static float src_alpha = 1;
256 static Color color0 = Color::Red();
257 static Color color1 = Color::Green();
258 static Color color2 = Color::Blue();
259
260 if (AiksTest::ImGuiBegin("Controls", nullptr,
261 ImGuiWindowFlags_AlwaysAutoResize)) {
262 ImGui::Checkbox("Cache the wheel", &cache_the_wheel);
263 ImGui::ListBox("Blending mode", &current_blend_index,
264 blend_modes.blend_mode_names.data(),
265 blend_modes.blend_mode_names.size());
266 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
267 ImGui::ColorEdit4("Color A", reinterpret_cast<float*>(&color0));
268 ImGui::ColorEdit4("Color B", reinterpret_cast<float*>(&color1));
269 ImGui::ColorEdit4("Color C", reinterpret_cast<float*>(&color2));
270 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
271 ImGui::End();
272 }
273
274 static Point content_scale;
275 Point new_content_scale = GetContentScale();
276
277 if (!cache_the_wheel || new_content_scale != content_scale) {
278 content_scale = new_content_scale;
279
280 // Render the color wheel to an image.
281
282 Canvas canvas;
283 canvas.Scale(content_scale);
284
285 canvas.Translate(Vector2(500, 400));
286 canvas.Scale(Vector2(3, 3));
287
288 draw_color_wheel(canvas);
289 auto color_wheel_picture = canvas.EndRecordingAsPicture();
290 auto snapshot = color_wheel_picture.Snapshot(renderer);
291 if (!snapshot.has_value() || !snapshot->texture) {
292 return std::nullopt;
293 }
294 color_wheel_image = std::make_shared<Image>(snapshot->texture);
295 color_wheel_transform = snapshot->transform;
296 }
297
298 Canvas canvas;
299
300 // Blit the color wheel backdrop to the screen with managed alpha.
301 canvas.SaveLayer({.color = Color::White().WithAlpha(dst_alpha),
302 .blend_mode = BlendMode::kSource});
303 {
304 canvas.DrawPaint({.color = Color::White()});
305
306 canvas.Save();
307 canvas.Transform(color_wheel_transform);
308 canvas.DrawImage(color_wheel_image, Point(), Paint());
309 canvas.Restore();
310 }
311 canvas.Restore();
312
313 canvas.Scale(content_scale);
314 canvas.Translate(Vector2(500, 400));
315 canvas.Scale(Vector2(3, 3));
316
317 // Draw 3 circles to a subpass and blend it in.
318 canvas.SaveLayer(
319 {.color = Color::White().WithAlpha(src_alpha),
320 .blend_mode = blend_modes.blend_mode_values[current_blend_index]});
321 {
322 Paint paint;
323 paint.blend_mode = BlendMode::kPlus;
324 const Scalar x = std::sin(k2Pi / 3);
325 const Scalar y = -std::cos(k2Pi / 3);
326 paint.color = color0;
327 canvas.DrawCircle(Point(-x, y) * 45, 65, paint);
328 paint.color = color1;
329 canvas.DrawCircle(Point(0, -1) * 45, 65, paint);
330 paint.color = color2;
331 canvas.DrawCircle(Point(x, y) * 45, 65, paint);
332 }
333 canvas.Restore();
334
335 return canvas.EndRecordingAsPicture();
336 };
337
338 ASSERT_TRUE(OpenPlaygroundHere(callback));
339 }

References impeller::testing::BlendModeSelection::blend_mode_names, impeller::testing::BlendModeSelection::blend_mode_values, impeller::Color::Blue(), impeller::saturated::distance, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawImage(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), GetBlendModeSelection(), impeller::Color::Green(), impeller::AiksPlayground::ImGuiBegin(), impeller::k2Pi, impeller::kPhi, impeller::kPlus, impeller::kSource, impeller::kSourceOver, paint, impeller::Radians::radians, impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), impeller::Picture::Snapshot(), impeller::Canvas::Transform(), impeller::Canvas::Translate(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [123/456]

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

Definition at line 404 of file aiks_unittests.cc.

404 {
405 Canvas canvas;
406
407 // Render a texture directly.
408 {
409 Paint paint;
410 auto image =
411 std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
412 paint.color = Color::Red();
413
414 canvas.Save();
415 canvas.Translate({100, 200, 0});
416 canvas.Scale(Vector2{0.5, 0.5});
417 canvas.DrawImage(image, Point::MakeXY(100.0, 100.0), paint);
418 canvas.Restore();
419 }
420
421 // Render an offscreen rendered texture.
422 {
423 Paint red;
424 red.color = Color::Red();
425 Paint green;
426 green.color = Color::Green();
427 Paint blue;
428 blue.color = Color::Blue();
429
430 Paint alpha;
431 alpha.color = Color::Red().WithAlpha(0.5);
432
433 canvas.SaveLayer(alpha);
434
435 canvas.DrawRect(Rect::MakeXYWH(000, 000, 100, 100), red);
436 canvas.DrawRect(Rect::MakeXYWH(020, 020, 100, 100), green);
437 canvas.DrawRect(Rect::MakeXYWH(040, 040, 100, 100), blue);
438
439 canvas.Restore();
440 }
441
442 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
443 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::Canvas::DrawImage(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::TPoint< Scalar >::MakeXY(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::Save(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), impeller::Canvas::Translate(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [124/456]

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

Definition at line 2658 of file aiks_unittests.cc.

2658 {
2659 Canvas canvas; // Depth 1 (base pass)
2660 canvas.DrawRRect(Rect::MakeLTRB(0, 0, 100, 100), {10, 10}, {}); // Depth 2
2661 canvas.Save();
2662 {
2663 canvas.ClipRRect(Rect::MakeLTRB(0, 0, 50, 50), {10, 10}, {}); // Depth 4
2664 canvas.SaveLayer({}); // Depth 4
2665 {
2666 canvas.DrawRRect(Rect::MakeLTRB(0, 0, 50, 50), {10, 10}, {}); // Depth 3
2667 }
2668 canvas.Restore(); // Restore the savelayer.
2669 }
2670 canvas.Restore(); // Depth 5 -- this will no longer append a restore entity
2671 // once we switch to the clip depth approach.
2672
2673 auto picture = canvas.EndRecordingAsPicture();
2674
2675 std::vector<uint32_t> expected = {
2676 2, // DrawRRect
2677 4, // ClipRRect -- Has a depth value equal to the max depth of all the
2678 // content it affect. In this case, the SaveLayer and all
2679 // its contents are affected.
2680 4, // SaveLayer -- The SaveLayer is drawn to the parent pass after its
2681 // contents are rendered, so it should have a depth value
2682 // greater than all its contents.
2683 3, // DrawRRect
2684 5, // Restore (no longer necessary when clipping on the depth buffer)
2685 };
2686
2687 std::vector<uint32_t> actual;
2688
2689 picture.pass->IterateAllElements([&](EntityPass::Element& element) -> bool {
2690 if (auto* subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
2691 actual.push_back(subpass->get()->GetClipDepth());
2692 }
2693 if (Entity* entity = std::get_if<Entity>(&element)) {
2694 actual.push_back(entity->GetClipDepth());
2695 }
2696 return true;
2697 });
2698
2699 ASSERT_EQ(actual.size(), expected.size());
2700 for (size_t i = 0; i < expected.size(); i++) {
2701 EXPECT_EQ(expected[i], actual[i]) << "Index: " << i;
2702 }
2703 }

References impeller::Canvas::ClipRRect(), impeller::Canvas::DrawRRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Picture::pass, impeller::Canvas::Restore(), impeller::Canvas::Save(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [125/456]

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

Definition at line 1377 of file aiks_unittests.cc.

1377 {
1378 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
1379 Canvas canvas;
1380 canvas.Scale(GetContentScale());
1381
1382 Paint alpha;
1383 alpha.color = Color::Red().WithAlpha(0.5);
1384
1385 auto current = Point{25, 25};
1386 const auto offset = Point{25, 25};
1387 const auto size = Size(100, 100);
1388
1389 static PlaygroundPoint point_a(Point(40, 40), 10, Color::White());
1390 static PlaygroundPoint point_b(Point(160, 160), 10, Color::White());
1391 auto [b0, b1] = DrawPlaygroundLine(point_a, point_b);
1392 auto bounds = Rect::MakeLTRB(b0.x, b0.y, b1.x, b1.y);
1393
1394 canvas.DrawRect(bounds, Paint{.color = Color::Yellow(),
1395 .stroke_width = 5.0f,
1396 .style = Paint::Style::kStroke});
1397
1398 canvas.SaveLayer(alpha, bounds);
1399
1400 canvas.DrawRect(Rect::MakeOriginSize(current, size),
1401 Paint{.color = Color::Red()});
1402 canvas.DrawRect(Rect::MakeOriginSize(current += offset, size),
1403 Paint{.color = Color::Green()});
1404 canvas.DrawRect(Rect::MakeOriginSize(current += offset, size),
1405 Paint{.color = Color::Blue()});
1406
1407 canvas.Restore();
1408
1409 return canvas.EndRecordingAsPicture();
1410 };
1411
1412 ASSERT_TRUE(OpenPlaygroundHere(callback));
1413 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::DrawPlaygroundLine(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Paint::kStroke, impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeOriginSize(), offset, impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), impeller::Color::White(), impeller::Color::WithAlpha(), and impeller::Color::Yellow().

## ◆ TEST_P() [126/456]

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

Definition at line 94 of file aiks_blend_unittests.cc.

94 {
95 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
96 Color{0.1294, 0.5882, 0.9529, 1.0}};
97 std::vector<Scalar> stops = {0.0, 1.0};
98
99 Paint paint = {
100 .color_source = ColorSource::MakeLinearGradient(
101 {0, 0}, {100, 100}, std::move(colors), std::move(stops),
102 Entity::TileMode::kRepeat, Matrix::MakeScale(Vector3(0.3, 0.3, 0.3))),
103 .blend_mode = BlendMode::kLighten,
104 };
105
106 Canvas canvas;
107 canvas.DrawPaint({.color = Color::Blue()});
108 canvas.Scale(Vector2(2, 2));
109 canvas.ClipRect(Rect::MakeLTRB(0, 0, 200, 200));
110 canvas.DrawCircle({100, 100}, 100, paint);
111 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
112 }

References impeller::Color::Blue(), impeller::Canvas::ClipRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kLighten, impeller::Entity::kRepeat, impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), paint, and impeller::Canvas::Scale().

## ◆ TEST_P() [127/456]

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

Definition at line 129 of file aiks_dl_atlas_unittests.cc.

129 {
130 DisplayListBuilder builder;
131 // Draws the image as four squares stiched together.
132 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
133
134 builder.Scale(0.25, 0.25);
135 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
136 /*colors=*/nullptr, /*count=*/4, DlBlendMode::kModulate,
137 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
138
139 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
140 }

## ◆ TEST_P() [128/456]

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

Definition at line 52 of file aiks_dl_atlas_unittests.cc.

52 {
53 DisplayListBuilder builder;
54 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
55
56 builder.Scale(GetContentScale().x, GetContentScale().y);
57 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
58 /*colors=*/nullptr, /*count=*/4, DlBlendMode::kSrcOver,
59 DlImageSampling::kNearestNeighbor, nullptr);
60
61 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
62 }

## ◆ TEST_P() [129/456]

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

Definition at line 112 of file aiks_dl_atlas_unittests.cc.

112 {
113 auto atlas = DlImageImpeller::Make(CreateTextureForFixture("bay_bridge.jpg"));
114 auto size = atlas->impeller_texture()->GetSize();
115 std::vector<SkRect> texture_coordinates = {
116 SkRect::MakeLTRB(0, 0, size.width, size.height)};
117 std::vector<SkRSXform> transforms = {MakeTranslation(0, 0)};
118
119 DisplayListBuilder builder;
120 builder.Scale(GetContentScale().x, GetContentScale().y);
121 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
122 /*colors=*/nullptr, /*count=*/1, DlBlendMode::kSrcOver,
123 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
124
125 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
126 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [130/456]

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

Definition at line 158 of file aiks_dl_atlas_unittests.cc.

158 {
159 DisplayListBuilder builder;
160 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
161 PixelFormat::kB10G10R10A10XR);
162
163 // Draws the image as four squares stiched together.
164 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
165 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
166 DlColor::kBlue(), DlColor::kYellow()};
167
168 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
169 colors.data(), /*count=*/4, DlBlendMode::kPlus,
170 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
171
172 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
173 }

References impeller::kB10G10R10A10XR.

## ◆ TEST_P() [131/456]

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

Definition at line 64 of file aiks_dl_atlas_unittests.cc.

64 {
65 DisplayListBuilder builder;
66 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
67
68 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
69 DlColor::kBlue(), DlColor::kYellow()};
70
71 builder.Scale(GetContentScale().x, GetContentScale().y);
72 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
73 colors.data(), /*count=*/4, DlBlendMode::kModulate,
74 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
75
76 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
77 }

## ◆ TEST_P() [132/456]

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

Definition at line 143 of file aiks_dl_atlas_unittests.cc.

143 {
144 DisplayListBuilder builder;
145 // Draws the image as four squares stiched together.
146 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
147 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
148 DlColor::kBlue(), DlColor::kYellow()};
149
150 builder.Scale(0.25, 0.25);
151 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
152 colors.data(), /*count=*/4, DlBlendMode::kModulate,
153 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
154
155 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
156 }

## ◆ TEST_P() [133/456]

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

Definition at line 79 of file aiks_dl_atlas_unittests.cc.

79 {
80 DisplayListBuilder builder;
81 // Draws the image as four squares stiched together.
82 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
83
84 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kGreen(),
85 DlColor::kBlue(), DlColor::kYellow()};
86
87 builder.Scale(GetContentScale().x, GetContentScale().y);
88 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
89 colors.data(), /*count=*/4, DlBlendMode::kSrcATop,
90 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr);
91
92 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
93 }

## ◆ TEST_P() [134/456]

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

Definition at line 95 of file aiks_dl_atlas_unittests.cc.

95 {
96 DisplayListBuilder builder;
97 // Draws the image as four squares stiched together slightly
98 // opaque
99 auto [texture_coordinates, transforms, atlas] = CreateTestData(this);
100
101 DlPaint paint;
102 paint.setAlpha(128);
103 builder.Scale(GetContentScale().x, GetContentScale().y);
104 builder.DrawAtlas(atlas, transforms.data(), texture_coordinates.data(),
105 /*colors=*/nullptr, 4, DlBlendMode::kSrcOver,
106 DlImageSampling::kNearestNeighbor, /*cullRect=*/nullptr,
107 &paint);
108
109 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
110 }

References paint.

## ◆ TEST_P() [135/456]

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

Definition at line 256 of file aiks_path_unittests.cc.

256 {
257 Canvas canvas;
258 canvas.Scale(GetContentScale());
259 Paint paint;
260 paint.color = Color::Blue();
261 paint.stroke_width = 10;
262
263 auto draw = [&canvas](Paint& paint) {
264 for (auto cap : {Cap::kButt, Cap::kSquare, Cap::kRound}) {
265 paint.stroke_cap = cap;
266 Point origin = {100, 100};
267 Point p0 = {50, 0};
268 Point p1 = {150, 0};
269 canvas.DrawLine({150, 100}, {250, 100}, paint);
270 for (int d = 15; d < 90; d += 15) {
271 Matrix m = Matrix::MakeRotationZ(Degrees(d));
272 canvas.DrawLine(origin + m * p0, origin + m * p1, paint);
273 }
274 canvas.DrawLine({100, 150}, {100, 250}, paint);
275 canvas.DrawCircle({origin}, 35, paint);
276
277 canvas.DrawLine({250, 250}, {250, 250}, paint);
278
279 canvas.Translate({250, 0});
280 }
281 canvas.Translate({-750, 250});
282 };
283
284 std::vector<Color> colors = {
285 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
286 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
287 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
288 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
289 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
290 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
291 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
292 std::vector<Scalar> stops = {
293 0.0,
294 (1.0 / 6.0) * 1,
295 (1.0 / 6.0) * 2,
296 (1.0 / 6.0) * 3,
297 (1.0 / 6.0) * 4,
298 (1.0 / 6.0) * 5,
299 1.0,
300 };
301
302 auto texture = CreateTextureForFixture("airplane.jpg",
303 /*enable_mipmapping=*/true);
304
305 draw(paint);
306
307 paint.color_source = ColorSource::MakeRadialGradient(
308 {100, 100}, 200, std::move(colors), std::move(stops),
309 Entity::TileMode::kMirror, {});
310 draw(paint);
311
312 paint.color_source = ColorSource::MakeImage(
313 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
314 Matrix::MakeTranslation({-150, 75}));
315 draw(paint);
316
317 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
318 }

References impeller::Color::Blue(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawLine(), impeller::Canvas::EndRecordingAsPicture(), impeller::kButt, impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::kRound, impeller::kSquare, impeller::ColorSource::MakeImage(), impeller::ColorSource::MakeRadialGradient(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeTranslation(), paint, impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [136/456]

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

Definition at line 19 of file aiks_dl_opacity_unittests.cc.

19 {
20 DisplayListBuilder builder;
21
22 DlPaint green;
23 green.setColor(DlColor::kGreen().modulateOpacity(0.5));
24
25 DlPaint alpha;
26 alpha.setColor(DlColor::kRed().modulateOpacity(0.5));
27
28 builder.SaveLayer(nullptr, &alpha);
29 builder.DrawRect(SkRect::MakeXYWH(0, 0, 100, 100), green);
30 builder.Restore();
31
32 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
33 }

## ◆ TEST_P() [137/456]

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

Definition at line 1594 of file aiks_unittests.cc.

1594 {
1595 Canvas canvas;
1596 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
1597 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
1598 .blend_mode = BlendMode::kSourceOver});
1599
1600 Picture picture = canvas.EndRecordingAsPicture();
1601 auto expected = Color::Red().Blend(Color::CornflowerBlue().WithAlpha(0.75),
1602 BlendMode::kSourceOver);
1603 ASSERT_EQ(picture.pass->GetClearColor(), expected);
1604
1605 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
1606 std::shared_ptr<Context> real_context = GetContext();
1607 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
1608 AiksContext renderer(mock_context, nullptr);
1609 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
1610
1611 ASSERT_EQ(spy->render_passes_.size(), 1llu);
1612 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
1613 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
1614 }

References impeller::Color::Blend(), impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSource, impeller::kSourceOver, impeller::Picture::pass, impeller::Color::Red(), impeller::Picture::ToImage(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [138/456]

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

Definition at line 2214 of file aiks_unittests.cc.

2214 {
2215 auto runtime_stages = OpenAssetAsRuntimeStage("gradient.frag.iplr");
2216 auto runtime_stage =
2217 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2218 ASSERT_TRUE(runtime_stage);
2219 ASSERT_TRUE(runtime_stage->IsDirty());
2220
2221 struct FragUniforms {
2222 Size size;
2223 } frag_uniforms = {.size = Size::MakeWH(400, 400)};
2224 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2225 uniform_data->resize(sizeof(FragUniforms));
2226 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2227
2228 std::vector<RuntimeEffectContents::TextureInput> texture_inputs;
2229
2230 Paint paint;
2231 paint.color_source = ColorSource::MakeRuntimeEffect(
2232 runtime_stage, uniform_data, texture_inputs);
2233
2234 Canvas canvas;
2235 canvas.Save();
2236 canvas.Scale(GetContentScale());
2237 canvas.DrawPaint(paint);
2238 canvas.Restore();
2239
2240 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2241 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::ColorSource::MakeRuntimeEffect(), impeller::TSize< Scalar >::MakeWH(), paint, impeller::PlaygroundBackendToRuntimeStageBackend(), impeller::Canvas::Restore(), impeller::Canvas::Save(), and impeller::Canvas::Scale().

## ◆ TEST_P() [139/456]

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

Definition at line 77 of file aiks_blend_unittests.cc.

77 {
78 Paint filtered = {
79 .color = Color::Black(),
80 .mask_blur_descriptor =
81 Paint::MaskBlurDescriptor{
82 .style = FilterContents::BlurStyle::kNormal,
83 .sigma = Sigma(60),
84 },
85 };
86
87 Canvas canvas;
88 canvas.DrawPaint({.color = Color::White()});
89 canvas.DrawCircle({300, 300}, 200, filtered);
90 canvas.DrawPaint({.color = Color::Green(), .blend_mode = BlendMode::kScreen});
91 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
92 }

References impeller::Color::Black(), impeller::Paint::color, impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::FilterContents::kNormal, impeller::kScreen, impeller::Paint::MaskBlurDescriptor::style, and impeller::Color::White().

## ◆ TEST_P() [140/456]

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

Definition at line 1641 of file aiks_unittests.cc.

1641 {
1642 Canvas canvas;
1643 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
1644 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
1645 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
1646 {.color = Color::CornflowerBlue().WithAlpha(0.75),
1647 .blend_mode = BlendMode::kSourceOver});
1648
1649 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
1650 Picture picture = canvas.EndRecordingAsPicture();
1651 std::shared_ptr<Context> real_context = GetContext();
1652 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
1653 AiksContext renderer(mock_context, nullptr);
1654 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
1655
1656 ASSERT_EQ(spy->render_passes_.size(), 1llu);
1657 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
1658 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
1659 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSource, impeller::kSourceOver, impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Picture::ToImage(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [141/456]

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

Definition at line 1701 of file aiks_unittests.cc.

1701 {
1702 Canvas canvas;
1703 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
1704 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
1705 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
1706 {.color = Color::CornflowerBlue().WithAlpha(0.75),
1707 .blend_mode = BlendMode::kSourceOver});
1708
1709 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
1710 Picture picture = canvas.EndRecordingAsPicture();
1711 std::shared_ptr<Context> real_context = GetContext();
1712 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
1713 AiksContext renderer(mock_context, nullptr);
1714 std::shared_ptr<Image> image = picture.ToImage(renderer, {301, 301});
1715
1716 ASSERT_EQ(spy->render_passes_.size(), 1llu);
1717 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
1718 ASSERT_EQ(render_pass->GetCommands().size(), 2llu);
1719 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSource, impeller::kSourceOver, impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Picture::ToImage(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [142/456]

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

Definition at line 1681 of file aiks_unittests.cc.

1681 {
1682 Canvas canvas;
1683 canvas.Translate(Vector3(150.0, 150.0, 0.0));
1684 canvas.Rotate(Degrees(45.0));
1685 canvas.Translate(Vector3(-150.0, -150.0, 0.0));
1686 canvas.DrawRect(Rect::MakeXYWH(0, 0, 300, 300),
1687 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
1688
1689 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
1690 Picture picture = canvas.EndRecordingAsPicture();
1691 std::shared_ptr<Context> real_context = GetContext();
1692 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
1693 AiksContext renderer(mock_context, nullptr);
1694 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
1695
1696 ASSERT_EQ(spy->render_passes_.size(), 1llu);
1697 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
1698 ASSERT_EQ(render_pass->GetCommands().size(), 1llu);
1699 }

References impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSource, impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Rotate(), impeller::Picture::ToImage(), and impeller::Canvas::Translate().

## ◆ TEST_P() [143/456]

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

Definition at line 1661 of file aiks_unittests.cc.

1661 {
1662 Canvas canvas;
1663 canvas.DrawRRect(Rect::MakeXYWH(0, 0, 300, 300), {5.0, 5.0},
1664 {.color = Color::Red(), .blend_mode = BlendMode::kSource});
1665 canvas.DrawRRect(Rect::MakeXYWH(0, 0, 300, 300), {5.0, 5.0},
1666 {.color = Color::CornflowerBlue().WithAlpha(0.75),
1667 .blend_mode = BlendMode::kSourceOver});
1668
1669 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
1670 Picture picture = canvas.EndRecordingAsPicture();
1671 std::shared_ptr<Context> real_context = GetContext();
1672 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
1673 AiksContext renderer(mock_context, nullptr);
1674 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
1675
1676 ASSERT_EQ(spy->render_passes_.size(), 1llu);
1677 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
1678 ASSERT_EQ(render_pass->GetCommands().size(), 2llu);
1679 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawRRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSource, impeller::kSourceOver, impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Picture::ToImage(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [144/456]

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

Definition at line 320 of file aiks_path_unittests.cc.

320 {
321 Canvas canvas;
322 Paint paint;
323 paint.color = Color::Red();
324 paint.style = Paint::Style::kStroke;
325 paint.stroke_width = 10;
326
327 canvas.Translate({100, 100});
328 canvas.DrawPath(
329 PathBuilder{}.AddRect(Rect::MakeSize(Size{100, 100})).TakePath(),
330 {paint});
331
332 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
333 }

References impeller::PathBuilder::AddRect(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Paint::kStroke, impeller::TRect< Scalar >::MakeSize(), paint, impeller::Color::Red(), and impeller::Canvas::Translate().

## ◆ TEST_P() [145/456]

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

Definition at line 335 of file aiks_path_unittests.cc.

335 {
336 Canvas canvas;
337 Paint paint;
338 paint.color = Color::Red();
339 paint.style = Paint::Style::kStroke;
340 paint.stroke_width = 10;
341 paint.stroke_join = Join::kBevel;
342
343 canvas.Translate({100, 100});
344 canvas.DrawPath(
345 PathBuilder{}.AddRect(Rect::MakeSize(Size{100, 100})).TakePath(),
346 {paint});
347
348 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
349 }

References impeller::PathBuilder::AddRect(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::kBevel, impeller::Paint::kStroke, impeller::TRect< Scalar >::MakeSize(), paint, impeller::Color::Red(), and impeller::Canvas::Translate().

## ◆ TEST_P() [146/456]

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

Definition at line 2401 of file aiks_unittests.cc.

2401 {
2402 Canvas canvas;
2403 canvas.Transform(Matrix(1.0, 0.0, 0.0, 0.0, //
2404 0.0, 1.0, 0.0, 0.0, //
2405 0.0, 0.0, 1.0, 0.01, //
2406 0.0, 0.0, 0.0, 1.0) * //
2407 Matrix::MakeRotationY({Degrees{10}}));
2408
2409 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), canvas, "Hello world",
2410 "Roboto-Regular.ttf"));
2411
2412 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2413 }

References impeller::Canvas::EndRecordingAsPicture(), impeller::Matrix::MakeRotationY(), RenderTextInCanvasSkia(), and impeller::Canvas::Transform().

## ◆ TEST_P() [147/456]

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

Definition at line 2415 of file aiks_unittests.cc.

2415 {
2416 Canvas canvas;
2417 Paint save_paint;
2418 canvas.SaveLayer(save_paint);
2419 canvas.Transform(Matrix(1.0, 0.0, 0.0, 0.0, //
2420 0.0, 1.0, 0.0, 0.0, //
2421 0.0, 0.0, 1.0, 0.01, //
2422 0.0, 0.0, 0.0, 1.0) * //
2423 Matrix::MakeRotationY({Degrees{10}}));
2424
2425 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), canvas, "Hello world",
2426 "Roboto-Regular.ttf"));
2427 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2428 }

References impeller::Canvas::EndRecordingAsPicture(), impeller::Matrix::MakeRotationY(), RenderTextInCanvasSkia(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Transform().

## ◆ TEST_P() [148/456]

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

Definition at line 259 of file aiks_dl_vertices_unittests.cc.

259 {
260 auto texture = CreateTextureForFixture("embarcadero.jpg");
261 auto dl_image = DlImageImpeller::Make(texture);
262 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
263 SkPoint::Make(200, 100),
264 SkPoint::Make(300, 300)};
265 std::vector<SkPoint> texture_coordinates = {
266 SkPoint::Make(0, 0), SkPoint::Make(100, 200), SkPoint::Make(200, 100)};
267
268 auto vertices = flutter::DlVertices::Make(
269 flutter::DlVertexMode::kTriangles, 3, positions.data(),
270 texture_coordinates.data(), /*colors=*/nullptr);
271
272 flutter::DisplayListBuilder builder;
273 flutter::DlPaint paint;
274
275 auto image_source = flutter::DlImageColorSource(
276 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
277
278 paint.setColorSource(&image_source);
279 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
280
281 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
282 }

References impeller::DlImageImpeller::Make(), and paint.

## ◆ TEST_P() [149/456]

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

Definition at line 284 of file aiks_dl_vertices_unittests.cc.

285 {
286 auto texture = CreateTextureForFixture("embarcadero.jpg");
287 auto dl_image = DlImageImpeller::Make(texture);
288 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
289 SkPoint::Make(200, 100),
290 SkPoint::Make(300, 300)};
291 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
292 flutter::DlColor::kGreen(),
293 flutter::DlColor::kWhite()};
294 std::vector<SkPoint> texture_coordinates = {
295 SkPoint::Make(0, 0), SkPoint::Make(100, 200), SkPoint::Make(200, 100)};
296
297 auto vertices = flutter::DlVertices::Make(
298 flutter::DlVertexMode::kTriangles, 3, positions.data(),
299 texture_coordinates.data(), colors.data());
300
301 flutter::DisplayListBuilder builder;
302 flutter::DlPaint paint;
303
304 auto image_source = flutter::DlImageColorSource(
305 dl_image, flutter::DlTileMode::kRepeat, flutter::DlTileMode::kRepeat);
306
307 paint.setColorSource(&image_source);
308 builder.DrawVertices(vertices, flutter::DlBlendMode::kModulate, paint);
309
310 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
311 }

References impeller::DlImageImpeller::Make(), and paint.

## ◆ TEST_P() [150/456]

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

Definition at line 204 of file aiks_dl_vertices_unittests.cc.

204 {
205 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
206 SkPoint::Make(200, 100),
207 SkPoint::Make(300, 300)};
208
209 auto vertices = flutter::DlVertices::Make(
210 flutter::DlVertexMode::kTriangles, 3, positions.data(),
211 /*texture_coordinates=*/nullptr, /*colors=*/nullptr);
212
213 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
214 flutter::DlColor::kRed()};
215 const float stops[2] = {0.0, 1.0};
216
217 auto linear = flutter::DlColorSource::MakeLinear(
218 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
219 flutter::DlTileMode::kRepeat);
220
221 flutter::DisplayListBuilder builder;
222 flutter::DlPaint paint;
223
224 paint.setColorSource(linear);
225 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
226
227 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
228 }

References paint.

## ◆ TEST_P() [151/456]

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

Definition at line 230 of file aiks_dl_vertices_unittests.cc.

230 {
231 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
232 SkPoint::Make(200, 100),
233 SkPoint::Make(300, 300)};
234 std::vector<SkPoint> texture_coordinates = {SkPoint::Make(300, 100),
235 SkPoint::Make(100, 200),
236 SkPoint::Make(300, 300)};
237
238 auto vertices = flutter::DlVertices::Make(
239 flutter::DlVertexMode::kTriangles, 3, positions.data(),
240 texture_coordinates.data(), /*colors=*/nullptr);
241
242 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
243 flutter::DlColor::kRed()};
244 const float stops[2] = {0.0, 1.0};
245
246 auto linear = flutter::DlColorSource::MakeLinear(
247 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
248 flutter::DlTileMode::kRepeat);
249
250 flutter::DisplayListBuilder builder;
251 flutter::DlPaint paint;
252
253 paint.setColorSource(linear);
254 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
255
256 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
257 }

References paint.

## ◆ TEST_P() [152/456]

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

Definition at line 333 of file aiks_dl_vertices_unittests.cc.

333 {
334 std::vector<SkPoint> positions = {
335 SkPoint::Make(100, 300), SkPoint::Make(200, 100), SkPoint::Make(300, 300),
336 SkPoint::Make(200, 500)};
337 auto color = flutter::DlColor::kBlue().withAlpha(0x99);
338 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
339 std::vector<flutter::DlColor> colors = {color, color, color, color};
340
341 auto vertices = flutter::DlVertices::Make(
342 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
343 /*texture_coordinates=*/nullptr, colors.data(), indices.size(),
344 indices.data());
345
346 flutter::DisplayListBuilder builder;
347 flutter::DlPaint paint;
348 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
349 paint.setColor(flutter::DlColor::kRed());
350
351 builder.DrawRect(SkRect::MakeLTRB(0, 0, 400, 400), paint);
352 builder.DrawVertices(vertices, flutter::DlBlendMode::kDst, paint);
353
354 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
355 }

References color, and paint.

## ◆ TEST_P() [153/456]

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

Definition at line 313 of file aiks_dl_vertices_unittests.cc.

313 {
314 std::vector<SkPoint> positions = {
315 SkPoint::Make(100, 300), SkPoint::Make(200, 100), SkPoint::Make(300, 300),
316 SkPoint::Make(200, 500)};
317 std::vector<uint16_t> indices = {0, 1, 2, 0, 2, 3};
318
319 auto vertices = flutter::DlVertices::Make(
320 flutter::DlVertexMode::kTriangles, positions.size(), positions.data(),
321 /*texture_coordinates=*/nullptr, /*colors=*/nullptr, indices.size(),
322 indices.data());
323
324 flutter::DisplayListBuilder builder;
325 flutter::DlPaint paint;
326
327 paint.setColor(flutter::DlColor::kRed());
328 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
329
330 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
331 }

References paint.

## ◆ TEST_P() [154/456]

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

Definition at line 180 of file aiks_dl_vertices_unittests.cc.

180 {
181 // Use negative coordinates and then scale the transform by -1, -1 to make
182 // sure coverage is taking the transform into account.
183 std::vector<SkPoint> positions = {SkPoint::Make(-100, -300),
184 SkPoint::Make(-200, -100),
185 SkPoint::Make(-300, -300)};
186 std::vector<flutter::DlColor> colors = {flutter::DlColor::kWhite(),
187 flutter::DlColor::kGreen(),
188 flutter::DlColor::kWhite()};
189
190 auto vertices = flutter::DlVertices::Make(
191 flutter::DlVertexMode::kTriangles, 3, positions.data(),
192 /*texture_coordinates=*/nullptr, colors.data());
193
194 flutter::DisplayListBuilder builder;
195 flutter::DlPaint paint;
196
197 paint.setColor(flutter::DlColor::kRed().modulateOpacity(0.5));
198 builder.Scale(-1, -1);
199 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
200
201 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
202 }

References paint.

## ◆ TEST_P() [155/456]

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

Definition at line 359 of file aiks_dl_vertices_unittests.cc.

359 {
360 std::vector<SkPoint> positions_lt = {
361 SkPoint::Make(0, 0), //
362 SkPoint::Make(50, 0), //
363 SkPoint::Make(0, 50), //
364 SkPoint::Make(50, 50), //
365 };
366
367 auto vertices_lt = flutter::DlVertices::Make(
368 flutter::DlVertexMode::kTriangleStrip, positions_lt.size(),
369 positions_lt.data(),
370 /*texture_coordinates=*/positions_lt.data(), /*colors=*/nullptr,
371 /*index_count=*/0,
372 /*indices=*/nullptr);
373
374 std::vector<SkPoint> positions_rt = {
375 SkPoint::Make(50, 0), //
376 SkPoint::Make(100, 0), //
377 SkPoint::Make(50, 50), //
378 SkPoint::Make(100, 50), //
379 };
380
381 auto vertices_rt = flutter::DlVertices::Make(
382 flutter::DlVertexMode::kTriangleStrip, positions_rt.size(),
383 positions_rt.data(),
384 /*texture_coordinates=*/positions_rt.data(), /*colors=*/nullptr,
385 /*index_count=*/0,
386 /*indices=*/nullptr);
387
388 std::vector<SkPoint> positions_lb = {
389 SkPoint::Make(0, 50), //
390 SkPoint::Make(50, 50), //
391 SkPoint::Make(0, 100), //
392 SkPoint::Make(50, 100), //
393 };
394
395 auto vertices_lb = flutter::DlVertices::Make(
396 flutter::DlVertexMode::kTriangleStrip, positions_lb.size(),
397 positions_lb.data(),
398 /*texture_coordinates=*/positions_lb.data(), /*colors=*/nullptr,
399 /*index_count=*/0,
400 /*indices=*/nullptr);
401
402 std::vector<SkPoint> positions_rb = {
403 SkPoint::Make(50, 50), //
404 SkPoint::Make(100, 50), //
405 SkPoint::Make(50, 100), //
406 SkPoint::Make(100, 100), //
407 };
408
409 auto vertices_rb = flutter::DlVertices::Make(
410 flutter::DlVertexMode::kTriangleStrip, positions_rb.size(),
411 positions_rb.data(),
412 /*texture_coordinates=*/positions_rb.data(), /*colors=*/nullptr,
413 /*index_count=*/0,
414 /*indices=*/nullptr);
415
416 flutter::DisplayListBuilder builder;
417 flutter::DlPaint paint;
418 flutter::DlPaint rect_paint;
419 rect_paint.setColor(DlColor::kBlue());
420
421 auto runtime_stages =
422 OpenAssetAsRuntimeStage("runtime_stage_simple.frag.iplr");
423
424 auto runtime_stage =
425 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
426 ASSERT_TRUE(runtime_stage);
427
428 auto runtime_effect = DlRuntimeEffect::MakeImpeller(runtime_stage);
429 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
430 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
431 runtime_effect, {}, uniform_data);
432
433 paint.setColorSource(color_source);
434
435 builder.Scale(GetContentScale().x, GetContentScale().y);
436 builder.Save();
437 builder.DrawRect(SkRect::MakeLTRB(0, 0, 100, 100), rect_paint);
438 builder.DrawVertices(vertices_lt, flutter::DlBlendMode::kSrcOver, paint);
439 builder.DrawVertices(vertices_rt, flutter::DlBlendMode::kSrcOver, paint);
440 builder.DrawVertices(vertices_lb, flutter::DlBlendMode::kSrcOver, paint);
441 builder.DrawVertices(vertices_rb, flutter::DlBlendMode::kSrcOver, paint);
442 builder.Restore();
443
444 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
445 }

References paint, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [156/456]

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

Definition at line 449 of file aiks_dl_vertices_unittests.cc.

450 {
451 std::vector<SkPoint> positions_lt = {
452 SkPoint::Make(200, 200), //
453 SkPoint::Make(250, 200), //
454 SkPoint::Make(200, 250), //
455 SkPoint::Make(250, 250), //
456 };
457
458 auto vertices = flutter::DlVertices::Make(
459 flutter::DlVertexMode::kTriangleStrip, positions_lt.size(),
460 positions_lt.data(),
461 /*texture_coordinates=*/positions_lt.data(), /*colors=*/nullptr,
462 /*index_count=*/0,
463 /*indices=*/nullptr);
464
465 flutter::DisplayListBuilder builder;
466 flutter::DlPaint paint;
467 flutter::DlPaint rect_paint;
468 rect_paint.setColor(DlColor::kBlue());
469
470 auto runtime_stages =
471 OpenAssetAsRuntimeStage("runtime_stage_position.frag.iplr");
472
473 auto runtime_stage =
474 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
475 ASSERT_TRUE(runtime_stage);
476
477 auto runtime_effect = DlRuntimeEffect::MakeImpeller(runtime_stage);
478 auto rect_data = std::vector<Rect>{Rect::MakeLTRB(200, 200, 250, 250)};
479
480 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
481 uniform_data->resize(rect_data.size() * sizeof(Rect));
482 memcpy(uniform_data->data(), rect_data.data(), uniform_data->size());
483
484 auto color_source = flutter::DlColorSource::MakeRuntimeEffect(
485 runtime_effect, {}, uniform_data);
486
487 paint.setColorSource(color_source);
488
489 builder.Scale(GetContentScale().x, GetContentScale().y);
490 builder.DrawRect(SkRect::MakeLTRB(200, 200, 250, 250), rect_paint);
491 builder.DrawVertices(vertices, flutter::DlBlendMode::kSrcOver, paint);
492
493 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
494 }

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

## ◆ TEST_P() [157/456]

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

Definition at line 2568 of file aiks_unittests.cc.

2568 {
2569 Canvas canvas;
2570 canvas.Scale(GetContentScale());
2571 canvas.DrawPaint(Paint{.color = Color::Red()});
2572 canvas.ClipRect(Rect::MakeXYWH(100, 100, 200, 200));
2573 canvas.SaveLayer(Paint{.color = Color::Blue()});
2574 canvas.Restore();
2575 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2576 }

References impeller::Color::Blue(), impeller::Canvas::ClipRect(), impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Scale().

## ◆ TEST_P() [158/456]

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

Definition at line 2578 of file aiks_unittests.cc.

2578 {
2579 Canvas canvas;
2580 canvas.Scale(GetContentScale());
2581 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2582 canvas.DrawImage(image, {10, 10}, {});
2583 canvas.ClipRect(Rect::MakeXYWH(100, 100, 200, 200));
2584 canvas.SaveLayer(Paint{.blend_mode = BlendMode::kClear});
2585 canvas.Restore();
2586 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2587 }

References impeller::Paint::blend_mode, impeller::Canvas::ClipRect(), impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::kClear, impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Scale().

## ◆ TEST_P() [159/456]

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

Definition at line 1261 of file aiks_unittests.cc.

1261 {
1262 Canvas canvas;
1263 canvas.Scale(GetContentScale());
1264 Paint paint;
1265 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
1266 .style = FilterContents::BlurStyle::kNormal,
1267 .sigma = Sigma{1},
1268 };
1269
1270 canvas.DrawPaint({.color = Color::White()});
1271
1272 paint.color = Color::Blue();
1273 for (int i = 0; i < 5; i++) {
1274 Scalar y = i * 125;
1275 Scalar y_radius = i * 15;
1276 for (int j = 0; j < 5; j++) {
1277 Scalar x = j * 125;
1278 Scalar x_radius = j * 15;
1279 canvas.DrawRRect(Rect::MakeXYWH(x + 50, y + 50, 100.0f, 100.0f),
1280 {x_radius, y_radius}, paint);
1281 }
1282 }
1283
1284 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1285 }

References impeller::Color::Blue(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::FilterContents::kNormal, impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Canvas::Scale(), impeller::Paint::MaskBlurDescriptor::style, and impeller::Color::White().

## ◆ TEST_P() [160/456]

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

Definition at line 716 of file aiks_dl_gradient_unittests.cc.

716 {
717 DisplayListBuilder builder;
718 DlPaint paint;
719 builder.Translate(100.0f, 0);
720
721 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
722 DlColor::kGreen()};
723 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
724
725 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {300, 0}, stops.size(),
726 colors.data(), stops.data(),
727 DlTileMode::kClamp));
728
729 paint.setColor(DlColor::kWhite());
730 builder.DrawRect(SkRect::MakeXYWH(0, 0, 300, 300), paint);
731 builder.Translate(400, 0);
732 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 300, 300), 4, 4),
733 paint);
734
735 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
736 }

References paint.

## ◆ TEST_P() [161/456]

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

Definition at line 762 of file aiks_dl_gradient_unittests.cc.

762 {
763 DisplayListBuilder builder;
764 DlPaint paint;
765 builder.Translate(100.0f, 0);
766
767 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
768 DlColor::kGreen()};
769 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
770
771 paint.setColorSource(DlColorSource::MakeLinear({300, 0}, {0, 0}, stops.size(),
772 colors.data(), stops.data(),
773 DlTileMode::kClamp));
774
775 paint.setColor(DlColor::kWhite());
776 builder.DrawRect(SkRect::MakeXYWH(0, 0, 300, 300), paint);
777 builder.Translate(400, 0);
778 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 300, 300), 4, 4),
779 paint);
780
781 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
782 }

References paint.

## ◆ TEST_P() [162/456]

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

Definition at line 739 of file aiks_dl_gradient_unittests.cc.

739 {
740 DisplayListBuilder builder;
741 DlPaint paint;
742 builder.Translate(100.0f, 0);
743
744 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
745 DlColor::kGreen()};
746 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
747
748 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {0, 300}, stops.size(),
749 colors.data(), stops.data(),
750 DlTileMode::kClamp));
751
752 paint.setColor(DlColor::kWhite());
753 builder.DrawRect(SkRect::MakeXYWH(0, 0, 300, 300), paint);
754 builder.Translate(400, 0);
755 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 300, 300), 4, 4),
756 paint);
757
758 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
759 }

References paint.

## ◆ TEST_P() [163/456]

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

Definition at line 785 of file aiks_dl_gradient_unittests.cc.

785 {
786 DisplayListBuilder builder;
787 DlPaint paint;
788 builder.Translate(100.0f, 0);
789
790 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
791 DlColor::kGreen()};
792 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
793
794 paint.setColorSource(DlColorSource::MakeLinear({0, 300}, {0, 0}, stops.size(),
795 colors.data(), stops.data(),
796 DlTileMode::kClamp));
797
798 paint.setColor(DlColor::kWhite());
799 builder.DrawRect(SkRect::MakeXYWH(0, 0, 300, 300), paint);
800 builder.Translate(400, 0);
801 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 300, 300), 4, 4),
802 paint);
803
804 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
805 }

References paint.

## ◆ TEST_P() [164/456]

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

Definition at line 923 of file aiks_unittests.cc.

923 {
924 Canvas canvas;
925 canvas.Scale(GetContentScale());
926 Paint paint;
927 const int color_count = 3;
928 Color colors[color_count] = {
929 Color::Blue(),
930 Color::Green(),
931 Color::Crimson(),
932 };
933
934 paint.color = Color::White();
935 canvas.DrawPaint(paint);
936
937 int c_index = 0;
938 int radius = 600;
939 while (radius > 0) {
940 paint.color = colors[(c_index++) % color_count];
941 canvas.DrawCircle({10, 10}, radius, paint);
942 if (radius > 30) {
943 radius -= 10;
944 } else {
945 radius -= 2;
946 }
947 }
948
949 std::vector<Color> gradient_colors = {
950 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
951 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
952 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
953 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
954 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
955 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
956 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
957 std::vector<Scalar> stops = {
958 0.0,
959 (1.0 / 6.0) * 1,
960 (1.0 / 6.0) * 2,
961 (1.0 / 6.0) * 3,
962 (1.0 / 6.0) * 4,
963 (1.0 / 6.0) * 5,
964 1.0,
965 };
966 auto texture = CreateTextureForFixture("airplane.jpg",
967 /*enable_mipmapping=*/true);
968
969 paint.color_source = ColorSource::MakeRadialGradient(
970 {500, 600}, 75, std::move(gradient_colors), std::move(stops),
971 Entity::TileMode::kMirror, {});
972 canvas.DrawCircle({500, 600}, 100, paint);
973
974 paint.color_source = ColorSource::MakeImage(
975 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
976 Matrix::MakeTranslation({700, 200}));
977 canvas.DrawCircle({800, 300}, 100, paint);
978
979 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
980 }

References impeller::Color::Blue(), impeller::Color::Crimson(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::ColorSource::MakeImage(), impeller::ColorSource::MakeRadialGradient(), impeller::Matrix::MakeTranslation(), paint, impeller::Canvas::Scale(), and impeller::Color::White().

## ◆ TEST_P() [165/456]

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

Definition at line 1046 of file aiks_unittests.cc.

1046 {
1047 Canvas canvas;
1048 canvas.Scale(GetContentScale());
1049 Paint paint;
1050 const int color_count = 3;
1051 Color colors[color_count] = {
1052 Color::Blue(),
1053 Color::Green(),
1054 Color::Crimson(),
1055 };
1056
1057 paint.color = Color::White();
1058 canvas.DrawPaint(paint);
1059
1060 int c_index = 0;
1061 int long_radius = 600;
1062 int short_radius = 600;
1063 while (long_radius > 0 && short_radius > 0) {
1064 paint.color = colors[(c_index++) % color_count];
1065 canvas.DrawOval(Rect::MakeXYWH(10 - long_radius, 10 - short_radius,
1066 long_radius * 2, short_radius * 2),
1067 paint);
1068 canvas.DrawOval(Rect::MakeXYWH(1000 - short_radius, 750 - long_radius,
1069 short_radius * 2, long_radius * 2),
1070 paint);
1071 if (short_radius > 30) {
1072 short_radius -= 10;
1073 long_radius -= 5;
1074 } else {
1075 short_radius -= 2;
1076 long_radius -= 1;
1077 }
1078 }
1079
1080 std::vector<Color> gradient_colors = {
1081 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1082 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1083 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1084 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1085 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1086 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1087 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1088 std::vector<Scalar> stops = {
1089 0.0,
1090 (1.0 / 6.0) * 1,
1091 (1.0 / 6.0) * 2,
1092 (1.0 / 6.0) * 3,
1093 (1.0 / 6.0) * 4,
1094 (1.0 / 6.0) * 5,
1095 1.0,
1096 };
1097 auto texture = CreateTextureForFixture("airplane.jpg",
1098 /*enable_mipmapping=*/true);
1099
1100 paint.color = Color::White().WithAlpha(0.5);
1101
1102 paint.color_source = ColorSource::MakeRadialGradient(
1103 {300, 650}, 75, std::move(gradient_colors), std::move(stops),
1104 Entity::TileMode::kMirror, {});
1105 canvas.DrawOval(Rect::MakeXYWH(200, 625, 200, 50), paint);
1106 canvas.DrawOval(Rect::MakeXYWH(275, 550, 50, 200), paint);
1107
1108 paint.color_source = ColorSource::MakeImage(
1109 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1110 Matrix::MakeTranslation({610, 15}));
1111 canvas.DrawOval(Rect::MakeXYWH(610, 90, 200, 50), paint);
1112 canvas.DrawOval(Rect::MakeXYWH(685, 15, 50, 200), paint);
1113
1114 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1115 }

References impeller::Color::Blue(), impeller::Color::Crimson(), impeller::Canvas::DrawOval(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::ColorSource::MakeImage(), impeller::ColorSource::MakeRadialGradient(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Canvas::Scale(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [166/456]

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

Definition at line 1287 of file aiks_unittests.cc.

1287 {
1288 Canvas canvas;
1289 canvas.Scale(GetContentScale());
1290 Paint paint;
1291 const int color_count = 3;
1292 Color colors[color_count] = {
1293 Color::Blue(),
1294 Color::Green(),
1295 Color::Crimson(),
1296 };
1297
1298 paint.color = Color::White();
1299 canvas.DrawPaint(paint);
1300
1301 auto draw_rrect_as_path = [&canvas](const Rect& rect, const Size& radii,
1302 const Paint& paint) {
1303 PathBuilder builder = PathBuilder();
1304 builder.AddRoundedRect(rect, radii);
1305 canvas.DrawPath(builder.TakePath(), paint);
1306 };
1307
1308 int c_index = 0;
1309 for (int i = 0; i < 4; i++) {
1310 for (int j = 0; j < 4; j++) {
1311 paint.color = colors[(c_index++) % color_count];
1312 draw_rrect_as_path(Rect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80),
1313 Size(i * 5 + 10, j * 5 + 10), paint);
1314 }
1315 }
1316 paint.color = colors[(c_index++) % color_count];
1317 draw_rrect_as_path(Rect::MakeXYWH(10, 420, 380, 80), Size(40, 40), paint);
1318 paint.color = colors[(c_index++) % color_count];
1319 draw_rrect_as_path(Rect::MakeXYWH(410, 20, 80, 380), Size(40, 40), paint);
1320
1321 std::vector<Color> gradient_colors = {
1322 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1323 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1324 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1325 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1326 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1327 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1328 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1329 std::vector<Scalar> stops = {
1330 0.0,
1331 (1.0 / 6.0) * 1,
1332 (1.0 / 6.0) * 2,
1333 (1.0 / 6.0) * 3,
1334 (1.0 / 6.0) * 4,
1335 (1.0 / 6.0) * 5,
1336 1.0,
1337 };
1338 auto texture = CreateTextureForFixture("airplane.jpg",
1339 /*enable_mipmapping=*/true);
1340
1341 paint.color = Color::White().WithAlpha(0.1);
1342 paint.color_source = ColorSource::MakeRadialGradient(
1343 {550, 550}, 75, gradient_colors, stops, Entity::TileMode::kMirror, {});
1344 for (int i = 1; i <= 10; i++) {
1345 int j = 11 - i;
1346 draw_rrect_as_path(Rect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1347 550 + i * 20, 550 + j * 20),
1348 Size(i * 10, j * 10), paint);
1349 }
1350 paint.color = Color::White().WithAlpha(0.5);
1351 paint.color_source = ColorSource::MakeRadialGradient(
1352 {200, 650}, 75, std::move(gradient_colors), std::move(stops),
1353 Entity::TileMode::kMirror, {});
1354 draw_rrect_as_path(Rect::MakeLTRB(100, 610, 300, 690), Size(40, 40), paint);
1355 draw_rrect_as_path(Rect::MakeLTRB(160, 550, 240, 750), Size(40, 40), paint);
1356
1357 paint.color = Color::White().WithAlpha(0.1);
1358 paint.color_source = ColorSource::MakeImage(
1359 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1360 Matrix::MakeTranslation({520, 20}));
1361 for (int i = 1; i <= 10; i++) {
1362 int j = 11 - i;
1363 draw_rrect_as_path(Rect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1364 720 + i * 20, 220 + j * 20),
1365 Size(i * 10, j * 10), paint);
1366 }
1367 paint.color = Color::White().WithAlpha(0.5);
1368 paint.color_source = ColorSource::MakeImage(
1369 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1370 Matrix::MakeTranslation({800, 300}));
1371 draw_rrect_as_path(Rect::MakeLTRB(800, 410, 1000, 490), Size(40, 40), paint);
1372 draw_rrect_as_path(Rect::MakeLTRB(860, 350, 940, 550), Size(40, 40), paint);
1373
1374 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1375 }

References impeller::PathBuilder::AddRoundedRect(), impeller::Color::Blue(), impeller::Color::Crimson(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::ColorSource::MakeImage(), impeller::TRect< Scalar >::MakeLTRB(), impeller::ColorSource::MakeRadialGradient(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Canvas::Scale(), impeller::PathBuilder::TakePath(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [167/456]

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

Definition at line 1117 of file aiks_unittests.cc.

1117 {
1118 Canvas canvas;
1119 canvas.Scale(GetContentScale());
1120 Paint paint;
1121 const int color_count = 3;
1122 Color colors[color_count] = {
1123 Color::Blue(),
1124 Color::Green(),
1125 Color::Crimson(),
1126 };
1127
1128 paint.color = Color::White();
1129 canvas.DrawPaint(paint);
1130
1131 int c_index = 0;
1132 for (int i = 0; i < 4; i++) {
1133 for (int j = 0; j < 4; j++) {
1134 paint.color = colors[(c_index++) % color_count];
1135 canvas.DrawRRect(Rect::MakeXYWH(i * 100 + 10, j * 100 + 20, 80, 80),
1136 Size(i * 5 + 10, j * 5 + 10), paint);
1137 }
1138 }
1139 paint.color = colors[(c_index++) % color_count];
1140 canvas.DrawRRect(Rect::MakeXYWH(10, 420, 380, 80), Size(40, 40), paint);
1141 paint.color = colors[(c_index++) % color_count];
1142 canvas.DrawRRect(Rect::MakeXYWH(410, 20, 80, 380), Size(40, 40), paint);
1143
1144 std::vector<Color> gradient_colors = {
1145 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1146 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1147 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1148 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1149 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1150 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1151 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1152 std::vector<Scalar> stops = {
1153 0.0,
1154 (1.0 / 6.0) * 1,
1155 (1.0 / 6.0) * 2,
1156 (1.0 / 6.0) * 3,
1157 (1.0 / 6.0) * 4,
1158 (1.0 / 6.0) * 5,
1159 1.0,
1160 };
1161 auto texture = CreateTextureForFixture("airplane.jpg",
1162 /*enable_mipmapping=*/true);
1163
1164 paint.color = Color::White().WithAlpha(0.1);
1165 paint.color_source = ColorSource::MakeRadialGradient(
1166 {550, 550}, 75, gradient_colors, stops, Entity::TileMode::kMirror, {});
1167 for (int i = 1; i <= 10; i++) {
1168 int j = 11 - i;
1169 canvas.DrawRRect(Rect::MakeLTRB(550 - i * 20, 550 - j * 20, //
1170 550 + i * 20, 550 + j * 20),
1171 Size(i * 10, j * 10), paint);
1172 }
1173 paint.color = Color::White().WithAlpha(0.5);
1174 paint.color_source = ColorSource::MakeRadialGradient(
1175 {200, 650}, 75, std::move(gradient_colors), std::move(stops),
1176 Entity::TileMode::kMirror, {});
1177 canvas.DrawRRect(Rect::MakeLTRB(100, 610, 300, 690), Size(40, 40), paint);
1178 canvas.DrawRRect(Rect::MakeLTRB(160, 550, 240, 750), Size(40, 40), paint);
1179
1180 paint.color = Color::White().WithAlpha(0.1);
1181 paint.color_source = ColorSource::MakeImage(
1182 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1183 Matrix::MakeTranslation({520, 20}));
1184 for (int i = 1; i <= 10; i++) {
1185 int j = 11 - i;
1186 canvas.DrawRRect(Rect::MakeLTRB(720 - i * 20, 220 - j * 20, //
1187 720 + i * 20, 220 + j * 20),
1188 Size(i * 10, j * 10), paint);
1189 }
1190 paint.color = Color::White().WithAlpha(0.5);
1191 paint.color_source = ColorSource::MakeImage(
1192 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1193 Matrix::MakeTranslation({800, 300}));
1194 canvas.DrawRRect(Rect::MakeLTRB(800, 410, 1000, 490), Size(40, 40), paint);
1195 canvas.DrawRRect(Rect::MakeLTRB(860, 350, 940, 550), Size(40, 40), paint);
1196
1197 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1198 }

References impeller::Color::Blue(), impeller::Color::Crimson(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::ColorSource::MakeImage(), impeller::TRect< Scalar >::MakeLTRB(), impeller::ColorSource::MakeRadialGradient(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Canvas::Scale(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [168/456]

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

Definition at line 566 of file aiks_blend_unittests.cc.

566 {
567 auto texture = CreateTextureForFixture("airplane.jpg",
568 /*enable_mipmapping=*/true);
569
570 Canvas canvas;
571 canvas.Rotate(Degrees(30));
572 canvas.DrawImage(std::make_shared<Image>(texture), {200, 200},
573 {.color_filter = ColorFilter::MakeBlend(
574 BlendMode::kColorDodge, Color::Orange())});
575
576 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
577 }

References impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::kColorDodge, impeller::ColorFilter::MakeBlend(), impeller::Color::Orange(), and impeller::Canvas::Rotate().

## ◆ TEST_P() [169/456]

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

Definition at line 341 of file aiks_blend_unittests.cc.

341 {
342 Canvas canvas;
343
344 canvas.SaveLayer({
345 .color_filter =
346 ColorFilter::MakeBlend(BlendMode::kColorDodge, Color::Red()),
347 });
348
349 canvas.Translate({500, 300, 0});
350 canvas.Rotate(Radians(2 * kPi / 3));
351 canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
352
353 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
354 }

References impeller::Color::Blue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kColorDodge, impeller::kPi, impeller::ColorFilter::MakeBlend(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Rotate(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Translate().

## ◆ TEST_P() [170/456]

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

Definition at line 553 of file aiks_blend_unittests.cc.

553 {
554 auto texture = CreateTextureForFixture("airplane.jpg",
555 /*enable_mipmapping=*/true);
556
557 Canvas canvas;
558 canvas.Rotate(Degrees(30));
559 canvas.DrawImage(std::make_shared<Image>(texture), {200, 200},
560 {.color_filter = ColorFilter::MakeBlend(BlendMode::kSourceIn,
561 Color::Orange())});
562
563 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
564 }

References impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::kSourceIn, impeller::ColorFilter::MakeBlend(), impeller::Color::Orange(), and impeller::Canvas::Rotate().

## ◆ TEST_P() [171/456]

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

Definition at line 876 of file aiks_unittests.cc.

876 {
877 PixelFormat pixel_format =
878 GetContext()->GetCapabilities()->GetDefaultColorFormat();
879 EXPECT_TRUE(pixel_format == PixelFormat::kR8G8B8A8UNormInt ||
880 pixel_format == PixelFormat::kB8G8R8A8UNormInt)
881 << "pixel format: " << PixelFormatToString(pixel_format);
882 }

References impeller::kB8G8R8A8UNormInt, impeller::kR8G8B8A8UNormInt, and impeller::PixelFormatToString().

## ◆ TEST_P() [172/456]

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

Definition at line 871 of file aiks_unittests.cc.

871 {
872 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
873 PixelFormat::kB10G10R10A10XR);
874 }

References impeller::kB10G10R10A10XR.

## ◆ TEST_P() [173/456]

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

Definition at line 579 of file aiks_blend_unittests.cc.

579 {
580 auto texture = CreateTextureForFixture("airplane.jpg",
581 /*enable_mipmapping=*/true);
582
583 // Draw with an advanced blend that can use FramebufferBlendContents and
584 // verify that the scale transform is correctly applied to the image.
585 Canvas canvas;
586 canvas.DrawPaint({.color = Color::DarkGray()});
587 canvas.Scale(Vector2(0.4, 0.4));
588 canvas.DrawImage(std::make_shared<Image>(texture), {20, 20},
589 {.blend_mode = BlendMode::kMultiply});
590
591 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
592 }

References impeller::Color::DarkGray(), impeller::Canvas::DrawImage(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kMultiply, and impeller::Canvas::Scale().

## ◆ TEST_P() [174/456]

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

If correct, this test should draw a green circle. If any red is visible, there is a depth bug.

Definition at line 122 of file aiks_dl_clip_unittests.cc.

122 {
123 DisplayListBuilder builder;
124
125 // Clear the whole canvas with white.
126 DlPaint paint;
127 paint.setColor(DlColor::kWhite());
128 builder.DrawPaint(paint);
129
130 builder.ClipPath(SkPath::Circle(150, 150, 50), DlCanvas::ClipOp::kIntersect);
131
132 // Draw a red rectangle that should not show through the circle clip.
133 paint.setColor(DlColor::kRed());
134 paint.setBlendMode(DlBlendMode::kMultiply);
135 builder.DrawRect(SkRect::MakeXYWH(100, 100, 100, 100), paint);
136
137 // Draw a green circle that shows through the clip.
138 paint.setColor(DlColor::kGreen());
139 paint.setBlendMode(DlBlendMode::kSrcOver);
140 builder.DrawCircle(SkPoint::Make(150, 150), 50, paint);
141
142 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
143 }

References paint.

## ◆ TEST_P() [175/456]

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

Definition at line 1057 of file aiks_blur_unittests.cc.

1057 {
1058 size_t blur_required_mip_count =
1059 GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4;
1060
1061 Canvas canvas;
1062 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
1063 canvas.SaveLayer({}, std::nullopt,
1064 ImageFilter::MakeBlur(Sigma(3), Sigma(3),
1065 FilterContents::BlurStyle::kNormal,
1066 Entity::TileMode::kClamp));
1067 canvas.Restore();
1068
1069 Picture picture = canvas.EndRecordingAsPicture();
1070 std::shared_ptr<RenderTargetCache> cache =
1071 std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
1072 AiksContext aiks_context(GetContext(), nullptr, cache);
1073 picture.ToImage(aiks_context, {100, 100});
1074
1075 size_t max_mip_count = 0;
1076 for (auto it = cache->GetRenderTargetDataBegin();
1077 it != cache->GetRenderTargetDataEnd(); ++it) {
1078 max_mip_count = std::max(it->config.mip_count, max_mip_count);
1079 }
1080 EXPECT_EQ(max_mip_count, blur_required_mip_count);
1081 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kOpenGLES, impeller::ImageFilter::MakeBlur(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Picture::ToImage().

## ◆ TEST_P() [176/456]

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

Definition at line 763 of file aiks_blur_unittests.cc.

763 {
764 // This test is for checking out how stable rendering is when content is
765 // translated underneath a blur. Animating under a blur can cause
766 // *shimmering* to happen as a result of pixel alignment.
767 // See also: https://github.com/flutter/flutter/issues/140193
768 auto boston = std::make_shared<Image>(
769 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true));
770 ASSERT_TRUE(boston);
771 int64_t count = 0;
772 Scalar sigma = 20.0;
773 Scalar freq = 0.1;
774 Scalar amp = 50.0;
775 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
776 if (AiksTest::ImGuiBegin("Controls", nullptr,
777 ImGuiWindowFlags_AlwaysAutoResize)) {
778 ImGui::SliderFloat("Sigma", &sigma, 0, 200);
779 ImGui::SliderFloat("Frequency", &freq, 0.01, 2.0);
780 ImGui::SliderFloat("Amplitude", &amp, 1, 100);
781 ImGui::End();
782 }
783
784 Canvas canvas;
785 canvas.Scale(GetContentScale());
786 Scalar y = amp * sin(freq * 2.0 * M_PI * count / 60);
787 canvas.DrawImage(boston,
788 Point(1024 / 2 - boston->GetSize().width / 2,
789 (768 / 2 - boston->GetSize().height / 2) + y),
790 {});
791 static PlaygroundPoint point_a(Point(100, 100), 20, Color::Red());
792 static PlaygroundPoint point_b(Point(900, 700), 20, Color::Red());
793 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
794 canvas.ClipRect(
795 Rect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
796 canvas.ClipRect(Rect::MakeLTRB(100, 100, 900, 700));
797 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
798 ImageFilter::MakeBlur(Sigma(sigma), Sigma(sigma),
799 FilterContents::BlurStyle::kNormal,
800 Entity::TileMode::kClamp));
801 count += 1;
802 return canvas.EndRecordingAsPicture();
803 };
804 ASSERT_TRUE(OpenPlaygroundHere(callback));
805 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawImage(), impeller::DrawPlaygroundLine(), impeller::Canvas::EndRecordingAsPicture(), impeller::AiksPlayground::ImGuiBegin(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSource, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Color::Red(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Scale().

## ◆ TEST_P() [177/456]

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

Definition at line 479 of file aiks_blur_unittests.cc.

479 {
480 Canvas canvas;
481
482 canvas.Scale(GetContentScale());
483 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
484 canvas.DrawImageRect(
485 std::make_shared<Image>(boston),
486 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height),
487 Rect::MakeLTRB(0, 0, GetWindowSize().width, 100), Paint{});
488 canvas.DrawRRect(Rect::MakeLTRB(0, 110, GetWindowSize().width, 210),
489 Size(10, 10), Paint{.color = Color::Magenta()});
490 canvas.ClipRect(Rect::MakeLTRB(0, 50, GetWindowSize().width, 150));
491 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
492 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
493 FilterContents::BlurStyle::kNormal,
494 Entity::TileMode::kClamp));
495 canvas.Restore();
496 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
497 }

References impeller::Canvas::ClipRect(), impeller::Paint::color, impeller::Canvas::DrawImageRect(), impeller::Canvas::DrawRRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSource, impeller::Color::Magenta(), impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Scale().

## ◆ TEST_P() [178/456]

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

Definition at line 461 of file aiks_blur_unittests.cc.

461 {
462 Canvas canvas;
463
464 canvas.Scale(GetContentScale());
465 canvas.DrawRRect(Rect::MakeLTRB(0, 0, GetWindowSize().width, 100),
466 Size(10, 10), Paint{.color = Color::LimeGreen()});
467 canvas.DrawRRect(Rect::MakeLTRB(0, 110, GetWindowSize().width, 210),
468 Size(10, 10), Paint{.color = Color::Magenta()});
469 canvas.ClipRect(Rect::MakeLTRB(100, 0, 200, GetWindowSize().height));
470 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
471 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
472 FilterContents::BlurStyle::kNormal,
473 Entity::TileMode::kClamp));
474 canvas.Restore();
475
476 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
477 }

References impeller::Canvas::ClipRect(), impeller::Paint::color, impeller::Canvas::DrawRRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSource, impeller::Color::LimeGreen(), impeller::Color::Magenta(), impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Scale().

## ◆ TEST_P() [179/456]

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

Definition at line 737 of file aiks_blur_unittests.cc.

737 {
738 for (int32_t i = 0; i < 5; ++i) {
739 Canvas canvas;
740 ISize clip_size = ISize(i, i);
741 canvas.ClipRect(
742 Rect::MakeXYWH(400, 400, clip_size.width, clip_size.height));
743 canvas.DrawCircle(
744 {400, 400}, 200,
745 {
746 .color = Color::Green(),
747 .image_filter = ImageFilter::MakeBlur(
748 Sigma(0.1), Sigma(0.1), FilterContents::BlurStyle::kNormal,
749 Entity::TileMode::kDecal),
750 });
751 canvas.Restore();
752
753 Picture picture = canvas.EndRecordingAsPicture();
754 std::shared_ptr<RenderTargetCache> cache =
755 std::make_shared<RenderTargetCache>(
756 GetContext()->GetResourceAllocator());
757 AiksContext aiks_context(GetContext(), nullptr, cache);
758 std::shared_ptr<Image> image = picture.ToImage(aiks_context, {1024, 768});
759 EXPECT_TRUE(image) << " clip rect " << i;
760 }
761 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::TSize< T >::height, impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), impeller::Picture::ToImage(), and impeller::TSize< T >::width.

## ◆ TEST_P() [180/456]

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

Definition at line 1122 of file aiks_blur_unittests.cc.

1122 {
1123 size_t blur_required_mip_count =
1124 GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4;
1125 fml::testing::LogCapture log_capture;
1126 Canvas canvas;
1127 canvas.SaveLayer(
1128 {.image_filter = ImageFilter::MakeBlur(Sigma(30), Sigma(30),
1129 FilterContents::BlurStyle::kNormal,
1130 Entity::TileMode::kClamp)});
1131 canvas.DrawCircle({200, 200}, 50, {.color = Color::Chartreuse()});
1132
1133 Picture picture = canvas.EndRecordingAsPicture();
1134 std::shared_ptr<RenderTargetCache> cache =
1135 std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
1136 AiksContext aiks_context(GetContext(), nullptr, cache);
1137 picture.ToImage(aiks_context, {1024, 768});
1138
1139 size_t max_mip_count = 0;
1140 for (auto it = cache->GetRenderTargetDataBegin();
1141 it != cache->GetRenderTargetDataEnd(); ++it) {
1142 max_mip_count = std::max(it->config.mip_count, max_mip_count);
1143 }
1144 EXPECT_EQ(max_mip_count, blur_required_mip_count);
1145 // The log is FML_DLOG, so only check in debug builds.
1146 #ifndef NDEBUG
1147 if (GetParam() != PlaygroundBackend::kOpenGLES) {
1148 EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
1149 std::string::npos);
1150 } else {
1151 EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
1152 std::string::npos);
1153 }
1154 #endif
1155 }

References impeller::Color::Chartreuse(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::GaussianBlurFilterContents::kNoMipsError, impeller::FilterContents::kNormal, impeller::kOpenGLES, impeller::ImageFilter::MakeBlur(), impeller::Canvas::SaveLayer(), and impeller::Picture::ToImage().

## ◆ TEST_P() [181/456]

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

Definition at line 1083 of file aiks_blur_unittests.cc.

1083 {
1084 fml::testing::LogCapture log_capture;
1085 size_t blur_required_mip_count =
1086 GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4;
1087
1088 Canvas canvas;
1089 canvas.DrawPaint({.color = Color::Wheat()});
1090 canvas.SaveLayer({.blend_mode = BlendMode::kMultiply});
1091 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
1092 canvas.SaveLayer({}, std::nullopt,
1093 ImageFilter::MakeBlur(Sigma(30), Sigma(30),
1094 FilterContents::BlurStyle::kNormal,
1095 Entity::TileMode::kClamp));
1096 canvas.DrawCircle({200, 200}, 50, {.color = Color::Chartreuse()});
1097
1098 Picture picture = canvas.EndRecordingAsPicture();
1099 std::shared_ptr<RenderTargetCache> cache =
1100 std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
1101 AiksContext aiks_context(GetContext(), nullptr, cache);
1102 picture.ToImage(aiks_context, {100, 100});
1103
1104 size_t max_mip_count = 0;
1105 for (auto it = cache->GetRenderTargetDataBegin();
1106 it != cache->GetRenderTargetDataEnd(); ++it) {
1107 max_mip_count = std::max(it->config.mip_count, max_mip_count);
1108 }
1109 EXPECT_EQ(max_mip_count, blur_required_mip_count);
1110 // The log is FML_DLOG, so only check in debug builds.
1111 #ifndef NDEBUG
1112 if (GetParam() != PlaygroundBackend::kOpenGLES) {
1113 EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
1114 std::string::npos);
1115 } else {
1116 EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
1117 std::string::npos);
1118 }
1119 #endif
1120 }

References impeller::Color::Chartreuse(), impeller::Color::CornflowerBlue(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::kMultiply, impeller::GaussianBlurFilterContents::kNoMipsError, impeller::FilterContents::kNormal, impeller::kOpenGLES, impeller::ImageFilter::MakeBlur(), impeller::Canvas::SaveLayer(), impeller::Picture::ToImage(), and impeller::Color::Wheat().

## ◆ TEST_P() [182/456]

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

Definition at line 1157 of file aiks_blur_unittests.cc.

1157 {
1158 size_t blur_required_mip_count =
1159 GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4;
1160 fml::testing::LogCapture log_capture;
1161 Canvas canvas;
1162 canvas.DrawPath(PathBuilder{}
1163 .MoveTo({100, 100})
1164 .LineTo({200, 100})
1165 .LineTo({150, 200})
1166 .LineTo({50, 200})
1167 .Close()
1168 .TakePath(),
1169 {.color = Color::Chartreuse(),
1170 .image_filter = ImageFilter::MakeBlur(
1171 Sigma(30), Sigma(30), FilterContents::BlurStyle::kNormal,
1172 Entity::TileMode::kClamp)});
1173
1174 Picture picture = canvas.EndRecordingAsPicture();
1175 std::shared_ptr<RenderTargetCache> cache =
1176 std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
1177 AiksContext aiks_context(GetContext(), nullptr, cache);
1178 picture.ToImage(aiks_context, {1024, 768});
1179
1180 size_t max_mip_count = 0;
1181 for (auto it = cache->GetRenderTargetDataBegin();
1182 it != cache->GetRenderTargetDataEnd(); ++it) {
1183 max_mip_count = std::max(it->config.mip_count, max_mip_count);
1184 }
1185 EXPECT_EQ(max_mip_count, blur_required_mip_count);
1186 // The log is FML_DLOG, so only check in debug builds.
1187 #ifndef NDEBUG
1188 if (GetParam() != PlaygroundBackend::kOpenGLES) {
1189 EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
1190 std::string::npos);
1191 } else {
1192 EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError),
1193 std::string::npos);
1194 }
1195 #endif
1196 }

References impeller::Color::Chartreuse(), impeller::Close(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::GaussianBlurFilterContents::kNoMipsError, impeller::FilterContents::kNormal, impeller::kOpenGLES, impeller::LineTo(), impeller::ImageFilter::MakeBlur(), impeller::PathBuilder::MoveTo(), and impeller::Picture::ToImage().

## ◆ TEST_P() [183/456]

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

Definition at line 551 of file aiks_blur_unittests.cc.

551 {
552 Canvas canvas;
553
554 canvas.Scale(GetContentScale());
555 canvas.Scale({0.5, 0.5, 1.0});
556 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
557 canvas.DrawImage(std::make_shared<Image>(boston), Point(100, 100), Paint{});
558 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
559 ImageFilter::MakeBlur(Sigma(50.0), Sigma(0.0),
560 FilterContents::BlurStyle::kNormal,
561 Entity::TileMode::kClamp));
562 canvas.Restore();
563 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
564 }

References impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSource, impeller::ImageFilter::MakeBlur(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Scale().

## ◆ TEST_P() [184/456]

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

Definition at line 570 of file aiks_blur_unittests.cc.

570 {
571 Canvas canvas;
572 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
573 Rect bounds =
574 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
575 Vector2 image_center = Vector2(bounds.GetSize() / 2);
576 Paint paint = {.image_filter =
577 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
578 FilterContents::BlurStyle::kNormal,
579 Entity::TileMode::kDecal)};
580 Vector2 clip_size = {150, 75};
581 Vector2 center = Vector2(1024, 768) / 2;
582 canvas.Scale(GetContentScale());
583 canvas.ClipRect(
584 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size));
585 canvas.Translate({center.x, center.y, 0});
586 canvas.Scale({0.6, 0.6, 1});
587 canvas.Rotate(Degrees(25));
588
589 canvas.DrawImageRect(std::make_shared<Image>(boston), /*source=*/bounds,
590 /*dest=*/bounds.Shift(-image_center), paint);
591
592 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
593 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawImageRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< T >::Expand(), impeller::TRect< T >::GetSize(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Canvas::Rotate(), impeller::Canvas::Scale(), impeller::TRect< T >::Shift(), impeller::Canvas::Translate(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [185/456]

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

Definition at line 619 of file aiks_blur_unittests.cc.

619 {
620 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
621
622 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
623 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
624 const Entity::TileMode tile_modes[] = {
625 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
626 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
627
628 static float rotation = 0;
629 static float scale = 0.6;
630 static int selected_tile_mode = 3;
631
632 if (AiksTest::ImGuiBegin("Controls", nullptr,
633 ImGuiWindowFlags_AlwaysAutoResize)) {
634 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
635 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
636 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
637 sizeof(tile_mode_names) / sizeof(char*));
638 ImGui::End();
639 }
640
641 Canvas canvas;
642 Rect bounds =
643 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
644 Vector2 image_center = Vector2(bounds.GetSize() / 2);
645 Paint paint = {.image_filter =
646 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
647 FilterContents::BlurStyle::kNormal,
648 tile_modes[selected_tile_mode])};
649 static PlaygroundPoint point_a(Point(362, 309), 20, Color::Red());
650 static PlaygroundPoint point_b(Point(662, 459), 20, Color::Red());
651 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
652 Vector2 center = Vector2(1024, 768) / 2;
653 canvas.Scale(GetContentScale());
654 canvas.ClipRect(
655 Rect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
656 canvas.Translate({center.x, center.y, 0});
657 canvas.Scale({scale, scale, 1});
658 canvas.Rotate(Degrees(rotation));
659
660 canvas.DrawImageRect(std::make_shared<Image>(boston), /*source=*/bounds,
661 /*dest=*/bounds.Shift(-image_center), paint);
662 return canvas.EndRecordingAsPicture();
663 };
664
665 ASSERT_TRUE(OpenPlaygroundHere(callback));
666 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawImageRect(), impeller::DrawPlaygroundLine(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< T >::GetSize(), impeller::AiksPlayground::ImGuiBegin(), impeller::Entity::kClamp, impeller::Entity::kDecal, impeller::Entity::kMirror, impeller::FilterContents::kNormal, impeller::Entity::kRepeat, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Color::Red(), impeller::Canvas::Rotate(), impeller::Canvas::Scale(), scale, impeller::TRect< T >::Shift(), impeller::Canvas::Translate(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [186/456]

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

Definition at line 668 of file aiks_blur_unittests.cc.

668 {
669 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
670 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
671 const Entity::TileMode tile_modes[] = {
672 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
673 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
674
675 static float rotation = 45;
676 static float scale = 0.6;
677 static int selected_tile_mode = 3;
678
679 if (AiksTest::ImGuiBegin("Controls", nullptr,
680 ImGuiWindowFlags_AlwaysAutoResize)) {
681 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
682 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
683 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
684 sizeof(tile_mode_names) / sizeof(char*));
685 ImGui::End();
686 }
687
688 Canvas canvas;
689 Paint paint = {.color = Color::Green(),
690 .image_filter =
691 ImageFilter::MakeBlur(Sigma(50.0), Sigma(0.0),
692 FilterContents::BlurStyle::kNormal,
693 tile_modes[selected_tile_mode])};
694 Vector2 center = Vector2(1024, 768) / 2;
695 canvas.Scale(GetContentScale());
696 canvas.Translate({center.x, center.y, 0});
697 canvas.Scale({scale, scale, 1});
698 canvas.Rotate(Degrees(rotation));
699
700 canvas.DrawRRect(Rect::MakeXYWH(-100, -100, 200, 200), Size(10, 10), paint);
701 return canvas.EndRecordingAsPicture();
702 };
703
704 ASSERT_TRUE(OpenPlaygroundHere(callback));
705 }

References impeller::Canvas::DrawRRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::AiksPlayground::ImGuiBegin(), impeller::Entity::kClamp, impeller::Entity::kDecal, impeller::Entity::kMirror, impeller::FilterContents::kNormal, impeller::Entity::kRepeat, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Canvas::Rotate(), impeller::Canvas::Scale(), scale, impeller::Canvas::Translate(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [187/456]

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

Definition at line 595 of file aiks_blur_unittests.cc.

595 {
596 Canvas canvas;
597 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
598 Rect bounds =
599 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
600 Vector2 image_center = Vector2(bounds.GetSize() / 2);
601 Paint paint = {.image_filter =
602 ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
603 FilterContents::BlurStyle::kNormal,
604 Entity::TileMode::kDecal)};
605 Vector2 clip_size = {150, 75};
606 Vector2 center = Vector2(1024, 768) / 2;
607 canvas.Scale(GetContentScale());
608 canvas.ClipRect(
609 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size));
610 canvas.Translate({center.x, center.y, 0});
611 canvas.Scale({0.6, 0.6, 1});
612
613 canvas.DrawImageRect(std::make_shared<Image>(boston), /*source=*/bounds,
614 /*dest=*/bounds.Shift(-image_center), paint);
615
616 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
617 }

References impeller::Canvas::ClipRect(), impeller::Canvas::DrawImageRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< T >::Expand(), impeller::TRect< T >::GetSize(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Canvas::Scale(), impeller::TRect< T >::Shift(), impeller::Canvas::Translate(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [188/456]

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

Definition at line 1044 of file aiks_blur_unittests.cc.

1044 {
1045 Canvas canvas;
1046 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
1047 canvas.SaveLayer({}, std::nullopt,
1048 ImageFilter::MakeBlur(Sigma(3), Sigma(3),
1049 FilterContents::BlurStyle::kNormal,
1050 Entity::TileMode::kClamp));
1051 canvas.Restore();
1052
1053 Picture picture = canvas.EndRecordingAsPicture();
1054 EXPECT_EQ(4, picture.pass->GetRequiredMipCount());
1055 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::ImageFilter::MakeBlur(), impeller::Picture::pass, impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [189/456]

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

Definition at line 710 of file aiks_blur_unittests.cc.

710 {
711 for (int32_t i = 1; i < 5; ++i) {
712 Canvas canvas;
713 Scalar fi = i;
714 canvas.DrawPath(
715 PathBuilder{}
716 .MoveTo({100, 100})
717 .LineTo({100.f + fi, 100.f + fi})
718 .TakePath(),
719 {.color = Color::Chartreuse(),
720 .image_filter = ImageFilter::MakeBlur(
721 Sigma(0.1), Sigma(0.1), FilterContents::BlurStyle::kNormal,
722 Entity::TileMode::kClamp)});
723
724 Picture picture = canvas.EndRecordingAsPicture();
725 std::shared_ptr<RenderTargetCache> cache =
726 std::make_shared<RenderTargetCache>(
727 GetContext()->GetResourceAllocator());
728 AiksContext aiks_context(GetContext(), nullptr, cache);
729 std::shared_ptr<Image> image = picture.ToImage(aiks_context, {1024, 768});
730 EXPECT_TRUE(image) << " length " << i;
731 }
732 }

References impeller::Color::Chartreuse(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::LineTo(), impeller::ImageFilter::MakeBlur(), impeller::PathBuilder::MoveTo(), and impeller::Picture::ToImage().

## ◆ TEST_P() [190/456]

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

Definition at line 906 of file aiks_blur_unittests.cc.

906 {
907 Canvas canvas;
908 canvas.Scale(GetContentScale());
909
910 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
911
912 Paint paint;
913 paint.color = Color::Green();
914 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
915 .style = FilterContents::BlurStyle::kInner,
916 .sigma = Sigma(30),
917 };
918 canvas.DrawPath(PathBuilder()
919 .MoveTo({200, 200})
920 .LineTo({300, 400})
921 .LineTo({100, 400})
922 .Close()
923 .TakePath(),
924 paint);
925
926 // Draw another thing to make sure the clip area is reset.
927 Paint red;
928 red.color = Color::Red();
929 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
930
931 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
932 }

References impeller::Close(), impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::FilterContents::kInner, impeller::LineTo(), impeller::TRect< Scalar >::MakeXYWH(), impeller::MoveTo(), paint, impeller::Color::Red(), impeller::Canvas::Scale(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [191/456]

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

Definition at line 807 of file aiks_blur_unittests.cc.

807 {
808 Canvas canvas;
809 canvas.Scale(GetContentScale());
810
811 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
812
813 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
814 Color{0.7568, 0.2627, 0.2118, 1.0}};
815 std::vector<Scalar> stops = {0.0, 1.0};
816
817 Paint paint;
818 paint.color_source = ColorSource::MakeLinearGradient(
819 {0, 0}, {200, 200}, std::move(colors), std::move(stops),
820 Entity::TileMode::kMirror, {});
821 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
822 .style = FilterContents::BlurStyle::kInner,
823 .sigma = Sigma(30),
824 };
825 canvas.DrawPath(PathBuilder()
826 .MoveTo({200, 200})
827 .LineTo({300, 400})
828 .LineTo({100, 400})
829 .Close()
830 .TakePath(),
831 paint);
832
833 // Draw another thing to make sure the clip area is reset.
834 Paint red;
835 red.color = Color::Red();
836 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
837 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
838 }

References impeller::Close(), impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::FilterContents::kInner, impeller::Entity::kMirror, impeller::LineTo(), impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeXYWH(), impeller::MoveTo(), paint, impeller::Color::Red(), impeller::Canvas::Scale(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [192/456]

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

Definition at line 934 of file aiks_blur_unittests.cc.

934 {
935 Canvas canvas;
936 canvas.Scale(GetContentScale());
937
938 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
939
940 Paint paint;
941 paint.color = Color::Green();
942 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
943 .style = FilterContents::BlurStyle::kOuter,
944 .sigma = Sigma(30),
945 };
946 canvas.DrawPath(PathBuilder()
947 .MoveTo({200, 200})
948 .LineTo({300, 400})
949 .LineTo({100, 400})
950 .Close()
951 .TakePath(),
952 paint);
953
954 // Draw another thing to make sure the clip area is reset.
955 Paint red;
956 red.color = Color::Red();
957 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
958
959 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
960 }

References impeller::Close(), impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::FilterContents::kOuter, impeller::LineTo(), impeller::TRect< Scalar >::MakeXYWH(), impeller::MoveTo(), paint, impeller::Color::Red(), impeller::Canvas::Scale(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [193/456]

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

Definition at line 873 of file aiks_blur_unittests.cc.

873 {
874 Canvas canvas;
875 canvas.Scale(GetContentScale());
876
877 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
878
879 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
880 Color{0.7568, 0.2627, 0.2118, 1.0}};
881 std::vector<Scalar> stops = {0.0, 1.0};
882
883 Paint paint;
884 paint.color_source = ColorSource::MakeLinearGradient(
885 {0, 0}, {200, 200}, std::move(colors), std::move(stops),
886 Entity::TileMode::kMirror, {});
887 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
888 .style = FilterContents::BlurStyle::kOuter,
889 .sigma = Sigma(30),
890 };
891 canvas.DrawPath(PathBuilder()
892 .MoveTo({200, 200})
893 .LineTo({300, 400})
894 .LineTo({100, 400})
895 .Close()
896 .TakePath(),
897 paint);
898
899 // Draw another thing to make sure the clip area is reset.
900 Paint red;
901 red.color = Color::Red();
902 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
903 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
904 }

References impeller::Close(), impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kMirror, impeller::FilterContents::kOuter, impeller::LineTo(), impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeXYWH(), impeller::MoveTo(), paint, impeller::Color::Red(), impeller::Canvas::Scale(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [194/456]

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

Definition at line 962 of file aiks_blur_unittests.cc.

962 {
963 Canvas canvas;
964 canvas.Scale(GetContentScale());
965
966 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
967
968 Paint paint;
969 paint.color = Color::Green();
970 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
971 .style = FilterContents::BlurStyle::kSolid,
972 .sigma = Sigma(30),
973 };
974 canvas.DrawPath(PathBuilder()
975 .MoveTo({200, 200})
976 .LineTo({300, 400})
977 .LineTo({100, 400})
978 .Close()
979 .TakePath(),
980 paint);
981
982 // Draw another thing to make sure the clip area is reset.
983 Paint red;
984 red.color = Color::Red();
985 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
986
987 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
988 }

References impeller::Close(), impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::FilterContents::kSolid, impeller::LineTo(), impeller::TRect< Scalar >::MakeXYWH(), impeller::MoveTo(), paint, impeller::Color::Red(), impeller::Canvas::Scale(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [195/456]

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

Definition at line 840 of file aiks_blur_unittests.cc.

840 {
841 Canvas canvas;
842 canvas.Scale(GetContentScale());
843
844 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
845
846 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
847 Color{0.7568, 0.2627, 0.2118, 1.0}};
848 std::vector<Scalar> stops = {0.0, 1.0};
849
850 Paint paint;
851 paint.color_source = ColorSource::MakeLinearGradient(
852 {0, 0}, {200, 200}, std::move(colors), std::move(stops),
853 Entity::TileMode::kMirror, {});
854 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
855 .style = FilterContents::BlurStyle::kSolid,
856 .sigma = Sigma(30),
857 };
858 canvas.DrawPath(PathBuilder()
859 .MoveTo({200, 200})
860 .LineTo({300, 400})
861 .LineTo({100, 400})
862 .Close()
863 .TakePath(),
864 paint);
865
866 // Draw another thing to make sure the clip area is reset.
867 Paint red;
868 red.color = Color::Red();
869 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
870 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
871 }

References impeller::Close(), impeller::Paint::color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kMirror, impeller::FilterContents::kSolid, impeller::LineTo(), impeller::ColorSource::MakeLinearGradient(), impeller::TRect< Scalar >::MakeXYWH(), impeller::MoveTo(), paint, impeller::Color::Red(), impeller::Canvas::Scale(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [196/456]

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

Definition at line 503 of file aiks_blur_unittests.cc.

503 {
504 if (GetParam() != PlaygroundBackend::kMetal) {
505 GTEST_SKIP_(
506 "This backend doesn't yet support setting device capabilities.");
507 }
508 if (!WillRenderSomething()) {
509 // Sometimes these tests are run without playgrounds enabled which is
510 // pointless for this test since we are asserting that
511 // `SupportsDecalSamplerAddressMode` is called.
512 GTEST_SKIP_("This test requires playgrounds.");
513 }
514
515 std::shared_ptr<const Capabilities> old_capabilities =
516 GetContext()->GetCapabilities();
517 auto mock_capabilities = std::make_shared<MockCapabilities>();
518 EXPECT_CALL(*mock_capabilities, SupportsDecalSamplerAddressMode())
519 .Times(::testing::AtLeast(1))
520 .WillRepeatedly(::testing::Return(false));
521 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultColorFormat);
522 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultStencilFormat);
523 FLT_FORWARD(mock_capabilities, old_capabilities,
524 GetDefaultDepthStencilFormat);
525 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsOffscreenMSAA);
526 FLT_FORWARD(mock_capabilities, old_capabilities,
527 SupportsImplicitResolvingMSAA);
528 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsReadFromResolve);
529 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsFramebufferFetch);
530 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsSSBO);
531 FLT_FORWARD(mock_capabilities, old_capabilities, SupportsCompute);
532 FLT_FORWARD(mock_capabilities, old_capabilities,
533 SupportsTextureToTextureBlits);
534 FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultGlyphAtlasFormat);
535 ASSERT_TRUE(SetCapabilities(mock_capabilities).ok());
536
537 auto texture = std::make_shared<Image>(CreateTextureForFixture("boston.jpg"));
538 Canvas canvas;
539 canvas.Scale(GetContentScale() * 0.5);
540 canvas.DrawPaint({.color = Color::Black()});
541 canvas.DrawImage(
542 texture, Point(200, 200),
543 {
544 .image_filter = ImageFilter::MakeBlur(
545 Sigma(20.0), Sigma(20.0), FilterContents::BlurStyle::kNormal,
546 Entity::TileMode::kDecal),
547 });
548 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
549 }

References impeller::Color::Black(), impeller::Canvas::DrawImage(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), FLT_FORWARD, impeller::Entity::kDecal, impeller::kMetal, impeller::FilterContents::kNormal, impeller::ImageFilter::MakeBlur(), and impeller::Canvas::Scale().

## ◆ TEST_P() [197/456]

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

Definition at line 624 of file aiks_dl_gradient_unittests.cc.

624 {
625 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
626 auto callback = [&]() -> sk_sp<DisplayList> {
627 static float scale = 3;
628 static bool add_circle_clip = true;
629 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
630 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
631 DlTileMode::kMirror, DlTileMode::kDecal};
632 static int selected_tile_mode = 0;
633 static float alpha = 1;
634
635 if (AiksTest::ImGuiBegin("Controls", nullptr,
636 ImGuiWindowFlags_AlwaysAutoResize)) {
637 ImGui::SliderFloat("Scale", &scale, 0, 6);
638 ImGui::Checkbox("Circle clip", &add_circle_clip);
639 ImGui::SliderFloat("Alpha", &alpha, 0, 1);
640 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
641 sizeof(tile_mode_names) / sizeof(char*));
642 ImGui::End();
643 }
644
645 DisplayListBuilder builder;
646 builder.Scale(GetContentScale().x, GetContentScale().y);
647 DlPaint paint;
648 paint.setColor(DlColor::kWhite());
649 builder.DrawPaint(paint);
650
651 paint.setDrawStyle(DlDrawStyle::kStroke);
652 paint.setColor(DlColor::kWhite().withAlpha(alpha * 255));
653 paint.setStrokeWidth(10);
654 auto tile_mode = tile_modes[selected_tile_mode];
655
656 std::vector<DlColor> colors = {
657 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
658 DlColor(Color{0.1294, 0.5882, 0.9529, 1.0}.ToARGB())};
659 std::vector<Scalar> stops = {0.0, 1.0};
660
661 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {50, 50},
662 stops.size(), colors.data(),
663 stops.data(), tile_mode));
664
665 SkPath path;
666 path.moveTo(20, 20);
667 path.quadTo({60, 20}, {60, 60});
668 path.close();
669 path.moveTo(60, 20);
670 path.quadTo({60, 60}, {20, 60});
671
672 builder.Scale(scale, scale);
673
674 if (add_circle_clip) {
675 static PlaygroundPoint circle_clip_point_a(Point(60, 300), 20,
676 Color::Red());
677 static PlaygroundPoint circle_clip_point_b(Point(600, 300), 20,
678 Color::Red());
679 auto [handle_a, handle_b] =
680 DrawPlaygroundLine(circle_clip_point_a, circle_clip_point_b);
681
682 SkMatrix screen_to_canvas;
683 if (!builder.GetTransform().invert(&screen_to_canvas)) {
684 return nullptr;
685 }
686 Matrix ip_matrix = ToMatrix(screen_to_canvas);
687 Point point_a = ip_matrix * handle_a * GetContentScale();
688 Point point_b = ip_matrix * handle_b * GetContentScale();
689
690 Point middle = (point_a + point_b) / 2;
691 auto radius = point_a.GetDistance(middle);
692 SkPath circle;
693 circle.addCircle(middle.x, middle.y, radius);
694 builder.ClipPath(circle);
695 }
696
697 for (auto join :
698 {DlStrokeJoin::kBevel, DlStrokeJoin::kRound, DlStrokeJoin::kMiter}) {
699 paint.setStrokeJoin(join);
700 for (auto cap :
701 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
702 paint.setStrokeCap(cap);
703 builder.DrawPath(path, paint);
704 builder.Translate(80, 0);
705 }
706 builder.Translate(-240, 60);
707 }
708
709 return builder.Build();
710 };
711
712 ASSERT_TRUE(OpenPlaygroundHere(callback));
713 }

References impeller::DrawPlaygroundLine(), impeller::TPoint< T >::GetDistance(), paint, scale, impeller::Color::ToARGB(), impeller::ToMatrix(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [198/456]

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

Definition at line 1016 of file aiks_blur_unittests.cc.

1016 {
1017 // This makes sure if mip maps are recycled across invocations of blurs the
1018 // contents get updated each frame correctly. If they aren't updated the color
1019 // inside the blur and outside the blur will be different.
1020 //
1021 // If there is some change to render target caching this could display a false
1022 // positive in the future. Also, if the LOD that is rendered is 1 it could
1023 // present a false positive.
1024 int32_t count = 0;
1025 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
1026 Canvas canvas;
1027 if (count++ == 0) {
1028 canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()});
1029 } else {
1030 canvas.DrawCircle({100, 100}, 50, {.color = Color::Chartreuse()});
1031 }
1032 canvas.ClipRRect(Rect::MakeLTRB(75, 50, 375, 275), {20, 20});
1033 canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
1034 ImageFilter::MakeBlur(Sigma(30.0), Sigma(30.0),
1035 FilterContents::BlurStyle::kNormal,
1036 Entity::TileMode::kClamp));
1037 canvas.Restore();
1038 return canvas.EndRecordingAsPicture();
1039 };
1040
1041 ASSERT_TRUE(OpenPlaygroundHere(callback));
1042 }

References impeller::Color::Chartreuse(), impeller::Canvas::ClipRRect(), impeller::Color::CornflowerBlue(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSource, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [199/456]

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

Definition at line 2611 of file aiks_unittests.cc.

2611 {
2612 // Compare with https://fiddle.skia.org/c/6cdc5aefb291fda3833b806ca347a885
2613
2614 Canvas canvas;
2615 auto texture = CreateTextureForFixture("monkey.png");
2616
2617 canvas.DrawPaint({.color = Color::White()});
2618
2619 // Translation
2620 {
2621 Paint paint;
2622 paint.color_source = ColorSource::MakeImage(
2623 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
2624 Matrix::MakeTranslation({50, 50}));
2625 canvas.DrawRect(Rect::MakeLTRB(0, 0, 100, 100), paint);
2626 }
2627
2628 // Rotation/skew
2629 {
2630 canvas.Save();
2631 canvas.Rotate(Degrees(45));
2632 Paint paint;
2633 paint.color_source = ColorSource::MakeImage(
2634 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
2635 Matrix(1, -1, 0, 0, //
2636 1, 1, 0, 0, //
2637 0, 0, 1, 0, //
2638 0, 0, 0, 1) //
2639 );
2640 canvas.DrawRect(Rect::MakeLTRB(100, 0, 200, 100), paint);
2641 canvas.Restore();
2642 }
2643
2644 // Scale
2645 {
2646 canvas.Translate(Vector2(100, 0));
2647 canvas.Scale(Vector2(100, 100));
2648 Paint paint;
2649 paint.color_source = ColorSource::MakeImage(
2650 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
2651 Matrix::MakeScale(Vector2(0.005, 0.005)));
2652 canvas.DrawRect(Rect::MakeLTRB(0, 0, 1, 1), paint);
2653 }
2654
2655 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2656 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kRepeat, impeller::ColorSource::MakeImage(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), paint, impeller::Canvas::Restore(), impeller::Canvas::Rotate(), impeller::Canvas::Save(), impeller::Canvas::Scale(), impeller::Canvas::Translate(), and impeller::Color::White().

## ◆ TEST_P() [200/456]

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

Definition at line 1910 of file aiks_unittests.cc.

1910 {
1911 Canvas canvas;
1912 canvas.Scale(GetContentScale());
1913
1914 auto test = [&canvas](const std::shared_ptr<ImageFilter>& filter) {
1915 auto DrawLine = [&canvas](const Point& p0, const Point& p1,
1916 const Paint& p) {
1917 auto path = PathBuilder{}
1918 .AddLine(p0, p1)
1919 .SetConvexity(Convexity::kConvex)
1920 .TakePath();
1921 Paint paint = p;
1922 paint.style = Paint::Style::kStroke;
1923 canvas.DrawPath(path, paint);
1924 };
1925 // Registration marks for the edge of the SaveLayer
1926 DrawLine(Point(75, 100), Point(225, 100), {.color = Color::White()});
1927 DrawLine(Point(75, 200), Point(225, 200), {.color = Color::White()});
1928 DrawLine(Point(100, 75), Point(100, 225), {.color = Color::White()});
1929 DrawLine(Point(200, 75), Point(200, 225), {.color = Color::White()});
1930
1931 canvas.SaveLayer({.image_filter = filter},
1932 Rect::MakeLTRB(100, 100, 200, 200));
1933 {
1934 // DrawPaint to verify correct behavior when the contents are unbounded.
1935 canvas.DrawPaint({.color = Color::Yellow()});
1936
1937 // Contrasting rectangle to see interior blurring
1938 canvas.DrawRect(Rect::MakeLTRB(125, 125, 175, 175),
1939 {.color = Color::Blue()});
1940 }
1941 canvas.Restore();
1942 };
1943
1944 test(ImageFilter::MakeBlur(Sigma{10.0}, Sigma{10.0},
1945 FilterContents::BlurStyle::kNormal,
1946 Entity::TileMode::kDecal));
1947
1948 canvas.Translate({200.0, 0.0});
1949
1950 test(ImageFilter::MakeDilate(Radius{10.0}, Radius{10.0}));
1951
1952 canvas.Translate({200.0, 0.0});
1953
1954 test(ImageFilter::MakeErode(Radius{10.0}, Radius{10.0}));
1955
1956 canvas.Translate({-400.0, 200.0});
1957
1958 auto rotate_filter =
1959 ImageFilter::MakeMatrix(Matrix::MakeTranslation({150, 150}) *
1960 Matrix::MakeRotationZ(Degrees{10.0}) *
1961 Matrix::MakeTranslation({-150, -150}),
1962 SamplerDescriptor{});
1963 test(rotate_filter);
1964
1965 canvas.Translate({200.0, 0.0});
1966
1967 auto rgb_swap_filter = ImageFilter::MakeFromColorFilter(
1968 *ColorFilter::MakeMatrix({.array = {
1969 0, 1, 0, 0, 0, //
1970 0, 0, 1, 0, 0, //
1971 1, 0, 0, 0, 0, //
1972 0, 0, 0, 1, 0 //
1973 }}));
1974 test(rgb_swap_filter);
1975
1976 canvas.Translate({200.0, 0.0});
1977
1978 test(ImageFilter::MakeCompose(*rotate_filter, *rgb_swap_filter));
1979
1980 canvas.Translate({-400.0, 200.0});
1981
1982 test(ImageFilter::MakeLocalMatrix(Matrix::MakeTranslation({25.0, 25.0}),
1983 *rotate_filter));
1984
1985 canvas.Translate({200.0, 0.0});
1986
1987 test(ImageFilter::MakeLocalMatrix(Matrix::MakeTranslation({25.0, 25.0}),
1988 *rgb_swap_filter));
1989
1990 canvas.Translate({200.0, 0.0});
1991
1992 test(ImageFilter::MakeLocalMatrix(
1993 Matrix::MakeTranslation({25.0, 25.0}),
1994 *ImageFilter::MakeCompose(*rotate_filter, *rgb_swap_filter)));
1995
1996 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1997 }

References impeller::PathBuilder::AddLine(), impeller::Color::Blue(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kConvex, impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::Paint::kStroke, impeller::ImageFilter::MakeBlur(), impeller::ImageFilter::MakeCompose(), impeller::ImageFilter::MakeDilate(), impeller::ImageFilter::MakeErode(), impeller::ImageFilter::MakeFromColorFilter(), impeller::ImageFilter::MakeLocalMatrix(), impeller::TRect< Scalar >::MakeLTRB(), impeller::ColorFilter::MakeMatrix(), impeller::ImageFilter::MakeMatrix(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeTranslation(), paint, impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), impeller::PathBuilder::SetConvexity(), impeller::PathBuilder::TakePath(), impeller::Canvas::Translate(), impeller::Color::White(), and impeller::Color::Yellow().

## ◆ TEST_P() [201/456]

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

Definition at line 1999 of file aiks_unittests.cc.

1999 {
2000 Canvas canvas;
2001 canvas.Scale(GetContentScale());
2002
2003 auto blur_filter = ImageFilter::MakeBlur(Sigma{10.0}, Sigma{10.0},
2004 FilterContents::BlurStyle::kNormal,
2005 Entity::TileMode::kDecal);
2006
2007 canvas.SaveLayer({.image_filter = blur_filter}, std::nullopt);
2008 {
2009 // DrawPaint to verify correct behavior when the contents are unbounded.
2010 canvas.DrawPaint({.color = Color::Yellow()});
2011
2012 // Contrasting rectangle to see interior blurring
2013 canvas.DrawRect(Rect::MakeLTRB(125, 125, 175, 175),
2014 {.color = Color::Blue()});
2015 }
2016 canvas.Restore();
2017
2018 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2019 }

References impeller::Color::Blue(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::ImageFilter::MakeBlur(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), and impeller::Color::Yellow().

## ◆ TEST_P() [202/456]

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

Definition at line 1820 of file aiks_unittests.cc.

1820 {
1821 Canvas canvas;
1822
1823 canvas.SaveLayer({
1824 .color_filter = ColorFilter::MakeLinearToSrgb(),
1825 });
1826
1827 canvas.Translate({500, 300, 0});
1828 canvas.Rotate(Radians(2 * kPi / 3));
1829 canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
1830
1831 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1832 }

References impeller::Color::Blue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kPi, impeller::ColorFilter::MakeLinearToSrgb(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Rotate(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Translate().

## ◆ TEST_P() [203/456]

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

Definition at line 1198 of file aiks_blur_unittests.cc.

1198 {
1199 Scalar sigma = 70;
1200 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
1201 if (AiksTest::ImGuiBegin("Controls", nullptr,
1202 ImGuiWindowFlags_AlwaysAutoResize)) {
1203 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
1204 ImGui::End();
1205 }
1206 Canvas canvas;
1207 canvas.Scale(GetContentScale());
1208 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
1209
1210 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1211 ColorSource image_source = ColorSource::MakeImage(
1212 boston, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {}, {});
1213
1214 canvas.Transform(Matrix::MakeTranslation({100, 100, 0}) *
1215 Matrix::MakeScale({0.5, 0.5, 1.0}));
1216 Paint paint = {
1217 .color_source = image_source,
1218 .mask_blur_descriptor =
1219 Paint::MaskBlurDescriptor{
1220 .style = FilterContents::BlurStyle::kNormal,
1221 .sigma = Sigma(sigma),
1222 },
1223 };
1224 canvas.DrawRect(
1225 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height),
1226 paint);
1227
1228 return canvas.EndRecordingAsPicture();
1229 };
1230 ASSERT_TRUE(OpenPlaygroundHere(callback));
1231 }

References impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::AiksPlayground::ImGuiBegin(), impeller::FilterContents::kNormal, impeller::Entity::kRepeat, impeller::ColorSource::MakeImage(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Canvas::Scale(), impeller::Paint::MaskBlurDescriptor::style, and impeller::Canvas::Transform().

## ◆ TEST_P() [204/456]

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

Definition at line 990 of file aiks_blur_unittests.cc.

990 {
991 Scalar sigma = 30;
992 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
993 if (AiksTest::ImGuiBegin("Controls", nullptr,
994 ImGuiWindowFlags_AlwaysAutoResize)) {
995 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
996 ImGui::End();
997 }
998 Canvas canvas;
999 canvas.Scale(GetContentScale());
1000 Paint paint;
1001 paint.color = Color::Green();
1002 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
1003 .style = FilterContents::BlurStyle::kNormal,
1004 .sigma = Sigma(sigma),
1005 };
1006 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1007 canvas.DrawImage(std::make_shared<Image>(boston), {200, 200}, paint);
1008 Paint red;
1009 red.color = Color::Red();
1010 canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
1011 return canvas.EndRecordingAsPicture();
1012 };
1013 ASSERT_TRUE(OpenPlaygroundHere(callback));
1014 }

References impeller::Paint::color, impeller::Canvas::DrawImage(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::AiksPlayground::ImGuiBegin(), impeller::FilterContents::kNormal, impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Color::Red(), impeller::Canvas::Scale(), and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [205/456]

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

Definition at line 277 of file aiks_blur_unittests.cc.

277 {
278 Canvas canvas;
279
280 Paint paint = {
281 .color = Color::Blue(),
282 .mask_blur_descriptor =
283 Paint::MaskBlurDescriptor{
284 .style = FilterContents::BlurStyle::kNormal,
285 .sigma = Sigma(0),
286 },
287 };
288
289 canvas.DrawCircle({300, 300}, 200, paint);
290 canvas.DrawRect(Rect::MakeLTRB(100, 300, 500, 600), paint);
291
292 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
293 }

References impeller::Color::Blue(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::FilterContents::kNormal, impeller::TRect< Scalar >::MakeLTRB(), paint, and impeller::Paint::MaskBlurDescriptor::style.

## ◆ TEST_P() [206/456]

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

Definition at line 2366 of file aiks_unittests.cc.

2366 {
2367 Canvas canvas;
2368 canvas.DrawPaint({.color = Color::Black()});
2369 canvas.SaveLayer({}, std::nullopt);
2370 {
2371 canvas.DrawCircle(Point(200, 200), 100,
2372 {.color = Color::Green().WithAlpha(0.5),
2373 .blend_mode = BlendMode::kPlus});
2374 // Should render a second circle, centered on the bottom-right-most edge of
2375 // the circle.
2376 canvas.SaveLayer(
2377 {}, std::nullopt,
2378 ImageFilter::MakeMatrix(
2379 Matrix::MakeTranslation(Vector2(1, 1) * (100 + 100 * k1OverSqrt2)) *
2380 Matrix::MakeScale(Vector2(1, 1) * 0.5) *
2381 Matrix::MakeTranslation(Vector2(-100, -100)),
2382 SamplerDescriptor{}));
2383 canvas.Restore();
2384 }
2385 canvas.Restore();
2386
2387 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2388 }

References impeller::Color::Black(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::k1OverSqrt2, impeller::kPlus, impeller::ImageFilter::MakeMatrix(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [207/456]

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

Definition at line 2530 of file aiks_unittests.cc.

2531 {
2532 Canvas canvas;
2533 canvas.Scale(GetContentScale());
2534 canvas.Translate({100, 100});
2535 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
2536 // +300 translation applied by a SaveLayer image filter.
2537 canvas.SaveLayer({
2538 .image_filter = std::make_shared<MatrixImageFilter>(
2539 Matrix::MakeTranslation({300, 0}) * Matrix::MakeScale({2, 2, 2}),
2540 SamplerDescriptor{}),
2541 });
2542 canvas.DrawCircle({-150, 0}, 50, {.color = Color::Green()});
2543 canvas.Restore();
2544
2545 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2546 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [208/456]

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

Definition at line 2513 of file aiks_unittests.cc.

2513 {
2514 Canvas canvas;
2515 canvas.Scale(GetContentScale());
2516 canvas.Translate({100, 100});
2517 // Draw a circle in a SaveLayer at -300, but move it back on-screen with a
2518 // +300 translation applied by a SaveLayer image filter.
2519 canvas.SaveLayer({
2520 .image_filter = std::make_shared<MatrixImageFilter>(
2521 Matrix::MakeTranslation({300, 0}), SamplerDescriptor{}),
2522 });
2523 canvas.DrawCircle({-300, 0}, 100, {.color = Color::Green()});
2524 canvas.Restore();
2525
2526 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2527 }

References impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::Matrix::MakeTranslation(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [209/456]

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

Definition at line 2486 of file aiks_unittests.cc.

2486 {
2487 Scalar scale = 2.0;
2488 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
2489 if (AiksTest::ImGuiBegin("Controls", nullptr,
2490 ImGuiWindowFlags_AlwaysAutoResize)) {
2491 ImGui::SliderFloat("Scale", &scale, 1, 2);
2492 ImGui::End();
2493 }
2494 Canvas canvas;
2495 canvas.Scale(GetContentScale());
2496 auto image =
2497 std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2498 canvas.Translate({600, -200});
2499 canvas.SaveLayer({
2500 .image_filter = std::make_shared<MatrixImageFilter>(
2501 Matrix::MakeScale({scale, scale, 1}), SamplerDescriptor{}),
2502 });
2503 canvas.DrawImage(image, {0, 0},
2504 Paint{.color = Color::White().WithAlpha(0.5)});
2505 canvas.Restore();
2506 return canvas.EndRecordingAsPicture();
2507 };
2508
2509 ASSERT_TRUE(OpenPlaygroundHere(callback));
2510 }

References impeller::Paint::color, impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::AiksPlayground::ImGuiBegin(), impeller::Matrix::MakeScale(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), scale, impeller::Canvas::Translate(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [210/456]

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

Definition at line 2339 of file aiks_unittests.cc.

2339 {
2340 Canvas canvas;
2341 canvas.DrawPaint({.color = Color::Black()});
2342 canvas.SaveLayer({}, std::nullopt);
2343 {
2344 canvas.DrawCircle(Point(200, 200), 100,
2345 {.color = Color::Green().WithAlpha(0.5),
2346 .blend_mode = BlendMode::kPlus});
2347 // Should render a second circle, centered on the bottom-right-most edge of
2348 // the circle.
2349 canvas.SaveLayer({.image_filter = ImageFilter::MakeMatrix(
2350 Matrix::MakeTranslation(Vector2(1, 1) *
2351 (200 + 100 * k1OverSqrt2)) *
2352 Matrix::MakeScale(Vector2(1, 1) * 0.5) *
2353 Matrix::MakeTranslation(Vector2(-200, -200)),
2354 SamplerDescriptor{})},
2355 std::nullopt);
2356 canvas.DrawCircle(Point(200, 200), 100,
2357 {.color = Color::Green().WithAlpha(0.5),
2358 .blend_mode = BlendMode::kPlus});
2359 canvas.Restore();
2360 }
2361 canvas.Restore();
2362
2363 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2364 }

References impeller::Color::Black(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::k1OverSqrt2, impeller::kPlus, impeller::ImageFilter::MakeMatrix(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [211/456]

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

Definition at line 2785 of file aiks_unittests.cc.

2785 {
2786 TextureDescriptor texture_descriptor;
2787 texture_descriptor.size = ISize{1024, 1024};
2788 texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
2789 texture_descriptor.storage_mode = StorageMode::kHostVisible;
2790 texture_descriptor.mip_count = texture_descriptor.size.MipCount();
2791
2792 std::vector<uint8_t> bytes(4194304);
2793 bool alternate = false;
2794 for (auto i = 0u; i < 4194304; i += 4) {
2795 if (alternate) {
2796 bytes[i] = 255;
2797 bytes[i + 1] = 0;
2798 bytes[i + 2] = 0;
2799 bytes[i + 3] = 255;
2800 } else {
2801 bytes[i] = 0;
2802 bytes[i + 1] = 255;
2803 bytes[i + 2] = 0;
2804 bytes[i + 3] = 255;
2805 }
2806 alternate = !alternate;
2807 }
2808
2809 ASSERT_EQ(texture_descriptor.GetByteSizeOfBaseMipLevel(), bytes.size());
2810 auto mapping = std::make_shared<fml::NonOwnedMapping>(
2811 bytes.data(), // data
2812 texture_descriptor.GetByteSizeOfBaseMipLevel() // size
2813 );
2814 auto texture =
2815 GetContext()->GetResourceAllocator()->CreateTexture(texture_descriptor);
2816
2817 auto device_buffer =
2818 GetContext()->GetResourceAllocator()->CreateBufferWithCopy(*mapping);
2819 auto command_buffer = GetContext()->CreateCommandBuffer();
2820 auto blit_pass = command_buffer->CreateBlitPass();
2821
2822 blit_pass->AddCopy(DeviceBuffer::AsBufferView(std::move(device_buffer)),
2823 texture);
2824 blit_pass->GenerateMipmap(texture);
2825 EXPECT_TRUE(blit_pass->EncodeCommands(GetContext()->GetResourceAllocator()));
2826 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({command_buffer}).ok());
2827
2828 auto image = std::make_shared<Image>(texture);
2829
2830 Canvas canvas;
2831 canvas.DrawImageRect(image, Rect::MakeSize(texture->GetSize()),
2832 Rect::MakeLTRB(0, 0, 100, 100), {});
2833
2834 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2835 }

References impeller::DeviceBuffer::AsBufferView(), impeller::Canvas::DrawImageRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TextureDescriptor::format, impeller::TextureDescriptor::GetByteSizeOfBaseMipLevel(), impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeSize(), impeller::TextureDescriptor::mip_count, impeller::TSize< T >::MipCount(), impeller::TextureDescriptor::size, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [212/456]

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

Definition at line 2137 of file aiks_unittests.cc.

2137 {
2138 Canvas canvas;
2139 canvas.Scale(Vector2(1.618, 1.618));
2140 canvas.DrawCircle(Point(), 10,
2141 {
2142 .color = Color::CornflowerBlue(),
2143 .blend_mode = BlendMode::kSourceOver,
2144 });
2145 Picture picture = canvas.EndRecordingAsPicture();
2146
2147 // Extract the SolidColorSource.
2148 // Entity entity;
2149 std::vector<Entity> entity;
2150 std::shared_ptr<SolidColorContents> contents;
2151 picture.pass->IterateAllEntities([e = &entity, &contents](Entity& entity) {
2152 if (ScalarNearlyEqual(entity.GetTransform().GetScale().x, 1.618f)) {
2153 contents =
2154 std::static_pointer_cast<SolidColorContents>(entity.GetContents());
2155 e->emplace_back(entity.Clone());
2156 return false;
2157 }
2158 return true;
2159 });
2160
2161 ASSERT_TRUE(entity.size() >= 1);
2162 ASSERT_TRUE(contents->IsOpaque());
2163 ASSERT_EQ(entity[0].GetBlendMode(), BlendMode::kSource);
2164 }

References impeller::Entity::Clone(), impeller::Color::CornflowerBlue(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::GetContents(), impeller::Matrix::GetScale(), impeller::Entity::GetTransform(), impeller::kSource, impeller::kSourceOver, impeller::Picture::pass, impeller::ScalarNearlyEqual(), impeller::Canvas::Scale(), and impeller::Vector3::x.

## ◆ TEST_P() [213/456]

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

Definition at line 114 of file aiks_blend_unittests.cc.

114 {
115 Paint paint;
116 Canvas canvas;
117 // Default is kSourceOver.
118 paint.color = Color(1, 0, 0, 0.5);
119 canvas.DrawCircle(Point(150, 200), 100, paint);
120 paint.color = Color(0, 1, 0, 0.5);
121 canvas.DrawCircle(Point(250, 200), 100, paint);
122
123 paint.blend_mode = BlendMode::kPlus;
124 paint.color = Color::Red();
125 canvas.DrawCircle(Point(450, 250), 100, paint);
126 paint.color = Color::Green();
127 canvas.DrawCircle(Point(550, 250), 100, paint);
128 paint.color = Color::Blue();
129 canvas.DrawCircle(Point(500, 150), 100, paint);
130 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
131 }

References impeller::Color::Blue(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::kPlus, paint, and impeller::Color::Red().

## ◆ TEST_P() [214/456]

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

Definition at line 1567 of file aiks_unittests.cc.

1567 {
1568 // validate that a paint with a color filter "HasFilters", no other filters
1569 // impact this setting.
1570 Paint paint;
1571
1572 ASSERT_FALSE(paint.HasColorFilter());
1573
1574 paint.color_filter =
1575 ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Blue());
1576
1577 ASSERT_TRUE(paint.HasColorFilter());
1578
1579 paint.image_filter = ImageFilter::MakeBlur(Sigma(1.0), Sigma(1.0),
1580 FilterContents::BlurStyle::kNormal,
1581 Entity::TileMode::kClamp);
1582
1583 ASSERT_TRUE(paint.HasColorFilter());
1584
1585 paint.mask_blur_descriptor = {};
1586
1587 ASSERT_TRUE(paint.HasColorFilter());
1588
1589 paint.color_filter = nullptr;
1590
1591 ASSERT_FALSE(paint.HasColorFilter());
1592 }

References impeller::Color::Blue(), impeller::Entity::kClamp, impeller::FilterContents::kNormal, impeller::kSourceOver, impeller::ColorFilter::MakeBlend(), impeller::ImageFilter::MakeBlur(), and paint.

## ◆ TEST_P() [215/456]

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

Definition at line 1618 of file aiks_unittests.cc.

1619 {
1620 Canvas canvas;
1621 canvas.SaveLayer({}, std::nullopt, ImageFilter::MakeMatrix(Matrix(), {}));
1622 canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
1623 canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
1624 .blend_mode = BlendMode::kSourceOver});
1625 canvas.Restore();
1626
1627 Picture picture = canvas.EndRecordingAsPicture();
1628
1629 std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
1630 std::shared_ptr<Context> real_context = GetContext();
1631 std::shared_ptr<ContextMock> mock_context = spy->MakeContext(real_context);
1632 AiksContext renderer(mock_context, nullptr);
1633 std::shared_ptr<Image> image = picture.ToImage(renderer, {300, 300});
1634
1635 ASSERT_EQ(spy->render_passes_.size(),
1636 GetBackend() == PlaygroundBackend::kOpenGLES ? 4llu : 3llu);
1637 std::shared_ptr<RenderPass> render_pass = spy->render_passes_[0];
1638 ASSERT_EQ(render_pass->GetCommands().size(), 0llu);
1639 }

References impeller::Color::CornflowerBlue(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kOpenGLES, impeller::kSource, impeller::kSourceOver, impeller::ImageFilter::MakeMatrix(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Picture::ToImage(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [216/456]

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

Definition at line 2430 of file aiks_unittests.cc.

2430 {
2431 Canvas canvas;
2432
2433 // Should render a green square in the middle of a blue circle.
2434 canvas.SaveLayer({});
2435 {
2436 canvas.Translate(Point(100, 100));
2437 canvas.DrawCircle(Point(200, 200), 200, {.color = Color::Blue()});
2438 canvas.ClipRect(Rect::MakeXYWH(100, 100, 200, 200));
2439 canvas.DrawCircle(Point(200, 200), 200,
2440 {
2441 .color = Color::Green(),
2442 .blend_mode = BlendMode::kSourceOver,
2443 .image_filter = ImageFilter::MakeFromColorFilter(
2444 *ColorFilter::MakeBlend(BlendMode::kDestination,
2445 Color::White())),
2446 });
2447 canvas.Restore();
2448 }
2449
2450 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2451 }

References impeller::Color::Blue(), impeller::Canvas::ClipRect(), impeller::Canvas::DrawCircle(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::kDestination, impeller::kSourceOver, impeller::ColorFilter::MakeBlend(), impeller::ImageFilter::MakeFromColorFilter(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Translate(), and impeller::Color::White().

## ◆ TEST_P() [217/456]

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

Definition at line 2454 of file aiks_unittests.cc.

2454 {
2455 auto context = MakeContext();
2456 std::weak_ptr<Texture> weak_texture;
2457
2458 {
2459 auto texture = CreateTextureForFixture("table_mountain_nx.png");
2460
2461 Canvas canvas;
2462 canvas.Scale(GetContentScale());
2463 canvas.Translate({100.0f, 100.0f, 0});
2464
2465 Paint paint;
2466 paint.color_source = ColorSource::MakeImage(
2467 texture, Entity::TileMode::kClamp, Entity::TileMode::kClamp, {}, {});
2468 canvas.DrawRect(Rect::MakeXYWH(0, 0, 600, 600), paint);
2469
2470 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2471 }
2472
2473 // See https://github.com/flutter/flutter/issues/134751.
2474 //
2475 // If the fence waiter was working this may not be released by the end of the
2476 // scope above. Adding a manual shutdown so that future changes to the fence
2477 // waiter will not flake this test.
2478 context->Shutdown();
2479
2480 // The texture should be released by now.
2481 ASSERT_TRUE(weak_texture.expired()) << "When the texture is no longer in use "
2482 "by the backend, it should be "
2483 "released.";
2484 }

References impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Entity::kClamp, impeller::ColorSource::MakeImage(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [218/456]

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

Definition at line 19 of file aiks_dl_path_unittests.cc.

19 {
20 DisplayListBuilder builder;
21 builder.Transform(SkMatrix::Translate(300, 300) * SkMatrix::RotateDeg(90));
22
23 SkPath arrow_stem;
24 SkPath arrow_head;
25
26 arrow_stem.moveTo({120, 190}).lineTo({120, 50});
27 arrow_head.moveTo({50, 120}).lineTo({120, 190}).lineTo({190, 120});
28
29 auto filter =
30 DlBlendColorFilter::Make(DlColor::kAliceBlue(), DlBlendMode::kSrcIn);
31
32 DlPaint paint;
33 paint.setStrokeWidth(15.0);
34 paint.setStrokeCap(DlStrokeCap::kRound);
35 paint.setStrokeJoin(DlStrokeJoin::kRound);
36 paint.setDrawStyle(DlDrawStyle::kStroke);
37 paint.setColorFilter(filter);
38 paint.setColor(DlColor::kBlack());
39
40 builder.DrawPath(arrow_stem, paint);
41 builder.DrawPath(arrow_head, paint);
42
43 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
44 }

References paint.

## ◆ TEST_P() [219/456]

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

Definition at line 1415 of file aiks_unittests.cc.

1415 {
1416 // Compare with https://fiddle.skia.org/c/9e03de8567ffb49e7e83f53b64bcf636
1417 Canvas canvas;
1418 Paint paint;
1419
1420 paint.color = Color::Black();
1421 Rect rect = Rect::MakeXYWH(25, 25, 25, 25);
1422 canvas.DrawRect(rect, paint);
1423
1424 canvas.Translate({10, 10});
1425 canvas.SaveLayer({});
1426
1427 paint.color = Color::Green();
1428 canvas.DrawRect(rect, paint);
1429
1430 canvas.Restore();
1431
1432 canvas.Translate({10, 10});
1433 paint.color = Color::Red();
1434 canvas.DrawRect(rect, paint);
1435
1436 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1437 }

References impeller::Color::Black(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Translate().

## ◆ TEST_P() [220/456]

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

Definition at line 1496 of file aiks_unittests.cc.

1496 {
1497 Canvas canvas;
1498 canvas.Scale(GetContentScale());
1499 canvas.Translate(Vector2(100, 100));
1500
1501 auto texture = std::make_shared<Image>(CreateTextureForFixture("boston.jpg"));
1502 auto draw_image_layer = [&canvas, &texture](const Paint& paint) {
1503 canvas.SaveLayer(paint);
1504 canvas.DrawImage(texture, {}, Paint{});
1505 canvas.Restore();
1506 };
1507
1508 Paint effect_paint;
1509 effect_paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
1510 .style = FilterContents::BlurStyle::kNormal,
1511 .sigma = Sigma{6},
1512 };
1513 draw_image_layer(effect_paint);
1514
1515 canvas.Translate(Vector2(300, 300));
1516 canvas.Scale(Vector2(3, 3));
1517 draw_image_layer(effect_paint);
1518
1519 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1520 }

References impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::FilterContents::kNormal, impeller::Paint::mask_blur_descriptor, paint, impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), impeller::Canvas::Scale(), impeller::Paint::MaskBlurDescriptor::style, and impeller::Canvas::Translate().

## ◆ TEST_P() [221/456]

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

Definition at line 2878 of file aiks_unittests.cc.

2878 {
2879 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
2880
2881 // Replace part of the texture with a red rectangle.
2882 std::vector<uint8_t> bytes(100 * 100 * 4);
2883 for (auto i = 0u; i < bytes.size(); i += 4) {
2884 bytes[i] = 255;
2885 bytes[i + 1] = 0;
2886 bytes[i + 2] = 0;
2887 bytes[i + 3] = 255;
2888 }
2889 auto mapping =
2890 std::make_shared<fml::NonOwnedMapping>(bytes.data(), bytes.size());
2891 auto device_buffer =
2892 GetContext()->GetResourceAllocator()->CreateBufferWithCopy(*mapping);
2893 auto cmd_buffer = GetContext()->CreateCommandBuffer();
2894 auto blit_pass = cmd_buffer->CreateBlitPass();
2895 blit_pass->AddCopy(DeviceBuffer::AsBufferView(device_buffer), bridge,
2896 IRect::MakeLTRB(50, 50, 150, 150));
2897
2898 auto did_submit =
2899 blit_pass->EncodeCommands(GetContext()->GetResourceAllocator()) &&
2900 GetContext()->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok();
2901 ASSERT_TRUE(did_submit);
2902
2903 auto image = std::make_shared<Image>(bridge);
2904
2905 Canvas canvas;
2906 canvas.DrawImage(image, {0, 0}, {});
2907
2908 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2909 }

References impeller::DeviceBuffer::AsBufferView(), impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), and impeller::TRect< T >::MakeLTRB().

## ◆ TEST_P() [222/456]

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

Definition at line 1439 of file aiks_unittests.cc.

1439 {
1440 Canvas canvas;
1441 Paint paint;
1442 Rect rect = Rect::MakeXYWH(0, 0, 1000, 1000);
1443
1444 // Black, green, and red squares offset by [10, 10].
1445 {
1446 canvas.SaveLayer({}, Rect::MakeXYWH(25, 25, 25, 25));
1447 paint.color = Color::Black();
1448 canvas.DrawRect(rect, paint);
1449 canvas.Restore();
1450 }
1451
1452 {
1453 canvas.SaveLayer({}, Rect::MakeXYWH(35, 35, 25, 25));
1454 paint.color = Color::Green();
1455 canvas.DrawRect(rect, paint);
1456 canvas.Restore();
1457 }
1458
1459 {
1460 canvas.SaveLayer({}, Rect::MakeXYWH(45, 45, 25, 25));
1461 paint.color = Color::Red();
1462 canvas.DrawRect(rect, paint);
1463 canvas.Restore();
1464 }
1465
1466 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1467 }

References impeller::Color::Black(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::TRect< Scalar >::MakeXYWH(), paint, impeller::Color::Red(), impeller::Canvas::Restore(), and impeller::Canvas::SaveLayer().

## ◆ TEST_P() [223/456]

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

Definition at line 2390 of file aiks_unittests.cc.

2390 {
2391 auto contents = SolidColorContents();
2392 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.75));
2393 auto result = contents.ApplyColorFilter([](const Color& color) {
2394 return color.Blend(Color::LimeGreen().WithAlpha(0.75), BlendMode::kScreen);
2395 });
2396 ASSERT_TRUE(result);
2397 ASSERT_COLOR_NEAR(contents.GetColor(),
2398 Color(0.424452, 0.828743, 0.79105, 0.9375));
2399 }

References ASSERT_COLOR_NEAR, color, impeller::Color::CornflowerBlue(), impeller::kScreen, and impeller::Color::LimeGreen().

## ◆ TEST_P() [224/456]

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

Definition at line 1200 of file aiks_unittests.cc.

1200 {
1201 Canvas canvas;
1202 canvas.Scale(GetContentScale());
1203 Paint paint;
1204 paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
1205 .style = FilterContents::BlurStyle::kNormal,
1206 .sigma = Sigma{1},
1207 };
1208
1209 canvas.DrawPaint({.color = Color::White()});
1210
1211 paint.color = Color::Crimson();
1212 Scalar y = 100.0f;
1213 for (int i = 0; i < 5; i++) {
1214 Scalar x = (i + 1) * 100;
1215 Scalar radius = x / 10.0f;
1216 canvas.DrawRect(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
1217 radius, 60.0f - radius),
1218 paint);
1219 }
1220
1221 paint.color = Color::Blue();
1222 y += 100.0f;
1223 for (int i = 0; i < 5; i++) {
1224 Scalar x = (i + 1) * 100;
1225 Scalar radius = x / 10.0f;
1226 canvas.DrawCircle({x + 25, y + 25}, radius, paint);
1227 }
1228
1229 paint.color = Color::Green();
1230 y += 100.0f;
1231 for (int i = 0; i < 5; i++) {
1232 Scalar x = (i + 1) * 100;
1233 Scalar radius = x / 10.0f;
1234 canvas.DrawOval(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
1235 radius, 60.0f - radius),
1236 paint);
1237 }
1238
1239 paint.color = Color::Purple();
1240 y += 100.0f;
1241 for (int i = 0; i < 5; i++) {
1242 Scalar x = (i + 1) * 100;
1243 Scalar radius = x / 20.0f;
1244 canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), //
1245 {radius, radius}, //
1246 paint);
1247 }
1248
1249 paint.color = Color::Orange();
1250 y += 100.0f;
1251 for (int i = 0; i < 5; i++) {
1252 Scalar x = (i + 1) * 100;
1253 Scalar radius = x / 20.0f;
1254 canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), //
1255 {radius, 5.0f}, paint);
1256 }
1257
1258 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1259 }

References impeller::Color::Blue(), impeller::Color::Crimson(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawOval(), impeller::Canvas::DrawPaint(), impeller::Canvas::DrawRect(), impeller::Canvas::DrawRRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::FilterContents::kNormal, impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Orange(), paint, impeller::Color::Purple(), impeller::Canvas::Scale(), impeller::Paint::MaskBlurDescriptor::style, and impeller::Color::White().

## ◆ TEST_P() [225/456]

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

Definition at line 187 of file aiks_path_unittests.cc.

187 {
188 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
189 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
190 static Color color = Color::Black().WithAlpha(0.5);
191 static float scale = 3;
192 static bool add_circle_clip = true;
193
194 if (AiksTest::ImGuiBegin("Controls", nullptr,
195 ImGuiWindowFlags_AlwaysAutoResize)) {
196 ImGui::ColorEdit4("Color", reinterpret_cast<float*>(&color));
197 ImGui::SliderFloat("Scale", &scale, 0, 6);
198 ImGui::Checkbox("Circle clip", &add_circle_clip);
199 ImGui::End();
200 }
201
202 Canvas canvas;
203 canvas.Scale(GetContentScale());
204 Paint paint;
205
206 paint.color = Color::White();
207 canvas.DrawPaint(paint);
208
209 paint.color = color;
210 paint.style = Paint::Style::kStroke;
211 paint.stroke_width = 10;
212
213 Path path = PathBuilder{}
214 .MoveTo({20, 20})
215 .QuadraticCurveTo({60, 20}, {60, 60})
216 .Close()
217 .MoveTo({60, 20})
218 .QuadraticCurveTo({60, 60}, {20, 60})
219 .TakePath();
220
221 canvas.Scale(Vector2(scale, scale));
222
223 if (add_circle_clip) {
224 static PlaygroundPoint circle_clip_point_a(Point(60, 300), 20,
225 Color::Red());
226 static PlaygroundPoint circle_clip_point_b(Point(600, 300), 20,
227 Color::Red());
228 auto [handle_a, handle_b] =
229 DrawPlaygroundLine(circle_clip_point_a, circle_clip_point_b);
230
231 auto screen_to_canvas = canvas.GetCurrentTransform().Invert();
232 Point point_a = screen_to_canvas * handle_a * GetContentScale();
233 Point point_b = screen_to_canvas * handle_b * GetContentScale();
234
235 Point middle = (point_a + point_b) / 2;
236 auto radius = point_a.GetDistance(middle);
237 canvas.ClipPath(PathBuilder{}.AddCircle(middle, radius).TakePath());
238 }
239
240 for (auto join : {Join::kBevel, Join::kRound, Join::kMiter}) {
241 paint.stroke_join = join;
242 for (auto cap : {Cap::kButt, Cap::kSquare, Cap::kRound}) {
243 paint.stroke_cap = cap;
244 canvas.DrawPath(path, paint);
245 canvas.Translate({80, 0});
246 }
247 canvas.Translate({-240, 60});
248 }
249
250 return canvas.EndRecordingAsPicture();
251 };
252
253 ASSERT_TRUE(OpenPlaygroundHere(callback));
254 }

References impeller::PathBuilder::AddCircle(), impeller::Color::Black(), impeller::Canvas::ClipPath(), impeller::Close(), color, impeller::Canvas::DrawPaint(), impeller::Canvas::DrawPath(), impeller::DrawPlaygroundLine(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::GetCurrentTransform(), impeller::TPoint< T >::GetDistance(), impeller::AiksPlayground::ImGuiBegin(), impeller::Matrix::Invert(), impeller::kBevel, impeller::kButt, impeller::kMiter, impeller::kRound, impeller::kSquare, impeller::Paint::kStroke, impeller::PathBuilder::MoveTo(), paint, impeller::Color::Red(), impeller::Canvas::Scale(), scale, impeller::PathBuilder::TakePath(), impeller::Canvas::Translate(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [226/456]

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

Definition at line 1834 of file aiks_unittests.cc.

1834 {
1835 Canvas canvas;
1836
1837 canvas.SaveLayer({
1838 .color_filter = ColorFilter::MakeSrgbToLinear(),
1839 });
1840
1841 canvas.Translate({500, 300, 0});
1842 canvas.Rotate(Radians(2 * kPi / 3));
1843 canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
1844
1845 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1846 }

References impeller::Color::Blue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kPi, impeller::ColorFilter::MakeSrgbToLinear(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Rotate(), impeller::Canvas::SaveLayer(), and impeller::Canvas::Translate().

## ◆ TEST_P() [227/456]

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

Definition at line 982 of file aiks_unittests.cc.

982 {
983 Canvas canvas;
984 canvas.Scale(GetContentScale());
985 Paint paint;
986 const int color_count = 3;
987 Color colors[color_count] = {
988 Color::Blue(),
989 Color::Green(),
990 Color::Crimson(),
991 };
992
993 paint.color = Color::White();
994 canvas.DrawPaint(paint);
995
996 int c_index = 0;
997
998 auto draw = [&paint, &colors, &c_index](Canvas& canvas, Point center,
999 Scalar r, Scalar dr, int n) {
1000 for (int i = 0; i < n; i++) {
1001 paint.color = colors[(c_index++) % color_count];
1002 canvas.DrawCircle(center, r, paint);
1003 r += dr;
1004 }
1005 };
1006
1007 paint.style = Paint::Style::kStroke;
1008 paint.stroke_width = 1;
1009 draw(canvas, {10, 10}, 2, 2, 14); // r = [2, 28], covers [1,29]
1010 paint.stroke_width = 5;
1011 draw(canvas, {10, 10}, 35, 10, 56); // r = [35, 585], covers [30,590]
1012
1013 std::vector<Color> gradient_colors = {
1014 Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0},
1015 Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0},
1016 Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0},
1017 Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0},
1018 Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0},
1019 Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0},
1020 Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}};
1021 std::vector<Scalar> stops = {
1022 0.0,
1023 (1.0 / 6.0) * 1,
1024 (1.0 / 6.0) * 2,
1025 (1.0 / 6.0) * 3,
1026 (1.0 / 6.0) * 4,
1027 (1.0 / 6.0) * 5,
1028 1.0,
1029 };
1030 auto texture = CreateTextureForFixture("airplane.jpg",
1031 /*enable_mipmapping=*/true);
1032
1033 paint.color_source = ColorSource::MakeRadialGradient(
1034 {500, 600}, 75, std::move(gradient_colors), std::move(stops),
1035 Entity::TileMode::kMirror, {});
1036 draw(canvas, {500, 600}, 5, 10, 10);
1037
1038 paint.color_source = ColorSource::MakeImage(
1039 texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {},
1040 Matrix::MakeTranslation({700, 200}));
1041 draw(canvas, {800, 300}, 5, 10, 10);
1042
1043 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1044 }

References impeller::Color::Blue(), impeller::Color::Crimson(), impeller::Canvas::DrawPaint(), impeller::Color::Green(), impeller::Entity::kMirror, impeller::Entity::kRepeat, impeller::Paint::kStroke, impeller::ColorSource::MakeImage(), impeller::ColorSource::MakeRadialGradient(), impeller::Matrix::MakeTranslation(), paint, impeller::Canvas::Scale(), and impeller::Color::White().

## ◆ TEST_P() [228/456]

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

Definition at line 2838 of file aiks_unittests.cc.

2838 {
2839 Path path = PathBuilder{}
2840 .MoveTo({0, 400})
2841 .LineTo({0, 0})
2842 .LineTo({400, 0})
2843 // MoveTo implicitly adds a contour, ensure that close doesn't
2844 // add another nearly-empty contour.
2845 .MoveTo({0, 400})
2846 .Close()
2847 .TakePath();
2848
2849 Canvas canvas;
2850 canvas.Translate({50, 50, 0});
2851 canvas.DrawPath(path, {
2852 .color = Color::Blue(),
2853 .stroke_width = 10,
2854 .stroke_cap = Cap::kRound,
2855 .style = Paint::Style::kStroke,
2856 });
2857 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2858 }

References impeller::Color::Blue(), impeller::Close(), impeller::Canvas::DrawPath(), impeller::Canvas::EndRecordingAsPicture(), impeller::kRound, impeller::Paint::kStroke, impeller::LineTo(), impeller::MoveTo(), impeller::PathBuilder::MoveTo(), and impeller::Canvas::Translate().

## ◆ TEST_P() [229/456]

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

Definition at line 2589 of file aiks_unittests.cc.

2589 {
2590 Canvas canvas;
2591
2592 // Use a non-srcOver blend mode to ensure that we don't detect this as an
2593 // opacity peephole optimization.
2594 canvas.SaveLayer(
2595 {.color = Color::Blue().WithAlpha(0.5), .blend_mode = BlendMode::kSource},
2596 Rect::MakeLTRB(0, 0, 200, 200));
2597 canvas.DrawPaint(
2598 {.color = Color::BlackTransparent(), .blend_mode = BlendMode::kSource});
2599 canvas.Restore();
2600
2601 canvas.SaveLayer(
2602 {.color = Color::Blue(), .blend_mode = BlendMode::kDestinationOver});
2603 canvas.Restore();
2604
2605 // This playground should appear blank on CI since we are only drawing
2606 // transparent black. If the clear color optimization is broken, the texture
2607 // will be filled with NaNs and may produce a magenta texture on macOS or iOS.
2608 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2609 }

References impeller::Color::BlackTransparent(), impeller::Color::Blue(), impeller::Canvas::DrawPaint(), impeller::Canvas::EndRecordingAsPicture(), impeller::kDestinationOver, impeller::kSource, impeller::TRect< Scalar >::MakeLTRB(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [230/456]

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

Definition at line 2306 of file aiks_unittests.cc.

2306 {
2307 auto mapping = flutter::testing::OpenFixtureAsSkData("Roboto-Regular.ttf");
2308 ASSERT_NE(mapping, nullptr);
2309
2310 Scalar font_size = 100;
2311 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
2312 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
2313
2314 Paint text_paint;
2315 text_paint.color = Color::Blue();
2316
2317 std::vector<Color> colors = {Color{0.9568, 0.2627, 0.2118, 1.0},
2318 Color{0.1294, 0.5882, 0.9529, 1.0}};
2319 std::vector<Scalar> stops = {
2320 0.0,
2321 1.0,
2322 };
2323 text_paint.color_source = ColorSource::MakeLinearGradient(
2324 {0, 0}, {100, 100}, std::move(colors), std::move(stops),
2325 Entity::TileMode::kRepeat, {});
2326
2327 Canvas canvas;
2328 canvas.Translate({100, 100});
2329 canvas.Rotate(Radians(kPi / 4));
2330
2331 auto blob = SkTextBlob::MakeFromString("Hello", sk_font);
2332 ASSERT_NE(blob, nullptr);
2333 auto frame = MakeTextFrameFromTextBlobSkia(blob);
2334 canvas.DrawTextFrame(frame, Point(), text_paint);
2335
2336 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2337 }

References impeller::Color::Blue(), impeller::Paint::color, impeller::Paint::color_source, font_size, impeller::kPi, impeller::Entity::kRepeat, impeller::ColorSource::MakeLinearGradient(), impeller::MakeTextFrameFromTextBlobSkia(), and impeller::Canvas::Translate().

## ◆ TEST_P() [231/456]

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

Definition at line 684 of file aiks_unittests.cc.

684 {
685 // "Random" numbers between 0 and 1. Hardcoded to avoid flakiness in goldens.
686 std::array<Scalar, 20> phase_offsets = {
687 7.82637e-06, 0.131538, 0.755605, 0.45865, 0.532767,
688 0.218959, 0.0470446, 0.678865, 0.679296, 0.934693,
689 0.383502, 0.519416, 0.830965, 0.0345721, 0.0534616,
690 0.5297, 0.671149, 0.00769819, 0.383416, 0.0668422};
691 auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
692 static float font_size = 20;
693 static float phase_variation = 0.2;
694 static float speed = 0.5;
695 static float magnitude = 100;
696 if (AiksTest::ImGuiBegin("Controls", nullptr,
697 ImGuiWindowFlags_AlwaysAutoResize)) {
698 ImGui::SliderFloat("Font size", &font_size, 5, 50);
699 ImGui::SliderFloat("Phase variation", &phase_variation, 0, 1);
700 ImGui::SliderFloat("Oscillation speed", &speed, 0, 2);
701 ImGui::SliderFloat("Oscillation magnitude", &magnitude, 0, 300);
702 ImGui::End();
703 }
704
705 Canvas canvas;
706 canvas.Scale(GetContentScale());
707
708 for (size_t i = 0; i < phase_offsets.size(); i++) {
709 auto position =
710 Point(200 + magnitude *
711 std::sin((-phase_offsets[i] * k2Pi * phase_variation +
712 GetSecondsElapsed() * speed)), //
713 200 + i * font_size * 1.1 //
714 );
715 if (!RenderTextInCanvasSkia(
716 GetContext(), canvas,
717 "the quick brown fox jumped over "
718 "the lazy dog!.?",
719 "Roboto-Regular.ttf",
720 {.font_size = font_size, .position = position})) {
721 return std::nullopt;
722 }
723 }
724 return canvas.EndRecordingAsPicture();
725 };
726
727 ASSERT_TRUE(OpenPlaygroundHere(callback));
728 }

References impeller::Canvas::EndRecordingAsPicture(), font_size, impeller::AiksPlayground::ImGuiBegin(), impeller::k2Pi, RenderTextInCanvasSkia(), and impeller::Canvas::Scale().

## ◆ TEST_P() [232/456]

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

Definition at line 839 of file aiks_unittests.cc.

839 {
840 Canvas canvas;
841 canvas.Scale(GetContentScale());
842 canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});
843
844 canvas.Transform(Matrix(0.25, -0.3, 0, -0.002, //
845 0, 0.5, 0, 0, //
846 0, 0, 0.3, 0, //
847 100, 100, 0, 1.3));
848 ASSERT_TRUE(RenderTextInCanvasSkia(
849 GetContext(), canvas, "the quick brown fox jumped over the lazy dog!.?",
850 "Roboto-Regular.ttf"));
851
852 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
853 }

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

## ◆ TEST_P() [233/456]

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

Definition at line 884 of file aiks_unittests.cc.

884 {
885 Canvas canvas;
886 ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(), Matrix());
887
888 // clang-format off
889 canvas.Translate(Vector3(100, 200));
890 ASSERT_MATRIX_NEAR(
891 canvas.GetCurrentTransform(),
892 Matrix( 1, 0, 0, 0,
893 0, 1, 0, 0,
894 0, 0, 1, 0,
895 100, 200, 0, 1));
896
897 canvas.Rotate(Radians(kPiOver2));
898 ASSERT_MATRIX_NEAR(
899 canvas.GetCurrentTransform(),
900 Matrix( 0, 1, 0, 0,
901 -1, 0, 0, 0,
902 0, 0, 1, 0,
903 100, 200, 0, 1));
904
905 canvas.Scale(Vector3(2, 3));
906 ASSERT_MATRIX_NEAR(
907 canvas.GetCurrentTransform(),
908 Matrix( 0, 2, 0, 0,
909 -3, 0, 0, 0,
910 0, 0, 0, 0,
911 100, 200, 0, 1));
912
913 canvas.Translate(Vector3(100, 200));
914 ASSERT_MATRIX_NEAR(
915 canvas.GetCurrentTransform(),
916 Matrix( 0, 2, 0, 0,
917 -3, 0, 0, 0,
918 0, 0, 0, 0,
919 -500, 400, 0, 1));
920 // clang-format on
921 }

References ASSERT_MATRIX_NEAR, impeller::Canvas::GetCurrentTransform(), impeller::kPiOver2, impeller::Canvas::Rotate(), impeller::Canvas::Scale(), and impeller::Canvas::Translate().

## ◆ TEST_P() [234/456]

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

Definition at line 1848 of file aiks_unittests.cc.

1848 {
1849 Canvas canvas;
1850
1851 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
1852
1853 canvas.SaveLayer({.color = Color::Black().WithAlpha(0.5)});
1854 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
1855 canvas.Restore();
1856
1857 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1858 }

References impeller::Color::Black(), impeller::Color::Blue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [235/456]

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

Definition at line 2021 of file aiks_unittests.cc.

2021 {
2022 Canvas canvas;
2023
2024 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2025 canvas.DrawImage(image, {100, 100}, {});
2026
2027 canvas.SaveLayer({.color = Color::Black().WithAlpha(0.5)});
2028 canvas.DrawImage(image, {100, 500}, {});
2029 canvas.Restore();
2030
2031 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2032 }

References impeller::Color::Black(), impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [236/456]

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

Definition at line 2105 of file aiks_unittests.cc.

2105 {
2106 Canvas canvas;
2107 canvas.DrawRect(Rect::MakeXYWH(0, 0, 400, 400), {.color = Color::Red()});
2108 canvas.SaveLayer({
2109 .color = Color::Black().WithAlpha(0.5),
2110 .blend_mode = BlendMode::kLighten,
2111 });
2112 canvas.DrawCircle({200, 200}, 100, {.color = Color::Green()});
2113 canvas.Restore();
2114 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2115 }

References impeller::Color::Black(), impeller::Canvas::DrawCircle(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::kLighten, impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [237/456]

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

Definition at line 1860 of file aiks_unittests.cc.

1860 {
1861 Canvas canvas;
1862
1863 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
1864
1865 canvas.SaveLayer({
1866 .color = Color::Black().WithAlpha(0.5),
1867 .color_filter =
1868 ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red()),
1869 });
1870 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
1871 canvas.Restore();
1872
1873 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1874 }

References impeller::Color::Black(), impeller::Color::Blue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kDestinationOver, impeller::ColorFilter::MakeBlend(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [238/456]

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

Definition at line 1876 of file aiks_unittests.cc.

1876 {
1877 Canvas canvas;
1878
1879 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
1880
1881 canvas.SaveLayer({
1882 .color = Color::Black().WithAlpha(0.5),
1883 .image_filter = ImageFilter::MakeFromColorFilter(
1884 *ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red())),
1885 });
1886
1887 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
1888 canvas.Restore();
1889
1890 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1891 }

References impeller::Color::Black(), impeller::Color::Blue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kDestinationOver, impeller::ColorFilter::MakeBlend(), impeller::ImageFilter::MakeFromColorFilter(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [239/456]

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

Definition at line 1893 of file aiks_unittests.cc.

1893 {
1894 Canvas canvas;
1895
1896 canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
1897
1898 canvas.SaveLayer({
1899 .color = Color::Black().WithAlpha(0.5),
1900 .color_filter =
1901 ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red()),
1902 });
1903
1904 canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
1905 canvas.Restore();
1906
1907 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
1908 }

References impeller::Color::Black(), impeller::Color::Blue(), impeller::Canvas::DrawRect(), impeller::Canvas::EndRecordingAsPicture(), impeller::kDestinationOver, impeller::ColorFilter::MakeBlend(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [240/456]

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

Definition at line 2079 of file aiks_unittests.cc.

2080 {
2081 Canvas canvas;
2082
2083 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2084 canvas.DrawImage(image, {100, 100}, {});
2085
2086 canvas.SaveLayer({
2087 .color = Color::Black().WithAlpha(0.5),
2088 .image_filter = ImageFilter::MakeFromColorFilter(
2089 *ColorFilter::MakeMatrix({.array =
2090 {
2091 1, 0, 0, 0, 0, //
2092 0, 1, 0, 0, 0, //
2093 0, 0.2, 1, 0, 0, //
2094 0, 0, 0, 0.5, 0 //
2095 }})),
2096 .color_filter =
2097 ColorFilter::MakeBlend(BlendMode::kModulate, Color::Green()),
2098 });
2099 canvas.DrawImage(image, {100, 500}, {});
2100 canvas.Restore();
2101
2102 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2103 }

References impeller::Color::Black(), impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::Color::Green(), impeller::kModulate, impeller::ColorFilter::MakeBlend(), impeller::ImageFilter::MakeFromColorFilter(), impeller::ColorFilter::MakeMatrix(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [241/456]

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

Definition at line 2034 of file aiks_unittests.cc.

2034 {
2035 Canvas canvas;
2036
2037 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2038 canvas.DrawImage(image, {100, 100}, {});
2039
2040 canvas.SaveLayer({
2041 .color = Color::Black().WithAlpha(0.5),
2042 .color_filter = ColorFilter::MakeMatrix({.array =
2043 {
2044 1, 0, 0, 0, 0, //
2045 0, 1, 0, 0, 0, //
2046 0, 0, 1, 0, 0, //
2047 0, 0, 0, 2, 0 //
2048 }}),
2049 });
2050 canvas.DrawImage(image, {100, 500}, {});
2051 canvas.Restore();
2052
2053 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2054 }

References impeller::Color::Black(), impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::ColorFilter::MakeMatrix(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [242/456]

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

Definition at line 2056 of file aiks_unittests.cc.

2056 {
2057 Canvas canvas;
2058
2059 auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
2060 canvas.DrawImage(image, {100, 100}, {});
2061
2062 canvas.SaveLayer({
2063 .color = Color::Black().WithAlpha(0.5),
2064 .image_filter = ImageFilter::MakeFromColorFilter(
2065 *ColorFilter::MakeMatrix({.array =
2066 {
2067 1, 0, 0, 0, 0, //
2068 0, 1, 0, 0, 0, //
2069 0, 0, 1, 0, 0, //
2070 0, 0, 0, 2, 0 //
2071 }})),
2072 });
2073 canvas.DrawImage(image, {100, 500}, {});
2074 canvas.Restore();
2075
2076 ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
2077 }

References impeller::Color::Black(), impeller::Canvas::DrawImage(), impeller::Canvas::EndRecordingAsPicture(), impeller::ImageFilter::MakeFromColorFilter(), impeller::ColorFilter::MakeMatrix(), impeller::Canvas::Restore(), impeller::Canvas::SaveLayer(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [243/456]

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

Definition at line 807 of file aiks_dl_gradient_unittests.cc.

807 {
808 DisplayListBuilder builder;
809 DlPaint paint;
810 builder.Translate(100.0f, 0);
811
812 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
813 DlColor::kGreen()};
814 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
815
816 // Inset the start and end point to verify that we do not apply
817 // the fast gradient condition.
818 paint.setColorSource(
819 DlColorSource::MakeLinear({0, 150}, {0, 100}, stops.size(), colors.data(),
820 stops.data(), DlTileMode::kRepeat));
821
822 paint.setColor(DlColor::kWhite());
823 builder.DrawRect(SkRect::MakeXYWH(0, 0, 300, 300), paint);
824 builder.Translate(400, 0);
825 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 300, 300), 4, 4),
826 paint);
827
828 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
829 }

References paint.

## ◆ TEST_P() [244/456]

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

Definition at line 93 of file aiks_dl_vertices_unittests.cc.

93 {
94 DisplayListBuilder builder;
95 DlPaint paint;
96 auto image =
97 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
98 auto size = image->impeller_texture()->GetSize();
99
100 paint.setColorSource(std::make_shared<DlImageColorSource>(
101 image, DlTileMode::kClamp, DlTileMode::kClamp));
102
103 std::vector<SkPoint> positions = {
104 SkPoint::Make(0, 0), SkPoint::Make(size.width, 0),
105 SkPoint::Make(0, size.height), SkPoint::Make(size.width, 0),
106 SkPoint::Make(0, 0), SkPoint::Make(size.width, size.height),
107 };
108 std::vector<DlColor> colors = {
109 DlColor::kRed().withAlpha(128), DlColor::kBlue().withAlpha(128),
110 DlColor::kGreen().withAlpha(128), DlColor::kRed().withAlpha(128),
111 DlColor::kBlue().withAlpha(128), DlColor::kGreen().withAlpha(128),
112 };
113
114 auto vertices =
115 MakeVertices(DlVertexMode::kTriangles, positions, {}, {}, colors);
116
117 builder.DrawVertices(vertices, DlBlendMode::kDstOver, paint);
118 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
119 }

References impeller::DlImageImpeller::Make(), impeller::MakeVertices(), and paint.

## ◆ TEST_P() [245/456]

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

Definition at line 121 of file aiks_dl_vertices_unittests.cc.

121 {
122 DisplayListBuilder builder;
123 DlPaint paint;
124 auto image =
125 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
126 auto size = image->impeller_texture()->GetSize();
127
128 paint.setColorSource(std::make_shared<DlImageColorSource>(
129 image, DlTileMode::kClamp, DlTileMode::kClamp));
130
131 std::vector<SkPoint> positions = {
132 SkPoint::Make(0, 0), SkPoint::Make(size.width, 0),
133 SkPoint::Make(0, size.height), SkPoint::Make(size.width, 0),
134 SkPoint::Make(0, 0), SkPoint::Make(size.width, size.height),
135 };
136 std::vector<DlColor> colors = {
137 DlColor::kRed().modulateOpacity(0.5),
138 DlColor::kBlue().modulateOpacity(0.5),
139 DlColor::kGreen().modulateOpacity(0.5),
140 DlColor::kRed().modulateOpacity(0.5),
141 DlColor::kBlue().modulateOpacity(0.5),
142 DlColor::kGreen().modulateOpacity(0.5),
143 };
144
145 auto vertices =
146 MakeVertices(DlVertexMode::kTriangles, positions, {}, {}, colors);
147
148 builder.DrawVertices(vertices, DlBlendMode::kColorBurn, paint);
149 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
150 }

References impeller::DlImageImpeller::Make(), impeller::MakeVertices(), and paint.

## ◆ TEST_P() [246/456]

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

Definition at line 47 of file aiks_dl_vertices_unittests.cc.

47 {
48 DisplayListBuilder builder;
49 DlPaint paint;
50 auto image =
51 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
52 auto size = image->impeller_texture()->GetSize();
53
54 paint.setColorSource(std::make_shared<DlImageColorSource>(
55 image, DlTileMode::kClamp, DlTileMode::kClamp));
56
57 std::vector<SkPoint> vertex_coordinates = {SkPoint::Make(0, 0),
58 SkPoint::Make(size.width, 0),
59 SkPoint::Make(0, size.height)};
60 auto vertices = MakeVertices(DlVertexMode::kTriangleStrip, vertex_coordinates,
61 {0, 1, 2}, {}, {});
62
63 builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
64 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
65 }

References impeller::DlImageImpeller::Make(), impeller::MakeVertices(), and paint.

## ◆ TEST_P() [247/456]

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

Definition at line 68 of file aiks_dl_vertices_unittests.cc.

68 {
69 DisplayListBuilder builder;
70 DlPaint paint;
71 auto image =
72 DlImageImpeller::Make(CreateTextureForFixture("table_mountain_nx.png"));
73 auto size = image->impeller_texture()->GetSize();
74
75 SkMatrix matrix;
76 matrix.setTranslateX(100);
77 matrix.setTranslateY(100);
78 paint.setColorSource(std::make_shared<DlImageColorSource>(
79 image, DlTileMode::kClamp, DlTileMode::kClamp, DlImageSampling::kLinear,
80 &matrix));
81
82 std::vector<SkPoint> positions = {SkPoint::Make(0, 0),
83 SkPoint::Make(size.width, 0),
84 SkPoint::Make(0, size.height)};
85 auto vertices =
86 MakeVertices(DlVertexMode::kTriangleStrip, positions, {0, 1, 2}, {}, {});
87
88 builder.DrawVertices(vertices, DlBlendMode::kSrcOver, paint);
89 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
90 }

References impeller::DlImageImpeller::Make(), impeller::MakeVertices(), and paint.

## ◆ TEST_P() [248/456]

impeller::testing::TEST_P | ( | AllocatorMTLTest | ,
|  | DebugTraceMemoryStatistics |
| ) |  |

Definition at line 28 of file allocator_mtl_unittests.mm.

28 {
29 auto& context_mtl = ContextMTL::Cast(*GetContext());
30 const auto& allocator = context_mtl.GetResourceAllocator();
31
32 EXPECT_EQ(allocator->DebugGetHeapUsage(), 0u);
33
34 // Memoryless texture does not increase allocated size.
35 {
36 TextureDescriptor desc;
37 desc.format = PixelFormat::kR8G8B8A8UNormInt;
38 desc.storage_mode = StorageMode::kDeviceTransient;
39 desc.size = {1024, 1024};
40 auto texture_1 = allocator->CreateTexture(desc);
41
42 EXPECT_EQ(allocator->DebugGetHeapUsage(), 0u);
43
44 // Private storage texture increases allocated size.
45 desc.storage_mode = StorageMode::kDevicePrivate;
46 auto texture_2 = allocator->CreateTexture(desc);
47
48 #ifdef IMPELLER_DEBUG
49 EXPECT_EQ(allocator->DebugGetHeapUsage(), 4u);
50 #else
51 EXPECT_EQ(allocator->DebugGetHeapUsage(), 0u);
52 #endif // IMPELLER_DEBUG
53
54 // Host storage texture increases allocated size.
55 desc.storage_mode = StorageMode::kHostVisible;
56 auto texture_3 = allocator->CreateTexture(desc);
57
58 #ifdef IMPELLER_DEBUG
59 EXPECT_EQ(allocator->DebugGetHeapUsage(), 8u);
60 #else
61 EXPECT_EQ(allocator->DebugGetHeapUsage(), 0u);
62 #endif // IMPELLER_DEBUG
63 }
64
65 // After all textures are out of scope, memory has been decremented.
66 EXPECT_EQ(allocator->DebugGetHeapUsage(), 0u);
67 }

References impeller::BackendCast< ContextMTL, Context >::Cast(), impeller::TextureDescriptor::format, impeller::kDevicePrivate, impeller::kDeviceTransient, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::size, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [249/456]

impeller::testing::TEST_P | ( | BlendFilterContentsTest | ,
|  | AdvancedBlendColorAlignsColorTo4 |
| ) |  |

Definition at line 45 of file blend_filter_contents_unittests.cc.

45 {
46 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
47 BlendFilterContents filter_contents;
48 filter_contents.SetInputs({FilterInput::Make(texture)});
49 filter_contents.SetForegroundColor(Color(1.0, 0.0, 0.0, 1.0));
50 filter_contents.SetBlendMode(BlendMode::kColorDodge);
51
52 std::shared_ptr<ContentContext> renderer = GetContentContext();
53 // Add random byte to get the HostBuffer in a bad alignment.
54 uint8_t byte = 0xff;
55 BufferView buffer_view =
56 renderer->GetTransientsBuffer().Emplace(&byte, /*length=*/1, /*align=*/1);
57 EXPECT_EQ(buffer_view.range.offset, 4u);
58 EXPECT_EQ(buffer_view.range.length, 1u);
59 Entity entity;
60
61 std::optional<Entity> result = filter_contents.GetEntity(
62 *renderer, entity, /*coverage_hint=*/std::nullopt);
63
64 EXPECT_TRUE(result.has_value());
65 }

References buffer_view, impeller::FilterContents::GetEntity(), impeller::kColorDodge, impeller::FilterInput::Make(), impeller::BlendFilterContents::SetBlendMode(), impeller::BlendFilterContents::SetForegroundColor(), and impeller::FilterContents::SetInputs().

## ◆ TEST_P() [250/456]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | BlitAcrossDifferentPixelFormatsFails |
| ) |  |

Definition at line 19 of file blit_pass_unittests.cc.

19 {
20 ScopedValidationDisable scope; // avoid noise in output.
21 auto context = GetContext();
22 auto cmd_buffer = context->CreateCommandBuffer();
23 auto blit_pass = cmd_buffer->CreateBlitPass();
24
25 TextureDescriptor src_desc;
26 src_desc.format = PixelFormat::kA8UNormInt;
27 src_desc.size = {100, 100};
28 src_desc.storage_mode = StorageMode::kHostVisible;
29 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
30
31 TextureDescriptor dst_format;
32 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
33 dst_format.size = {100, 100};
34 dst_format.storage_mode = StorageMode::kHostVisible;
35 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
36
37 EXPECT_FALSE(blit_pass->AddCopy(src, dst));
38 }

References impeller::TextureDescriptor::format, impeller::kA8UNormInt, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::size, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [251/456]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | BlitAcrossDifferentSampleCountsFails |
| ) |  |

Definition at line 40 of file blit_pass_unittests.cc.

40 {
41 ScopedValidationDisable scope; // avoid noise in output.
42 auto context = GetContext();
43 auto cmd_buffer = context->CreateCommandBuffer();
44 auto blit_pass = cmd_buffer->CreateBlitPass();
45
46 TextureDescriptor src_desc;
47 src_desc.format = PixelFormat::kR8G8B8A8UNormInt;
48 src_desc.sample_count = SampleCount::kCount4;
49 src_desc.size = {100, 100};
50 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
51
52 TextureDescriptor dst_format;
53 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
54 dst_format.size = {100, 100};
55 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
56
57 EXPECT_FALSE(blit_pass->AddCopy(src, dst));
58 }

References impeller::TextureDescriptor::format, impeller::kCount4, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::sample_count, and impeller::TextureDescriptor::size.

## ◆ TEST_P() [252/456]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | BlitPassesForMatchingFormats |
| ) |  |

Definition at line 60 of file blit_pass_unittests.cc.

60 {
61 ScopedValidationDisable scope; // avoid noise in output.
62 auto context = GetContext();
63 auto cmd_buffer = context->CreateCommandBuffer();
64 auto blit_pass = cmd_buffer->CreateBlitPass();
65
66 TextureDescriptor src_desc;
67 src_desc.format = PixelFormat::kR8G8B8A8UNormInt;
68 src_desc.size = {100, 100};
69 src_desc.storage_mode = StorageMode::kHostVisible;
70 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
71
72 TextureDescriptor dst_format;
73 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
74 dst_format.size = {100, 100};
75 dst_format.storage_mode = StorageMode::kHostVisible;
76 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
77
78 EXPECT_TRUE(blit_pass->AddCopy(src, dst));
79 }

References impeller::TextureDescriptor::format, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::TextureDescriptor::size, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [253/456]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | CanBlitSmallRegionToUninitializedTexture |
| ) |  |

Definition at line 109 of file blit_pass_unittests.cc.

109 {
110 auto context = GetContext();
111 auto cmd_buffer = context->CreateCommandBuffer();
112 auto blit_pass = cmd_buffer->CreateBlitPass();
113
114 TextureDescriptor dst_format;
115 dst_format.storage_mode = StorageMode::kDevicePrivate;
116 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
117 dst_format.size = {1000, 1000};
118 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
119
120 DeviceBufferDescriptor src_format;
121 src_format.size = 4;
122 src_format.storage_mode = StorageMode::kHostVisible;
123 auto src = context->GetResourceAllocator()->CreateBuffer(src_format);
124
125 ASSERT_TRUE(dst);
126
127 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
128 IRect::MakeLTRB(0, 0, 1, 1), "", /*slice=*/0));
129 EXPECT_TRUE(blit_pass->EncodeCommands(GetContext()->GetResourceAllocator()));
130 EXPECT_TRUE(context->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok());
131 }

References impeller::DeviceBuffer::AsBufferView(), impeller::TextureDescriptor::format, impeller::kDevicePrivate, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::TRect< T >::MakeLTRB(), impeller::DeviceBufferDescriptor::size, impeller::TextureDescriptor::size, impeller::DeviceBufferDescriptor::storage_mode, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [254/456]

impeller::testing::TEST_P | ( | BlitPassTest | ,
|  | ChecksInvalidSliceParameters |
| ) |  |

Definition at line 81 of file blit_pass_unittests.cc.

81 {
82 ScopedValidationDisable scope; // avoid noise in output.
83 auto context = GetContext();
84 auto cmd_buffer = context->CreateCommandBuffer();
85 auto blit_pass = cmd_buffer->CreateBlitPass();
86
87 TextureDescriptor dst_format;
88 dst_format.storage_mode = StorageMode::kDevicePrivate;
89 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
90 dst_format.size = {100, 100};
91 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
92
93 DeviceBufferDescriptor src_format;
94 src_format.size = 40000;
95 src_format.storage_mode = StorageMode::kHostVisible;
96 auto src = context->GetResourceAllocator()->CreateBuffer(src_format);
97
98 ASSERT_TRUE(dst);
99 ASSERT_TRUE(src);
100
101 EXPECT_FALSE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
102 std::nullopt, "", /*slice=*/25));
103 EXPECT_FALSE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
104 std::nullopt, "", /*slice=*/6));
105 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
106 std::nullopt, "", /*slice=*/0));
107 }

References impeller::DeviceBuffer::AsBufferView(), impeller::TextureDescriptor::format, impeller::kDevicePrivate, impeller::kHostVisible, impeller::kR8G8B8A8UNormInt, impeller::DeviceBufferDescriptor::size, impeller::TextureDescriptor::size, impeller::DeviceBufferDescriptor::storage_mode, and impeller::TextureDescriptor::storage_mode.

## ◆ TEST_P() [255/456]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | 1DThreadgroupSizingIsCorrect |
| ) |  |

Definition at line 175 of file compute_unittests.cc.

175 {
176 using CS = ThreadgroupSizingTestComputeShader;
177 auto context = GetContext();
178 ASSERT_TRUE(context);
179 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
180
181 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
182 auto pipeline_desc =
183 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
184 ASSERT_TRUE(pipeline_desc.has_value());
185 auto compute_pipeline =
186 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
187 ASSERT_TRUE(compute_pipeline);
188
189 auto cmd_buffer = context->CreateCommandBuffer();
190 auto pass = cmd_buffer->CreateComputePass();
191 ASSERT_TRUE(pass && pass->IsValid());
192
193 static constexpr size_t kCount = 2048;
194
195 pass->SetPipeline(compute_pipeline);
196
197 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
198 context, "Output Buffer");
199
200 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
201
202 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
203 ASSERT_TRUE(pass->EncodeCommands());
204
205 fml::AutoResetWaitableEvent latch;
206 ASSERT_TRUE(
207 context->GetCommandQueue()
208 ->Submit({cmd_buffer},
209 [&latch, output_buffer](CommandBuffer::Status status) {
210 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
211
212 auto view = DeviceBuffer::AsBufferView(output_buffer);
213 EXPECT_EQ(view.range.length,
214 sizeof(CS::OutputData<kCount>));
215
216 CS::OutputData<kCount>* output =
217 reinterpret_cast<CS::OutputData<kCount>*>(
218 output_buffer->OnGetContents());
219 EXPECT_TRUE(output);
220 EXPECT_EQ(output->data[kCount - 1], kCount - 1);
221 latch.Signal();
222 })
223 .ok());
224
225 latch.Wait();
226 }

## ◆ TEST_P() [256/456]

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 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
377 ASSERT_TRUE(context);
378 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
379
380 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
381 auto pipeline_desc =
382 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
383 ASSERT_TRUE(pipeline_desc.has_value());
384 auto compute_pipeline =
385 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
386 ASSERT_TRUE(compute_pipeline);
387
388 auto cmd_buffer = context->CreateCommandBuffer();
389 auto pass = cmd_buffer->CreateComputePass();
390 ASSERT_TRUE(pass && pass->IsValid());
391
392 static constexpr size_t kCount = 5;
393
394 pass->SetPipeline(compute_pipeline);
395
396 CS::Info info{.count = kCount};
397 CS::Input0<kCount> input_0;
398 CS::Input1<kCount> input_1;
399 for (size_t i = 0; i < kCount; i++) {
400 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
401 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
402 }
403
404 input_0.fixed_array[1] = IPoint32(2, 2);
405 input_1.fixed_array[0] = UintPoint32(3, 3);
406 input_0.some_int = 5;
407 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
408
409 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
410 context, "Output Buffer");
411
412 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
413 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
414 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
415 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
416
417 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
418 ASSERT_TRUE(pass->EncodeCommands());
419
420 fml::AutoResetWaitableEvent latch;
421 ASSERT_TRUE(
422 context->GetCommandQueue()
423 ->Submit(
424 {cmd_buffer},
425 [&latch, output_buffer, &input_0,
426 &input_1](CommandBuffer::Status status) {
427 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
428
429 auto view = DeviceBuffer::AsBufferView(output_buffer);
430 EXPECT_EQ(view.range.length, sizeof(CS::Output<kCount>));
431
432 CS::Output<kCount>* output =
433 reinterpret_cast<CS::Output<kCount>*>(
434 output_buffer->OnGetContents());
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,
440 Vector4(computed.x + 2 + input_1.some_struct.i,
441 computed.y + 3 + input_1.some_struct.vf.x,
442 computed.z + 5 + input_1.some_struct.vf.y,
443 computed.w));
444 }
445 latch.Signal();
446 })
447 .ok());
448
449 latch.Wait();
450 }

## ◆ TEST_P() [257/456]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanComputePrefixSum |
| ) |  |

Definition at line 109 of file compute_unittests.cc.

109 {
110 using CS = PrefixSumTestComputeShader;
111 auto context = GetContext();
112 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
113 ASSERT_TRUE(context);
114 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
115
116 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
117 auto pipeline_desc =
118 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
119 ASSERT_TRUE(pipeline_desc.has_value());
120 auto compute_pipeline =
121 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
122 ASSERT_TRUE(compute_pipeline);
123
124 auto cmd_buffer = context->CreateCommandBuffer();
125 auto pass = cmd_buffer->CreateComputePass();
126 ASSERT_TRUE(pass && pass->IsValid());
127
128 static constexpr size_t kCount = 5;
129
130 pass->SetPipeline(compute_pipeline);
131
132 CS::InputData<kCount> input_data;
133 input_data.count = kCount;
134 for (size_t i = 0; i < kCount; i++) {
135 input_data.data[i] = 1 + i;
136 }
137
138 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
139 context, "Output Buffer");
140
141 CS::BindInputData(*pass, host_buffer->EmplaceStorageBuffer(input_data));
142 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
143
144 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
145 ASSERT_TRUE(pass->EncodeCommands());
146
147 fml::AutoResetWaitableEvent latch;
148 ASSERT_TRUE(
149 context->GetCommandQueue()
150 ->Submit({cmd_buffer},
151 [&latch, output_buffer](CommandBuffer::Status status) {
152 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
153
154 auto view = DeviceBuffer::AsBufferView(output_buffer);
155 EXPECT_EQ(view.range.length,
156 sizeof(CS::OutputData<kCount>));
157
158 CS::OutputData<kCount>* output =
159 reinterpret_cast<CS::OutputData<kCount>*>(
160 output_buffer->OnGetContents());
161 EXPECT_TRUE(output);
162
163 constexpr uint32_t expected[kCount] = {1, 3, 6, 10, 15};
164 for (size_t i = 0; i < kCount; i++) {
165 auto computed_sum = output->data[i];
166 EXPECT_EQ(computed_sum, expected[i]);
167 }
168 latch.Signal();
169 })
170 .ok());
171
172 latch.Wait();
173 }

References impeller::DeviceBuffer::AsBufferView(), and impeller::HostBuffer::Create().

## ◆ TEST_P() [258/456]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanComputePrefixSumLargeInteractive |
| ) |  |

Definition at line 228 of file compute_unittests.cc.

228 {
229 using CS = PrefixSumTestComputeShader;
230
231 auto context = GetContext();
232 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
233
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->SetPipeline(compute_pipeline);
250
251 CS::InputData<kCount> input_data;
252 input_data.count = kCount;
253 for (size_t i = 0; i < kCount; i++) {
254 input_data.data[i] = 1 + i;
255 }
256
257 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::OutputData<kCount>>(
258 context, "Output Buffer");
259
260 CS::BindInputData(*pass, host_buffer->EmplaceStorageBuffer(input_data));
261 CS::BindOutputData(*pass, DeviceBuffer::AsBufferView(output_buffer));
262
263 pass->Compute(ISize(kCount, 1));
264 pass->EncodeCommands();
265 host_buffer->Reset();
266 return context->GetCommandQueue()->Submit({cmd_buffer}).ok();
267 };
268 ASSERT_TRUE(OpenPlaygroundHere(callback));
269 }

## ◆ TEST_P() [259/456]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CanCreateComputePass |
| ) |  |

Definition at line 30 of file compute_unittests.cc.

30 {
31 using CS = SampleComputeShader;
32 auto context = GetContext();
33 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
34 ASSERT_TRUE(context);
35 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
36
37 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
38 auto pipeline_desc =
39 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
40 ASSERT_TRUE(pipeline_desc.has_value());
41 auto compute_pipeline =
42 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
43 ASSERT_TRUE(compute_pipeline);
44
45 auto cmd_buffer = context->CreateCommandBuffer();
46 auto pass = cmd_buffer->CreateComputePass();
47 ASSERT_TRUE(pass && pass->IsValid());
48
49 static constexpr size_t kCount = 5;
50
51 pass->SetPipeline(compute_pipeline);
52
53 CS::Info info{.count = kCount};
54 CS::Input0<kCount> input_0;
55 CS::Input1<kCount> input_1;
56 for (size_t i = 0; i < kCount; i++) {
57 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
58 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
59 }
60
61 input_0.fixed_array[1] = IPoint32(2, 2);
62 input_1.fixed_array[0] = UintPoint32(3, 3);
63 input_0.some_int = 5;
64 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
65
66 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
67 context, "Output Buffer");
68
69 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
70 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
71 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
72 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
73
74 ASSERT_TRUE(pass->Compute(ISize(kCount, 1)).ok());
75 ASSERT_TRUE(pass->EncodeCommands());
76
77 fml::AutoResetWaitableEvent latch;
78 ASSERT_TRUE(
79 context->GetCommandQueue()
80 ->Submit(
81 {cmd_buffer},
82 [&latch, output_buffer, &input_0,
83 &input_1](CommandBuffer::Status status) {
84 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
85
86 auto view = DeviceBuffer::AsBufferView(output_buffer);
87 EXPECT_EQ(view.range.length, sizeof(CS::Output<kCount>));
88
89 CS::Output<kCount>* output =
90 reinterpret_cast<CS::Output<kCount>*>(
91 output_buffer->OnGetContents());
92 EXPECT_TRUE(output);
93 for (size_t i = 0; i < kCount; i++) {
94 Vector4 vector = output->elements[i];
95 Vector4 computed = input_0.elements[i] * input_1.elements[i];
96 EXPECT_EQ(vector,
97 Vector4(computed.x + 2 + input_1.some_struct.i,
98 computed.y + 3 + input_1.some_struct.vf.x,
99 computed.z + 5 + input_1.some_struct.vf.y,
100 computed.w));
101 }
102 latch.Signal();
103 })
104 .ok());
105
106 latch.Wait();
107 }

References impeller::DeviceBuffer::AsBufferView(), and impeller::HostBuffer::Create().

## ◆ TEST_P() [260/456]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | CapabilitiesReportSupport |
| ) |  |

Definition at line 24 of file compute_unittests.cc.

24 {
25 auto context = GetContext();
26 ASSERT_TRUE(context);
27 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
28 }

## ◆ TEST_P() [261/456]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | MultiStageInputAndOutput |
| ) |  |

Definition at line 271 of file compute_unittests.cc.

271 {
272 using CS1 = Stage1ComputeShader;
273 using Stage1PipelineBuilder = ComputePipelineBuilder<CS1>;
274 using CS2 = Stage2ComputeShader;
275 using Stage2PipelineBuilder = ComputePipelineBuilder<CS2>;
276
277 auto context = GetContext();
278 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
279 ASSERT_TRUE(context);
280 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
281
282 auto pipeline_desc_1 =
283 Stage1PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
284 ASSERT_TRUE(pipeline_desc_1.has_value());
285 auto compute_pipeline_1 =
286 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_1).Get();
287 ASSERT_TRUE(compute_pipeline_1);
288
289 auto pipeline_desc_2 =
290 Stage2PipelineBuilder::MakeDefaultPipelineDescriptor(*context);
291 ASSERT_TRUE(pipeline_desc_2.has_value());
292 auto compute_pipeline_2 =
293 context->GetPipelineLibrary()->GetPipeline(pipeline_desc_2).Get();
294 ASSERT_TRUE(compute_pipeline_2);
295
296 auto cmd_buffer = context->CreateCommandBuffer();
297 auto pass = cmd_buffer->CreateComputePass();
298 ASSERT_TRUE(pass && pass->IsValid());
299
300 static constexpr size_t kCount1 = 5;
301 static constexpr size_t kCount2 = kCount1 * 2;
302
303 CS1::Input<kCount1> input_1;
304 input_1.count = kCount1;
305 for (size_t i = 0; i < kCount1; i++) {
306 input_1.elements[i] = i;
307 }
308
309 CS2::Input<kCount2> input_2;
310 input_2.count = kCount2;
311 for (size_t i = 0; i < kCount2; i++) {
312 input_2.elements[i] = i;
313 }
314
315 auto output_buffer_1 = CreateHostVisibleDeviceBuffer<CS1::Output<kCount2>>(
316 context, "Output Buffer Stage 1");
317 auto output_buffer_2 = CreateHostVisibleDeviceBuffer<CS2::Output<kCount2>>(
318 context, "Output Buffer Stage 2");
319
320 {
321 pass->SetPipeline(compute_pipeline_1);
322
323 CS1::BindInput(*pass, host_buffer->EmplaceStorageBuffer(input_1));
324 CS1::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer_1));
325
326 ASSERT_TRUE(pass->Compute(ISize(512, 1)).ok());
327 pass->AddBufferMemoryBarrier();
328 }
329
330 {
331 pass->SetPipeline(compute_pipeline_2);
332
333 CS1::BindInput(*pass, DeviceBuffer::AsBufferView(output_buffer_1));
334 CS2::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer_2));
335 ASSERT_TRUE(pass->Compute(ISize(512, 1)).ok());
336 }
337
338 ASSERT_TRUE(pass->EncodeCommands());
339
340 fml::AutoResetWaitableEvent latch;
341 ASSERT_TRUE(
342 context->GetCommandQueue()
343 ->Submit({cmd_buffer},
344 [&latch, &output_buffer_1,
345 &output_buffer_2](CommandBuffer::Status status) {
346 EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
347
348 CS1::Output<kCount2>* output_1 =
349 reinterpret_cast<CS1::Output<kCount2>*>(
350 output_buffer_1->OnGetContents());
351 EXPECT_TRUE(output_1);
352 EXPECT_EQ(output_1->count, 10u);
353 EXPECT_THAT(
354 output_1->elements,
355 ::testing::ElementsAre(0, 0, 2, 3, 4, 6, 6, 9, 8, 12));
356
357 CS2::Output<kCount2>* output_2 =
358 reinterpret_cast<CS2::Output<kCount2>*>(
359 output_buffer_2->OnGetContents());
360 EXPECT_TRUE(output_2);
361 EXPECT_EQ(output_2->count, 10u);
362 EXPECT_THAT(output_2->elements,
363 ::testing::ElementsAre(0, 0, 4, 6, 8, 12, 12,
364 18, 16, 24));
365
366 latch.Signal();
367 })
368 .ok());
369
370 latch.Wait();
371 }

References impeller::kCount1.

## ◆ TEST_P() [262/456]

impeller::testing::TEST_P | ( | ComputeTest | ,
|  | ReturnsEarlyWhenAnyGridDimensionIsZero |
| ) |  |

Definition at line 452 of file compute_unittests.cc.

452 {
453 using CS = SampleComputeShader;
454 auto context = GetContext();
455 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
456 ASSERT_TRUE(context);
457 ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
458
459 using SamplePipelineBuilder = ComputePipelineBuilder<CS>;
460 auto pipeline_desc =
461 SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
462 ASSERT_TRUE(pipeline_desc.has_value());
463 auto compute_pipeline =
464 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
465 ASSERT_TRUE(compute_pipeline);
466
467 auto cmd_buffer = context->CreateCommandBuffer();
468 auto pass = cmd_buffer->CreateComputePass();
469 ASSERT_TRUE(pass && pass->IsValid());
470
471 static constexpr size_t kCount = 5;
472
473 pass->SetPipeline(compute_pipeline);
474
475 CS::Info info{.count = kCount};
476 CS::Input0<kCount> input_0;
477 CS::Input1<kCount> input_1;
478 for (size_t i = 0; i < kCount; i++) {
479 input_0.elements[i] = Vector4(2.0 + i, 3.0 + i, 4.0 + i, 5.0 * i);
480 input_1.elements[i] = Vector4(6.0, 7.0, 8.0, 9.0);
481 }
482
483 input_0.fixed_array[1] = IPoint32(2, 2);
484 input_1.fixed_array[0] = UintPoint32(3, 3);
485 input_0.some_int = 5;
486 input_1.some_struct = CS::SomeStruct{.vf = Point(3, 4), .i = 42};
487
488 auto output_buffer = CreateHostVisibleDeviceBuffer<CS::Output<kCount>>(
489 context, "Output Buffer");
490
491 CS::BindInfo(*pass, host_buffer->EmplaceUniform(info));
492 CS::BindInput0(*pass, host_buffer->EmplaceStorageBuffer(input_0));
493 CS::BindInput1(*pass, host_buffer->EmplaceStorageBuffer(input_1));
494 CS::BindOutput(*pass, DeviceBuffer::AsBufferView(output_buffer));
495
496 // Intentionally making the grid size zero in one dimension. No GPU will
497 // tolerate this.
498 EXPECT_FALSE(pass->Compute(ISize(0, 1)).ok());
499 pass->EncodeCommands();
500 }

## ◆ TEST_P() [263/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanBlendDstOverAndDstCorrectly |
| ) |  |

Definition at line 1238 of file dl_unittests.cc.

1238 {
1239 flutter::DisplayListBuilder builder;
1240
1241 {
1242 builder.SaveLayer(nullptr, nullptr);
1243 builder.Translate(100, 100);
1244 flutter::DlPaint paint;
1245 paint.setColor(flutter::DlColor::kRed());
1246 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1247 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1248 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
1249 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1250 builder.Restore();
1251 }
1252 {
1253 builder.SaveLayer(nullptr, nullptr);
1254 builder.Translate(300, 100);
1255 flutter::DlPaint paint;
1256 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1257 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1258 paint.setColor(flutter::DlColor::kRed());
1259 paint.setBlendMode(flutter::DlBlendMode::kDstOver);
1260 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1261 builder.Restore();
1262 }
1263 {
1264 builder.SaveLayer(nullptr, nullptr);
1265 builder.Translate(100, 300);
1266 flutter::DlPaint paint;
1267 paint.setColor(flutter::DlColor::kRed());
1268 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1269 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1270 paint.setBlendMode(flutter::DlBlendMode::kSrc);
1271 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1272 builder.Restore();
1273 }
1274 {
1275 builder.SaveLayer(nullptr, nullptr);
1276 builder.Translate(300, 300);
1277 flutter::DlPaint paint;
1278 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1279 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1280 paint.setColor(flutter::DlColor::kRed());
1281 paint.setBlendMode(flutter::DlBlendMode::kDst);
1282 builder.DrawRect(SkRect::MakeSize({200, 200}), paint);
1283 builder.Restore();
1284 }
1285
1286 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1287 }

References paint.

## ◆ TEST_P() [264/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanClampTheResultingColorOfColorMatrixFilter |
| ) |  |

Definition at line 616 of file dl_unittests.cc.

616 {
617 auto texture = CreateTextureForFixture("boston.jpg");
618 const float inner_color_matrix[20] = {
619 1, 0, 0, 0, 0, //
620 0, 1, 0, 0, 0, //
621 0, 0, 1, 0, 0, //
622 0, 0, 0, 2, 0, //
623 };
624 const float outer_color_matrix[20] = {
625 1, 0, 0, 0, 0, //
626 0, 1, 0, 0, 0, //
627 0, 0, 1, 0, 0, //
628 0, 0, 0, 0.5, 0, //
629 };
630 auto inner_color_filter =
631 std::make_shared<flutter::DlMatrixColorFilter>(inner_color_matrix);
632 auto outer_color_filter =
633 std::make_shared<flutter::DlMatrixColorFilter>(outer_color_matrix);
634 auto inner =
635 std::make_shared<flutter::DlColorFilterImageFilter>(inner_color_filter);
636 auto outer =
637 std::make_shared<flutter::DlColorFilterImageFilter>(outer_color_filter);
638 auto compose = std::make_shared<flutter::DlComposeImageFilter>(outer, inner);
639
640 flutter::DisplayListBuilder builder;
641 flutter::DlPaint paint;
642 paint.setImageFilter(compose.get());
643 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
644 flutter::DlImageSampling::kNearestNeighbor, &paint);
645 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
646 }

References impeller::DlImageImpeller::Make(), and paint.

## ◆ TEST_P() [265/456]

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

Definition at line 406 of file dl_unittests.cc.

406 {
407 flutter::DisplayListBuilder builder;
408 flutter::DlPaint paint;
409
410 paint.setColor(flutter::DlColor::kRed());
411 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
412 paint.setStrokeWidth(10);
413
414 builder.Translate(300, 300);
415
416 // Move to (50, 50) and draw lines from:
417 // 1. (50, height)
418 // 2. (width, height)
419 // 3. (width, 50)
420 SkPath path;
421 path.moveTo(50, 50);
422 path.lineTo(50, 100);
423 path.lineTo(100, 100);
424 path.lineTo(100, 50);
425 builder.DrawPath(path, paint);
426
427 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
428 }

References paint.

## ◆ TEST_P() [266/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawArc |
| ) |  |

Definition at line 152 of file dl_unittests.cc.

152 {
153 auto callback = [&]() {
154 static float start_angle = 45;
155 static float sweep_angle = 270;
156 static float stroke_width = 10;
157 static bool use_center = true;
158
159 static int selected_cap = 0;
160 const char* cap_names[] = {"Butt", "Round", "Square"};
161 flutter::DlStrokeCap cap;
162
163 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
164 ImGui::SliderFloat("Start angle", &start_angle, -360, 360);
165 ImGui::SliderFloat("Sweep angle", &sweep_angle, -360, 360);
166 ImGui::SliderFloat("Stroke width", &stroke_width, 0, 300);
167 ImGui::Combo("Cap", &selected_cap, cap_names,
168 sizeof(cap_names) / sizeof(char*));
169 ImGui::Checkbox("Use center", &use_center);
170 ImGui::End();
171
172 switch (selected_cap) {
173 case 0:
174 cap = flutter::DlStrokeCap::kButt;
175 break;
176 case 1:
177 cap = flutter::DlStrokeCap::kRound;
178 break;
179 case 2:
180 cap = flutter::DlStrokeCap::kSquare;
181 break;
182 default:
183 cap = flutter::DlStrokeCap::kButt;
184 break;
185 }
186
187 static PlaygroundPoint point_a(Point(200, 200), 20, Color::White());
188 static PlaygroundPoint point_b(Point(400, 400), 20, Color::White());
189 auto [p1, p2] = DrawPlaygroundLine(point_a, point_b);
190
191 flutter::DisplayListBuilder builder;
192 flutter::DlPaint paint;
193
194 Vector2 scale = GetContentScale();
195 builder.Scale(scale.x, scale.y);
196 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
197 paint.setStrokeCap(cap);
198 paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
199 paint.setStrokeMiter(10);
200 auto rect = SkRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
201 paint.setColor(flutter::DlColor::kGreen());
202 paint.setStrokeWidth(2);
203 builder.DrawRect(rect, paint);
204 paint.setColor(flutter::DlColor::kRed());
205 paint.setStrokeWidth(stroke_width);
206 builder.DrawArc(rect, start_angle, sweep_angle, use_center, paint);
207
208 return builder.Build();
209 };
210 ASSERT_TRUE(OpenPlaygroundHere(callback));
211 }

References impeller::DrawPlaygroundLine(), paint, scale, stroke_width, and impeller::Color::White().

## ◆ TEST_P() [267/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawBackdropFilter |
| ) |  |

Definition at line 648 of file dl_unittests.cc.

648 {
649 auto texture = CreateTextureForFixture("embarcadero.jpg");
650
651 auto callback = [&]() {
652 static float sigma[] = {10, 10};
653 static float ctm_scale = 1;
654 static bool use_bounds = true;
655 static bool draw_circle = true;
656 static bool add_clip = true;
657
658 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
659 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
660 ImGui::SliderFloat("Scale", &ctm_scale, 0, 10);
661 ImGui::NewLine();
662 ImGui::TextWrapped(
663 "If everything is working correctly, none of the options below should "
664 "impact the filter's appearance.");
665 ImGui::Checkbox("Use SaveLayer bounds", &use_bounds);
666 ImGui::Checkbox("Draw child element", &draw_circle);
667 ImGui::Checkbox("Add pre-clip", &add_clip);
668 ImGui::End();
669
670 flutter::DisplayListBuilder builder;
671
672 Vector2 scale = ctm_scale * GetContentScale();
673 builder.Scale(scale.x, scale.y);
674
675 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
676 flutter::DlTileMode::kClamp);
677
678 std::optional<SkRect> bounds;
679 if (use_bounds) {
680 static PlaygroundPoint point_a(Point(350, 150), 20, Color::White());
681 static PlaygroundPoint point_b(Point(800, 600), 20, Color::White());
682 auto [p1, p2] = DrawPlaygroundLine(point_a, point_b);
683 bounds = SkRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
684 }
685
686 // Insert a clip to test that the backdrop filter handles stencil depths > 0
687 // correctly.
688 if (add_clip) {
689 builder.ClipRect(SkRect::MakeLTRB(0, 0, 99999, 99999),
690 flutter::DlCanvas::ClipOp::kIntersect, true);
691 }
692
693 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
694 flutter::DlImageSampling::kNearestNeighbor, nullptr);
695 builder.SaveLayer(bounds.has_value() ? &bounds.value() : nullptr, nullptr,
696 &filter);
697
698 if (draw_circle) {
699 static PlaygroundPoint center_point(Point(500, 400), 20, Color::Red());
700 auto circle_center = DrawPlaygroundPoint(center_point);
701
702 flutter::DlPaint paint;
703 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
704 paint.setStrokeCap(flutter::DlStrokeCap::kButt);
705 paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
706 paint.setStrokeWidth(10);
707 paint.setColor(flutter::DlColor::kRed().withAlpha(100));
708 builder.DrawCircle({circle_center.x, circle_center.y}, 100, paint);
709 }
710
711 return builder.Build();
712 };
713
714 ASSERT_TRUE(OpenPlaygroundHere(callback));
715 }

References impeller::DrawPlaygroundLine(), impeller::DrawPlaygroundPoint(), impeller::DlImageImpeller::Make(), paint, impeller::Color::Red(), scale, and impeller::Color::White().

## ◆ TEST_P() [268/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawCapsAndJoins |
| ) |  |

Definition at line 106 of file dl_unittests.cc.

106 {
107 flutter::DisplayListBuilder builder;
108 flutter::DlPaint paint;
109
110 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
111 paint.setStrokeWidth(30);
112 paint.setColor(flutter::DlColor::kRed());
113
114 auto path =
115 SkPathBuilder{}.moveTo(-50, 0).lineTo(0, -50).lineTo(50, 0).snapshot();
116
117 builder.Translate(100, 100);
118 {
119 paint.setStrokeCap(flutter::DlStrokeCap::kButt);
120 paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
121 paint.setStrokeMiter(4);
122 builder.DrawPath(path, paint);
123 }
124
125 {
126 builder.Save();
127 builder.Translate(0, 100);
128 // The joint in the path is 45 degrees. A miter length of 1 convert to a
129 // bevel in this case.
130 paint.setStrokeMiter(1);
131 builder.DrawPath(path, paint);
132 builder.Restore();
133 }
134
135 builder.Translate(150, 0);
136 {
137 paint.setStrokeCap(flutter::DlStrokeCap::kSquare);
138 paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
139 builder.DrawPath(path, paint);
140 }
141
142 builder.Translate(150, 0);
143 {
144 paint.setStrokeCap(flutter::DlStrokeCap::kRound);
145 paint.setStrokeJoin(flutter::DlStrokeJoin::kRound);
146 builder.DrawPath(path, paint);
147 }
148
149 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
150 }

References paint.

## ◆ TEST_P() [269/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawCorrectlyWithColorFilterAndImageFilter |
| ) |  |

Definition at line 1289 of file dl_unittests.cc.

1289 {
1290 flutter::DisplayListBuilder builder;
1291 const float green_color_matrix[20] = {
1292 0, 0, 0, 0, 0, //
1293 0, 0, 0, 0, 1, //
1294 0, 0, 0, 0, 0, //
1295 0, 0, 0, 1, 0, //
1296 };
1297 const float blue_color_matrix[20] = {
1298 0, 0, 0, 0, 0, //
1299 0, 0, 0, 0, 0, //
1300 0, 0, 0, 0, 1, //
1301 0, 0, 0, 1, 0, //
1302 };
1303 auto green_color_filter =
1304 std::make_shared<flutter::DlMatrixColorFilter>(green_color_matrix);
1305 auto blue_color_filter =
1306 std::make_shared<flutter::DlMatrixColorFilter>(blue_color_matrix);
1307 auto blue_image_filter =
1308 std::make_shared<flutter::DlColorFilterImageFilter>(blue_color_filter);
1309
1310 flutter::DlPaint paint;
1311 paint.setColor(flutter::DlColor::kRed());
1312 paint.setColorFilter(green_color_filter);
1313 paint.setImageFilter(blue_image_filter);
1314 builder.DrawRect(SkRect::MakeLTRB(100, 100, 500, 500), paint);
1315 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1316 }

References paint.

## ◆ TEST_P() [270/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawImage |
| ) |  |

Definition at line 98 of file dl_unittests.cc.

98 {
99 auto texture = CreateTextureForFixture("embarcadero.jpg");
100 flutter::DisplayListBuilder builder;
101 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
102 flutter::DlImageSampling::kNearestNeighbor, nullptr);
103 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
104 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [271/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImage |
| ) |  |

Definition at line 717 of file dl_unittests.cc.

717 {
718 // Image is drawn with corners to scale and center pieces stretched to fit.
719 auto texture = CreateTextureForFixture("embarcadero.jpg");
720 flutter::DisplayListBuilder builder;
721 auto size = texture->GetSize();
722 builder.DrawImageNine(
723 DlImageImpeller::Make(texture),
724 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
725 size.height * 3 / 4),
726 SkRect::MakeLTRB(0, 0, size.width * 2, size.height * 2),
727 flutter::DlFilterMode::kNearest, nullptr);
728 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
729 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [272/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterBiggerThanDest |
| ) |  |

Definition at line 763 of file dl_unittests.cc.

763 {
764 // Edge case, the width and height of the corners does not leave any
765 // room for the center slices. Only the corners are displayed.
766 auto texture = CreateTextureForFixture("embarcadero.jpg");
767 flutter::DisplayListBuilder builder;
768 auto size = texture->GetSize();
769 builder.DrawImageNine(
770 DlImageImpeller::Make(texture),
771 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
772 size.height * 3 / 4),
773 SkRect::MakeLTRB(0, 0, size.width / 2, size.height / 2),
774 flutter::DlFilterMode::kNearest, nullptr);
775 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
776 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [273/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterHeightBiggerThanDest |
| ) |  |

Definition at line 747 of file dl_unittests.cc.

747 {
748 // Edge case, the height of the corners does not leave any room for the
749 // center slice. The center (across the horizontal axis) is folded out of the
750 // resulting image.
751 auto texture = CreateTextureForFixture("embarcadero.jpg");
752 flutter::DisplayListBuilder builder;
753 auto size = texture->GetSize();
754 builder.DrawImageNine(
755 DlImageImpeller::Make(texture),
756 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
757 size.height * 3 / 4),
758 SkRect::MakeLTRB(0, 0, size.width, size.height / 2),
759 flutter::DlFilterMode::kNearest, nullptr);
760 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
761 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [274/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCenterWidthBiggerThanDest |
| ) |  |

Definition at line 731 of file dl_unittests.cc.

731 {
732 // Edge case, the width of the corners does not leave any room for the
733 // center slice. The center (across the vertical axis) is folded out of the
734 // resulting image.
735 auto texture = CreateTextureForFixture("embarcadero.jpg");
736 flutter::DisplayListBuilder builder;
737 auto size = texture->GetSize();
738 builder.DrawImageNine(
739 DlImageImpeller::Make(texture),
740 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
741 size.height * 3 / 4),
742 SkRect::MakeLTRB(0, 0, size.width / 2, size.height),
743 flutter::DlFilterMode::kNearest, nullptr);
744 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
745 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [275/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawNinePatchImageCornersScaledDown |
| ) |  |

Definition at line 778 of file dl_unittests.cc.

778 {
779 // Edge case, there is not enough room for the corners to be drawn
780 // without scaling them down.
781 auto texture = CreateTextureForFixture("embarcadero.jpg");
782 flutter::DisplayListBuilder builder;
783 auto size = texture->GetSize();
784 builder.DrawImageNine(
785 DlImageImpeller::Make(texture),
786 SkIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
787 size.height * 3 / 4),
788 SkRect::MakeLTRB(0, 0, size.width / 4, size.height / 4),
789 flutter::DlFilterMode::kNearest, nullptr);
790 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
791 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [276/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawPaintWithColorSource |
| ) |  |

Definition at line 1186 of file dl_unittests.cc.

1186 {
1187 const flutter::DlColor colors[2] = {
1188 flutter::DlColor(0xFFF44336),
1189 flutter::DlColor(0xFF2196F3),
1190 };
1191 const float stops[2] = {0.0, 1.0};
1192 flutter::DlPaint paint;
1193 flutter::DisplayListBuilder builder;
1194 auto clip_bounds = SkRect::MakeWH(300.0, 300.0);
1195 builder.Save();
1196 builder.Translate(100, 100);
1197 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1198 auto linear =
1199 flutter::DlColorSource::MakeLinear({0.0, 0.0}, {100.0, 100.0}, 2, colors,
1200 stops, flutter::DlTileMode::kRepeat);
1201 paint.setColorSource(linear);
1202 builder.DrawPaint(paint);
1203 builder.Restore();
1204
1205 builder.Save();
1206 builder.Translate(500, 100);
1207 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1208 auto radial = flutter::DlColorSource::MakeRadial(
1209 {100.0, 100.0}, 100.0, 2, colors, stops, flutter::DlTileMode::kRepeat);
1210 paint.setColorSource(radial);
1211 builder.DrawPaint(paint);
1212 builder.Restore();
1213
1214 builder.Save();
1215 builder.Translate(100, 500);
1216 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1217 auto sweep =
1218 flutter::DlColorSource::MakeSweep({100.0, 100.0}, 180.0, 270.0, 2, colors,
1219 stops, flutter::DlTileMode::kRepeat);
1220 paint.setColorSource(sweep);
1221 builder.DrawPaint(paint);
1222 builder.Restore();
1223
1224 builder.Save();
1225 builder.Translate(500, 500);
1226 builder.ClipRect(clip_bounds, flutter::DlCanvas::ClipOp::kIntersect, false);
1227 auto texture = CreateTextureForFixture("table_mountain_nx.png");
1228 auto image = std::make_shared<flutter::DlImageColorSource>(
1229 DlImageImpeller::Make(texture), flutter::DlTileMode::kRepeat,
1230 flutter::DlTileMode::kRepeat);
1231 paint.setColorSource(image);
1232 builder.DrawPaint(paint);
1233 builder.Restore();
1234
1235 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1236 }

References impeller::DlImageImpeller::Make(), and paint.

## ◆ TEST_P() [277/456]

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

Definition at line 805 of file dl_unittests.cc.

805 {
806 flutter::DisplayListBuilder builder;
807 SkPoint points[7] = {
808 {0, 0}, //
809 {100, 100}, //
810 {100, 0}, //
811 {0, 100}, //
812 {0, 0}, //
813 {48, 48}, //
814 {52, 52}, //
815 };
816 std::vector<flutter::DlStrokeCap> caps = {
817 flutter::DlStrokeCap::kButt,
818 flutter::DlStrokeCap::kRound,
819 flutter::DlStrokeCap::kSquare,
820 };
821 flutter::DlPaint paint =
822 flutter::DlPaint() //
823 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
824 .setStrokeWidth(20);
825 builder.Translate(50, 50);
826 for (auto cap : caps) {
827 paint.setStrokeCap(cap);
828 builder.Save();
829 builder.DrawPoints(flutter::DlCanvas::PointMode::kPoints, 7, points, paint);
830 builder.Translate(150, 0);
831 builder.DrawPoints(flutter::DlCanvas::PointMode::kLines, 5, points, paint);
832 builder.Translate(150, 0);
833 builder.DrawPoints(flutter::DlCanvas::PointMode::kPolygon, 5, points,
834 paint);
835 builder.Restore();
836 builder.Translate(0, 150);
837 }
838 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
839 }

References paint.

## ◆ TEST_P() [278/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawRect |
| ) |  |

Definition at line 49 of file dl_unittests.cc.

49 {
50 flutter::DisplayListBuilder builder;
51 builder.DrawRect(SkRect::MakeXYWH(10, 10, 100, 100),
52 flutter::DlPaint(flutter::DlColor::kBlue()));
53 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
54 }

## ◆ TEST_P() [279/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawRectWithLinearToSrgbColorFilter |
| ) |  |

Definition at line 1170 of file dl_unittests.cc.

1170 {
1171 flutter::DlPaint paint;
1172 paint.setColor(flutter::DlColor(0xFF2196F3).withAlpha(128));
1173 flutter::DisplayListBuilder builder;
1174 paint.setColorFilter(
1175 flutter::DlLinearToSrgbGammaColorFilter::kInstance.get());
1176 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), paint);
1177 builder.Translate(0, 200);
1178
1179 paint.setColorFilter(
1180 flutter::DlSrgbToLinearGammaColorFilter::kInstance.get());
1181 builder.DrawRect(SkRect::MakeXYWH(0, 0, 200, 200), paint);
1182
1183 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1184 }

References paint.

## ◆ TEST_P() [280/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawShadow |
| ) |  |

Definition at line 864 of file dl_unittests.cc.

864 {
865 flutter::DisplayListBuilder builder;
866 flutter::DlPaint paint;
867
868 auto content_scale = GetContentScale() * 0.8;
869 builder.Scale(content_scale.x, content_scale.y);
870
871 constexpr size_t star_spikes = 5;
872 constexpr SkScalar half_spike_rotation = kPi / star_spikes;
873 constexpr SkScalar radius = 40;
874 constexpr SkScalar spike_size = 10;
875 constexpr SkScalar outer_radius = radius + spike_size;
876 constexpr SkScalar inner_radius = radius - spike_size;
877 std::array<SkPoint, star_spikes * 2> star;
878 for (size_t i = 0; i < star_spikes; i++) {
879 const SkScalar rotation = half_spike_rotation * i * 2;
880 star[i * 2] = SkPoint::Make(50 + std::sin(rotation) * outer_radius,
881 50 - std::cos(rotation) * outer_radius);
882 star[i * 2 + 1] = SkPoint::Make(
883 50 + std::sin(rotation + half_spike_rotation) * inner_radius,
884 50 - std::cos(rotation + half_spike_rotation) * inner_radius);
885 }
886
887 std::array<SkPath, 4> paths = {
888 SkPath{}.addRect(SkRect::MakeXYWH(0, 0, 200, 100)),
889 SkPath{}.addRRect(
890 SkRRect::MakeRectXY(SkRect::MakeXYWH(20, 0, 200, 100), 30, 30)),
891 SkPath{}.addCircle(100, 50, 50),
892 SkPath{}.addPoly(star.data(), star.size(), true),
893 };
894 paint.setColor(flutter::DlColor::kWhite());
895 builder.DrawPaint(paint);
896 paint.setColor(flutter::DlColor::kCyan());
897 builder.Translate(100, 50);
898 for (size_t x = 0; x < paths.size(); x++) {
899 builder.Save();
900 for (size_t y = 0; y < 6; y++) {
901 builder.DrawShadow(paths[x], flutter::DlColor::kBlack(), 3 + y * 8, false,
902 1);
903 builder.DrawPath(paths[x], paint);
904 builder.Translate(0, 150);
905 }
906 builder.Restore();
907 builder.Translate(250, 0);
908 }
909
910 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
911 }

References impeller::kPi, and paint.

## ◆ TEST_P() [281/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawStrokedText |
| ) |  |

Definition at line 466 of file dl_unittests.cc.

466 {
467 flutter::DisplayListBuilder builder;
468 flutter::DlPaint paint;
469
470 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
471 paint.setColor(flutter::DlColor::kRed());
472 builder.DrawTextBlob(
473 SkTextBlob::MakeFromString("stoked about stroked text", CreateTestFont()),
474 250, 250, paint);
475
476 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
477 }

References paint.

## ◆ TEST_P() [282/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextBlob |
| ) |  |

Definition at line 56 of file dl_unittests.cc.

56 {
57 flutter::DisplayListBuilder builder;
58 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
59 100, 100, flutter::DlPaint(flutter::DlColor::kBlue()));
60 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
61 }

## ◆ TEST_P() [283/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextBlobWithGradient |
| ) |  |

Definition at line 63 of file dl_unittests.cc.

63 {
64 flutter::DisplayListBuilder builder;
65
66 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
67 flutter::DlColor::kRed()};
68 const float stops[2] = {0.0, 1.0};
69
70 auto linear = flutter::DlColorSource::MakeLinear({0.0, 0.0}, {300.0, 300.0},
71 2, colors.data(), stops,
72 flutter::DlTileMode::kClamp);
73 flutter::DlPaint paint;
74 paint.setColorSource(linear);
75
76 builder.DrawTextBlob(
77 SkTextBlob::MakeFromString("Hello World", CreateTestFont()), 100, 100,
78 paint);
79 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
80 }

References paint.

## ◆ TEST_P() [284/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawTextWithSaveLayer |
| ) |  |

Definition at line 82 of file dl_unittests.cc.

82 {
83 flutter::DisplayListBuilder builder;
84 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
85 100, 100, flutter::DlPaint(flutter::DlColor::kRed()));
86
87 flutter::DlPaint save_paint;
88 float alpha = 0.5;
89 save_paint.setAlpha(static_cast<uint8_t>(255 * alpha));
90 builder.SaveLayer(nullptr, &save_paint);
91 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello with half alpha",
92 CreateTestFontOfSize(100)),
93 100, 300, flutter::DlPaint(flutter::DlColor::kRed()));
94 builder.Restore();
95 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
96 }

## ◆ TEST_P() [285/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithBlendColorFilter |
| ) |  |

Definition at line 518 of file dl_unittests.cc.

518 {
519 auto texture = CreateTextureForFixture("embarcadero.jpg");
520 flutter::DisplayListBuilder builder;
521 flutter::DlPaint paint;
522
523 // Pipeline blended image.
524 {
525 auto filter = flutter::DlBlendColorFilter(flutter::DlColor::kYellow(),
526 flutter::DlBlendMode::kModulate);
527 paint.setColorFilter(&filter);
528 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
529 flutter::DlImageSampling::kNearestNeighbor, &paint);
530 }
531
532 // Advanced blended image.
533 {
534 auto filter = flutter::DlBlendColorFilter(flutter::DlColor::kRed(),
535 flutter::DlBlendMode::kScreen);
536 paint.setColorFilter(&filter);
537 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(250, 250),
538 flutter::DlImageSampling::kNearestNeighbor, &paint);
539 }
540
541 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
542 }

References impeller::DlImageImpeller::Make(), and paint.

## ◆ TEST_P() [286/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithColorFilterImageFilter |
| ) |  |

Definition at line 544 of file dl_unittests.cc.

544 {
545 const float invert_color_matrix[20] = {
546 -1, 0, 0, 0, 1, //
547 0, -1, 0, 0, 1, //
548 0, 0, -1, 0, 1, //
549 0, 0, 0, 1, 0, //
550 };
551 auto texture = CreateTextureForFixture("boston.jpg");
552 flutter::DisplayListBuilder builder;
553 flutter::DlPaint paint;
554
555 auto color_filter =
556 std::make_shared<flutter::DlMatrixColorFilter>(invert_color_matrix);
557 auto image_filter =
558 std::make_shared<flutter::DlColorFilterImageFilter>(color_filter);
559
560 paint.setImageFilter(image_filter.get());
561 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
562 flutter::DlImageSampling::kNearestNeighbor, &paint);
563
564 builder.Translate(0, 700);
565 paint.setColorFilter(color_filter.get());
566 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
567 flutter::DlImageSampling::kNearestNeighbor, &paint);
568 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
569 }

References impeller::DlImageImpeller::Make(), and paint.

## ◆ TEST_P() [287/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithComposeImageFilter |
| ) |  |

Definition at line 596 of file dl_unittests.cc.

596 {
597 auto texture = CreateTextureForFixture("boston.jpg");
598 flutter::DisplayListBuilder builder;
599 flutter::DlPaint paint;
600
601 auto dilate = std::make_shared<flutter::DlDilateImageFilter>(10.0, 10.0);
602 auto erode = std::make_shared<flutter::DlErodeImageFilter>(10.0, 10.0);
603 auto open = std::make_shared<flutter::DlComposeImageFilter>(dilate, erode);
604 auto close = std::make_shared<flutter::DlComposeImageFilter>(erode, dilate);
605
606 paint.setImageFilter(open.get());
607 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
608 flutter::DlImageSampling::kNearestNeighbor, &paint);
609 builder.Translate(0, 700);
610 paint.setImageFilter(close.get());
611 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
612 flutter::DlImageSampling::kNearestNeighbor, &paint);
613 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
614 }

References impeller::DlImageImpeller::Make(), and paint.

## ◆ TEST_P() [288/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithImageBlurFilter |
| ) |  |

Definition at line 571 of file dl_unittests.cc.

571 {
572 auto texture = CreateTextureForFixture("embarcadero.jpg");
573
574 auto callback = [&]() {
575 static float sigma[] = {10, 10};
576
577 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
578 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
579 ImGui::End();
580
581 flutter::DisplayListBuilder builder;
582 flutter::DlPaint paint;
583
584 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
585 flutter::DlTileMode::kClamp);
586 paint.setImageFilter(&filter);
587 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
588 flutter::DlImageSampling::kNearestNeighbor, &paint);
589
590 return builder.Build();
591 };
592
593 ASSERT_TRUE(OpenPlaygroundHere(callback));
594 }

References impeller::DlImageImpeller::Make(), and paint.

## ◆ TEST_P() [289/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMaskBlur |
| ) |  |

Definition at line 430 of file dl_unittests.cc.

430 {
431 auto texture = CreateTextureForFixture("embarcadero.jpg");
432 flutter::DisplayListBuilder builder;
433 flutter::DlPaint paint;
434
435 // Mask blurred image.
436 {
437 auto filter =
438 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
439 paint.setMaskFilter(&filter);
440 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
441 flutter::DlImageSampling::kNearestNeighbor, &paint);
442 }
443
444 // Mask blurred filled path.
445 {
446 paint.setColor(flutter::DlColor::kYellow());
447 auto filter =
448 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kOuter, 10.0f);
449 paint.setMaskFilter(&filter);
450 builder.DrawArc(SkRect::MakeXYWH(410, 110, 100, 100), 45, 270, true, paint);
451 }
452
453 // Mask blurred text.
454 {
455 auto filter =
456 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kSolid, 10.0f);
457 paint.setMaskFilter(&filter);
458 builder.DrawTextBlob(
459 SkTextBlob::MakeFromString("Testing", CreateTestFont()), 220, 170,
460 paint);
461 }
462
463 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
464 }

References impeller::DlImageImpeller::Make(), and paint.

## ◆ TEST_P() [290/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilter |
| ) |  |

Definition at line 1010 of file dl_unittests.cc.

1010 {
1011 auto boston = CreateTextureForFixture("boston.jpg");
1012
1013 auto callback = [&]() {
1014 static int selected_matrix_type = 0;
1015 const char* matrix_type_names[] = {"Matrix", "Local Matrix"};
1016
1017 static float ctm_translation[2] = {200, 200};
1018 static float ctm_scale[2] = {0.65, 0.65};
1019 static float ctm_skew[2] = {0, 0};
1020
1021 static bool enable = true;
1022 static float translation[2] = {100, 100};
1023 static float scale[2] = {0.8, 0.8};
1024 static float skew[2] = {0.2, 0.2};
1025
1026 static bool enable_savelayer = true;
1027
1028 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1029 {
1030 ImGui::Combo("Filter type", &selected_matrix_type, matrix_type_names,
1031 sizeof(matrix_type_names) / sizeof(char*));
1032
1033 ImGui::TextWrapped("Current Transform");
1034 ImGui::SliderFloat2("CTM Translation", ctm_translation, 0, 1000);
1035 ImGui::SliderFloat2("CTM Scale", ctm_scale, 0, 3);
1036 ImGui::SliderFloat2("CTM Skew", ctm_skew, -3, 3);
1037
1038 ImGui::TextWrapped(
1039 "MatrixFilter and LocalMatrixFilter modify the CTM in the same way. "
1040 "The only difference is that MatrixFilter doesn't affect the effect "
1041 "transform, whereas LocalMatrixFilter does.");
1042 // Note: See this behavior in:
1043 // https://fiddle.skia.org/c/6cbb551ab36d06f163db8693972be954
1044 ImGui::Checkbox("Enable", &enable);
1045 ImGui::SliderFloat2("Filter Translation", translation, 0, 1000);
1046 ImGui::SliderFloat2("Filter Scale", scale, 0, 3);
1047 ImGui::SliderFloat2("Filter Skew", skew, -3, 3);
1048
1049 ImGui::TextWrapped(
1050 "Rendering the filtered image within a layer can expose bounds "
1051 "issues. If the rendered image gets cut off when this setting is "
1052 "enabled, there's a coverage bug in the filter.");
1053 ImGui::Checkbox("Render in layer", &enable_savelayer);
1054 }
1055 ImGui::End();
1056
1057 flutter::DisplayListBuilder builder;
1058 flutter::DlPaint paint;
1059
1060 if (enable_savelayer) {
1061 builder.SaveLayer(nullptr, nullptr);
1062 }
1063 {
1064 auto content_scale = GetContentScale();
1065 builder.Scale(content_scale.x, content_scale.y);
1066
1067 // Set the current transform
1068 auto ctm_matrix =
1069 SkMatrix::MakeAll(ctm_scale[0], ctm_skew[0], ctm_translation[0], //
1070 ctm_skew[1], ctm_scale[1], ctm_translation[1], //
1071 0, 0, 1);
1072 builder.Transform(ctm_matrix);
1073
1074 // Set the matrix filter
1075 auto filter_matrix =
1076 SkMatrix::MakeAll(scale[0], skew[0], translation[0], //
1077 skew[1], scale[1], translation[1], //
1078 0, 0, 1);
1079
1080 if (enable) {
1081 switch (selected_matrix_type) {
1082 case 0: {
1083 auto filter = flutter::DlMatrixImageFilter(
1084 filter_matrix, flutter::DlImageSampling::kLinear);
1085 paint.setImageFilter(&filter);
1086 break;
1087 }
1088 case 1: {
1089 auto internal_filter =
1090 flutter::DlBlurImageFilter(10, 10, flutter::DlTileMode::kDecal)
1091 .shared();
1092 auto filter = flutter::DlLocalMatrixImageFilter(filter_matrix,
1093 internal_filter);
1094 paint.setImageFilter(&filter);
1095 break;
1096 }
1097 }
1098 }
1099
1100 builder.DrawImage(DlImageImpeller::Make(boston), {},
1101 flutter::DlImageSampling::kLinear, &paint);
1102 }
1103 if (enable_savelayer) {
1104 builder.Restore();
1105 }
1106
1107 return builder.Build();
1108 };
1109
1110 ASSERT_TRUE(OpenPlaygroundHere(callback));
1111 }

References impeller::DlImageImpeller::Make(), paint, and scale.

## ◆ TEST_P() [291/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithMatrixFilterWhenSavingLayer |
| ) |  |

Definition at line 1113 of file dl_unittests.cc.

1113 {
1114 auto callback = [&]() {
1115 static float translation[2] = {0, 0};
1116 static bool enable_save_layer = true;
1117
1118 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1119 ImGui::SliderFloat2("Translation", translation, -130, 130);
1120 ImGui::Checkbox("Enable save layer", &enable_save_layer);
1121 ImGui::End();
1122
1123 flutter::DisplayListBuilder builder;
1124 builder.Save();
1125 builder.Scale(2.0, 2.0);
1126 flutter::DlPaint paint;
1127 paint.setColor(flutter::DlColor::kYellow());
1128 builder.DrawRect(SkRect::MakeWH(300, 300), paint);
1129 paint.setStrokeWidth(1.0);
1130 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1131 paint.setColor(flutter::DlColor::kBlack().withAlpha(0x80));
1132 builder.DrawLine(SkPoint::Make(150, 0), SkPoint::Make(150, 300), paint);
1133 builder.DrawLine(SkPoint::Make(0, 150), SkPoint::Make(300, 150), paint);
1134
1135 flutter::DlPaint save_paint;
1136 SkRect bounds = SkRect::MakeXYWH(100, 100, 100, 100);
1137 SkMatrix translate_matrix =
1138 SkMatrix::Translate(translation[0], translation[1]);
1139 if (enable_save_layer) {
1140 auto filter = flutter::DlMatrixImageFilter(
1141 translate_matrix, flutter::DlImageSampling::kNearestNeighbor);
1142 save_paint.setImageFilter(filter.shared());
1143 builder.SaveLayer(&bounds, &save_paint);
1144 } else {
1145 builder.Save();
1146 builder.Transform(translate_matrix);
1147 }
1148
1149 SkMatrix filter_matrix = SkMatrix::I();
1150 filter_matrix.postTranslate(-150, -150);
1151 filter_matrix.postScale(0.2f, 0.2f);
1152 filter_matrix.postTranslate(150, 150);
1153 auto filter = flutter::DlMatrixImageFilter(
1154 filter_matrix, flutter::DlImageSampling::kNearestNeighbor);
1155
1156 save_paint.setImageFilter(filter.shared());
1157
1158 builder.SaveLayer(&bounds, &save_paint);
1159 flutter::DlPaint paint2;
1160 paint2.setColor(flutter::DlColor::kBlue());
1161 builder.DrawRect(bounds, paint2);
1162 builder.Restore();
1163 builder.Restore();
1164 return builder.Build();
1165 };
1166
1167 ASSERT_TRUE(OpenPlaygroundHere(callback));
1168 }

References paint.

## ◆ TEST_P() [292/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawWithOddPathWinding |
| ) |  |

Definition at line 386 of file dl_unittests.cc.

386 {
387 flutter::DisplayListBuilder builder;
388 flutter::DlPaint paint;
389
390 paint.setColor(flutter::DlColor::kRed());
391 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
392
393 builder.Translate(300, 300);
394 SkPath path;
395 path.setFillType(SkPathFillType::kEvenOdd);
396 path.addCircle(0, 0, 100);
397 path.addCircle(0, 0, 50);
398 builder.DrawPath(path, paint);
399
400 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
401 }

References paint.

## ◆ TEST_P() [293/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawZeroLengthLine |
| ) |  |

Definition at line 841 of file dl_unittests.cc.

841 {
842 flutter::DisplayListBuilder builder;
843 std::vector<flutter::DlStrokeCap> caps = {
844 flutter::DlStrokeCap::kButt,
845 flutter::DlStrokeCap::kRound,
846 flutter::DlStrokeCap::kSquare,
847 };
848 flutter::DlPaint paint =
849 flutter::DlPaint() //
850 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
851 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
852 .setStrokeCap(flutter::DlStrokeCap::kButt) //
853 .setStrokeWidth(20);
854 SkPath path = SkPath().addPoly({{150, 50}, {150, 50}}, false);
855 for (auto cap : caps) {
856 paint.setStrokeCap(cap);
857 builder.DrawLine({50, 50}, {50, 50}, paint);
858 builder.DrawPath(path, paint);
859 builder.Translate(0, 150);
860 }
861 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
862 }

References paint.

## ◆ TEST_P() [294/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | CanDrawZeroWidthLine |
| ) |  |

Definition at line 976 of file dl_unittests.cc.

976 {
977 flutter::DisplayListBuilder builder;
978 std::vector<flutter::DlStrokeCap> caps = {
979 flutter::DlStrokeCap::kButt,
980 flutter::DlStrokeCap::kRound,
981 flutter::DlStrokeCap::kSquare,
982 };
983 flutter::DlPaint paint = //
984 flutter::DlPaint() //
985 .setColor(flutter::DlColor::kWhite()) //
986 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
987 .setStrokeWidth(0);
988 flutter::DlPaint outline_paint = //
989 flutter::DlPaint() //
990 .setColor(flutter::DlColor::kYellow()) //
991 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
992 .setStrokeCap(flutter::DlStrokeCap::kSquare) //
993 .setStrokeWidth(1);
994 SkPath path = SkPath().addPoly({{150, 50}, {160, 50}}, false);
995 for (auto cap : caps) {
996 paint.setStrokeCap(cap);
997 builder.DrawLine({50, 50}, {60, 50}, paint);
998 builder.DrawRect({45, 45, 65, 55}, outline_paint);
999 builder.DrawLine({100, 50}, {100, 50}, paint);
1000 if (cap != flutter::DlStrokeCap::kButt) {
1001 builder.DrawRect({95, 45, 105, 55}, outline_paint);
1002 }
1003 builder.DrawPath(path, paint);
1004 builder.DrawRect(path.getBounds().makeOutset(5, 5), outline_paint);
1005 builder.Translate(0, 150);
1006 }
1007 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1008 }

References paint.

## ◆ TEST_P() [295/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | ClipDrawRRectWithNonCircularRadii |
| ) |  |

Definition at line 1393 of file dl_unittests.cc.

1393 {
1394 flutter::DisplayListBuilder builder;
1395
1396 flutter::DlPaint fill_paint = //
1397 flutter::DlPaint() //
1398 .setColor(flutter::DlColor::kBlue()) //
1399 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1400 .setStrokeWidth(10);
1401 flutter::DlPaint stroke_paint = //
1402 flutter::DlPaint() //
1403 .setColor(flutter::DlColor::kGreen()) //
1404 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1405 .setStrokeWidth(10);
1406
1407 builder.DrawRRect(
1408 SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1409 fill_paint);
1410 builder.DrawRRect(
1411 SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1412 stroke_paint);
1413
1414 builder.DrawRRect(
1415 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1416 fill_paint);
1417 builder.DrawRRect(
1418 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1419 stroke_paint);
1420
1421 flutter::DlPaint reference_paint = //
1422 flutter::DlPaint() //
1423 .setColor(flutter::DlColor::kMidGrey()) //
1424 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1425 .setStrokeWidth(10);
1426
1427 builder.DrawRRect(
1428 SkRRect::MakeRectXY(SkRect::MakeXYWH(500, 500, 300, 300), 40, 40),
1429 reference_paint);
1430 builder.DrawRRect(
1431 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 100, 300, 300), 120, 120),
1432 reference_paint);
1433
1434 flutter::DlPaint clip_fill_paint = //
1435 flutter::DlPaint() //
1436 .setColor(flutter::DlColor::kCyan()) //
1437 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1438 .setStrokeWidth(10);
1439
1440 builder.Save();
1441 builder.ClipRRect(
1442 SkRRect::MakeRectXY(SkRect::MakeXYWH(900, 100, 300, 300), 120, 40));
1443 builder.DrawPaint(clip_fill_paint);
1444 builder.Restore();
1445
1446 builder.Save();
1447 builder.ClipRRect(
1448 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, 900, 300, 300), 40, 120));
1449 builder.DrawPaint(clip_fill_paint);
1450 builder.Restore();
1451
1452 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1453 }

## ◆ TEST_P() [296/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DispatcherDoesNotCullPerspectiveTransformedChildDisplayLists |
| ) |  |

Definition at line 913 of file dl_unittests.cc.

914 {
915 // Regression test for https://github.com/flutter/flutter/issues/130613
916 flutter::DisplayListBuilder sub_builder(true);
917 sub_builder.DrawRect(SkRect::MakeXYWH(0, 0, 50, 50),
918 flutter::DlPaint(flutter::DlColor::kRed()));
919 auto display_list = sub_builder.Build();
920
921 DlDispatcher dispatcher(Rect::MakeLTRB(0, 0, 2400, 1800));
922 dispatcher.scale(2.0, 2.0);
923 dispatcher.translate(-93.0, 0.0);
924 // clang-format off
925 dispatcher.transformFullPerspective(
926 0.8, -0.2, -0.1, -0.0,
927 0.0, 1.0, 0.0, 0.0,
928 1.4, 1.3, 1.0, 0.0,
929 63.2, 65.3, 48.6, 1.1
930 );
931 // clang-format on
932 dispatcher.translate(35.0, 75.0);
933 dispatcher.drawDisplayList(display_list, 1.0f);
934 auto picture = dispatcher.EndRecordingAsPicture();
935
936 bool found = false;
937 picture.pass->IterateAllEntities([&found](Entity& entity) {
938 if (std::static_pointer_cast<SolidColorContents>(entity.GetContents())
939 ->GetColor() == Color::Red()) {
940 found = true;
941 return false;
942 }
943
944 return true;
945 });
946 EXPECT_TRUE(found);
947 }

References impeller::DlDispatcherBase::drawDisplayList(), impeller::DlDispatcherBase::EndRecordingAsPicture(), impeller::Entity::GetContents(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Picture::pass, impeller::Color::Red(), impeller::DlDispatcherBase::scale(), impeller::DlDispatcherBase::transformFullPerspective(), and impeller::DlDispatcherBase::translate().

## ◆ TEST_P() [297/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawMaskBlursThatMightUseSaveLayers |
| ) |  |

Definition at line 1655 of file dl_unittests.cc.

1655 {
1656 flutter::DisplayListBuilder builder;
1657 builder.DrawColor(flutter::DlColor::kWhite(), flutter::DlBlendMode::kSrc);
1658 Vector2 scale = GetContentScale();
1659 builder.Scale(scale.x, scale.y);
1660
1661 builder.Save();
1662 // We need a small transform op to avoid a deferred save
1663 builder.Translate(1.0f, 1.0f);
1664 auto solid_filter =
1665 flutter::DlBlurMaskFilter::Make(flutter::DlBlurStyle::kSolid, 5.0f);
1666 flutter::DlPaint solid_alpha_paint =
1667 flutter::DlPaint() //
1668 .setMaskFilter(solid_filter) //
1669 .setColor(flutter::DlColor::kBlue()) //
1670 .setAlpha(0x7f);
1671 for (int x = 1; x <= 4; x++) {
1672 for (int y = 1; y <= 4; y++) {
1673 builder.DrawRect(SkRect::MakeXYWH(x * 100, y * 100, 80, 80),
1674 solid_alpha_paint);
1675 }
1676 }
1677 builder.Restore();
1678
1679 builder.Save();
1680 builder.Translate(500.0f, 0.0f);
1681 auto normal_filter =
1682 flutter::DlBlurMaskFilter::Make(flutter::DlBlurStyle::kNormal, 5.0f);
1683 auto rotate_if = flutter::DlMatrixImageFilter::Make(
1684 SkMatrix::RotateDeg(10), flutter::DlImageSampling::kLinear);
1685 flutter::DlPaint normal_if_paint =
1686 flutter::DlPaint() //
1687 .setMaskFilter(solid_filter) //
1688 .setImageFilter(rotate_if) //
1689 .setColor(flutter::DlColor::kGreen()) //
1690 .setAlpha(0x7f);
1691 for (int x = 1; x <= 4; x++) {
1692 for (int y = 1; y <= 4; y++) {
1693 builder.DrawRect(SkRect::MakeXYWH(x * 100, y * 100, 80, 80),
1694 normal_if_paint);
1695 }
1696 }
1697 builder.Restore();
1698
1699 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1700 }

References scale.

## ◆ TEST_P() [298/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawPaintIgnoresMaskFilter |
| ) |  |

Definition at line 1632 of file dl_unittests.cc.

1632 {
1633 flutter::DisplayListBuilder builder;
1634 builder.DrawPaint(flutter::DlPaint().setColor(flutter::DlColor::kWhite()));
1635
1636 auto filter = flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
1637 builder.DrawCircle({300, 300}, 200,
1638 flutter::DlPaint().setMaskFilter(&filter));
1639
1640 std::vector<flutter::DlColor> colors = {flutter::DlColor::kGreen(),
1641 flutter::DlColor::kGreen()};
1642 const float stops[2] = {0.0, 1.0};
1643 auto linear = flutter::DlColorSource::MakeLinear(
1644 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
1645 flutter::DlTileMode::kRepeat);
1646 flutter::DlPaint blend_paint =
1647 flutter::DlPaint() //
1648 .setColorSource(linear) //
1649 .setBlendMode(flutter::DlBlendMode::kScreen);
1650 builder.DrawPaint(blend_paint);
1651
1652 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1653 }

## ◆ TEST_P() [299/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawShapes |
| ) |  |

Definition at line 1355 of file dl_unittests.cc.

1355 {
1356 flutter::DisplayListBuilder builder;
1357 std::vector<flutter::DlStrokeJoin> joins = {
1358 flutter::DlStrokeJoin::kBevel,
1359 flutter::DlStrokeJoin::kRound,
1360 flutter::DlStrokeJoin::kMiter,
1361 };
1362 flutter::DlPaint paint = //
1363 flutter::DlPaint() //
1364 .setColor(flutter::DlColor::kWhite()) //
1365 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1366 .setStrokeWidth(10);
1367 flutter::DlPaint stroke_paint = //
1368 flutter::DlPaint() //
1369 .setColor(flutter::DlColor::kWhite()) //
1370 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1371 .setStrokeWidth(10);
1372 SkPath path = SkPath().addPoly({{150, 50}, {160, 50}}, false);
1373
1374 builder.Translate(300, 50);
1375 builder.Scale(0.8, 0.8);
1376 for (auto join : joins) {
1377 paint.setStrokeJoin(join);
1378 stroke_paint.setStrokeJoin(join);
1379 builder.DrawRect(SkRect::MakeXYWH(0, 0, 100, 100), paint);
1380 builder.DrawRect(SkRect::MakeXYWH(0, 150, 100, 100), stroke_paint);
1381 builder.DrawRRect(
1382 SkRRect::MakeRectXY(SkRect::MakeXYWH(150, 0, 100, 100), 30, 30), paint);
1383 builder.DrawRRect(
1384 SkRRect::MakeRectXY(SkRect::MakeXYWH(150, 150, 100, 100), 30, 30),
1385 stroke_paint);
1386 builder.DrawCircle({350, 50}, 50, paint);
1387 builder.DrawCircle({350, 200}, 50, stroke_paint);
1388 builder.Translate(0, 300);
1389 }
1390 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1391 }

References paint.

## ◆ TEST_P() [300/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | DrawVerticesBlendModes |
| ) |  |

Definition at line 1455 of file dl_unittests.cc.

1455 {
1456 std::vector<const char*> blend_mode_names;
1457 std::vector<flutter::DlBlendMode> blend_mode_values;
1458 {
1459 const std::vector<std::tuple<const char*, flutter::DlBlendMode>> blends = {
1460 // Pipeline blends (Porter-Duff alpha compositing)
1461 {"Clear", flutter::DlBlendMode::kClear},
1462 {"Source", flutter::DlBlendMode::kSrc},
1463 {"Destination", flutter::DlBlendMode::kDst},
1464 {"SourceOver", flutter::DlBlendMode::kSrcOver},
1465 {"DestinationOver", flutter::DlBlendMode::kDstOver},
1466 {"SourceIn", flutter::DlBlendMode::kSrcIn},
1467 {"DestinationIn", flutter::DlBlendMode::kDstIn},
1468 {"SourceOut", flutter::DlBlendMode::kSrcOut},
1469 {"DestinationOut", flutter::DlBlendMode::kDstOut},
1470 {"SourceATop", flutter::DlBlendMode::kSrcATop},
1471 {"DestinationATop", flutter::DlBlendMode::kDstATop},
1472 {"Xor", flutter::DlBlendMode::kXor},
1473 {"Plus", flutter::DlBlendMode::kPlus},
1474 {"Modulate", flutter::DlBlendMode::kModulate},
1475 // Advanced blends (color component blends)
1476 {"Screen", flutter::DlBlendMode::kScreen},
1477 {"Overlay", flutter::DlBlendMode::kOverlay},
1478 {"Darken", flutter::DlBlendMode::kDarken},
1479 {"Lighten", flutter::DlBlendMode::kLighten},
1480 {"ColorDodge", flutter::DlBlendMode::kColorDodge},
1481 {"ColorBurn", flutter::DlBlendMode::kColorBurn},
1482 {"HardLight", flutter::DlBlendMode::kHardLight},
1483 {"SoftLight", flutter::DlBlendMode::kSoftLight},
1484 {"Difference", flutter::DlBlendMode::kDifference},
1485 {"Exclusion", flutter::DlBlendMode::kExclusion},
1486 {"Multiply", flutter::DlBlendMode::kMultiply},
1487 {"Hue", flutter::DlBlendMode::kHue},
1488 {"Saturation", flutter::DlBlendMode::kSaturation},
1489 {"Color", flutter::DlBlendMode::kColor},
1490 {"Luminosity", flutter::DlBlendMode::kLuminosity},
1491 };
1492 assert(blends.size() ==
1493 static_cast<size_t>(flutter::DlBlendMode::kLastMode) + 1);
1494 for (const auto& [name, mode] : blends) {
1495 blend_mode_names.push_back(name);
1496 blend_mode_values.push_back(mode);
1497 }
1498 }
1499
1500 auto callback = [&]() {
1501 static int current_blend_index = 3;
1502 static float dst_alpha = 1;
1503 static float src_alpha = 1;
1504 static float color0[4] = {1.0f, 0.0f, 0.0f, 1.0f};
1505 static float color1[4] = {0.0f, 1.0f, 0.0f, 1.0f};
1506 static float color2[4] = {0.0f, 0.0f, 1.0f, 1.0f};
1507 static float src_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
1508
1509 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1510 {
1511 ImGui::ListBox("Blending mode", &current_blend_index,
1512 blend_mode_names.data(), blend_mode_names.size());
1513 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
1514 ImGui::ColorEdit4("Color A", color0);
1515 ImGui::ColorEdit4("Color B", color1);
1516 ImGui::ColorEdit4("Color C", color2);
1517 ImGui::ColorEdit4("Source Color", src_color);
1518 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
1519 }
1520 ImGui::End();
1521
1522 std::vector<SkPoint> positions = {SkPoint::Make(100, 300),
1523 SkPoint::Make(200, 100),
1524 SkPoint::Make(300, 300)};
1525 std::vector<flutter::DlColor> colors = {
1526 toColor(color0).modulateOpacity(dst_alpha),
1527 toColor(color1).modulateOpacity(dst_alpha),
1528 toColor(color2).modulateOpacity(dst_alpha)};
1529
1530 auto vertices = flutter::DlVertices::Make(
1531 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1532 /*texture_coordinates=*/nullptr, colors.data());
1533
1534 flutter::DisplayListBuilder builder;
1535 flutter::DlPaint paint;
1536
1537 paint.setColor(toColor(src_color).modulateOpacity(src_alpha));
1538 builder.DrawVertices(vertices, blend_mode_values[current_blend_index],
1539 paint);
1540 return builder.Build();
1541 };
1542
1543 ASSERT_TRUE(OpenPlaygroundHere(callback));
1544 }

References paint, and toColor().

## ◆ TEST_P() [301/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | IgnoreMaskFilterWhenSavingLayer |
| ) |  |

Definition at line 505 of file dl_unittests.cc.

505 {
506 auto texture = CreateTextureForFixture("embarcadero.jpg");
507 flutter::DisplayListBuilder builder;
508 auto filter = flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
509 flutter::DlPaint paint;
510 paint.setMaskFilter(&filter);
511 builder.SaveLayer(nullptr, &paint);
512 builder.DrawImage(DlImageImpeller::Make(texture), SkPoint::Make(100, 100),
513 flutter::DlImageSampling::kNearestNeighbor);
514 builder.Restore();
515 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
516 }

References impeller::DlImageImpeller::Make(), and paint.

## ◆ TEST_P() [302/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | MaskBlursApplyCorrectlyToColorSources |
| ) |  |

Definition at line 1318 of file dl_unittests.cc.

1318 {
1319 auto blur_filter = std::make_shared<flutter::DlBlurMaskFilter>(
1320 flutter::DlBlurStyle::kNormal, 10);
1321
1322 flutter::DisplayListBuilder builder;
1323
1324 std::array<flutter::DlColor, 2> colors = {flutter::DlColor::kBlue(),
1325 flutter::DlColor::kGreen()};
1326 std::array<float, 2> stops = {0, 1};
1327 std::array<std::shared_ptr<flutter::DlColorSource>, 2> color_sources = {
1328 std::make_shared<flutter::DlColorColorSource>(flutter::DlColor::kWhite()),
1329 flutter::DlColorSource::MakeLinear(
1330 SkPoint::Make(0, 0), SkPoint::Make(100, 50), 2, colors.data(),
1331 stops.data(), flutter::DlTileMode::kClamp)};
1332
1333 int offset = 100;
1334 for (const auto& color_source : color_sources) {
1335 flutter::DlPaint paint;
1336 paint.setColorSource(color_source);
1337 paint.setMaskFilter(blur_filter);
1338
1339 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
1340 builder.DrawRRect(
1341 SkRRect::MakeRectXY(SkRect::MakeXYWH(100, offset, 100, 50), 30, 30),
1342 paint);
1343 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1344 paint.setStrokeWidth(10);
1345 builder.DrawRRect(
1346 SkRRect::MakeRectXY(SkRect::MakeXYWH(300, offset, 100, 50), 30, 30),
1347 paint);
1348
1349 offset += 100;
1350 }
1351
1352 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1353 }

References offset, and paint.

## ◆ TEST_P() [303/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | NinePatchImagePrecision |
| ) |  |

Definition at line 793 of file dl_unittests.cc.

793 {
794 // Draw a nine patch image with colored corners and verify that the corner
795 // color does not leak outside the intended region.
796 auto texture = CreateTextureForFixture("nine_patch_corners.png");
797 flutter::DisplayListBuilder builder;
798 builder.DrawImageNine(DlImageImpeller::Make(texture),
799 SkIRect::MakeXYWH(10, 10, 1, 1),
800 SkRect::MakeXYWH(0, 0, 200, 100),
801 flutter::DlFilterMode::kNearest, nullptr);
802 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
803 }

References impeller::DlImageImpeller::Make().

## ◆ TEST_P() [304/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | StrokedPathsDrawCorrectly |
| ) |  |

Definition at line 213 of file dl_unittests.cc.

213 {
214 auto callback = [&]() {
215 flutter::DisplayListBuilder builder;
216 flutter::DlPaint paint;
217
218 paint.setColor(flutter::DlColor::kRed());
219 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
220
221 static float stroke_width = 10.0f;
222 static int selected_stroke_type = 0;
223 static int selected_join_type = 0;
224 const char* stroke_types[] = {"Butte", "Round", "Square"};
225 const char* join_type[] = {"kMiter", "Round", "kBevel"};
226
227 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
228 ImGui::Combo("Cap", &selected_stroke_type, stroke_types,
229 sizeof(stroke_types) / sizeof(char*));
230 ImGui::Combo("Join", &selected_join_type, join_type,
231 sizeof(join_type) / sizeof(char*));
232 ImGui::SliderFloat("Stroke Width", &stroke_width, 10.0f, 50.0f);
233 ImGui::End();
234
235 flutter::DlStrokeCap cap;
236 flutter::DlStrokeJoin join;
237 switch (selected_stroke_type) {
238 case 0:
239 cap = flutter::DlStrokeCap::kButt;
240 break;
241 case 1:
242 cap = flutter::DlStrokeCap::kRound;
243 break;
244 case 2:
245 cap = flutter::DlStrokeCap::kSquare;
246 break;
247 default:
248 cap = flutter::DlStrokeCap::kButt;
249 break;
250 }
251 switch (selected_join_type) {
252 case 0:
253 join = flutter::DlStrokeJoin::kMiter;
254 break;
255 case 1:
256 join = flutter::DlStrokeJoin::kRound;
257 break;
258 case 2:
259 join = flutter::DlStrokeJoin::kBevel;
260 break;
261 default:
262 join = flutter::DlStrokeJoin::kMiter;
263 break;
264 }
265 paint.setStrokeCap(cap);
266 paint.setStrokeJoin(join);
267 paint.setStrokeWidth(stroke_width);
268
269 // Make rendering better to watch.
270 builder.Scale(1.5f, 1.5f);
271
272 // Rectangle
273 builder.Translate(100, 100);
274 builder.DrawRect(SkRect::MakeSize({100, 100}), paint);
275
276 // Rounded rectangle
277 builder.Translate(150, 0);
278 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10),
279 paint);
280
281 // Double rounded rectangle
282 builder.Translate(150, 0);
283 builder.DrawDRRect(
284 SkRRect::MakeRectXY(SkRect::MakeSize({100, 50}), 10, 10),
285 SkRRect::MakeRectXY(SkRect::MakeXYWH(10, 10, 80, 30), 10, 10), paint);
286
287 // Contour with duplicate join points
288 {
289 builder.Translate(150, 0);
290 SkPath path;
291 path.moveTo(0, 0);
292 path.lineTo(0, 0);
293 path.lineTo({100, 0});
294 path.lineTo({100, 0});
295 path.lineTo({100, 100});
296 builder.DrawPath(path, paint);
297 }
298
299 // Contour with duplicate start and end points
300
301 // Line.
302 builder.Translate(200, 0);
303 {
304 builder.Save();
305
306 SkPath line_path;
307 line_path.moveTo(0, 0);
308 line_path.moveTo(0, 0);
309 line_path.lineTo({0, 0});
310 line_path.lineTo({0, 0});
311 line_path.lineTo({50, 50});
312 line_path.lineTo({50, 50});
313 line_path.lineTo({100, 0});
314 line_path.lineTo({100, 0});
315 builder.DrawPath(line_path, paint);
316
317 builder.Translate(0, 100);
318 builder.DrawPath(line_path, paint);
319
320 builder.Translate(0, 100);
321 SkPath line_path2;
322 line_path2.moveTo(0, 0);
323 line_path2.lineTo(0, 0);
324 line_path2.lineTo(0, 0);
325 builder.DrawPath(line_path2, paint);
326
327 builder.Restore();
328 }
329
330 // Cubic.
331 builder.Translate(150, 0);
332 {
333 builder.Save();
334
335 SkPath cubic_path;
336 cubic_path.moveTo({0, 0});
337 cubic_path.cubicTo(0, 0, 140.0, 100.0, 140, 20);
338 builder.DrawPath(cubic_path, paint);
339
340 builder.Translate(0, 100);
341 SkPath cubic_path2;
342 cubic_path2.moveTo({0, 0});
343 cubic_path2.cubicTo(0, 0, 0, 0, 150, 150);
344 builder.DrawPath(cubic_path2, paint);
345
346 builder.Translate(0, 100);
347 SkPath cubic_path3;
348 cubic_path3.moveTo({0, 0});
349 cubic_path3.cubicTo(0, 0, 0, 0, 0, 0);
350 builder.DrawPath(cubic_path3, paint);
351
352 builder.Restore();
353 }
354
355 // Quad.
356 builder.Translate(200, 0);
357 {
358 builder.Save();
359
360 SkPath quad_path;
361 quad_path.moveTo(0, 0);
362 quad_path.moveTo(0, 0);
363 quad_path.quadTo({100, 40}, {50, 80});
364 builder.DrawPath(quad_path, paint);
365
366 builder.Translate(0, 150);
367 SkPath quad_path2;
368 quad_path2.moveTo(0, 0);
369 quad_path2.moveTo(0, 0);
370 quad_path2.quadTo({0, 0}, {100, 100});
371 builder.DrawPath(quad_path2, paint);
372
373 builder.Translate(0, 100);
374 SkPath quad_path3;
375 quad_path3.moveTo(0, 0);
376 quad_path3.quadTo({0, 0}, {0, 0});
377 builder.DrawPath(quad_path3, paint);
378
379 builder.Restore();
380 }
381 return builder.Build();
382 };
383 ASSERT_TRUE(OpenPlaygroundHere(callback));
384 }

References paint, and stroke_width.

## ◆ TEST_P() [305/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | StrokedTextNotOffsetFromNormalText |
| ) |  |

Definition at line 480 of file dl_unittests.cc.

480 {
481 flutter::DisplayListBuilder builder;
482 flutter::DlPaint paint;
483 auto const& text_blob = SkTextBlob::MakeFromString("00000", CreateTestFont());
484
485 // https://api.flutter.dev/flutter/material/Colors/blue-constant.html.
486 auto const& mat_blue = flutter::DlColor(0xFF2196f3);
487
488 // Draw a blue filled rectangle so the text is easier to see.
489 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
490 paint.setColor(mat_blue);
491 builder.DrawRect(SkRect::MakeXYWH(0, 0, 500, 500), paint);
492
493 // Draw stacked text, with stroked text on top.
494 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
495 paint.setColor(flutter::DlColor::kWhite());
496 builder.DrawTextBlob(text_blob, 250, 250, paint);
497
498 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
499 paint.setColor(flutter::DlColor::kBlack());
500 builder.DrawTextBlob(text_blob, 250, 250, paint);
501
502 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
503 }

References paint.

## ◆ TEST_P() [306/456]

impeller::testing::TEST_P | ( | DisplayListTest | ,
|  | TransparentShadowProducesCorrectColor |
| ) |  |

Definition at line 949 of file dl_unittests.cc.

949 {
950 DlDispatcher dispatcher;
951 dispatcher.save();
952 dispatcher.scale(1.618, 1.618);
953 SkPath path = SkPath{}.addRect(SkRect::MakeXYWH(0, 0, 200, 100));
954 flutter::DlOpReceiver::CacheablePath cache(path);
955 dispatcher.drawShadow(cache, flutter::DlColor::kTransparent(), 15, false, 1);
956 dispatcher.restore();
957 auto picture = dispatcher.EndRecordingAsPicture();
958
959 std::shared_ptr<SolidRRectBlurContents> rrect_blur;
960 picture.pass->IterateAllEntities([&rrect_blur](Entity& entity) {
961 if (ScalarNearlyEqual(entity.GetTransform().GetScale().x, 1.618f)) {
962 rrect_blur = std::static_pointer_cast<SolidRRectBlurContents>(
963 entity.GetContents());
964 return false;
965 }
966 return true;
967 });
968
969 ASSERT_NE(rrect_blur, nullptr);
970 ASSERT_EQ(rrect_blur->GetColor().red, 0);
971 ASSERT_EQ(rrect_blur->GetColor().green, 0);
972 ASSERT_EQ(rrect_blur->GetColor().blue, 0);
973 ASSERT_EQ(rrect_blur->GetColor().alpha, 0);
974 }

References impeller::DlDispatcherBase::drawShadow(), impeller::DlDispatcherBase::EndRecordingAsPicture(), impeller::Matrix::GetScale(), impeller::Entity::GetTransform(), impeller::Picture::pass, impeller::DlDispatcherBase::restore(), impeller::DlDispatcher::save(), impeller::ScalarNearlyEqual(), impeller::DlDispatcherBase::scale(), and impeller::Vector3::x.

## ◆ TEST_P() [307/456]

impeller::testing::TEST_P | ( | DriverInfoVKTest | ,
|  | CanDumpToLog |
| ) |  |

Definition at line 26 of file driver_info_vk_unittests.cc.

26 {
27 ASSERT_TRUE(GetContext());
28 const auto& driver_info =
29 SurfaceContextVK::Cast(*GetContext()).GetParent()->GetDriverInfo();
30 ASSERT_NE(driver_info, nullptr);
31 fml::testing::LogCapture log;
32 driver_info->DumpToLog();
33 ASSERT_TRUE(log.str().find("Driver Information") != std::string::npos);
34 }

References impeller::BackendCast< SurfaceContextVK, Context >::Cast(), and impeller::SurfaceContextVK::GetParent().

## ◆ TEST_P() [308/456]

impeller::testing::TEST_P | ( | DriverInfoVKTest | ,
|  | CanQueryDriverInfo |
| ) |  |

Definition at line 14 of file driver_info_vk_unittests.cc.

14 {
15 ASSERT_TRUE(GetContext());
16 const auto& driver_info =
17 SurfaceContextVK::Cast(*GetContext()).GetParent()->GetDriverInfo();
18 ASSERT_NE(driver_info, nullptr);
19 // 1.1 is the base Impeller version. The driver can't be lower than that.
20 ASSERT_TRUE(driver_info->GetAPIVersion().IsAtLeast(Version{1, 1, 0}));
21 ASSERT_NE(driver_info->GetVendor(), VendorVK::kUnknown);
22 ASSERT_NE(driver_info->GetDeviceType(), DeviceTypeVK::kUnknown);
23 ASSERT_NE(driver_info->GetDriverName(), "");
24 }

References impeller::BackendCast< SurfaceContextVK, Context >::Cast(), impeller::SurfaceContextVK::GetParent(), and impeller::kUnknown.

## ◆ TEST_P() [309/456]

impeller::testing::TEST_P | ( | EntityPassTargetTest | ,
|  | SwapWithMSAAImplicitResolve |
| ) |  |

Definition at line 53 of file entity_pass_target_unittests.cc.

53 {
54 auto content_context = GetContentContext();
55 auto buffer = content_context->GetContext()->CreateCommandBuffer();
56 auto context = content_context->GetContext();
57 auto& allocator = *context->GetResourceAllocator();
58
59 // Emulate implicit MSAA resolve by making color resolve and msaa texture the
60 // same.
61 RenderTarget render_target;
62 {
63 PixelFormat pixel_format =
64 context->GetCapabilities()->GetDefaultColorFormat();
65
66 // Create MSAA color texture.
67
68 TextureDescriptor color0_tex_desc;
69 color0_tex_desc.storage_mode = StorageMode::kDevicePrivate;
70 color0_tex_desc.type = TextureType::kTexture2DMultisample;
71 color0_tex_desc.sample_count = SampleCount::kCount4;
72 color0_tex_desc.format = pixel_format;
73 color0_tex_desc.size = ISize{100, 100};
74 color0_tex_desc.usage = TextureUsage::kRenderTarget;
75
76 auto color0_msaa_tex = allocator.CreateTexture(color0_tex_desc);
77
78 // Color attachment.
79
80 ColorAttachment color0;
81 color0.load_action = LoadAction::kDontCare;
82 color0.store_action = StoreAction::kStoreAndMultisampleResolve;
83 color0.texture = color0_msaa_tex;
84 color0.resolve_texture = color0_msaa_tex;
85
86 render_target.SetColorAttachment(color0, 0u);
87 render_target.SetStencilAttachment(std::nullopt);
88 }
89
90 auto entity_pass_target = EntityPassTarget(render_target, false, true);
91
92 auto color0 = entity_pass_target.GetRenderTarget()
93 .GetColorAttachments()
94 .find(0u)
95 ->second;
96 auto msaa_tex = color0.texture;
97 auto resolve_tex = color0.resolve_texture;
98
99 ASSERT_EQ(msaa_tex, resolve_tex);
100
101 entity_pass_target.Flip(
102 *content_context->GetContext()->GetResourceAllocator());
103
104 color0 = entity_pass_target.GetRenderTarget()
105 .GetColorAttachments()
106 .find(0u)
107 ->second;
108
109 ASSERT_NE(msaa_tex, color0.texture);
110 ASSERT_NE(resolve_tex, color0.resolve_texture);
111 ASSERT_EQ(color0.texture, color0.resolve_texture);
112 }

References impeller::TextureDescriptor::format, impeller::kCount4, impeller::kDevicePrivate, impeller::kDontCare, impeller::kRenderTarget, impeller::kStoreAndMultisampleResolve, impeller::kTexture2DMultisample, impeller::Attachment::load_action, impeller::Attachment::resolve_texture, impeller::TextureDescriptor::sample_count, impeller::RenderTarget::SetColorAttachment(), impeller::RenderTarget::SetStencilAttachment(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, impeller::Attachment::store_action, impeller::Attachment::texture, impeller::TextureDescriptor::type, and impeller::TextureDescriptor::usage.

## ◆ TEST_P() [310/456]

impeller::testing::TEST_P | ( | EntityPassTargetTest | ,
|  | SwapWithMSAATexture |
| ) |  |

Definition at line 19 of file entity_pass_target_unittests.cc.

19 {
20 if (GetContentContext()
21 ->GetDeviceCapabilities()
22 .SupportsImplicitResolvingMSAA()) {
23 GTEST_SKIP() << "Implicit MSAA is used on this device.";
24 }
25 auto content_context = GetContentContext();
26 auto buffer = content_context->GetContext()->CreateCommandBuffer();
27 auto render_target =
28 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
29 *content_context->GetContext(), {100, 100},
30 /*mip_count=*/1);
31
32 auto entity_pass_target = EntityPassTarget(render_target, false, false);
33
34 auto color0 = entity_pass_target.GetRenderTarget()
35 .GetColorAttachments()
36 .find(0u)
37 ->second;
38 auto msaa_tex = color0.texture;
39 auto resolve_tex = color0.resolve_texture;
40
41 entity_pass_target.Flip(
42 *content_context->GetContext()->GetResourceAllocator());
43
44 color0 = entity_pass_target.GetRenderTarget()
45 .GetColorAttachments()
46 .find(0u)
47 ->second;
48
49 ASSERT_EQ(msaa_tex, color0.texture);
50 ASSERT_NE(resolve_tex, color0.resolve_texture);
51 }

## ◆ TEST_P() [311/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | AdvancedBlendCoverageHintIsNotResetByEntityPass |
| ) |  |

Definition at line 2370 of file entity_unittests.cc.

2370 {
2371 if (GetContext()->GetCapabilities()->SupportsFramebufferFetch()) {
2372 GTEST_SKIP() << "Backends that support framebuffer fetch dont use coverage "
2373 "for advanced blends.";
2374 }
2375
2376 auto contents = std::make_shared<SolidColorContents>();
2377 contents->SetGeometry(Geometry::MakeRect(Rect::MakeXYWH(100, 100, 100, 100)));
2378 contents->SetColor(Color::Red());
2379
2380 Entity entity;
2381 entity.SetTransform(Matrix::MakeScale(Vector3(2, 2, 1)));
2382 entity.SetBlendMode(BlendMode::kColorBurn);
2383 entity.SetContents(contents);
2384
2385 auto coverage = entity.GetCoverage();
2386 EXPECT_TRUE(coverage.has_value());
2387
2388 auto pass = std::make_unique<EntityPass>();
2389 std::shared_ptr<RenderTargetCache> render_target_allocator =
2390 std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator());
2391 auto stencil_config = RenderTarget::AttachmentConfig{
2392 .storage_mode = StorageMode::kDevicePrivate,
2393 .load_action = LoadAction::kClear,
2394 .store_action = StoreAction::kDontCare,
2395 .clear_color = Color::BlackTransparent()};
2396 auto rt = render_target_allocator->CreateOffscreen(
2397 *GetContext(), ISize::MakeWH(1000, 1000),
2398 /*mip_count=*/1, "Offscreen", RenderTarget::kDefaultColorAttachmentConfig,
2399 stencil_config);
2400 auto content_context = ContentContext(
2401 GetContext(), TypographerContextSkia::Make(), render_target_allocator);
2402 pass->AddEntity(std::move(entity));
2403
2404 EXPECT_TRUE(pass->Render(content_context, rt));
2405
2406 auto contains_size = [&render_target_allocator](ISize size) -> bool {
2407 return std::find_if(render_target_allocator->GetRenderTargetDataBegin(),
2408 render_target_allocator->GetRenderTargetDataEnd(),
2409 [&size](const auto& data) {
2410 return data.config.size == size;
2411 }) != render_target_allocator->GetRenderTargetDataEnd();
2412 };
2413
2414 EXPECT_TRUE(contains_size(ISize(1000, 1000)))
2415 << "The root texture wasn't allocated";
2416 EXPECT_TRUE(contains_size(ISize(200, 200)))
2417 << "The ColorBurned texture wasn't allocated (100x100 scales up 2x)";
2418 }

References impeller::Color::BlackTransparent(), data, 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< T >::MakeWH(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Entity::SetBlendMode(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::RenderTarget::AttachmentConfig::storage_mode.

## ◆ TEST_P() [312/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BezierCircleScaled |
| ) |  |

Definition at line 993 of file entity_unittests.cc.

993 {
994 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
995 static float scale = 20;
996
997 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
998 ImGui::SliderFloat("Scale", &scale, 1, 100);
999 ImGui::End();
1000
1001 Entity entity;
1002 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
1003 auto path = PathBuilder{}
1004 .MoveTo({97.325, 34.818})
1005 .CubicCurveTo({98.50862885295136, 34.81812293973836},
1006 {99.46822048142015, 33.85863261475589},
1007 {99.46822048142015, 32.67499810206613})
1008 .CubicCurveTo({99.46822048142015, 31.491363589376355},
1009 {98.50862885295136, 30.53187326439389},
1010 {97.32499434685802, 30.531998226542708})
1011 .CubicCurveTo({96.14153655073771, 30.532123170035373},
1012 {95.18222070648729, 31.491540299350355},
1013 {95.18222070648729, 32.67499810206613})
1014 .CubicCurveTo({95.18222070648729, 33.85845590478189},
1015 {96.14153655073771, 34.81787303409686},
1016 {97.32499434685802, 34.81799797758954})
1017 .Close()
1018 .TakePath();
1019 entity.SetTransform(
1020 Matrix::MakeScale({scale, scale, 1.0}).Translate({-90, -20, 0}));
1021 entity.SetContents(SolidColorContents::Make(path, Color::Red()));
1022 return entity.Render(context, pass);
1023 };
1024 ASSERT_TRUE(OpenPlaygroundHere(callback));
1025 }

References impeller::Close(), impeller::SolidColorContents::Make(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::Render(), scale, impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [313/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BlendingModeOptions |
| ) |  |

Definition at line 862 of file entity_unittests.cc.

862 {
863 std::vector<const char*> blend_mode_names;
864 std::vector<BlendMode> blend_mode_values;
865 {
866 // Force an exhausiveness check with a switch. When adding blend modes,
867 // update this switch with a new name/value to make it selectable in the
868 // test GUI.
869
870 const BlendMode b{};
871 static_assert(b == BlendMode::kClear); // Ensure the first item in
872 // the switch is the first
873 // item in the enum.
874 static_assert(Entity::kLastPipelineBlendMode == BlendMode::kModulate);
875 switch (b) {
876 case BlendMode::kClear:
877 blend_mode_names.push_back("Clear");
878 blend_mode_values.push_back(BlendMode::kClear);
879 case BlendMode::kSource:
880 blend_mode_names.push_back("Source");
881 blend_mode_values.push_back(BlendMode::kSource);
882 case BlendMode::kDestination:
883 blend_mode_names.push_back("Destination");
884 blend_mode_values.push_back(BlendMode::kDestination);
885 case BlendMode::kSourceOver:
886 blend_mode_names.push_back("SourceOver");
887 blend_mode_values.push_back(BlendMode::kSourceOver);
888 case BlendMode::kDestinationOver:
889 blend_mode_names.push_back("DestinationOver");
890 blend_mode_values.push_back(BlendMode::kDestinationOver);
891 case BlendMode::kSourceIn:
892 blend_mode_names.push_back("SourceIn");
893 blend_mode_values.push_back(BlendMode::kSourceIn);
894 case BlendMode::kDestinationIn:
895 blend_mode_names.push_back("DestinationIn");
896 blend_mode_values.push_back(BlendMode::kDestinationIn);
897 case BlendMode::kSourceOut:
898 blend_mode_names.push_back("SourceOut");
899 blend_mode_values.push_back(BlendMode::kSourceOut);
900 case BlendMode::kDestinationOut:
901 blend_mode_names.push_back("DestinationOut");
902 blend_mode_values.push_back(BlendMode::kDestinationOut);
903 case BlendMode::kSourceATop:
904 blend_mode_names.push_back("SourceATop");
905 blend_mode_values.push_back(BlendMode::kSourceATop);
906 case BlendMode::kDestinationATop:
907 blend_mode_names.push_back("DestinationATop");
908 blend_mode_values.push_back(BlendMode::kDestinationATop);
909 case BlendMode::kXor:
910 blend_mode_names.push_back("Xor");
911 blend_mode_values.push_back(BlendMode::kXor);
912 case BlendMode::kPlus:
913 blend_mode_names.push_back("Plus");
914 blend_mode_values.push_back(BlendMode::kPlus);
915 case BlendMode::kModulate:
916 blend_mode_names.push_back("Modulate");
917 blend_mode_values.push_back(BlendMode::kModulate);
918 };
919 }
920
921 auto callback = [&](ContentContext& context, RenderPass& pass) {
922 auto world_matrix = Matrix::MakeScale(GetContentScale());
923 auto draw_rect = [&context, &pass, &world_matrix](
924 Rect rect, Color color, BlendMode blend_mode) -> bool {
925 using VS = SolidFillPipeline::VertexShader;
926 using FS = SolidFillPipeline::FragmentShader;
927
928 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
929 {
930 auto r = rect.GetLTRB();
931 vtx_builder.AddVertices({
932 {Point(r[0], r[1])},
933 {Point(r[2], r[1])},
934 {Point(r[2], r[3])},
935 {Point(r[0], r[1])},
936 {Point(r[2], r[3])},
937 {Point(r[0], r[3])},
938 });
939 }
940
941 pass.SetCommandLabel("Blended Rectangle");
942 auto options = OptionsFromPass(pass);
943 options.blend_mode = blend_mode;
944 options.primitive_type = PrimitiveType::kTriangle;
945 pass.SetPipeline(context.GetSolidFillPipeline(options));
946 pass.SetVertexBuffer(
947 vtx_builder.CreateVertexBuffer(context.GetTransientsBuffer()));
948
949 VS::FrameInfo frame_info;
950 frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
951 VS::BindFrameInfo(
952 pass, context.GetTransientsBuffer().EmplaceUniform(frame_info));
953 FS::FragInfo frag_info;
954 frag_info.color = color.Premultiply();
955 FS::BindFragInfo(
956 pass, context.GetTransientsBuffer().EmplaceUniform(frame_info));
957 return pass.Draw().ok();
958 };
959
960 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
961 static Color color1(1, 0, 0, 0.5), color2(0, 1, 0, 0.5);
962 ImGui::ColorEdit4("Color 1", reinterpret_cast<float*>(&color1));
963 ImGui::ColorEdit4("Color 2", reinterpret_cast<float*>(&color2));
964 static int current_blend_index = 3;
965 ImGui::ListBox("Blending mode", &current_blend_index,
966 blend_mode_names.data(), blend_mode_names.size());
967 ImGui::End();
968
969 BlendMode selected_mode = blend_mode_values[current_blend_index];
970
971 Point a, b, c, d;
972 static PlaygroundPoint point_a(Point(400, 100), 20, Color::White());
973 static PlaygroundPoint point_b(Point(200, 300), 20, Color::White());
974 std::tie(a, b) = DrawPlaygroundLine(point_a, point_b);
975 static PlaygroundPoint point_c(Point(470, 190), 20, Color::White());
976 static PlaygroundPoint point_d(Point(270, 390), 20, Color::White());
977 std::tie(c, d) = DrawPlaygroundLine(point_c, point_d);
978
979 bool result = true;
980 result = result &&
981 draw_rect(Rect::MakeXYWH(0, 0, pass.GetRenderTargetSize().width,
982 pass.GetRenderTargetSize().height),
983 Color(), BlendMode::kClear);
984 result = result && draw_rect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), color1,
985 BlendMode::kSourceOver);
986 result = result && draw_rect(Rect::MakeLTRB(c.x, c.y, d.x, d.y), color2,
987 selected_mode);
988 return result;
989 };
990 ASSERT_TRUE(OpenPlaygroundHere(callback));
991 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::saturated::b, color, impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::DrawPlaygroundLine(), impeller::HostBuffer::EmplaceUniform(), impeller::ContentContext::GetSolidFillPipeline(), impeller::ContentContext::GetTransientsBuffer(), 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::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), impeller::OptionsFromPass(), impeller::Color::White(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

## ◆ TEST_P() [314/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | BorderMaskBlurCoverageIsCorrect |
| ) |  |

Definition at line 1394 of file entity_unittests.cc.

1394 {
1395 auto fill = std::make_shared<SolidColorContents>();
1396 fill->SetGeometry(Geometry::MakeFillPath(
1397 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1398 fill->SetColor(Color::CornflowerBlue());
1399 auto border_mask_blur = FilterContents::MakeBorderMaskBlur(
1400 FilterInput::Make(fill), Radius{3}, Radius{4});
1401
1402 {
1403 Entity e;
1404 e.SetTransform(Matrix());
1405 auto actual = border_mask_blur->GetCoverage(e);
1406 auto expected = Rect::MakeXYWH(-3, -4, 306, 408);
1407 ASSERT_TRUE(actual.has_value());
1408 ASSERT_RECT_NEAR(actual.value(), expected);
1409 }
1410
1411 {
1412 Entity e;
1413 e.SetTransform(Matrix::MakeRotationZ(Radians{kPi / 4}));
1414 auto actual = border_mask_blur->GetCoverage(e);
1415 auto expected = Rect::MakeXYWH(-287.792, -4.94975, 504.874, 504.874);
1416 ASSERT_TRUE(actual.has_value());
1417 ASSERT_RECT_NEAR(actual.value(), expected);
1418 }
1419 }

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::SetTransform().

## ◆ TEST_P() [315/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanComputeGeometryForEmptyPathsWithoutCrashing |
| ) |  |

Definition at line 2549 of file entity_unittests.cc.

2549 {
2550 PathBuilder builder = {};
2551 builder.AddRect(Rect::MakeLTRB(0, 0, 0, 0));
2552 Path path = builder.TakePath();
2553
2554 EXPECT_TRUE(path.GetBoundingBox()->IsEmpty());
2555
2556 auto geom = Geometry::MakeFillPath(path);
2557
2558 Entity entity;
2559 RenderTarget target =
2560 GetContentContext()->GetRenderTargetCache()->CreateOffscreen(
2561 *GetContext(), {1, 1}, 1u);
2562 testing::MockRenderPass render_pass(GetContext(), target);
2563 auto position_result =
2564 geom->GetPositionBuffer(*GetContentContext(), entity, render_pass);
2565
2566 EXPECT_EQ(position_result.vertex_buffer.vertex_count, 0u);
2567
2568 EXPECT_EQ(geom->GetResultMode(), GeometryResult::Mode::kNormal);
2569 }

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

## ◆ TEST_P() [316/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanCreateEntity |
| ) |  |

Definition at line 71 of file entity_unittests.cc.

71 {
72 Entity entity;
73 ASSERT_TRUE(entity.GetTransform().IsIdentity());
74 }

References impeller::Entity::GetTransform(), and impeller::Matrix::IsIdentity().

## ◆ TEST_P() [317/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawCorrectlyWithRotatedTransform |
| ) |  |

Definition at line 546 of file entity_unittests.cc.

546 {
547 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
548 const char* input_axis[] = {"X", "Y", "Z"};
549 static int rotation_axis_index = 0;
550 static float rotation = 0;
551 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
552 ImGui::SliderFloat("Rotation", &rotation, -kPi, kPi);
553 ImGui::Combo("Rotation Axis", &rotation_axis_index, input_axis,
554 sizeof(input_axis) / sizeof(char*));
555 Matrix rotation_matrix;
556 switch (rotation_axis_index) {
557 case 0:
558 rotation_matrix = Matrix::MakeRotationX(Radians(rotation));
559 break;
560 case 1:
561 rotation_matrix = Matrix::MakeRotationY(Radians(rotation));
562 break;
563 case 2:
564 rotation_matrix = Matrix::MakeRotationZ(Radians(rotation));
565 break;
566 default:
567 rotation_matrix = Matrix{};
568 break;
569 }
570
571 if (ImGui::Button("Reset")) {
572 rotation = 0;
573 }
574 ImGui::End();
575 Matrix current_transform =
576 Matrix::MakeScale(GetContentScale())
577 .MakeTranslation(
578 Vector3(Point(pass.GetRenderTargetSize().width / 2.0,
579 pass.GetRenderTargetSize().height / 2.0)));
580 Matrix result_transform = current_transform * rotation_matrix;
581 Path path =
582 PathBuilder{}.AddRect(Rect::MakeXYWH(-300, -400, 600, 800)).TakePath();
583
584 Entity entity;
585 entity.SetTransform(result_transform);
586 entity.SetContents(SolidColorContents::Make(path, Color::Red()));
587 return entity.Render(context, pass);
588 };
589 ASSERT_TRUE(OpenPlaygroundHere(callback));
590 }

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::SetTransform(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [318/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawRect |
| ) |  |

Definition at line 265 of file entity_unittests.cc.

265 {
266 auto contents = std::make_shared<SolidColorContents>();
267 contents->SetGeometry(Geometry::MakeRect(Rect::MakeXYWH(100, 100, 100, 100)));
268 contents->SetColor(Color::Red());
269
270 Entity entity;
271 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
272 entity.SetContents(contents);
273
274 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
275 }

References impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [319/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanDrawRRect |
| ) |  |

Definition at line 277 of file entity_unittests.cc.

277 {
278 auto contents = std::make_shared<SolidColorContents>();
279 auto path = PathBuilder{}
280 .SetConvexity(Convexity::kConvex)
281 .AddRoundedRect(Rect::MakeXYWH(100, 100, 100, 100), 10.0)
282 .TakePath();
283 contents->SetGeometry(Geometry::MakeFillPath(path));
284 contents->SetColor(Color::Red());
285
286 Entity entity;
287 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
288 entity.SetContents(contents);
289
290 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
291 }

References impeller::PathBuilder::AddRoundedRect(), impeller::kConvex, impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), impeller::Color::Red(), impeller::Entity::SetContents(), impeller::PathBuilder::SetConvexity(), impeller::Entity::SetTransform(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [320/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CanRenderEmptyPathsWithoutCrashing |
| ) |  |

Definition at line 2571 of file entity_unittests.cc.

2571 {
2572 PathBuilder builder = {};
2573 builder.AddRect(Rect::MakeLTRB(0, 0, 0, 0));
2574 Path path = builder.TakePath();
2575
2576 EXPECT_TRUE(path.GetBoundingBox()->IsEmpty());
2577
2578 auto contents = std::make_shared<SolidColorContents>();
2579 contents->SetGeometry(Geometry::MakeFillPath(path));
2580 contents->SetColor(Color::Red());
2581
2582 Entity entity;
2583 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2584 entity.SetContents(contents);
2585
2586 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2587 }

References impeller::PathBuilder::AddRect(), impeller::Path::GetBoundingBox(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Color::Red(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [321/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ClipContentsGetClipCoverageIsCorrect |
| ) |  |

Definition at line 1534 of file entity_unittests.cc.

1534 {
1535 // Intersection: No stencil coverage, no geometry.
1536 {
1537 auto clip = std::make_shared<ClipContents>();
1538 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1539 auto result = clip->GetClipCoverage(Entity{}, Rect{});
1540
1541 ASSERT_FALSE(result.coverage.has_value());
1542 }
1543
1544 // Intersection: No stencil coverage, with geometry.
1545 {
1546 auto clip = std::make_shared<ClipContents>();
1547 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1548 clip->SetGeometry(Geometry::MakeFillPath(
1549 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath()));
1550 auto result = clip->GetClipCoverage(Entity{}, Rect{});
1551
1552 ASSERT_FALSE(result.coverage.has_value());
1553 }
1554
1555 // Intersection: With stencil coverage, no geometry.
1556 {
1557 auto clip = std::make_shared<ClipContents>();
1558 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1559 auto result =
1560 clip->GetClipCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1561
1562 ASSERT_FALSE(result.coverage.has_value());
1563 }
1564
1565 // Intersection: With stencil coverage, with geometry.
1566 {
1567 auto clip = std::make_shared<ClipContents>();
1568 clip->SetClipOperation(Entity::ClipOperation::kIntersect);
1569 clip->SetGeometry(Geometry::MakeFillPath(
1570 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 50, 50)).TakePath()));
1571 auto result =
1572 clip->GetClipCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1573
1574 ASSERT_TRUE(result.coverage.has_value());
1575 ASSERT_RECT_NEAR(result.coverage.value(), Rect::MakeLTRB(0, 0, 50, 50));
1576 ASSERT_EQ(result.type, Contents::ClipCoverage::Type::kAppend);
1577 }
1578
1579 // Difference: With stencil coverage, with geometry.
1580 {
1581 auto clip = std::make_shared<ClipContents>();
1582 clip->SetClipOperation(Entity::ClipOperation::kDifference);
1583 clip->SetGeometry(Geometry::MakeFillPath(
1584 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 50, 50)).TakePath()));
1585 auto result =
1586 clip->GetClipCoverage(Entity{}, Rect::MakeLTRB(0, 0, 100, 100));
1587
1588 ASSERT_TRUE(result.coverage.has_value());
1589 ASSERT_RECT_NEAR(result.coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
1590 ASSERT_EQ(result.type, Contents::ClipCoverage::Type::kAppend);
1591 }
1592 }

References impeller::PathBuilder::AddRect(), ASSERT_RECT_NEAR, impeller::Contents::ClipCoverage::kAppend, impeller::Entity::kDifference, impeller::Entity::kIntersect, impeller::Geometry::MakeFillPath(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [322/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ClipContentsOptimizesFullScreenIntersectClips |
| ) |  |

Definition at line 23 of file clip_contents_unittests.cc.

23 {
24 // Set up mock environment.
25
26 auto content_context = GetContentContext();
27 auto buffer = content_context->GetContext()->CreateCommandBuffer();
28 auto render_target =
29 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
30 *content_context->GetContext(), {100, 100},
31 /*mip_count=*/1);
32 auto render_pass = buffer->CreateRenderPass(render_target);
33 auto recording_pass = std::make_shared<RecordingRenderPass>(
34 render_pass, GetContext(), render_target);
35
36 // Set up clip contents.
37
38 auto contents = std::make_shared<ClipContents>();
39 contents->SetClipOperation(Entity::ClipOperation::kIntersect);
40 contents->SetGeometry(Geometry::MakeCover());
41
42 Entity entity;
43 entity.SetContents(std::move(contents));
44
45 // Render the clip contents.
46
47 ASSERT_TRUE(recording_pass->GetCommands().empty());
48 ASSERT_TRUE(entity.Render(*content_context, *recording_pass));
49 ASSERT_FALSE(recording_pass->GetCommands().empty());
50 }

References impeller::Entity::kIntersect, impeller::Geometry::MakeCover(), impeller::Entity::Render(), and impeller::Entity::SetContents().

## ◆ TEST_P() [323/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ClipContentsShouldRenderIsCorrect |
| ) |  |

Definition at line 1510 of file entity_unittests.cc.

1510 {
1511 // For clip ops, `ShouldRender` should always return true.
1512
1513 // Clip.
1514 {
1515 auto clip = std::make_shared<ClipContents>();
1516 ASSERT_TRUE(clip->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1517 clip->SetGeometry(Geometry::MakeFillPath(
1518 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath()));
1519 ASSERT_TRUE(clip->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1520 ASSERT_TRUE(
1521 clip->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1522 }
1523
1524 // Clip restore.
1525 {
1526 auto restore = std::make_shared<ClipRestoreContents>();
1527 ASSERT_TRUE(
1528 restore->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1529 ASSERT_TRUE(
1530 restore->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1531 }
1532 }

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

## ◆ TEST_P() [324/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterContentsWithLargeGeometry |
| ) |  |

Definition at line 2342 of file entity_unittests.cc.

2342 {
2343 Entity entity;
2344 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
2345 auto src_contents = std::make_shared<SolidColorContents>();
2346 src_contents->SetGeometry(
2347 Geometry::MakeRect(Rect::MakeLTRB(-300, -500, 30000, 50000)));
2348 src_contents->SetColor(Color::Red());
2349
2350 auto dst_contents = std::make_shared<SolidColorContents>();
2351 dst_contents->SetGeometry(
2352 Geometry::MakeRect(Rect::MakeLTRB(300, 500, 20000, 30000)));
2353 dst_contents->SetColor(Color::Blue());
2354
2355 auto contents = ColorFilterContents::MakeBlend(
2356 BlendMode::kSourceOver, {FilterInput::Make(dst_contents, false),
2357 FilterInput::Make(src_contents, false)});
2358 entity.SetContents(std::move(contents));
2359 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
2360 }

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::SetTransform().

## ◆ TEST_P() [325/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorAdvancedBlend |
| ) |  |

Definition at line 2175 of file entity_unittests.cc.

2175 {
2176 auto image = CreateTextureForFixture("boston.jpg");
2177 auto filter = ColorFilterContents::MakeBlend(
2178 BlendMode::kColorBurn, FilterInput::Make({image}), Color::Red());
2179
2180 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2181 Entity entity;
2182 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2183 Matrix::MakeTranslation({500, 300}) *
2184 Matrix::MakeScale(Vector2{0.5, 0.5}));
2185 entity.SetContents(filter);
2186 return entity.Render(context, pass);
2187 };
2188 ASSERT_TRUE(OpenPlaygroundHere(callback));
2189 }

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::SetTransform().

## ◆ TEST_P() [326/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorClearBlend |
| ) |  |

Definition at line 2191 of file entity_unittests.cc.

2191 {
2192 auto image = CreateTextureForFixture("boston.jpg");
2193 auto filter = ColorFilterContents::MakeBlend(
2194 BlendMode::kClear, FilterInput::Make({image}), Color::Red());
2195
2196 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2197 Entity entity;
2198 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2199 Matrix::MakeTranslation({500, 300}) *
2200 Matrix::MakeScale(Vector2{0.5, 0.5}));
2201 entity.SetContents(filter);
2202 return entity.Render(context, pass);
2203 };
2204 ASSERT_TRUE(OpenPlaygroundHere(callback));
2205 }

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::SetTransform().

## ◆ TEST_P() [327/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorDstBlend |
| ) |  |

Definition at line 2223 of file entity_unittests.cc.

2223 {
2224 auto image = CreateTextureForFixture("boston.jpg");
2225 auto filter = ColorFilterContents::MakeBlend(
2226 BlendMode::kDestination, FilterInput::Make({image}), Color::Red());
2227
2228 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2229 Entity entity;
2230 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2231 Matrix::MakeTranslation({500, 300}) *
2232 Matrix::MakeScale(Vector2{0.5, 0.5}));
2233 entity.SetContents(filter);
2234 return entity.Render(context, pass);
2235 };
2236 ASSERT_TRUE(OpenPlaygroundHere(callback));
2237 }

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::SetTransform().

## ◆ TEST_P() [328/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcBlend |
| ) |  |

Definition at line 2207 of file entity_unittests.cc.

2207 {
2208 auto image = CreateTextureForFixture("boston.jpg");
2209 auto filter = ColorFilterContents::MakeBlend(
2210 BlendMode::kSource, FilterInput::Make({image}), Color::Red());
2211
2212 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2213 Entity entity;
2214 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2215 Matrix::MakeTranslation({500, 300}) *
2216 Matrix::MakeScale(Vector2{0.5, 0.5}));
2217 entity.SetContents(filter);
2218 return entity.Render(context, pass);
2219 };
2220 ASSERT_TRUE(OpenPlaygroundHere(callback));
2221 }

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::SetTransform().

## ◆ TEST_P() [329/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorFilterWithForegroundColorSrcInBlend |
| ) |  |

Definition at line 2239 of file entity_unittests.cc.

2239 {
2240 auto image = CreateTextureForFixture("boston.jpg");
2241 auto filter = ColorFilterContents::MakeBlend(
2242 BlendMode::kSourceIn, FilterInput::Make({image}), Color::Red());
2243
2244 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2245 Entity entity;
2246 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
2247 Matrix::MakeTranslation({500, 300}) *
2248 Matrix::MakeScale(Vector2{0.5, 0.5}));
2249 entity.SetContents(filter);
2250 return entity.Render(context, pass);
2251 };
2252 ASSERT_TRUE(OpenPlaygroundHere(callback));
2253 }

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::SetTransform().

## ◆ TEST_P() [330/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterCoverageIsCorrect |
| ) |  |

Definition at line 1647 of file entity_unittests.cc.

1647 {
1648 // Set up a simple color background.
1649 auto fill = std::make_shared<SolidColorContents>();
1650 fill->SetGeometry(Geometry::MakeFillPath(
1651 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1652 fill->SetColor(Color::Coral());
1653
1654 // Set the color matrix filter.
1655 ColorMatrix matrix = {
1656 1, 1, 1, 1, 1, //
1657 1, 1, 1, 1, 1, //
1658 1, 1, 1, 1, 1, //
1659 1, 1, 1, 1, 1, //
1660 };
1661
1662 auto filter =
1663 ColorFilterContents::MakeColorMatrix(FilterInput::Make(fill), matrix);
1664
1665 Entity e;
1666 e.SetTransform(Matrix());
1667
1668 // Confirm that the actual filter coverage matches the expected coverage.
1669 auto actual = filter->GetCoverage(e);
1670 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1671
1672 ASSERT_TRUE(actual.has_value());
1673 ASSERT_RECT_NEAR(actual.value(), expected);
1674 }

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::SetTransform().

## ◆ TEST_P() [331/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ColorMatrixFilterEditable |
| ) |  |

Definition at line 1676 of file entity_unittests.cc.

1676 {
1677 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
1678 ASSERT_TRUE(bay_bridge);
1679
1680 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1681 // UI state.
1682 static ColorMatrix color_matrix = {
1683 1, 0, 0, 0, 0, //
1684 0, 3, 0, 0, 0, //
1685 0, 0, 1, 0, 0, //
1686 0, 0, 0, 1, 0, //
1687 };
1688 static float offset[2] = {500, 400};
1689 static float rotation = 0;
1690 static float scale[2] = {0.65, 0.65};
1691 static float skew[2] = {0, 0};
1692
1693 // Define the ImGui
1694 ImGui::Begin("Color Matrix", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1695 {
1696 std::string label = "##1";
1697 for (int i = 0; i < 20; i += 5) {
1698 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
1699 &(color_matrix.array[i]), 5, nullptr, nullptr,
1700 "%.2f", 0);
1701 label[2]++;
1702 }
1703
1704 ImGui::SliderFloat2("Translation", &offset[0], 0,
1705 pass.GetRenderTargetSize().width);
1706 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1707 ImGui::SliderFloat2("Scale", &scale[0], 0, 3);
1708 ImGui::SliderFloat2("Skew", &skew[0], -3, 3);
1709 }
1710 ImGui::End();
1711
1712 // Set the color matrix filter.
1713 auto filter = ColorFilterContents::MakeColorMatrix(
1714 FilterInput::Make(bay_bridge), color_matrix);
1715
1716 // Define the entity with the color matrix filter.
1717 Entity entity;
1718 entity.SetTransform(
1719 Matrix::MakeScale(GetContentScale()) *
1720 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1721 Matrix::MakeRotationZ(Radians(rotation)) *
1722 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1723 Matrix::MakeSkew(skew[0], skew[1]) *
1724 Matrix::MakeTranslation(-Point(bay_bridge->GetSize()) / 2));
1725 entity.SetContents(filter);
1726 entity.Render(context, pass);
1727
1728 return true;
1729 };
1730
1731 ASSERT_TRUE(OpenPlaygroundHere(callback));
1732 }

References impeller::ColorMatrix::array, impeller::kPi, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeColorMatrix(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeSkew(), impeller::Matrix::MakeTranslation(), offset, impeller::Entity::Render(), scale, impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [332/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ConicalGradientContentsIsOpaque |
| ) |  |

Definition at line 2283 of file entity_unittests.cc.

2283 {
2284 ConicalGradientContents contents;
2285 contents.SetColors({Color::CornflowerBlue()});
2286 ASSERT_FALSE(contents.IsOpaque());
2287 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2288 ASSERT_FALSE(contents.IsOpaque());
2289 }

References impeller::Color::CornflowerBlue(), impeller::Contents::IsOpaque(), impeller::ConicalGradientContents::SetColors(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [333/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentContextOptionsHasReasonableHashFunctions |
| ) |  |

Definition at line 2459 of file entity_unittests.cc.

2459 {
2460 ContentContextOptions opts;
2461 auto hash_a = ContentContextOptions::Hash{}(opts);
2462
2463 opts.blend_mode = BlendMode::kColorBurn;
2464 auto hash_b = ContentContextOptions::Hash{}(opts);
2465
2466 opts.has_depth_stencil_attachments = false;
2467 auto hash_c = ContentContextOptions::Hash{}(opts);
2468
2469 opts.primitive_type = PrimitiveType::kPoint;
2470 auto hash_d = ContentContextOptions::Hash{}(opts);
2471
2472 EXPECT_NE(hash_a, hash_b);
2473 EXPECT_NE(hash_b, hash_c);
2474 EXPECT_NE(hash_c, hash_d);
2475 }

References impeller::ContentContextOptions::blend_mode, impeller::ContentContextOptions::has_depth_stencil_attachments, impeller::kColorBurn, impeller::kPoint, and impeller::ContentContextOptions::primitive_type.

## ◆ TEST_P() [334/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ContentsGetBoundsForEmptyPathReturnsNullopt |
| ) |  |

Definition at line 1335 of file entity_unittests.cc.

1335 {
1336 Entity entity;
1337 entity.SetContents(std::make_shared<SolidColorContents>());
1338 ASSERT_FALSE(entity.GetCoverage().has_value());
1339 }

References impeller::Entity::GetCoverage(), and impeller::Entity::SetContents().

## ◆ TEST_P() [335/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CoverageForStrokePathWithNegativeValuesInTransform |
| ) |  |

Definition at line 2255 of file entity_unittests.cc.

2255 {
2256 auto arrow_head = PathBuilder{}
2257 .MoveTo({50, 120})
2258 .LineTo({120, 190})
2259 .LineTo({190, 120})
2260 .TakePath();
2261 auto geometry = Geometry::MakeStrokePath(arrow_head, 15.0, 4.0, Cap::kRound,
2262 Join::kRound);
2263
2264 auto transform = Matrix::MakeTranslation({300, 300}) *
2265 Matrix::MakeRotationZ(Radians(kPiOver2));
2266 // Note that e[0][0] used to be tested here, but it was -epsilon solely
2267 // due to floating point inaccuracy in the transcendental trig functions.
2268 // e[1][0] is the intended negative value that we care about (-1.0) as it
2269 // comes from the rotation of pi/2.
2270 EXPECT_LT(transform.e[1][0], 0.0f);
2271 auto coverage = geometry->GetCoverage(transform);
2272 ASSERT_RECT_NEAR(coverage.value(), Rect::MakeXYWH(102.5, 342.5, 85, 155));
2273 }

References ASSERT_RECT_NEAR, impeller::kPiOver2, impeller::kRound, impeller::LineTo(), impeller::Matrix::MakeRotationZ(), impeller::Geometry::MakeStrokePath(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::PathBuilder::MoveTo(), and transform.

## ◆ TEST_P() [336/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CubicCurveAndOverlapTest |
| ) |  |

Definition at line 592 of file entity_unittests.cc.

592 {
593 // Compare with https://fiddle.skia.org/c/7a05a3e186c65a8dfb732f68020aae06
594 Path path =
595 PathBuilder{}
596 .MoveTo({359.934, 96.6335})
597 .CubicCurveTo({358.189, 96.7055}, {356.436, 96.7908},
598 {354.673, 96.8895})
599 .CubicCurveTo({354.571, 96.8953}, {354.469, 96.9016},
600 {354.367, 96.9075})
601 .CubicCurveTo({352.672, 97.0038}, {350.969, 97.113},
602 {349.259, 97.2355})
603 .CubicCurveTo({349.048, 97.2506}, {348.836, 97.2678},
604 {348.625, 97.2834})
605 .CubicCurveTo({347.019, 97.4014}, {345.407, 97.5299},
606 {343.789, 97.6722})
607 .CubicCurveTo({343.428, 97.704}, {343.065, 97.7402},
608 {342.703, 97.7734})
609 .CubicCurveTo({341.221, 97.9086}, {339.736, 98.0505},
610 {338.246, 98.207})
611 .CubicCurveTo({337.702, 98.2642}, {337.156, 98.3292},
612 {336.612, 98.3894})
613 .CubicCurveTo({335.284, 98.5356}, {333.956, 98.6837},
614 {332.623, 98.8476})
615 .CubicCurveTo({332.495, 98.8635}, {332.366, 98.8818},
616 {332.237, 98.8982})
617 .LineTo({332.237, 102.601})
618 .LineTo({321.778, 102.601})
619 .LineTo({321.778, 100.382})
620 .CubicCurveTo({321.572, 100.413}, {321.367, 100.442},
621 {321.161, 100.476})
622 .CubicCurveTo({319.22, 100.79}, {317.277, 101.123},
623 {315.332, 101.479})
624 .CubicCurveTo({315.322, 101.481}, {315.311, 101.482},
625 {315.301, 101.484})
626 .LineTo({310.017, 105.94})
627 .LineTo({309.779, 105.427})
628 .LineTo({314.403, 101.651})
629 .CubicCurveTo({314.391, 101.653}, {314.379, 101.656},
630 {314.368, 101.658})
631 .CubicCurveTo({312.528, 102.001}, {310.687, 102.366},
632 {308.846, 102.748})
633 .CubicCurveTo({307.85, 102.955}, {306.855, 103.182}, {305.859, 103.4})
634 .CubicCurveTo({305.048, 103.579}, {304.236, 103.75},
635 {303.425, 103.936})
636 .LineTo({299.105, 107.578})
637 .LineTo({298.867, 107.065})
638 .LineTo({302.394, 104.185})
639 .LineTo({302.412, 104.171})
640 .CubicCurveTo({301.388, 104.409}, {300.366, 104.67},
641 {299.344, 104.921})
642 .CubicCurveTo({298.618, 105.1}, {297.89, 105.269}, {297.165, 105.455})
643 .CubicCurveTo({295.262, 105.94}, {293.36, 106.445},
644 {291.462, 106.979})
645 .CubicCurveTo({291.132, 107.072}, {290.802, 107.163},
646 {290.471, 107.257})
647 .CubicCurveTo({289.463, 107.544}, {288.455, 107.839},
648 {287.449, 108.139})
649 .CubicCurveTo({286.476, 108.431}, {285.506, 108.73},
650 {284.536, 109.035})
651 .CubicCurveTo({283.674, 109.304}, {282.812, 109.579},
652 {281.952, 109.859})
653 .CubicCurveTo({281.177, 110.112}, {280.406, 110.377},
654 {279.633, 110.638})
655 .CubicCurveTo({278.458, 111.037}, {277.256, 111.449},
656 {276.803, 111.607})
657 .CubicCurveTo({276.76, 111.622}, {276.716, 111.637},
658 {276.672, 111.653})
659 .CubicCurveTo({275.017, 112.239}, {273.365, 112.836},
660 {271.721, 113.463})
661 .LineTo({271.717, 113.449})
662 .CubicCurveTo({271.496, 113.496}, {271.238, 113.559},
663 {270.963, 113.628})
664 .CubicCurveTo({270.893, 113.645}, {270.822, 113.663},
665 {270.748, 113.682})
666 .CubicCurveTo({270.468, 113.755}, {270.169, 113.834},
667 {269.839, 113.926})
668 .CubicCurveTo({269.789, 113.94}, {269.732, 113.957},
669 {269.681, 113.972})
670 .CubicCurveTo({269.391, 114.053}, {269.081, 114.143},
671 {268.756, 114.239})
672 .CubicCurveTo({268.628, 114.276}, {268.5, 114.314},
673 {268.367, 114.354})
674 .CubicCurveTo({268.172, 114.412}, {267.959, 114.478},
675 {267.752, 114.54})
676 .CubicCurveTo({263.349, 115.964}, {258.058, 117.695},
677 {253.564, 119.252})
678 .CubicCurveTo({253.556, 119.255}, {253.547, 119.258},
679 {253.538, 119.261})
680 .CubicCurveTo({251.844, 119.849}, {250.056, 120.474},
681 {248.189, 121.131})
682 .CubicCurveTo({248, 121.197}, {247.812, 121.264}, {247.621, 121.331})
683 .CubicCurveTo({247.079, 121.522}, {246.531, 121.715},
684 {245.975, 121.912})
685 .CubicCurveTo({245.554, 122.06}, {245.126, 122.212},
686 {244.698, 122.364})
687 .CubicCurveTo({244.071, 122.586}, {243.437, 122.811},
688 {242.794, 123.04})
689 .CubicCurveTo({242.189, 123.255}, {241.58, 123.472},
690 {240.961, 123.693})
691 .CubicCurveTo({240.659, 123.801}, {240.357, 123.909},
692 {240.052, 124.018})
693 .CubicCurveTo({239.12, 124.351}, {238.18, 124.687}, {237.22, 125.032})
694 .LineTo({237.164, 125.003})
695 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
696 {235.81, 125.538})
697 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
698 {234.592, 125.977})
699 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
700 {234.59, 125.977})
701 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
702 {192.381, 141.429})
703 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
704 .LineTo({360, 160})
705 .LineTo({360, 119.256})
706 .LineTo({360, 106.332})
707 .LineTo({360, 96.6307})
708 .CubicCurveTo({359.978, 96.6317}, {359.956, 96.6326},
709 {359.934, 96.6335})
710 .Close()
711 .MoveTo({337.336, 124.143})
712 .CubicCurveTo({337.274, 122.359}, {338.903, 121.511},
713 {338.903, 121.511})
714 .CubicCurveTo({338.903, 121.511}, {338.96, 123.303},
715 {337.336, 124.143})
716 .Close()
717 .MoveTo({340.082, 121.849})
718 .CubicCurveTo({340.074, 121.917}, {340.062, 121.992},
719 {340.046, 122.075})
720 .CubicCurveTo({340.039, 122.109}, {340.031, 122.142},
721 {340.023, 122.177})
722 .CubicCurveTo({340.005, 122.26}, {339.98, 122.346},
723 {339.952, 122.437})
724 .CubicCurveTo({339.941, 122.473}, {339.931, 122.507},
725 {339.918, 122.544})
726 .CubicCurveTo({339.873, 122.672}, {339.819, 122.804},
727 {339.75, 122.938})
728 .CubicCurveTo({339.747, 122.944}, {339.743, 122.949},
729 {339.74, 122.955})
730 .CubicCurveTo({339.674, 123.08}, {339.593, 123.205},
731 {339.501, 123.328})
732 .CubicCurveTo({339.473, 123.366}, {339.441, 123.401},
733 {339.41, 123.438})
734 .CubicCurveTo({339.332, 123.534}, {339.243, 123.625},
735 {339.145, 123.714})
736 .CubicCurveTo({339.105, 123.75}, {339.068, 123.786},
737 {339.025, 123.821})
738 .CubicCurveTo({338.881, 123.937}, {338.724, 124.048},
739 {338.539, 124.143})
740 .CubicCurveTo({338.532, 123.959}, {338.554, 123.79},
741 {338.58, 123.626})
742 .CubicCurveTo({338.58, 123.625}, {338.58, 123.625}, {338.58, 123.625})
743 .CubicCurveTo({338.607, 123.455}, {338.65, 123.299},
744 {338.704, 123.151})
745 .CubicCurveTo({338.708, 123.14}, {338.71, 123.127},
746 {338.714, 123.117})
747 .CubicCurveTo({338.769, 122.971}, {338.833, 122.838},
748 {338.905, 122.712})
749 .CubicCurveTo({338.911, 122.702}, {338.916, 122.69200000000001},
750 {338.922, 122.682})
751 .CubicCurveTo({338.996, 122.557}, {339.072, 122.444},
752 {339.155, 122.34})
753 .CubicCurveTo({339.161, 122.333}, {339.166, 122.326},
754 {339.172, 122.319})
755 .CubicCurveTo({339.256, 122.215}, {339.339, 122.12},
756 {339.425, 122.037})
757 .CubicCurveTo({339.428, 122.033}, {339.431, 122.03},
758 {339.435, 122.027})
759 .CubicCurveTo({339.785, 121.687}, {340.106, 121.511},
760 {340.106, 121.511})
761 .CubicCurveTo({340.106, 121.511}, {340.107, 121.645},
762 {340.082, 121.849})
763 .Close()
764 .MoveTo({340.678, 113.245})
765 .CubicCurveTo({340.594, 113.488}, {340.356, 113.655},
766 {340.135, 113.775})
767 .CubicCurveTo({339.817, 113.948}, {339.465, 114.059},
768 {339.115, 114.151})
769 .CubicCurveTo({338.251, 114.379}, {337.34, 114.516},
770 {336.448, 114.516})
771 .CubicCurveTo({335.761, 114.516}, {335.072, 114.527},
772 {334.384, 114.513})
773 .CubicCurveTo({334.125, 114.508}, {333.862, 114.462},
774 {333.605, 114.424})
775 .CubicCurveTo({332.865, 114.318}, {332.096, 114.184},
776 {331.41, 113.883})
777 .CubicCurveTo({330.979, 113.695}, {330.442, 113.34},
778 {330.672, 112.813})
779 .CubicCurveTo({331.135, 111.755}, {333.219, 112.946},
780 {334.526, 113.833})
781 .CubicCurveTo({334.54, 113.816}, {334.554, 113.8}, {334.569, 113.784})
782 .CubicCurveTo({333.38, 112.708}, {331.749, 110.985},
783 {332.76, 110.402})
784 .CubicCurveTo({333.769, 109.82}, {334.713, 111.93},
785 {335.228, 113.395})
786 .CubicCurveTo({334.915, 111.889}, {334.59, 109.636},
787 {335.661, 109.592})
788 .CubicCurveTo({336.733, 109.636}, {336.408, 111.889},
789 {336.07, 113.389})
790 .CubicCurveTo({336.609, 111.93}, {337.553, 109.82},
791 {338.563, 110.402})
792 .CubicCurveTo({339.574, 110.984}, {337.942, 112.708},
793 {336.753, 113.784})
794 .CubicCurveTo({336.768, 113.8}, {336.782, 113.816},
795 {336.796, 113.833})
796 .CubicCurveTo({338.104, 112.946}, {340.187, 111.755},
797 {340.65, 112.813})
798 .CubicCurveTo({340.71, 112.95}, {340.728, 113.102},
799 {340.678, 113.245})
800 .Close()
801 .MoveTo({346.357, 106.771})
802 .CubicCurveTo({346.295, 104.987}, {347.924, 104.139},
803 {347.924, 104.139})
804 .CubicCurveTo({347.924, 104.139}, {347.982, 105.931},
805 {346.357, 106.771})
806 .Close()
807 .MoveTo({347.56, 106.771})
808 .CubicCurveTo({347.498, 104.987}, {349.127, 104.139},
809 {349.127, 104.139})
810 .CubicCurveTo({349.127, 104.139}, {349.185, 105.931},
811 {347.56, 106.771})
812 .Close()
813 .TakePath();
814 Entity entity;
815 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
816 entity.SetContents(SolidColorContents::Make(path, Color::Red()));
817 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
818 }

References impeller::Close(), impeller::LineTo(), impeller::SolidColorContents::Make(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [337/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | CubicCurveTest |
| ) |  |

Definition at line 524 of file entity_unittests.cc.

524 {
525 // Compare with https://fiddle.skia.org/c/b3625f26122c9de7afe7794fcf25ead3
526 Path path =
527 PathBuilder{}
528 .MoveTo({237.164, 125.003})
529 .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
530 {235.81, 125.538})
531 .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
532 {234.592, 125.977})
533 .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
534 {234.59, 125.977})
535 .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
536 {192.381, 141.429})
537 .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
538 .Close()
539 .TakePath();
540 Entity entity;
541 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
542 entity.SetContents(SolidColorContents::Make(path, Color::Red()));
543 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
544 }

References impeller::Close(), impeller::SolidColorContents::Make(), impeller::Matrix::MakeScale(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [338/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DecalSpecializationAppliedToMorphologyFilter |
| ) |  |

Definition at line 2443 of file entity_unittests.cc.

2443 {
2444 auto content_context = GetContentContext();
2445 auto default_color_burn = content_context->GetMorphologyFilterPipeline({
2446 .color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2447 });
2448
2449 auto decal_supported = static_cast<Scalar>(
2450 GetContext()->GetCapabilities()->SupportsDecalSamplerAddressMode());
2451 std::vector<Scalar> expected_constants = {decal_supported};
2452 ASSERT_EQ(default_color_burn->GetDescriptor().GetSpecializationConstants(),
2453 expected_constants);
2454 }

References impeller::kR8G8B8A8UNormInt.

## ◆ TEST_P() [339/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | DoesNotCullEntitiesByDefault |
| ) |  |

Definition at line 1496 of file entity_unittests.cc.

1496 {
1497 auto fill = std::make_shared<SolidColorContents>();
1498 fill->SetColor(Color::CornflowerBlue());
1499 fill->SetGeometry(
1500 Geometry::MakeRect(Rect::MakeLTRB(-1000, -1000, -900, -900)));
1501
1502 Entity entity;
1503 entity.SetContents(fill);
1504
1505 // Even though the entity is offscreen, this should still render because we do
1506 // not compute the coverage intersection by default.
1507 EXPECT_TRUE(entity.ShouldRender(Rect::MakeLTRB(0, 0, 100, 100)));
1508 }

References impeller::Color::CornflowerBlue(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Entity::SetContents(), and impeller::Entity::ShouldRender().

## ◆ TEST_P() [340/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | EntityPassCanMergeSubpassIntoParent |
| ) |  |

Definition at line 188 of file entity_unittests.cc.

188 {
189 // Both a red and a blue box should appear if the pass merging has worked
190 // correctly.
191
192 EntityPass pass;
193 auto subpass = CreatePassWithRectPath(Rect::MakeLTRB(0, 0, 100, 100),
194 Rect::MakeLTRB(50, 50, 150, 150),
195 ContentBoundsPromise::kUnknown, true);
196 pass.AddSubpass(std::move(subpass));
197
198 Entity entity;
199 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
200 auto contents = std::make_unique<SolidColorContents>();
201 contents->SetGeometry(Geometry::MakeRect(Rect::MakeLTRB(100, 100, 200, 200)));
202 contents->SetColor(Color::Blue());
203 entity.SetContents(std::move(contents));
204
205 pass.AddEntity(std::move(entity));
206
207 ASSERT_TRUE(OpenPlaygroundHere(pass));
208 }

References impeller::EntityPass::AddEntity(), impeller::EntityPass::AddSubpass(), impeller::Color::Blue(), CreatePassWithRectPath(), impeller::kUnknown, impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [341/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | EntityPassCoverageRespectsCoverageLimit |
| ) |  |

Definition at line 210 of file entity_unittests.cc.

210 {
211 // Rect is drawn entirely in negative area.
212 auto pass = CreatePassWithRectPath(Rect::MakeLTRB(-200, -200, -100, -100),
213 std::nullopt);
214
215 // Without coverage limit.
216 {
217 auto pass_coverage = pass->GetElementsCoverage(std::nullopt);
218 ASSERT_TRUE(pass_coverage.has_value());
219 ASSERT_RECT_NEAR(pass_coverage.value(),
220 Rect::MakeLTRB(-200, -200, -100, -100));
221 }
222
223 // With limit that doesn't overlap.
224 {
225 auto pass_coverage =
226 pass->GetElementsCoverage(Rect::MakeLTRB(0, 0, 100, 100));
227 ASSERT_FALSE(pass_coverage.has_value());
228 }
229
230 // With limit that partially overlaps.
231 {
232 auto pass_coverage =
233 pass->GetElementsCoverage(Rect::MakeLTRB(-150, -150, 0, 0));
234 ASSERT_TRUE(pass_coverage.has_value());
235 ASSERT_RECT_NEAR(pass_coverage.value(),
236 Rect::MakeLTRB(-150, -150, -100, -100));
237 }
238 }

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

## ◆ TEST_P() [342/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | EntityPassRespectsUntrustedSubpassBoundsLimit |
| ) |  |

Definition at line 125 of file entity_unittests.cc.

125 {
126 EntityPass pass;
127
128 auto subpass0 = CreatePassWithRectPath(Rect::MakeLTRB(0, 0, 100, 100),
129 Rect::MakeLTRB(50, 50, 150, 150));
130 auto subpass1 = CreatePassWithRectPath(Rect::MakeLTRB(500, 500, 1000, 1000),
131 Rect::MakeLTRB(800, 800, 900, 900));
132
133 auto subpass0_coverage =
134 pass.GetSubpassCoverage(*subpass0.get(), std::nullopt);
135 ASSERT_TRUE(subpass0_coverage.has_value());
136 ASSERT_RECT_NEAR(subpass0_coverage.value(), Rect::MakeLTRB(50, 50, 100, 100));
137
138 auto subpass1_coverage =
139 pass.GetSubpassCoverage(*subpass1.get(), std::nullopt);
140 ASSERT_TRUE(subpass1_coverage.has_value());
141 ASSERT_RECT_NEAR(subpass1_coverage.value(),
142 Rect::MakeLTRB(800, 800, 900, 900));
143
144 pass.AddSubpass(std::move(subpass0));
145 pass.AddSubpass(std::move(subpass1));
146
147 auto coverage = pass.GetElementsCoverage(std::nullopt);
148 ASSERT_TRUE(coverage.has_value());
149 ASSERT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(50, 50, 900, 900));
150 }

References impeller::EntityPass::AddSubpass(), ASSERT_RECT_NEAR, CreatePassWithRectPath(), impeller::EntityPass::GetElementsCoverage(), impeller::EntityPass::GetSubpassCoverage(), and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [343/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | EntityPassTrustsSnugSubpassBoundsLimit |
| ) |  |

Definition at line 152 of file entity_unittests.cc.

152 {
153 EntityPass pass;
154
155 auto subpass0 = //
156 CreatePassWithRectPath(Rect::MakeLTRB(10, 10, 90, 90),
157 Rect::MakeLTRB(5, 5, 95, 95),
158 ContentBoundsPromise::kContainsContents);
159 auto subpass1 = //
160 CreatePassWithRectPath(Rect::MakeLTRB(500, 500, 1000, 1000),
161 Rect::MakeLTRB(495, 495, 1005, 1005),
162 ContentBoundsPromise::kContainsContents);
163
164 auto subpass0_coverage =
165 pass.GetSubpassCoverage(*subpass0.get(), std::nullopt);
166 EXPECT_TRUE(subpass0_coverage.has_value());
167 // Result should be the overridden bounds
168 // (we lied about them being snug, but the property is respected)
169 EXPECT_RECT_NEAR(subpass0_coverage.value(), Rect::MakeLTRB(5, 5, 95, 95));
170
171 auto subpass1_coverage =
172 pass.GetSubpassCoverage(*subpass1.get(), std::nullopt);
173 EXPECT_TRUE(subpass1_coverage.has_value());
174 // Result should be the overridden bounds
175 // (we lied about them being snug, but the property is respected)
176 EXPECT_RECT_NEAR(subpass1_coverage.value(),
177 Rect::MakeLTRB(495, 495, 1005, 1005));
178
179 pass.AddSubpass(std::move(subpass0));
180 pass.AddSubpass(std::move(subpass1));
181
182 auto coverage = pass.GetElementsCoverage(std::nullopt);
183 EXPECT_TRUE(coverage.has_value());
184 // This result should be the union of the overridden bounds
185 EXPECT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(5, 5, 1005, 1005));
186 }

References impeller::EntityPass::AddSubpass(), CreatePassWithRectPath(), EXPECT_RECT_NEAR, impeller::EntityPass::GetElementsCoverage(), impeller::EntityPass::GetSubpassCoverage(), impeller::kContainsContents, and impeller::TRect< Scalar >::MakeLTRB().

## ◆ TEST_P() [344/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FailOnValidationError |
| ) |  |

Definition at line 2535 of file entity_unittests.cc.

2535 {
2536 if (GetParam() != PlaygroundBackend::kVulkan) {
2537 GTEST_SKIP() << "Validation is only fatal on Vulkan backend.";
2538 }
2539 EXPECT_DEATH(
2540 // The easiest way to trigger a validation error is to try to compile
2541 // a shader with an unsupported pixel format.
2542 GetContentContext()->GetBlendColorBurnPipeline({
2543 .color_attachment_pixel_format = PixelFormat::kUnknown,
2544 .has_depth_stencil_attachments = false,
2545 }),
2546 "");
2547 }

References impeller::kUnknown, and impeller::kVulkan.

## ◆ TEST_P() [345/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FillPathGeometryGetPositionBufferReturnsExpectedMode |
| ) |  |

Definition at line 2501 of file entity_unittests.cc.

2501 {
2502 RenderTarget target;
2503 testing::MockRenderPass mock_pass(GetContext(), target);
2504
2505 auto get_result = [this, &mock_pass](const Path& path) {
2506 auto geometry = Geometry::MakeFillPath(
2507 path, /* inner rect */ Rect::MakeLTRB(0, 0, 100, 100));
2508 return geometry->GetPositionBuffer(*GetContentContext(), {}, mock_pass);
2509 };
2510
2511 // Convex path
2512 {
2513 GeometryResult result =
2514 get_result(PathBuilder{}
2515 .AddRect(Rect::MakeLTRB(0, 0, 100, 100))
2516 .SetConvexity(Convexity::kConvex)
2517 .TakePath());
2518 EXPECT_EQ(result.mode, GeometryResult::Mode::kNormal);
2519 }
2520
2521 // Concave path
2522 {
2523 Path path = PathBuilder{}
2524 .MoveTo({0, 0})
2525 .LineTo({100, 0})
2526 .LineTo({100, 100})
2527 .LineTo({50, 50})
2528 .Close()
2529 .TakePath();
2530 GeometryResult result = get_result(path);
2531 EXPECT_EQ(result.mode, GeometryResult::Mode::kNonZero);
2532 }
2533 }

References impeller::PathBuilder::AddRect(), impeller::Close(), impeller::kConvex, impeller::GeometryResult::kNonZero, impeller::GeometryResult::kNormal, impeller::LineTo(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), impeller::GeometryResult::mode, and impeller::PathBuilder::MoveTo().

## ◆ TEST_P() [346/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | FilterCoverageRespectsCropRect |
| ) |  |

Definition at line 240 of file entity_unittests.cc.

240 {
241 auto image = CreateTextureForFixture("boston.jpg");
242 auto filter = ColorFilterContents::MakeBlend(BlendMode::kSoftLight,
243 FilterInput::Make({image}));
244
245 // Without the crop rect (default behavior).
246 {
247 auto actual = filter->GetCoverage({});
248 auto expected = Rect::MakeSize(image->GetSize());
249
250 ASSERT_TRUE(actual.has_value());
251 ASSERT_RECT_NEAR(actual.value(), expected);
252 }
253
254 // With the crop rect.
255 {
256 auto expected = Rect::MakeLTRB(50, 50, 100, 100);
257 filter->SetCoverageHint(expected);
258 auto actual = filter->GetCoverage({});
259
260 ASSERT_TRUE(actual.has_value());
261 ASSERT_RECT_NEAR(actual.value(), expected);
262 }
263 }

References ASSERT_RECT_NEAR, impeller::kSoftLight, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeSize().

## ◆ TEST_P() [347/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | Filters |
| ) |  |

Definition at line 1027 of file entity_unittests.cc.

1027 {
1028 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
1029 auto boston = CreateTextureForFixture("boston.jpg");
1030 auto kalimba = CreateTextureForFixture("kalimba.jpg");
1031 ASSERT_TRUE(bridge && boston && kalimba);
1032
1033 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1034 auto fi_bridge = FilterInput::Make(bridge);
1035 auto fi_boston = FilterInput::Make(boston);
1036 auto fi_kalimba = FilterInput::Make(kalimba);
1037
1038 std::shared_ptr<FilterContents> blend0 = ColorFilterContents::MakeBlend(
1039 BlendMode::kModulate, {fi_kalimba, fi_boston});
1040
1041 auto blend1 = ColorFilterContents::MakeBlend(
1042 BlendMode::kScreen,
1043 {FilterInput::Make(blend0), fi_bridge, fi_bridge, fi_bridge});
1044
1045 Entity entity;
1046 entity.SetTransform(Matrix::MakeScale(GetContentScale()) *
1047 Matrix::MakeTranslation({500, 300}) *
1048 Matrix::MakeScale(Vector2{0.5, 0.5}));
1049 entity.SetContents(blend1);
1050 return entity.Render(context, pass);
1051 };
1052 ASSERT_TRUE(OpenPlaygroundHere(callback));
1053 }

References impeller::kModulate, impeller::kScreen, impeller::FilterInput::Make(), impeller::ColorFilterContents::MakeBlend(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [348/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GaussianBlurFilter |
| ) |  |

Definition at line 1055 of file entity_unittests.cc.

1055 {
1056 auto boston =
1057 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true);
1058 ASSERT_TRUE(boston);
1059
1060 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1061 const char* input_type_names[] = {"Texture", "Solid Color"};
1062 const char* blur_type_names[] = {"Image blur", "Mask blur"};
1063 const char* pass_variation_names[] = {"New"};
1064 const char* blur_style_names[] = {"Normal", "Solid", "Outer", "Inner"};
1065 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1066 const FilterContents::BlurStyle blur_styles[] = {
1067 FilterContents::BlurStyle::kNormal, FilterContents::BlurStyle::kSolid,
1068 FilterContents::BlurStyle::kOuter, FilterContents::BlurStyle::kInner};
1069 const Entity::TileMode tile_modes[] = {
1070 Entity::TileMode::kClamp, Entity::TileMode::kRepeat,
1071 Entity::TileMode::kMirror, Entity::TileMode::kDecal};
1072
1073 // UI state.
1074 static int selected_input_type = 0;
1075 static Color input_color = Color::Black();
1076 static int selected_blur_type = 0;
1077 static int selected_pass_variation = 0;
1078 static bool combined_sigma = false;
1079 static float blur_amount_coarse[2] = {0, 0};
1080 static float blur_amount_fine[2] = {10, 10};
1081 static int selected_blur_style = 0;
1082 static int selected_tile_mode = 3;
1083 static Color cover_color(1, 0, 0, 0.2);
1084 static Color bounds_color(0, 1, 0, 0.1);
1085 static float offset[2] = {500, 400};
1086 static float rotation = 0;
1087 static float scale[2] = {0.65, 0.65};
1088 static float skew[2] = {0, 0};
1089 static float path_rect[4] = {0, 0,
1090 static_cast<float>(boston->GetSize().width),
1091 static_cast<float>(boston->GetSize().height)};
1092
1093 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1094 {
1095 ImGui::Combo("Input type", &selected_input_type, input_type_names,
1096 sizeof(input_type_names) / sizeof(char*));
1097 if (selected_input_type == 0) {
1098 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
1099 } else {
1100 ImGui::ColorEdit4("Input color",
1101 reinterpret_cast<float*>(&input_color));
1102 }
1103 ImGui::Combo("Blur type", &selected_blur_type, blur_type_names,
1104 sizeof(blur_type_names) / sizeof(char*));
1105 if (selected_blur_type == 0) {
1106 ImGui::Combo("Pass variation", &selected_pass_variation,
1107 pass_variation_names,
1108 sizeof(pass_variation_names) / sizeof(char*));
1109 }
1110 ImGui::Checkbox("Combined sigma", &combined_sigma);
1111 if (combined_sigma) {
1112 ImGui::SliderFloat("Sigma (coarse)", blur_amount_coarse, 0, 1000);
1113 ImGui::SliderFloat("Sigma (fine)", blur_amount_fine, 0, 10);
1114 blur_amount_coarse[1] = blur_amount_coarse[0];
1115 blur_amount_fine[1] = blur_amount_fine[0];
1116 } else {
1117 ImGui::SliderFloat2("Sigma (coarse)", blur_amount_coarse, 0, 1000);
1118 ImGui::SliderFloat2("Sigma (fine)", blur_amount_fine, 0, 10);
1119 }
1120 ImGui::Combo("Blur style", &selected_blur_style, blur_style_names,
1121 sizeof(blur_style_names) / sizeof(char*));
1122 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1123 sizeof(tile_mode_names) / sizeof(char*));
1124 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1125 ImGui::ColorEdit4("Bounds color",
1126 reinterpret_cast<float*>(&bounds_color));
1127 ImGui::SliderFloat2("Translation", offset, 0,
1128 pass.GetRenderTargetSize().width);
1129 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1130 ImGui::SliderFloat2("Scale", scale, 0, 3);
1131 ImGui::SliderFloat2("Skew", skew, -3, 3);
1132 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1133 }
1134 ImGui::End();
1135
1136 auto blur_sigma_x = Sigma{blur_amount_coarse[0] + blur_amount_fine[0]};
1137 auto blur_sigma_y = Sigma{blur_amount_coarse[1] + blur_amount_fine[1]};
1138
1139 std::shared_ptr<Contents> input;
1140 Size input_size;
1141
1142 auto input_rect =
1143 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1144 if (selected_input_type == 0) {
1145 auto texture = std::make_shared<TextureContents>();
1146 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1147 texture->SetDestinationRect(input_rect);
1148 texture->SetTexture(boston);
1149 texture->SetOpacity(input_color.alpha);
1150
1151 input = texture;
1152 input_size = input_rect.GetSize();
1153 } else {
1154 auto fill = std::make_shared<SolidColorContents>();
1155 fill->SetColor(input_color);
1156 fill->SetGeometry(
1157 Geometry::MakeFillPath(PathBuilder{}.AddRect(input_rect).TakePath()));
1158
1159 input = fill;
1160 input_size = input_rect.GetSize();
1161 }
1162
1163 std::shared_ptr<FilterContents> blur;
1164 switch (selected_pass_variation) {
1165 case 0:
1166 blur = std::make_shared<GaussianBlurFilterContents>(
1167 blur_sigma_x.sigma, blur_sigma_y.sigma,
1168 tile_modes[selected_tile_mode], blur_styles[selected_blur_style],
1169 /*geometry=*/nullptr);
1170 blur->SetInputs({FilterInput::Make(input)});
1171 break;
1172 case 1:
1173 blur = FilterContents::MakeGaussianBlur(
1174 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1175 tile_modes[selected_tile_mode], blur_styles[selected_blur_style]);
1176 break;
1177 };
1178 FML_CHECK(blur);
1179
1180 auto mask_blur = FilterContents::MakeBorderMaskBlur(
1181 FilterInput::Make(input), blur_sigma_x, blur_sigma_y,
1182 blur_styles[selected_blur_style]);
1183
1184 auto ctm = Matrix::MakeScale(GetContentScale()) *
1185 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1186 Matrix::MakeRotationZ(Radians(rotation)) *
1187 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1188 Matrix::MakeSkew(skew[0], skew[1]) *
1189 Matrix::MakeTranslation(-Point(input_size) / 2);
1190
1191 auto target_contents = selected_blur_type == 0 ? blur : mask_blur;
1192
1193 Entity entity;
1194 entity.SetContents(target_contents);
1195 entity.SetTransform(ctm);
1196
1197 entity.Render(context, pass);
1198
1199 // Renders a red "cover" rectangle that shows the original position of the
1200 // unfiltered input.
1201 Entity cover_entity;
1202 cover_entity.SetContents(SolidColorContents::Make(
1203 PathBuilder{}.AddRect(input_rect).TakePath(), cover_color));
1204 cover_entity.SetTransform(ctm);
1205
1206 cover_entity.Render(context, pass);
1207
1208 // Renders a green bounding rect of the target filter.
1209 Entity bounds_entity;
1210 std::optional<Rect> target_contents_coverage =
1211 target_contents->GetCoverage(entity);
1212 if (target_contents_coverage.has_value()) {
1213 bounds_entity.SetContents(SolidColorContents::Make(
1214 PathBuilder{}
1215 .AddRect(target_contents->GetCoverage(entity).value())
1216 .TakePath(),
1217 bounds_color));
1218 bounds_entity.SetTransform(Matrix());
1219
1220 bounds_entity.Render(context, pass);
1221 }
1222
1223 return true;
1224 };
1225 ASSERT_TRUE(OpenPlaygroundHere(callback));
1226 }

References impeller::PathBuilder::AddRect(), impeller::Color::alpha, impeller::Color::Black(), impeller::Entity::GetCoverage(), 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::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(), offset, impeller::Entity::Render(), scale, impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [349/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | GeometryBoundsAreTransformed |
| ) |  |

Definition at line 293 of file entity_unittests.cc.

293 {
294 auto geometry = Geometry::MakeRect(Rect::MakeXYWH(100, 100, 100, 100));
295 auto transform = Matrix::MakeScale({2.0, 2.0, 2.0});
296
297 ASSERT_RECT_NEAR(geometry->GetCoverage(transform).value(),
298 Rect::MakeXYWH(200, 200, 200, 200));
299 }

References ASSERT_RECT_NEAR, impeller::Geometry::MakeRect(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeXYWH(), and transform.

## ◆ TEST_P() [350/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | InheritOpacityTest |
| ) |  |

Definition at line 2125 of file entity_unittests.cc.

2125 {
2126 Entity entity;
2127
2128 // Texture contents can always accept opacity.
2129 auto texture_contents = std::make_shared<TextureContents>();
2130 texture_contents->SetOpacity(0.5);
2131 ASSERT_TRUE(texture_contents->CanInheritOpacity(entity));
2132
2133 texture_contents->SetInheritedOpacity(0.5);
2134 ASSERT_EQ(texture_contents->GetOpacity(), 0.25);
2135 texture_contents->SetInheritedOpacity(0.5);
2136 ASSERT_EQ(texture_contents->GetOpacity(), 0.25);
2137
2138 // Solid color contents can accept opacity if their geometry
2139 // doesn't overlap.
2140 auto solid_color = std::make_shared<SolidColorContents>();
2141 solid_color->SetGeometry(
2142 Geometry::MakeRect(Rect::MakeLTRB(100, 100, 200, 200)));
2143 solid_color->SetColor(Color::Blue().WithAlpha(0.5));
2144
2145 ASSERT_TRUE(solid_color->CanInheritOpacity(entity));
2146
2147 solid_color->SetInheritedOpacity(0.5);
2148 ASSERT_EQ(solid_color->GetColor().alpha, 0.25);
2149 solid_color->SetInheritedOpacity(0.5);
2150 ASSERT_EQ(solid_color->GetColor().alpha, 0.25);
2151
2152 // Color source contents can accept opacity if their geometry
2153 // doesn't overlap.
2154 auto tiled_texture = std::make_shared<TiledTextureContents>();
2155 tiled_texture->SetGeometry(
2156 Geometry::MakeRect(Rect::MakeLTRB(100, 100, 200, 200)));
2157 tiled_texture->SetOpacityFactor(0.5);
2158
2159 ASSERT_TRUE(tiled_texture->CanInheritOpacity(entity));
2160
2161 tiled_texture->SetInheritedOpacity(0.5);
2162 ASSERT_EQ(tiled_texture->GetOpacityFactor(), 0.25);
2163 tiled_texture->SetInheritedOpacity(0.5);
2164 ASSERT_EQ(tiled_texture->GetOpacityFactor(), 0.25);
2165
2166 // Clips and restores trivially accept opacity.
2167 ASSERT_TRUE(ClipContents().CanInheritOpacity(entity));
2168 ASSERT_TRUE(ClipRestoreContents().CanInheritOpacity(entity));
2169
2170 // Runtime effect contents can't accept opacity.
2171 auto runtime_effect = std::make_shared<RuntimeEffectContents>();
2172 ASSERT_FALSE(runtime_effect->CanInheritOpacity(entity));
2173 }

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

## ◆ TEST_P() [351/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearGradientContentsIsOpaque |
| ) |  |

Definition at line 2291 of file entity_unittests.cc.

2291 {
2292 LinearGradientContents contents;
2293 contents.SetColors({Color::CornflowerBlue()});
2294 ASSERT_TRUE(contents.IsOpaque());
2295 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2296 ASSERT_FALSE(contents.IsOpaque());
2297 contents.SetColors({Color::CornflowerBlue()});
2298 contents.SetTileMode(Entity::TileMode::kDecal);
2299 ASSERT_FALSE(contents.IsOpaque());
2300 }

References impeller::Color::CornflowerBlue(), impeller::LinearGradientContents::IsOpaque(), impeller::Entity::kDecal, impeller::LinearGradientContents::SetColors(), impeller::LinearGradientContents::SetTileMode(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [352/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilter |
| ) |  |

Definition at line 1755 of file entity_unittests.cc.

1755 {
1756 auto image = CreateTextureForFixture("kalimba.jpg");
1757 ASSERT_TRUE(image);
1758
1759 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1760 auto filtered =
1761 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(image));
1762
1763 // Define the entity that will serve as the control image as a Gaussian blur
1764 // filter with no filter at all.
1765 Entity entity_left;
1766 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
1767 Matrix::MakeTranslation({100, 300}) *
1768 Matrix::MakeScale(Vector2{0.5, 0.5}));
1769 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1770 Sigma{0}, Sigma{0});
1771 entity_left.SetContents(unfiltered);
1772
1773 // Define the entity that will be filtered from linear to sRGB.
1774 Entity entity_right;
1775 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
1776 Matrix::MakeTranslation({500, 300}) *
1777 Matrix::MakeScale(Vector2{0.5, 0.5}));
1778 entity_right.SetContents(filtered);
1779 return entity_left.Render(context, pass) &&
1780 entity_right.Render(context, pass);
1781 };
1782
1783 ASSERT_TRUE(OpenPlaygroundHere(callback));
1784 }

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::SetTransform().

## ◆ TEST_P() [353/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | LinearToSrgbFilterCoverageIsCorrect |
| ) |  |

Definition at line 1734 of file entity_unittests.cc.

1734 {
1735 // Set up a simple color background.
1736 auto fill = std::make_shared<SolidColorContents>();
1737 fill->SetGeometry(Geometry::MakeFillPath(
1738 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1739 fill->SetColor(Color::MintCream());
1740
1741 auto filter =
1742 ColorFilterContents::MakeLinearToSrgbFilter(FilterInput::Make(fill));
1743
1744 Entity e;
1745 e.SetTransform(Matrix());
1746
1747 // Confirm that the actual filter coverage matches the expected coverage.
1748 auto actual = filter->GetCoverage(e);
1749 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1750
1751 ASSERT_TRUE(actual.has_value());
1752 ASSERT_RECT_NEAR(actual.value(), expected);
1753 }

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::SetTransform().

## ◆ TEST_P() [354/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | MorphologyFilter |
| ) |  |

Definition at line 1228 of file entity_unittests.cc.

1228 {
1229 auto boston = CreateTextureForFixture("boston.jpg");
1230 ASSERT_TRUE(boston);
1231
1232 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1233 const char* morphology_type_names[] = {"Dilate", "Erode"};
1234 const FilterContents::MorphType morphology_types[] = {
1235 FilterContents::MorphType::kDilate, FilterContents::MorphType::kErode};
1236 static Color input_color = Color::Black();
1237 // UI state.
1238 static int selected_morphology_type = 0;
1239 static float radius[2] = {20, 20};
1240 static Color cover_color(1, 0, 0, 0.2);
1241 static Color bounds_color(0, 1, 0, 0.1);
1242 static float offset[2] = {500, 400};
1243 static float rotation = 0;
1244 static float scale[2] = {0.65, 0.65};
1245 static float skew[2] = {0, 0};
1246 static float path_rect[4] = {0, 0,
1247 static_cast<float>(boston->GetSize().width),
1248 static_cast<float>(boston->GetSize().height)};
1249 static float effect_transform_scale = 1;
1250
1251 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1252 {
1253 ImGui::Combo("Morphology type", &selected_morphology_type,
1254 morphology_type_names,
1255 sizeof(morphology_type_names) / sizeof(char*));
1256 ImGui::SliderFloat2("Radius", radius, 0, 200);
1257 ImGui::SliderFloat("Input opacity", &input_color.alpha, 0, 1);
1258 ImGui::ColorEdit4("Cover color", reinterpret_cast<float*>(&cover_color));
1259 ImGui::ColorEdit4("Bounds color",
1260 reinterpret_cast<float*>(&bounds_color));
1261 ImGui::SliderFloat2("Translation", offset, 0,
1262 pass.GetRenderTargetSize().width);
1263 ImGui::SliderFloat("Rotation", &rotation, 0, kPi * 2);
1264 ImGui::SliderFloat2("Scale", scale, 0, 3);
1265 ImGui::SliderFloat2("Skew", skew, -3, 3);
1266 ImGui::SliderFloat4("Path XYWH", path_rect, -1000, 1000);
1267 ImGui::SliderFloat("Effect transform scale", &effect_transform_scale, 0,
1268 3);
1269 }
1270 ImGui::End();
1271
1272 std::shared_ptr<Contents> input;
1273 Size input_size;
1274
1275 auto input_rect =
1276 Rect::MakeXYWH(path_rect[0], path_rect[1], path_rect[2], path_rect[3]);
1277 auto texture = std::make_shared<TextureContents>();
1278 texture->SetSourceRect(Rect::MakeSize(boston->GetSize()));
1279 texture->SetDestinationRect(input_rect);
1280 texture->SetTexture(boston);
1281 texture->SetOpacity(input_color.alpha);
1282
1283 input = texture;
1284 input_size = input_rect.GetSize();
1285
1286 auto contents = FilterContents::MakeMorphology(
1287 FilterInput::Make(input), Radius{radius[0]}, Radius{radius[1]},
1288 morphology_types[selected_morphology_type]);
1289 contents->SetEffectTransform(Matrix::MakeScale(
1290 Vector2{effect_transform_scale, effect_transform_scale}));
1291
1292 auto ctm = Matrix::MakeScale(GetContentScale()) *
1293 Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
1294 Matrix::MakeRotationZ(Radians(rotation)) *
1295 Matrix::MakeScale(Vector2(scale[0], scale[1])) *
1296 Matrix::MakeSkew(skew[0], skew[1]) *
1297 Matrix::MakeTranslation(-Point(input_size) / 2);
1298
1299 Entity entity;
1300 entity.SetContents(contents);
1301 entity.SetTransform(ctm);
1302
1303 entity.Render(context, pass);
1304
1305 // Renders a red "cover" rectangle that shows the original position of the
1306 // unfiltered input.
1307 Entity cover_entity;
1308 cover_entity.SetContents(SolidColorContents::Make(
1309 PathBuilder{}.AddRect(input_rect).TakePath(), cover_color));
1310 cover_entity.SetTransform(ctm);
1311
1312 cover_entity.Render(context, pass);
1313
1314 // Renders a green bounding rect of the target filter.
1315 Entity bounds_entity;
1316 bounds_entity.SetContents(SolidColorContents::Make(
1317 PathBuilder{}.AddRect(contents->GetCoverage(entity).value()).TakePath(),
1318 bounds_color));
1319 bounds_entity.SetTransform(Matrix());
1320
1321 bounds_entity.Render(context, pass);
1322
1323 return true;
1324 };
1325 ASSERT_TRUE(OpenPlaygroundHere(callback));
1326 }

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(), offset, impeller::Entity::Render(), scale, impeller::Entity::SetContents(), impeller::Entity::SetTransform(), and impeller::PathBuilder::TakePath().

## ◆ TEST_P() [355/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | PointFieldGeometryCoverage |
| ) |  |

Definition at line 2334 of file entity_unittests.cc.

2334 {
2335 std::vector<Point> points = {{10, 20}, {100, 200}};
2336 auto geometry = Geometry::MakePointField(points, 5.0, false);
2337 ASSERT_EQ(*geometry->GetCoverage(Matrix()), Rect::MakeLTRB(5, 15, 105, 205));
2338 ASSERT_EQ(*geometry->GetCoverage(Matrix::MakeTranslation({30, 0, 0})),
2339 Rect::MakeLTRB(35, 15, 135, 205));
2340 }

References impeller::TRect< Scalar >::MakeLTRB(), impeller::Geometry::MakePointField(), and impeller::Matrix::MakeTranslation().

## ◆ TEST_P() [356/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RadialGradientContentsIsOpaque |
| ) |  |

Definition at line 2302 of file entity_unittests.cc.

2302 {
2303 RadialGradientContents contents;
2304 contents.SetColors({Color::CornflowerBlue()});
2305 ASSERT_TRUE(contents.IsOpaque());
2306 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2307 ASSERT_FALSE(contents.IsOpaque());
2308 contents.SetColors({Color::CornflowerBlue()});
2309 contents.SetTileMode(Entity::TileMode::kDecal);
2310 ASSERT_FALSE(contents.IsOpaque());
2311 }

References impeller::Color::CornflowerBlue(), impeller::RadialGradientContents::IsOpaque(), impeller::Entity::kDecal, impeller::RadialGradientContents::SetColors(), impeller::RadialGradientContents::SetTileMode(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [357/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RRectShadowTest |
| ) |  |

Definition at line 1594 of file entity_unittests.cc.

1594 {
1595 auto callback = [&](ContentContext& context, RenderPass& pass) {
1596 static Color color = Color::Red();
1597 static float corner_radius = 100;
1598 static float blur_radius = 100;
1599 static bool show_coverage = false;
1600 static Color coverage_color = Color::Green().WithAlpha(0.2);
1601
1602 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1603 ImGui::SliderFloat("Corner radius", &corner_radius, 0, 300);
1604 ImGui::SliderFloat("Blur radius", &blur_radius, 0, 300);
1605 ImGui::ColorEdit4("Color", reinterpret_cast<Scalar*>(&color));
1606 ImGui::Checkbox("Show coverage", &show_coverage);
1607 if (show_coverage) {
1608 ImGui::ColorEdit4("Coverage color",
1609 reinterpret_cast<Scalar*>(&coverage_color));
1610 }
1611 ImGui::End();
1612
1613 static PlaygroundPoint top_left_point(Point(200, 200), 30, Color::White());
1614 static PlaygroundPoint bottom_right_point(Point(600, 400), 30,
1615 Color::White());
1616 auto [top_left, bottom_right] =
1617 DrawPlaygroundLine(top_left_point, bottom_right_point);
1618 auto rect =
1619 Rect::MakeLTRB(top_left.x, top_left.y, bottom_right.x, bottom_right.y);
1620
1621 auto contents = std::make_unique<SolidRRectBlurContents>();
1622 contents->SetRRect(rect, {corner_radius, corner_radius});
1623 contents->SetColor(color);
1624 contents->SetSigma(Radius(blur_radius));
1625
1626 Entity entity;
1627 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
1628 entity.SetContents(std::move(contents));
1629 entity.Render(context, pass);
1630
1631 auto coverage = entity.GetCoverage();
1632 if (show_coverage && coverage.has_value()) {
1633 auto bounds_contents = std::make_unique<SolidColorContents>();
1634 bounds_contents->SetGeometry(Geometry::MakeFillPath(
1635 PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath()));
1636 bounds_contents->SetColor(coverage_color.Premultiply());
1637 Entity bounds_entity;
1638 bounds_entity.SetContents(std::move(bounds_contents));
1639 bounds_entity.Render(context, pass);
1640 }
1641
1642 return true;
1643 };
1644 ASSERT_TRUE(OpenPlaygroundHere(callback));
1645 }

References impeller::PathBuilder::AddRect(), blur_radius, color, impeller::DrawPlaygroundLine(), impeller::Entity::GetCoverage(), impeller::Color::Green(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Color::Premultiply(), impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), impeller::PathBuilder::TakePath(), impeller::Color::White(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [358/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffect |
| ) |  |

Definition at line 1949 of file entity_unittests.cc.

1949 {
1950 auto runtime_stages =
1951 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
1952 auto runtime_stage =
1953 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
1954 ASSERT_TRUE(runtime_stage);
1955 ASSERT_TRUE(runtime_stage->IsDirty());
1956
1957 bool expect_dirty = true;
1958 Pipeline<PipelineDescriptor>* first_pipeline;
1959 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1960 EXPECT_EQ(runtime_stage->IsDirty(), expect_dirty);
1961
1962 auto contents = std::make_shared<RuntimeEffectContents>();
1963 contents->SetGeometry(Geometry::MakeCover());
1964 contents->SetRuntimeStage(runtime_stage);
1965
1966 struct FragUniforms {
1967 Vector2 iResolution;
1968 Scalar iTime;
1969 } frag_uniforms = {
1970 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
1971 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
1972 };
1973 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
1974 uniform_data->resize(sizeof(FragUniforms));
1975 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
1976 contents->SetUniformData(uniform_data);
1977
1978 Entity entity;
1979 entity.SetContents(contents);
1980 bool result = contents->Render(context, entity, pass);
1981
1982 if (expect_dirty) {
1983 EXPECT_NE(first_pipeline, pass.GetCommands().back().pipeline.get());
1984 first_pipeline = pass.GetCommands().back().pipeline.get();
1985 } else {
1986 EXPECT_EQ(pass.GetCommands().back().pipeline.get(), first_pipeline);
1987 }
1988
1989 expect_dirty = false;
1990 return result;
1991 };
1992
1993 // Simulate some renders and hot reloading of the shader.
1994 auto content_context = GetContentContext();
1995 {
1996 RenderTarget target =
1997 content_context->GetRenderTargetCache()->CreateOffscreen(
1998 *content_context->GetContext(), {1, 1}, 1u);
1999
2000 testing::MockRenderPass mock_pass(GetContext(), target);
2001 callback(*content_context, mock_pass);
2002 callback(*content_context, mock_pass);
2003
2004 // Dirty the runtime stage.
2005 runtime_stages = OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2006 runtime_stage =
2007 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2008
2009 ASSERT_TRUE(runtime_stage->IsDirty());
2010 expect_dirty = true;
2011
2012 callback(*content_context, mock_pass);
2013 }
2014 }

References impeller::Geometry::MakeCover(), impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::Entity::SetContents().

## ◆ TEST_P() [359/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectCanPrecache |
| ) |  |

Definition at line 2063 of file entity_unittests.cc.

2063 {
2064 auto runtime_stages =
2065 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2066 auto runtime_stage =
2067 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2068 ASSERT_TRUE(runtime_stage);
2069 ASSERT_TRUE(runtime_stage->IsDirty());
2070
2071 auto contents = std::make_shared<RuntimeEffectContents>();
2072 contents->SetRuntimeStage(runtime_stage);
2073
2074 EXPECT_TRUE(contents->BootstrapShader(*GetContentContext()));
2075 }

References impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [360/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectCanSuccessfullyRender |
| ) |  |

Definition at line 2016 of file entity_unittests.cc.

2016 {
2017 auto runtime_stages =
2018 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2019 auto runtime_stage =
2020 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2021 ASSERT_TRUE(runtime_stage);
2022 ASSERT_TRUE(runtime_stage->IsDirty());
2023
2024 auto contents = std::make_shared<RuntimeEffectContents>();
2025 contents->SetGeometry(Geometry::MakeCover());
2026
2027 contents->SetRuntimeStage(runtime_stage);
2028
2029 struct FragUniforms {
2030 Vector2 iResolution;
2031 Scalar iTime;
2032 } frag_uniforms = {
2033 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
2034 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
2035 };
2036 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2037 uniform_data->resize(sizeof(FragUniforms));
2038 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2039 contents->SetUniformData(uniform_data);
2040
2041 Entity entity;
2042 entity.SetContents(contents);
2043
2044 // Create a render target with a depth-stencil, similar to how EntityPass
2045 // does.
2046 RenderTarget target =
2047 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
2048 *GetContext(), {GetWindowSize().width, GetWindowSize().height}, 1,
2049 "RuntimeEffect Texture");
2050 testing::MockRenderPass pass(GetContext(), target);
2051
2052 ASSERT_TRUE(contents->Render(*GetContentContext(), entity, pass));
2053 ASSERT_EQ(pass.GetCommands().size(), 1u);
2054 const auto& command = pass.GetCommands()[0];
2055 ASSERT_TRUE(command.pipeline->GetDescriptor()
2056 .GetDepthStencilAttachmentDescriptor()
2057 .has_value());
2058 ASSERT_TRUE(command.pipeline->GetDescriptor()
2059 .GetFrontStencilAttachmentDescriptor()
2060 .has_value());
2061 }

References impeller::Geometry::MakeCover(), impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::Entity::SetContents().

## ◆ TEST_P() [361/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | RuntimeEffectSetsRightSizeWhenUniformIsStruct |
| ) |  |

Definition at line 2077 of file entity_unittests.cc.

2077 {
2078 if (GetBackend() != PlaygroundBackend::kVulkan) {
2079 GTEST_SKIP() << "Test only applies to Vulkan";
2080 }
2081
2082 auto runtime_stages =
2083 OpenAssetAsRuntimeStage("runtime_stage_example.frag.iplr");
2084 auto runtime_stage =
2085 runtime_stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
2086 ASSERT_TRUE(runtime_stage);
2087 ASSERT_TRUE(runtime_stage->IsDirty());
2088
2089 auto contents = std::make_shared<RuntimeEffectContents>();
2090 contents->SetGeometry(Geometry::MakeCover());
2091 contents->SetRuntimeStage(runtime_stage);
2092
2093 struct FragUniforms {
2094 Vector2 iResolution;
2095 Scalar iTime;
2096 } frag_uniforms = {
2097 .iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
2098 .iTime = static_cast<Scalar>(GetSecondsElapsed()),
2099 };
2100 auto uniform_data = std::make_shared<std::vector<uint8_t>>();
2101 uniform_data->resize(sizeof(FragUniforms));
2102 memcpy(uniform_data->data(), &frag_uniforms, sizeof(FragUniforms));
2103 contents->SetUniformData(uniform_data);
2104
2105 Entity entity;
2106 entity.SetContents(contents);
2107
2108 auto context = GetContentContext();
2109 RenderTarget target = context->GetRenderTargetCache()->CreateOffscreen(
2110 *context->GetContext(), {1, 1}, 1u);
2111
2112 testing::MockRenderPass pass(GetContext(), target);
2113 ASSERT_TRUE(contents->Render(*context, entity, pass));
2114 ASSERT_EQ(pass.GetCommands().size(), 1u);
2115 const auto& command = pass.GetCommands()[0];
2116 ASSERT_EQ(command.fragment_bindings.buffers.size(), 1u);
2117 // 16 bytes:
2118 // 8 bytes for iResolution
2119 // 4 bytes for iTime
2120 // 4 bytes padding
2121 EXPECT_EQ(command.fragment_bindings.buffers[0].view.resource.range.length,
2122 16u);
2123 }

References impeller::kVulkan, impeller::Geometry::MakeCover(), impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::Entity::SetContents().

## ◆ TEST_P() [362/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SetBlendMode |
| ) |  |

Definition at line 1328 of file entity_unittests.cc.

1328 {
1329 Entity entity;
1330 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kSourceOver);
1331 entity.SetBlendMode(BlendMode::kClear);
1332 ASSERT_EQ(entity.GetBlendMode(), BlendMode::kClear);
1333 }

References impeller::Entity::GetBlendMode(), impeller::kClear, impeller::kSourceOver, and impeller::Entity::SetBlendMode().

## ◆ TEST_P() [363/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsIsOpaque |
| ) |  |

Definition at line 2275 of file entity_unittests.cc.

2275 {
2276 SolidColorContents contents;
2277 contents.SetColor(Color::CornflowerBlue());
2278 ASSERT_TRUE(contents.IsOpaque());
2279 contents.SetColor(Color::CornflowerBlue().WithAlpha(0.5));
2280 ASSERT_FALSE(contents.IsOpaque());
2281 }

References impeller::Color::CornflowerBlue(), impeller::SolidColorContents::IsOpaque(), and impeller::SolidColorContents::SetColor().

## ◆ TEST_P() [364/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsStrokeSetMiterLimit |
| ) |  |

Definition at line 842 of file entity_unittests.cc.

842 {
843 {
844 auto geometry = Geometry::MakeStrokePath(Path{});
845 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
846 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
847 }
848
849 {
850 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, /*miter_limit=*/8.0);
851 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
852 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 8);
853 }
854
855 {
856 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, /*miter_limit=*/-1.0);
857 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
858 ASSERT_FLOAT_EQ(path_geometry->GetMiterLimit(), 4);
859 }
860 }

References impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [365/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidColorContentsStrokeSetStrokeCapsAndJoins |
| ) |  |

Definition at line 820 of file entity_unittests.cc.

820 {
821 {
822 auto geometry = Geometry::MakeStrokePath(Path{});
823 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
824 // Defaults.
825 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kButt);
826 ASSERT_EQ(path_geometry->GetStrokeJoin(), Join::kMiter);
827 }
828
829 {
830 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, 4.0, Cap::kSquare);
831 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
832 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kSquare);
833 }
834
835 {
836 auto geometry = Geometry::MakeStrokePath(Path{}, 1.0, 4.0, Cap::kRound);
837 auto path_geometry = static_cast<StrokePathGeometry*>(geometry.get());
838 ASSERT_EQ(path_geometry->GetStrokeCap(), Cap::kRound);
839 }
840 }

References impeller::kButt, impeller::kMiter, impeller::kRound, impeller::kSquare, and impeller::Geometry::MakeStrokePath().

## ◆ TEST_P() [366/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidFillCoverageIsCorrect |
| ) |  |

Definition at line 1421 of file entity_unittests.cc.

1421 {
1422 // No transform
1423 {
1424 auto fill = std::make_shared<SolidColorContents>();
1425 fill->SetColor(Color::CornflowerBlue());
1426 auto expected = Rect::MakeLTRB(100, 110, 200, 220);
1427 fill->SetGeometry(
1428 Geometry::MakeFillPath(PathBuilder{}.AddRect(expected).TakePath()));
1429
1430 auto coverage = fill->GetCoverage({});
1431 ASSERT_TRUE(coverage.has_value());
1432 ASSERT_RECT_NEAR(coverage.value(), expected);
1433 }
1434
1435 // Entity transform
1436 {
1437 auto fill = std::make_shared<SolidColorContents>();
1438 fill->SetColor(Color::CornflowerBlue());
1439 fill->SetGeometry(Geometry::MakeFillPath(
1440 PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath()));
1441
1442 Entity entity;
1443 entity.SetTransform(Matrix::MakeTranslation(Vector2(4, 5)));
1444 entity.SetContents(std::move(fill));
1445
1446 auto coverage = entity.GetCoverage();
1447 auto expected = Rect::MakeLTRB(104, 115, 204, 225);
1448 ASSERT_TRUE(coverage.has_value());
1449 ASSERT_RECT_NEAR(coverage.value(), expected);
1450 }
1451
1452 // No coverage for fully transparent colors
1453 {
1454 auto fill = std::make_shared<SolidColorContents>();
1455 fill->SetColor(Color::WhiteTransparent());
1456 fill->SetGeometry(Geometry::MakeFillPath(
1457 PathBuilder{}.AddRect(Rect::MakeLTRB(100, 110, 200, 220)).TakePath()));
1458
1459 auto coverage = fill->GetCoverage({});
1460 ASSERT_FALSE(coverage.has_value());
1461 }
1462 }

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::SetTransform(), and impeller::Color::WhiteTransparent().

## ◆ TEST_P() [367/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidFillShouldRenderIsCorrect |
| ) |  |

Definition at line 1464 of file entity_unittests.cc.

1464 {
1465 // No path.
1466 {
1467 auto fill = std::make_shared<SolidColorContents>();
1468 fill->SetColor(Color::CornflowerBlue());
1469 ASSERT_FALSE(fill->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1470 ASSERT_FALSE(
1471 fill->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1472 }
1473
1474 // With path.
1475 {
1476 auto fill = std::make_shared<SolidColorContents>();
1477 fill->SetColor(Color::CornflowerBlue());
1478 fill->SetGeometry(Geometry::MakeFillPath(
1479 PathBuilder{}.AddRect(Rect::MakeLTRB(0, 0, 100, 100)).TakePath()));
1480 ASSERT_TRUE(fill->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1481 ASSERT_FALSE(
1482 fill->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1483 }
1484
1485 // With paint cover.
1486 {
1487 auto fill = std::make_shared<SolidColorContents>();
1488 fill->SetColor(Color::CornflowerBlue());
1489 fill->SetGeometry(Geometry::MakeCover());
1490 ASSERT_TRUE(fill->ShouldRender(Entity{}, Rect::MakeSize(Size{100, 100})));
1491 ASSERT_TRUE(
1492 fill->ShouldRender(Entity{}, Rect::MakeLTRB(-100, -100, -50, -50)));
1493 }
1494 }

References impeller::PathBuilder::AddRect(), impeller::Color::CornflowerBlue(), impeller::Geometry::MakeCover(), impeller::Geometry::MakeFillPath(), impeller::TRect< Scalar >::MakeLTRB(), and impeller::TRect< Scalar >::MakeSize().

## ◆ TEST_P() [368/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SolidStrokeCoverageIsCorrect |
| ) |  |

Definition at line 1341 of file entity_unittests.cc.

1341 {
1342 {
1343 auto geometry = Geometry::MakeStrokePath(
1344 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 4.0,
1345 Cap::kButt, Join::kBevel);
1346
1347 Entity entity;
1348 auto contents = std::make_unique<SolidColorContents>();
1349 contents->SetGeometry(std::move(geometry));
1350 contents->SetColor(Color::Black());
1351 entity.SetContents(std::move(contents));
1352 auto actual = entity.GetCoverage();
1353 auto expected = Rect::MakeLTRB(-2, -2, 12, 12);
1354 ASSERT_TRUE(actual.has_value());
1355 ASSERT_RECT_NEAR(actual.value(), expected);
1356 }
1357
1358 // Cover the Cap::kSquare case.
1359 {
1360 auto geometry = Geometry::MakeStrokePath(
1361 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 4.0,
1362 Cap::kSquare, Join::kBevel);
1363
1364 Entity entity;
1365 auto contents = std::make_unique<SolidColorContents>();
1366 contents->SetGeometry(std::move(geometry));
1367 contents->SetColor(Color::Black());
1368 entity.SetContents(std::move(contents));
1369 auto actual = entity.GetCoverage();
1370 auto expected =
1371 Rect::MakeLTRB(-sqrt(8), -sqrt(8), 10 + sqrt(8), 10 + sqrt(8));
1372 ASSERT_TRUE(actual.has_value());
1373 ASSERT_RECT_NEAR(actual.value(), expected);
1374 }
1375
1376 // Cover the Join::kMiter case.
1377 {
1378 auto geometry = Geometry::MakeStrokePath(
1379 PathBuilder{}.AddLine({0, 0}, {10, 10}).TakePath(), 4.0, 2.0,
1380 Cap::kSquare, Join::kMiter);
1381
1382 Entity entity;
1383 auto contents = std::make_unique<SolidColorContents>();
1384 contents->SetGeometry(std::move(geometry));
1385 contents->SetColor(Color::Black());
1386 entity.SetContents(std::move(contents));
1387 auto actual = entity.GetCoverage();
1388 auto expected = Rect::MakeLTRB(-4, -4, 14, 14);
1389 ASSERT_TRUE(actual.has_value());
1390 ASSERT_RECT_NEAR(actual.value(), expected);
1391 }
1392 }

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() [369/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SpecializationConstantsAreAppliedToVariants |
| ) |  |

Definition at line 2420 of file entity_unittests.cc.

2420 {
2421 auto content_context = GetContentContext();
2422
2423 auto default_gyph = content_context->GetGlyphAtlasPipeline({
2424 .color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2425 .has_depth_stencil_attachments = false,
2426 });
2427 auto alt_gyph = content_context->GetGlyphAtlasPipeline(
2428 {.color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt,
2429 .has_depth_stencil_attachments = true});
2430
2431 EXPECT_NE(default_gyph, alt_gyph);
2432 EXPECT_EQ(default_gyph->GetDescriptor().GetSpecializationConstants(),
2433 alt_gyph->GetDescriptor().GetSpecializationConstants());
2434
2435 auto use_a8 = GetContext()->GetCapabilities()->GetDefaultGlyphAtlasFormat() ==
2436 PixelFormat::kA8UNormInt;
2437
2438 std::vector<Scalar> expected_constants = {static_cast<Scalar>(use_a8)};
2439 EXPECT_EQ(default_gyph->GetDescriptor().GetSpecializationConstants(),
2440 expected_constants);
2441 }

References impeller::kA8UNormInt, and impeller::kR8G8B8A8UNormInt.

## ◆ TEST_P() [370/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilter |
| ) |  |

Definition at line 1807 of file entity_unittests.cc.

1807 {
1808 auto image = CreateTextureForFixture("embarcadero.jpg");
1809 ASSERT_TRUE(image);
1810
1811 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1812 auto filtered =
1813 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(image));
1814
1815 // Define the entity that will serve as the control image as a Gaussian blur
1816 // filter with no filter at all.
1817 Entity entity_left;
1818 entity_left.SetTransform(Matrix::MakeScale(GetContentScale()) *
1819 Matrix::MakeTranslation({100, 300}) *
1820 Matrix::MakeScale(Vector2{0.5, 0.5}));
1821 auto unfiltered = FilterContents::MakeGaussianBlur(FilterInput::Make(image),
1822 Sigma{0}, Sigma{0});
1823 entity_left.SetContents(unfiltered);
1824
1825 // Define the entity that will be filtered from sRGB to linear.
1826 Entity entity_right;
1827 entity_right.SetTransform(Matrix::MakeScale(GetContentScale()) *
1828 Matrix::MakeTranslation({500, 300}) *
1829 Matrix::MakeScale(Vector2{0.5, 0.5}));
1830 entity_right.SetContents(filtered);
1831 return entity_left.Render(context, pass) &&
1832 entity_right.Render(context, pass);
1833 };
1834
1835 ASSERT_TRUE(OpenPlaygroundHere(callback));
1836 }

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::SetTransform().

## ◆ TEST_P() [371/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SrgbToLinearFilterCoverageIsCorrect |
| ) |  |

Definition at line 1786 of file entity_unittests.cc.

1786 {
1787 // Set up a simple color background.
1788 auto fill = std::make_shared<SolidColorContents>();
1789 fill->SetGeometry(Geometry::MakeFillPath(
1790 PathBuilder{}.AddRect(Rect::MakeXYWH(0, 0, 300, 400)).TakePath()));
1791 fill->SetColor(Color::DeepPink());
1792
1793 auto filter =
1794 ColorFilterContents::MakeSrgbToLinearFilter(FilterInput::Make(fill));
1795
1796 Entity e;
1797 e.SetTransform(Matrix());
1798
1799 // Confirm that the actual filter coverage matches the expected coverage.
1800 auto actual = filter->GetCoverage(e);
1801 auto expected = Rect::MakeXYWH(0, 0, 300, 400);
1802
1803 ASSERT_TRUE(actual.has_value());
1804 ASSERT_RECT_NEAR(actual.value(), expected);
1805 }

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::SetTransform().

## ◆ TEST_P() [372/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeCapAndJoinTest |
| ) |  |

Definition at line 384 of file entity_unittests.cc.

384 {
385 const Point padding(300, 250);
386 const Point margin(140, 180);
387
388 auto callback = [&](ContentContext& context, RenderPass& pass) {
389 // Slightly above sqrt(2) by default, so that right angles are just below
390 // the limit and acute angles are over the limit (causing them to get
391 // beveled).
392 static Scalar miter_limit = 1.41421357;
393 static Scalar width = 30;
394
395 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
396 {
397 ImGui::SliderFloat("Miter limit", &miter_limit, 0, 30);
398 ImGui::SliderFloat("Stroke width", &width, 0, 100);
399 if (ImGui::Button("Reset")) {
400 miter_limit = 1.41421357;
401 width = 30;
402 }
403 }
404 ImGui::End();
405
406 auto world_matrix = Matrix::MakeScale(GetContentScale());
407 auto render_path = [width = width, &context, &pass, &world_matrix](
408 const Path& path, Cap cap, Join join) {
409 auto contents = std::make_unique<SolidColorContents>();
410 contents->SetGeometry(
411 Geometry::MakeStrokePath(path, width, miter_limit, cap, join));
412 contents->SetColor(Color::Red());
413
414 Entity entity;
415 entity.SetTransform(world_matrix);
416 entity.SetContents(std::move(contents));
417
418 auto coverage = entity.GetCoverage();
419 if (coverage.has_value()) {
420 auto bounds_contents = std::make_unique<SolidColorContents>();
421 bounds_contents->SetGeometry(Geometry::MakeFillPath(
422 PathBuilder{}.AddRect(entity.GetCoverage().value()).TakePath()));
423 bounds_contents->SetColor(Color::Green().WithAlpha(0.5));
424 Entity bounds_entity;
425 bounds_entity.SetContents(std::move(bounds_contents));
426 bounds_entity.Render(context, pass);
427 }
428
429 entity.Render(context, pass);
430 };
431
432 const Point a_def(0, 0), b_def(0, 100), c_def(150, 0), d_def(150, -100),
433 e_def(75, 75);
434 const Scalar r = 30;
435 // Cap::kButt demo.
436 {
437 Point off = Point(0, 0) * padding + margin;
438 static PlaygroundPoint point_a(off + a_def, r, Color::Black());
439 static PlaygroundPoint point_b(off + b_def, r, Color::White());
440 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
441 static PlaygroundPoint point_c(off + c_def, r, Color::Black());
442 static PlaygroundPoint point_d(off + d_def, r, Color::White());
443 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
444 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
445 Cap::kButt, Join::kBevel);
446 }
447
448 // Cap::kSquare demo.
449 {
450 Point off = Point(1, 0) * padding + margin;
451 static PlaygroundPoint point_a(off + a_def, r, Color::Black());
452 static PlaygroundPoint point_b(off + b_def, r, Color::White());
453 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
454 static PlaygroundPoint point_c(off + c_def, r, Color::Black());
455 static PlaygroundPoint point_d(off + d_def, r, Color::White());
456 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
457 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
458 Cap::kSquare, Join::kBevel);
459 }
460
461 // Cap::kRound demo.
462 {
463 Point off = Point(2, 0) * padding + margin;
464 static PlaygroundPoint point_a(off + a_def, r, Color::Black());
465 static PlaygroundPoint point_b(off + b_def, r, Color::White());
466 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
467 static PlaygroundPoint point_c(off + c_def, r, Color::Black());
468 static PlaygroundPoint point_d(off + d_def, r, Color::White());
469 auto [c, d] = DrawPlaygroundLine(point_c, point_d);
470 render_path(PathBuilder{}.AddCubicCurve(a, b, d, c).TakePath(),
471 Cap::kRound, Join::kBevel);
472 }
473
474 // Join::kBevel demo.
475 {
476 Point off = Point(0, 1) * padding + margin;
477 static PlaygroundPoint point_a =
478 PlaygroundPoint(off + a_def, r, Color::White());
479 static PlaygroundPoint point_b =
480 PlaygroundPoint(off + e_def, r, Color::White());
481 static PlaygroundPoint point_c =
482 PlaygroundPoint(off + c_def, r, Color::White());
483 Point a = DrawPlaygroundPoint(point_a);
484 Point b = DrawPlaygroundPoint(point_b);
485 Point c = DrawPlaygroundPoint(point_c);
486 render_path(
487 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
488 Cap::kButt, Join::kBevel);
489 }
490
491 // Join::kMiter demo.
492 {
493 Point off = Point(1, 1) * padding + margin;
494 static PlaygroundPoint point_a(off + a_def, r, Color::White());
495 static PlaygroundPoint point_b(off + e_def, r, Color::White());
496 static PlaygroundPoint point_c(off + c_def, r, Color::White());
497 Point a = DrawPlaygroundPoint(point_a);
498 Point b = DrawPlaygroundPoint(point_b);
499 Point c = DrawPlaygroundPoint(point_c);
500 render_path(
501 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
502 Cap::kButt, Join::kMiter);
503 }
504
505 // Join::kRound demo.
506 {
507 Point off = Point(2, 1) * padding + margin;
508 static PlaygroundPoint point_a(off + a_def, r, Color::White());
509 static PlaygroundPoint point_b(off + e_def, r, Color::White());
510 static PlaygroundPoint point_c(off + c_def, r, Color::White());
511 Point a = DrawPlaygroundPoint(point_a);
512 Point b = DrawPlaygroundPoint(point_b);
513 Point c = DrawPlaygroundPoint(point_c);
514 render_path(
515 PathBuilder{}.MoveTo(a).LineTo(b).LineTo(c).Close().TakePath(),
516 Cap::kButt, Join::kRound);
517 }
518
519 return true;
520 };
521 ASSERT_TRUE(OpenPlaygroundHere(callback));
522 }

References impeller::PathBuilder::AddCubicCurve(), impeller::PathBuilder::AddRect(), impeller::saturated::b, impeller::Color::Black(), impeller::Close(), impeller::DrawPlaygroundLine(), impeller::DrawPlaygroundPoint(), impeller::Entity::GetCoverage(), impeller::Color::Green(), impeller::kBevel, impeller::kButt, impeller::kMiter, impeller::kRound, impeller::kSquare, impeller::LineTo(), impeller::Geometry::MakeFillPath(), impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), impeller::PathBuilder::MoveTo(), padding, impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), impeller::PathBuilder::TakePath(), and impeller::Color::White().

## ◆ TEST_P() [373/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | StrokeWithTextureContents |
| ) |  |

Definition at line 320 of file entity_unittests.cc.

320 {
321 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
322 Path path = PathBuilder{}
323 .MoveTo({100, 100})
324 .LineTo({100, 200})
325 .MoveTo({100, 300})
326 .LineTo({100, 400})
327 .MoveTo({100, 500})
328 .LineTo({100, 600})
329 .TakePath();
330
331 Entity entity;
332 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
333 auto contents = std::make_unique<TiledTextureContents>();
334 contents->SetGeometry(Geometry::MakeStrokePath(path, 100.0));
335 contents->SetTexture(bridge);
336 contents->SetTileModes(Entity::TileMode::kClamp, Entity::TileMode::kClamp);
337 entity.SetContents(std::move(contents));
338 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
339 }

References impeller::Entity::kClamp, impeller::LineTo(), impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), impeller::MoveTo(), impeller::PathBuilder::MoveTo(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [374/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | SweepGradientContentsIsOpaque |
| ) |  |

Definition at line 2313 of file entity_unittests.cc.

2313 {
2314 RadialGradientContents contents;
2315 contents.SetColors({Color::CornflowerBlue()});
2316 ASSERT_TRUE(contents.IsOpaque());
2317 contents.SetColors({Color::CornflowerBlue().WithAlpha(0.5)});
2318 ASSERT_FALSE(contents.IsOpaque());
2319 contents.SetColors({Color::CornflowerBlue()});
2320 contents.SetTileMode(Entity::TileMode::kDecal);
2321 ASSERT_FALSE(contents.IsOpaque());
2322 }

References impeller::Color::CornflowerBlue(), impeller::RadialGradientContents::IsOpaque(), impeller::Entity::kDecal, impeller::RadialGradientContents::SetColors(), impeller::RadialGradientContents::SetTileMode(), and impeller::Color::WithAlpha().

## ◆ TEST_P() [375/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TextContentsCeilsGlyphScaleToDecimal |
| ) |  |

Definition at line 2362 of file entity_unittests.cc.

2362 {
2363 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.4321111f, 12), 0.43f);
2364 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.5321111f, 12), 0.53f);
2365 ASSERT_EQ(TextFrame::RoundScaledFontSize(2.1f, 12), 2.1f);
2366 ASSERT_EQ(TextFrame::RoundScaledFontSize(0.0f, 12), 0.0f);
2367 ASSERT_EQ(TextFrame::RoundScaledFontSize(100000000.0f, 12), 48.0f);
2368 }

References impeller::TextFrame::RoundScaledFontSize().

## ◆ TEST_P() [376/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | ThreeStrokesInOnePath |
| ) |  |

Definition at line 301 of file entity_unittests.cc.

301 {
302 Path path = PathBuilder{}
303 .MoveTo({100, 100})
304 .LineTo({100, 200})
305 .MoveTo({100, 300})
306 .LineTo({100, 400})
307 .MoveTo({100, 500})
308 .LineTo({100, 600})
309 .TakePath();
310
311 Entity entity;
312 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
313 auto contents = std::make_unique<SolidColorContents>();
314 contents->SetGeometry(Geometry::MakeStrokePath(path, 5.0));
315 contents->SetColor(Color::Red());
316 entity.SetContents(std::move(contents));
317 ASSERT_TRUE(OpenPlaygroundHere(std::move(entity)));
318 }

References impeller::LineTo(), impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), impeller::MoveTo(), impeller::PathBuilder::MoveTo(), impeller::Color::Red(), impeller::Entity::SetContents(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [377/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsIsOpaque |
| ) |  |

Definition at line 2324 of file entity_unittests.cc.

2324 {
2325 auto bay_bridge = CreateTextureForFixture("bay_bridge.jpg");
2326 TiledTextureContents contents;
2327 contents.SetTexture(bay_bridge);
2328 // This is a placeholder test. Images currently never decompress as opaque
2329 // (whether in Flutter or the playground), and so this should currently always
2330 // return false in practice.
2331 ASSERT_FALSE(contents.IsOpaque());
2332 }

References impeller::TiledTextureContents::IsOpaque(), and impeller::TiledTextureContents::SetTexture().

## ◆ TEST_P() [378/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsRendersWithCorrectPipeline |
| ) |  |

Definition at line 20 of file tiled_texture_contents_unittests.cc.

20 {
21 TextureDescriptor texture_desc;
22 texture_desc.size = {100, 100};
23 texture_desc.type = TextureType::kTexture2D;
24 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
25 texture_desc.storage_mode = StorageMode::kDevicePrivate;
26 auto texture =
27 GetContext()->GetResourceAllocator()->CreateTexture(texture_desc);
28
29 TiledTextureContents contents;
30 contents.SetTexture(texture);
31 contents.SetGeometry(Geometry::MakeCover());
32
33 auto content_context = GetContentContext();
34 auto buffer = content_context->GetContext()->CreateCommandBuffer();
35 auto render_target =
36 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
37 *content_context->GetContext(), {100, 100},
38 /*mip_count=*/1);
39 auto render_pass = buffer->CreateRenderPass(render_target);
40 auto recording_pass = std::make_shared<RecordingRenderPass>(
41 render_pass, GetContext(), render_target);
42
43 ASSERT_TRUE(contents.Render(*GetContentContext(), {}, *recording_pass));
44 const std::vector<Command>& commands = recording_pass->GetCommands();
45
46 ASSERT_EQ(commands.size(), 1u);
47 EXPECT_TRUE(commands[0].pipeline->GetDescriptor().GetLabel().find(
48 "TextureFill Pipeline") != std::string::npos);
49
50 if (GetParam() == PlaygroundBackend::kMetal) {
51 recording_pass->EncodeCommands();
52 }
53 }

References impeller::TextureDescriptor::format, impeller::kDevicePrivate, impeller::kMetal, impeller::kR8G8B8A8UNormInt, impeller::kTexture2D, impeller::Geometry::MakeCover(), impeller::TiledTextureContents::Render(), impeller::ColorSourceContents::SetGeometry(), impeller::TiledTextureContents::SetTexture(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, and impeller::TextureDescriptor::type.

## ◆ TEST_P() [379/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TiledTextureContentsRendersWithCorrectPipelineExternalOES |
| ) |  |

Definition at line 57 of file tiled_texture_contents_unittests.cc.

57 {
58 if (GetParam() != PlaygroundBackend::kOpenGLES) {
59 GTEST_SKIP_(
60 "External OES textures are only valid for the OpenGLES backend.");
61 }
62
63 TextureDescriptor texture_desc;
64 texture_desc.size = {100, 100};
65 texture_desc.type = TextureType::kTextureExternalOES;
66 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
67 texture_desc.storage_mode = StorageMode::kDevicePrivate;
68 auto texture =
69 GetContext()->GetResourceAllocator()->CreateTexture(texture_desc);
70
71 TiledTextureContents contents;
72 contents.SetTexture(texture);
73 contents.SetGeometry(Geometry::MakeCover());
74
75 auto content_context = GetContentContext();
76 auto buffer = content_context->GetContext()->CreateCommandBuffer();
77 auto render_target =
78 GetContentContext()->GetRenderTargetCache()->CreateOffscreenMSAA(
79 *content_context->GetContext(), {100, 100},
80 /*mip_count=*/1);
81 auto render_pass = buffer->CreateRenderPass(render_target);
82
83 ASSERT_TRUE(contents.Render(*GetContentContext(), {}, *render_pass));
84 const std::vector<Command>& commands = render_pass->GetCommands();
85
86 ASSERT_EQ(commands.size(), 1u);
87 EXPECT_TRUE(commands[0].pipeline->GetDescriptor().GetLabel().find(
88 "TiledTextureFillExternal Pipeline") != std::string::npos);
89 }

References impeller::TextureDescriptor::format, impeller::kDevicePrivate, impeller::kOpenGLES, impeller::kR8G8B8A8UNormInt, impeller::kTextureExternalOES, impeller::Geometry::MakeCover(), impeller::TiledTextureContents::Render(), impeller::ColorSourceContents::SetGeometry(), impeller::TiledTextureContents::SetTexture(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, and impeller::TextureDescriptor::type.

## ◆ TEST_P() [380/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | TriangleInsideASquare |
| ) |  |

Definition at line 341 of file entity_unittests.cc.

341 {
342 auto callback = [&](ContentContext& context, RenderPass& pass) {
343 Point offset(100, 100);
344
345 static PlaygroundPoint point_a(Point(10, 10) + offset, 20, Color::White());
346 Point a = DrawPlaygroundPoint(point_a);
347 static PlaygroundPoint point_b(Point(210, 10) + offset, 20, Color::White());
348 Point b = DrawPlaygroundPoint(point_b);
349 static PlaygroundPoint point_c(Point(210, 210) + offset, 20,
350 Color::White());
351 Point c = DrawPlaygroundPoint(point_c);
352 static PlaygroundPoint point_d(Point(10, 210) + offset, 20, Color::White());
353 Point d = DrawPlaygroundPoint(point_d);
354 static PlaygroundPoint point_e(Point(50, 50) + offset, 20, Color::White());
355 Point e = DrawPlaygroundPoint(point_e);
356 static PlaygroundPoint point_f(Point(100, 50) + offset, 20, Color::White());
357 Point f = DrawPlaygroundPoint(point_f);
358 static PlaygroundPoint point_g(Point(50, 150) + offset, 20, Color::White());
359 Point g = DrawPlaygroundPoint(point_g);
360 Path path = PathBuilder{}
361 .MoveTo(a)
362 .LineTo(b)
363 .LineTo(c)
364 .LineTo(d)
365 .Close()
366 .MoveTo(e)
367 .LineTo(f)
368 .LineTo(g)
369 .Close()
370 .TakePath();
371
372 Entity entity;
373 entity.SetTransform(Matrix::MakeScale(GetContentScale()));
374 auto contents = std::make_unique<SolidColorContents>();
375 contents->SetGeometry(Geometry::MakeStrokePath(path, 20.0));
376 contents->SetColor(Color::Red());
377 entity.SetContents(std::move(contents));
378
379 return entity.Render(context, pass);
380 };
381 ASSERT_TRUE(OpenPlaygroundHere(callback));
382 }

References impeller::saturated::b, impeller::PathBuilder::Close(), impeller::DrawPlaygroundPoint(), impeller::PathBuilder::LineTo(), impeller::Matrix::MakeScale(), impeller::Geometry::MakeStrokePath(), impeller::PathBuilder::MoveTo(), offset, impeller::Color::Red(), impeller::Entity::Render(), impeller::Entity::SetContents(), impeller::Entity::SetTransform(), impeller::PathBuilder::TakePath(), and impeller::Color::White().

## ◆ TEST_P() [381/456]

impeller::testing::TEST_P | ( | EntityTest | ,
|  | YUVToRGBFilter |
| ) |  |

Definition at line 1916 of file entity_unittests.cc.

1916 {
1917 if (GetParam() == PlaygroundBackend::kOpenGLES) {
1918 // TODO(114588) : Support YUV to RGB filter on OpenGLES backend.
1919 GTEST_SKIP_("YUV to RGB filter is not supported on OpenGLES backend yet.");
1920 }
1921
1922 auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
1923 YUVColorSpace yuv_color_space_array[2]{YUVColorSpace::kBT601FullRange,
1924 YUVColorSpace::kBT601LimitedRange};
1925 for (int i = 0; i < 2; i++) {
1926 auto yuv_color_space = yuv_color_space_array[i];
1927 auto textures =
1928 CreateTestYUVTextures(GetContext().get(), yuv_color_space);
1929 auto filter_contents = FilterContents::MakeYUVToRGBFilter(
1930 textures[0], textures[1], yuv_color_space);
1931 Entity filter_entity;
1932 filter_entity.SetContents(filter_contents);
1933 auto snapshot = filter_contents->RenderToSnapshot(context, filter_entity);
1934
1935 Entity entity;
1936 auto contents = TextureContents::MakeRect(Rect::MakeLTRB(0, 0, 256, 256));
1937 contents->SetTexture(snapshot->texture);
1938 contents->SetSourceRect(Rect::MakeSize(snapshot->texture->GetSize()));
1939 entity.SetContents(contents);
1940 entity.SetTransform(
1941 Matrix::MakeTranslation({static_cast<Scalar>(100 + 400 * i), 300}));
1942 entity.Render(context, pass);
1943 }
1944 return true;
1945 };
1946 ASSERT_TRUE(OpenPlaygroundHere(callback));
1947 }

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::SetTransform().

## ◆ TEST_P() [382/456]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | CalculateUVsSimple |
| ) |  |

Definition at line 325 of file gaussian_blur_filter_contents_unittests.cc.

325 {
326 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
327 auto filter_input = FilterInput::Make(texture);
328 Entity entity;
329 Quad uvs = GaussianBlurFilterContents::CalculateUVs(
330 filter_input, entity, Rect::MakeSize(ISize(100, 100)), ISize(100, 100));
331 std::optional<Rect> uvs_bounds = Rect::MakePointBounds(uvs);
332 EXPECT_TRUE(uvs_bounds.has_value());
333 if (uvs_bounds.has_value()) {
334 EXPECT_TRUE(RectNear(uvs_bounds.value(), Rect::MakeXYWH(0, 0, 1, 1)));
335 }
336 }

References impeller::GaussianBlurFilterContents::CalculateUVs(), impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakePointBounds(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), RectNear(), and uvs.

## ◆ TEST_P() [383/456]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | CoverageWithEffectTransform |
| ) |  |

Definition at line 177 of file gaussian_blur_filter_contents_unittests.cc.

177 {
178 Matrix effect_transform = Matrix::MakeScale({2.0, 2.0, 1.0});
179 fml::StatusOr<Scalar> sigma_radius_1 =
180 CalculateSigmaForBlurRadius(1.0, effect_transform);
181 ASSERT_TRUE(sigma_radius_1.ok());
182 GaussianBlurFilterContents contents(
183 /*sigma_x=*/sigma_radius_1.value(),
184 /*sigma_y=*/sigma_radius_1.value(), Entity::TileMode::kDecal,
185 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
186 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
187 FilterInput::Vector inputs = {FilterInput::Make(texture)};
188 Entity entity;
189 entity.SetTransform(Matrix::MakeTranslation({100, 100, 0}));
190 std::optional<Rect> coverage =
191 contents.GetFilterCoverage(inputs, entity, effect_transform);
192 EXPECT_TRUE(coverage.has_value());
193 if (coverage.has_value()) {
194 EXPECT_RECT_NEAR(coverage.value(),
195 Rect::MakeLTRB(100 - 1, 100 - 1, 200 + 1, 200 + 1));
196 }
197 }

References EXPECT_RECT_NEAR, impeller::GaussianBlurFilterContents::GetFilterCoverage(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [384/456]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | CoverageWithTexture |
| ) |  |

Definition at line 156 of file gaussian_blur_filter_contents_unittests.cc.

156 {
157 fml::StatusOr<Scalar> sigma_radius_1 =
158 CalculateSigmaForBlurRadius(1.0, Matrix());
159 ASSERT_TRUE(sigma_radius_1.ok());
160 GaussianBlurFilterContents contents(
161 /*sigma_X=*/sigma_radius_1.value(),
162 /*sigma_y=*/sigma_radius_1.value(), Entity::TileMode::kDecal,
163 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
164 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
165 FilterInput::Vector inputs = {FilterInput::Make(texture)};
166 Entity entity;
167 entity.SetTransform(Matrix::MakeTranslation({100, 100, 0}));
168 std::optional<Rect> coverage =
169 contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
170
171 EXPECT_TRUE(coverage.has_value());
172 if (coverage.has_value()) {
173 EXPECT_RECT_NEAR(coverage.value(), Rect::MakeLTRB(99, 99, 201, 201));
174 }
175 }

References EXPECT_RECT_NEAR, impeller::GaussianBlurFilterContents::GetFilterCoverage(), impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeTranslation(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [385/456]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverage |
| ) |  |

Definition at line 229 of file gaussian_blur_filter_contents_unittests.cc.

229 {
230 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
231 fml::StatusOr<Scalar> sigma_radius_1 =
232 CalculateSigmaForBlurRadius(1.0, Matrix());
233 ASSERT_TRUE(sigma_radius_1.ok());
234 auto contents = std::make_unique<GaussianBlurFilterContents>(
235 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
236 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
237 contents->SetInputs({FilterInput::Make(texture)});
238 std::shared_ptr<ContentContext> renderer = GetContentContext();
239
240 Entity entity;
241 std::optional<Entity> result =
242 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
243 EXPECT_TRUE(result.has_value());
244 if (result.has_value()) {
245 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
246 std::optional<Rect> result_coverage = result.value().GetCoverage();
247 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
248 EXPECT_TRUE(result_coverage.has_value());
249 EXPECT_TRUE(contents_coverage.has_value());
250 if (result_coverage.has_value() && contents_coverage.has_value()) {
251 EXPECT_TRUE(RectNear(contents_coverage.value(),
252 Rect::MakeLTRB(-1, -1, 101, 101)));
253 EXPECT_TRUE(
254 RectNear(result_coverage.value(), Rect::MakeLTRB(-1, -1, 101, 101)));
255 }
256 }
257 }

References impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSourceOver, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), and RectNear().

## ◆ TEST_P() [386/456]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageRotated |
| ) |  |

Definition at line 292 of file gaussian_blur_filter_contents_unittests.cc.

293 {
294 std::shared_ptr<Texture> texture = MakeTexture(ISize(400, 300));
295 fml::StatusOr<Scalar> sigma_radius_1 =
296 CalculateSigmaForBlurRadius(1.0, Matrix());
297 auto contents = std::make_unique<GaussianBlurFilterContents>(
298 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
299 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
300 contents->SetInputs({FilterInput::Make(texture)});
301 std::shared_ptr<ContentContext> renderer = GetContentContext();
302
303 Entity entity;
304 // Rotate around the top left corner, then push it over to (100, 100).
305 entity.SetTransform(Matrix::MakeTranslation({400, 100, 0}) *
306 Matrix::MakeRotationZ(Degrees(90.0)));
307 std::optional<Entity> result =
308 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
309 EXPECT_TRUE(result.has_value());
310 if (result.has_value()) {
311 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
312 std::optional<Rect> result_coverage = result.value().GetCoverage();
313 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
314 EXPECT_TRUE(result_coverage.has_value());
315 EXPECT_TRUE(contents_coverage.has_value());
316 if (result_coverage.has_value() && contents_coverage.has_value()) {
317 EXPECT_TRUE(RectNear(contents_coverage.value(),
318 Rect::MakeLTRB(99, 99, 401, 501)));
319 EXPECT_TRUE(
320 RectNear(result_coverage.value(), Rect::MakeLTRB(99, 99, 401, 501)));
321 }
322 }
323 }

References impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSourceOver, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeRotationZ(), impeller::Matrix::MakeTranslation(), RectNear(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [387/456]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageTranslate |
| ) |  |

Definition at line 259 of file gaussian_blur_filter_contents_unittests.cc.

260 {
261 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
262 fml::StatusOr<Scalar> sigma_radius_1 =
263 CalculateSigmaForBlurRadius(1.0, Matrix());
264 ASSERT_TRUE(sigma_radius_1.ok());
265 auto contents = std::make_unique<GaussianBlurFilterContents>(
266 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
267 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
268 contents->SetInputs({FilterInput::Make(texture)});
269 std::shared_ptr<ContentContext> renderer = GetContentContext();
270
271 Entity entity;
272 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
273 std::optional<Entity> result =
274 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
275
276 EXPECT_TRUE(result.has_value());
277 if (result.has_value()) {
278 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
279 std::optional<Rect> result_coverage = result.value().GetCoverage();
280 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
281 EXPECT_TRUE(result_coverage.has_value());
282 EXPECT_TRUE(contents_coverage.has_value());
283 if (result_coverage.has_value() && contents_coverage.has_value()) {
284 EXPECT_TRUE(RectNear(contents_coverage.value(),
285 Rect::MakeLTRB(99, 199, 201, 301)));
286 EXPECT_TRUE(
287 RectNear(result_coverage.value(), Rect::MakeLTRB(99, 199, 201, 301)));
288 }
289 }
290 }

References impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSourceOver, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::Matrix::MakeTranslation(), RectNear(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [388/456]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | TextureContentsWithDestinationRect |
| ) |  |

Definition at line 338 of file gaussian_blur_filter_contents_unittests.cc.

338 {
339 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
340 auto texture_contents = std::make_shared<TextureContents>();
341 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
342 texture_contents->SetTexture(texture);
343 texture_contents->SetDestinationRect(Rect::MakeXYWH(
344 50, 40, texture->GetSize().width, texture->GetSize().height));
345
346 fml::StatusOr<Scalar> sigma_radius_1 =
347 CalculateSigmaForBlurRadius(1.0, Matrix());
348 auto contents = std::make_unique<GaussianBlurFilterContents>(
349 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
350 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
351 contents->SetInputs({FilterInput::Make(texture_contents)});
352 std::shared_ptr<ContentContext> renderer = GetContentContext();
353
354 Entity entity;
355 std::optional<Entity> result =
356 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
357 EXPECT_TRUE(result.has_value());
358 if (result.has_value()) {
359 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
360 std::optional<Rect> result_coverage = result.value().GetCoverage();
361 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
362 EXPECT_TRUE(result_coverage.has_value());
363 EXPECT_TRUE(contents_coverage.has_value());
364 if (result_coverage.has_value() && contents_coverage.has_value()) {
365 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
366 EXPECT_TRUE(RectNear(result_coverage.value(),
367 Rect::MakeLTRB(49.f, 39.f, 151.f, 141.f)));
368 }
369 }
370 }

References impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSourceOver, impeller::FilterInput::Make(), impeller::TRect< Scalar >::MakeLTRB(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), and RectNear().

## ◆ TEST_P() [389/456]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | TextureContentsWithDestinationRectScaled |
| ) |  |

Definition at line 372 of file gaussian_blur_filter_contents_unittests.cc.

373 {
374 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
375 auto texture_contents = std::make_shared<TextureContents>();
376 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
377 texture_contents->SetTexture(texture);
378 texture_contents->SetDestinationRect(Rect::MakeXYWH(
379 50, 40, texture->GetSize().width, texture->GetSize().height));
380
381 fml::StatusOr<Scalar> sigma_radius_1 =
382 CalculateSigmaForBlurRadius(1.0, Matrix());
383 auto contents = std::make_unique<GaussianBlurFilterContents>(
384 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
385 FilterContents::BlurStyle::kNormal,
386 /*mask_geometry=*/nullptr);
387 contents->SetInputs({FilterInput::Make(texture_contents)});
388 std::shared_ptr<ContentContext> renderer = GetContentContext();
389
390 Entity entity;
391 entity.SetTransform(Matrix::MakeScale({2.0, 2.0, 1.0}));
392 std::optional<Entity> result =
393 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
394 EXPECT_TRUE(result.has_value());
395 if (result.has_value()) {
396 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
397 std::optional<Rect> result_coverage = result.value().GetCoverage();
398 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
399 EXPECT_TRUE(result_coverage.has_value());
400 EXPECT_TRUE(contents_coverage.has_value());
401 if (result_coverage.has_value() && contents_coverage.has_value()) {
402 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
403 // Scaling a blurred entity doesn't seem to scale the blur radius linearly
404 // when comparing results with rrect_blur. That's why this is not
405 // Rect::MakeXYWH(98.f, 78.f, 204.0f, 204.f).
406 EXPECT_TRUE(RectNear(contents_coverage.value(),
407 Rect::MakeXYWH(94.f, 74.f, 212.0f, 212.f)));
408 }
409 }
410 }

References impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSourceOver, impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), RectNear(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [390/456]

impeller::testing::TEST_P | ( | GaussianBlurFilterContentsTest | ,
|  | TextureContentsWithEffectTransform |
| ) |  |

Definition at line 412 of file gaussian_blur_filter_contents_unittests.cc.

412 {
413 Matrix effect_transform = Matrix::MakeScale({2.0, 2.0, 1.0});
414 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
415 auto texture_contents = std::make_shared<TextureContents>();
416 texture_contents->SetSourceRect(Rect::MakeSize(texture->GetSize()));
417 texture_contents->SetTexture(texture);
418 texture_contents->SetDestinationRect(Rect::MakeXYWH(
419 50, 40, texture->GetSize().width, texture->GetSize().height));
420
421 fml::StatusOr<Scalar> sigma_radius_1 =
422 CalculateSigmaForBlurRadius(1.0, effect_transform);
423 ASSERT_TRUE(sigma_radius_1.ok());
424 auto contents = std::make_unique<GaussianBlurFilterContents>(
425 sigma_radius_1.value(), sigma_radius_1.value(), Entity::TileMode::kDecal,
426 FilterContents::BlurStyle::kNormal, /*mask_geometry=*/nullptr);
427 contents->SetInputs({FilterInput::Make(texture_contents)});
428 contents->SetEffectTransform(effect_transform);
429 std::shared_ptr<ContentContext> renderer = GetContentContext();
430
431 Entity entity;
432 std::optional<Entity> result =
433 contents->GetEntity(*renderer, entity, /*coverage_hint=*/{});
434 EXPECT_TRUE(result.has_value());
435 if (result.has_value()) {
436 EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
437 std::optional<Rect> result_coverage = result.value().GetCoverage();
438 std::optional<Rect> contents_coverage = contents->GetCoverage(entity);
439 EXPECT_TRUE(result_coverage.has_value());
440 EXPECT_TRUE(contents_coverage.has_value());
441 if (result_coverage.has_value() && contents_coverage.has_value()) {
442 EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
443 EXPECT_TRUE(RectNear(contents_coverage.value(),
444 Rect::MakeXYWH(49.f, 39.f, 102.f, 102.f)));
445 }
446 }
447 }

References impeller::Entity::kDecal, impeller::FilterContents::kNormal, impeller::kSourceOver, impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::TRect< Scalar >::MakeSize(), impeller::TRect< Scalar >::MakeXYWH(), and RectNear().

## ◆ TEST_P() [391/456]

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

Definition at line 15 of file host_buffer_unittests.cc.

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

References impeller::HostBuffer::Create().

## ◆ TEST_P() [392/456]

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

Definition at line 30 of file host_buffer_unittests.cc.

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

References impeller::HostBuffer::Create().

## ◆ TEST_P() [393/456]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplaceWithProcIsAligned |
| ) |  |

Definition at line 149 of file host_buffer_unittests.cc.

149 {
150 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
151
152 BufferView view = buffer->Emplace(std::array<char, 21>());
153 EXPECT_EQ(view.range, Range(0, 21));
154
155 view = buffer->Emplace(64, 16, [](uint8_t*) {});
156 EXPECT_EQ(view.range, Range(32, 64));
157 }

References impeller::HostBuffer::Create(), and impeller::BufferView::range.

## ◆ TEST_P() [394/456]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplacingLargerThanBlockSizeCreatesOneOffBuffer |
| ) |  |

Definition at line 106 of file host_buffer_unittests.cc.

106 {
107 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
108
109 // Emplace an amount larger than the block size, to verify that the host
110 // buffer does not create a buffer.
111 auto buffer_view = buffer->Emplace(nullptr, 1024000 + 10, 0);
112
113 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
114 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
115 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
116 }

References buffer_view, and impeller::HostBuffer::Create().

## ◆ TEST_P() [395/456]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | EmplacingLargerThanBlockSizeCreatesOneOffBufferCallback |
| ) |  |

Definition at line 93 of file host_buffer_unittests.cc.

94 {
95 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
96
97 // Emplace an amount larger than the block size, to verify that the host
98 // buffer does not create a buffer.
99 auto buffer_view = buffer->Emplace(1024000 + 10, 0, [](uint8_t* data) {});
100
101 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
102 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
103 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
104 }

References buffer_view, impeller::HostBuffer::Create(), and data.

## ◆ TEST_P() [396/456]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | HostBufferInitialState |
| ) |  |

Definition at line 70 of file host_buffer_unittests.cc.

70 {
71 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
72
73 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
74 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
75 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
76 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [397/456]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | ResetIncrementsFrameCounter |
| ) |  |

Definition at line 78 of file host_buffer_unittests.cc.

78 {
79 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
80
81 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
82
83 buffer->Reset();
84 EXPECT_EQ(buffer->GetStateForTest().current_frame, 1u);
85
86 buffer->Reset();
87 EXPECT_EQ(buffer->GetStateForTest().current_frame, 2u);
88
89 buffer->Reset();
90 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
91 }

References impeller::HostBuffer::Create().

## ◆ TEST_P() [398/456]

impeller::testing::TEST_P | ( | HostBufferTest | ,
|  | UnusedBuffersAreDiscardedWhenResetting |
| ) |  |

Definition at line 118 of file host_buffer_unittests.cc.

118 {
119 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
120
121 // Emplace two large allocations to force the allocation of a second buffer.
122 auto buffer_view_a = buffer->Emplace(1020000, 0, [](uint8_t* data) {});
123 auto buffer_view_b = buffer->Emplace(1020000, 0, [](uint8_t* data) {});
124
125 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 1u);
126 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 2u);
127 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
128
129 // Reset until we get back to this frame.
130 for (auto i = 0; i < 3; i++) {
131 buffer->Reset();
132 }
133
134 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
135 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 2u);
136 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
137
138 // Now when we reset, the buffer should get dropped.
139 // Reset until we get back to this frame.
140 for (auto i = 0; i < 3; i++) {
141 buffer->Reset();
142 }
143
144 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
145 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
146 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
147 }

References impeller::HostBuffer::Create(), and data.

## ◆ TEST_P() [399/456]

impeller::testing::TEST_P | ( | MatrixFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageClippedSubpassScale |
| ) |  |

Definition at line 180 of file matrix_filter_contents_unittests.cc.

181 {
182 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
183 MatrixFilterContents contents;
184 contents.SetInputs({FilterInput::Make(texture)});
185 contents.SetMatrix(Matrix::MakeScale({3, 3, 1}));
186 contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
187 contents.SetRenderingMode(
188 Entity::RenderingMode::kSubpassAppendSnapshotTransform);
189
190 Entity entity;
191 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
192
193 std::shared_ptr<ContentContext> renderer = GetContentContext();
194 std::optional<Entity> result =
195 contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
196 expectRenderCoverageEqual(result, contents.GetCoverage(entity),
197 Rect::MakeXYWH(100, 200, 300, 300));
198 }

References impeller::FilterContents::GetCoverage(), impeller::FilterContents::GetEntity(), impeller::Entity::kSubpassAppendSnapshotTransform, impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::FilterContents::SetEffectTransform(), impeller::FilterContents::SetInputs(), impeller::MatrixFilterContents::SetMatrix(), impeller::MatrixFilterContents::SetRenderingMode(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [400/456]

impeller::testing::TEST_P | ( | MatrixFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageClippedSubpassTranslate |
| ) |  |

Definition at line 143 of file matrix_filter_contents_unittests.cc.

144 {
145 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
146 MatrixFilterContents contents;
147 contents.SetInputs({FilterInput::Make(texture)});
148 contents.SetMatrix(Matrix::MakeTranslation({50, 100, 0}));
149 contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
150 contents.SetRenderingMode(
151 Entity::RenderingMode::kSubpassAppendSnapshotTransform);
152
153 Entity entity;
154 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
155
156 std::shared_ptr<ContentContext> renderer = GetContentContext();
157 std::optional<Entity> result =
158 contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
159 expectRenderCoverageEqual(result, contents.GetCoverage(entity),
160 Rect::MakeXYWH(200, 400, 100, 100));
161 }

References impeller::FilterContents::GetCoverage(), impeller::FilterContents::GetEntity(), impeller::Entity::kSubpassAppendSnapshotTransform, impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::FilterContents::SetEffectTransform(), impeller::FilterContents::SetInputs(), impeller::MatrixFilterContents::SetMatrix(), impeller::MatrixFilterContents::SetRenderingMode(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [401/456]

impeller::testing::TEST_P | ( | MatrixFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageIdentity |
| ) |  |

Definition at line 111 of file matrix_filter_contents_unittests.cc.

111 {
112 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
113 MatrixFilterContents contents;
114 contents.SetInputs({FilterInput::Make(texture)});
115
116 Entity entity;
117 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
118
119 std::shared_ptr<ContentContext> renderer = GetContentContext();
120 std::optional<Entity> result =
121 contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
122 expectRenderCoverageEqual(result, contents.GetCoverage(entity),
123 Rect::MakeXYWH(100, 200, 100, 100));
124 }

References impeller::FilterContents::GetCoverage(), impeller::FilterContents::GetEntity(), impeller::FilterInput::Make(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::FilterContents::SetInputs(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [402/456]

impeller::testing::TEST_P | ( | MatrixFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageScale |
| ) |  |

Definition at line 163 of file matrix_filter_contents_unittests.cc.

163 {
164 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
165 MatrixFilterContents contents;
166 contents.SetInputs({FilterInput::Make(texture)});
167 contents.SetMatrix(Matrix::MakeScale({3, 3, 1}));
168 contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
169
170 Entity entity;
171 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
172
173 std::shared_ptr<ContentContext> renderer = GetContentContext();
174 std::optional<Entity> result =
175 contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
176 expectRenderCoverageEqual(result, contents.GetCoverage(entity),
177 Rect::MakeXYWH(100, 200, 300, 300));
178 }

References impeller::FilterContents::GetCoverage(), impeller::FilterContents::GetEntity(), impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::FilterContents::SetEffectTransform(), impeller::FilterContents::SetInputs(), impeller::MatrixFilterContents::SetMatrix(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [403/456]

impeller::testing::TEST_P | ( | MatrixFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageSubpassScale |
| ) |  |

Definition at line 200 of file matrix_filter_contents_unittests.cc.

200 {
201 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
202 MatrixFilterContents contents;
203 contents.SetInputs({FilterInput::Make(texture)});
204 contents.SetMatrix(Matrix::MakeScale({3, 3, 1}));
205 contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
206 contents.SetRenderingMode(
207 Entity::RenderingMode::kSubpassPrependSnapshotTransform);
208
209 Entity entity;
210 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
211
212 std::shared_ptr<ContentContext> renderer = GetContentContext();
213 std::optional<Entity> result =
214 contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
215 expectRenderCoverageEqual(result, contents.GetCoverage(entity),
216 Rect::MakeXYWH(300, 600, 300, 300));
217 }

References impeller::FilterContents::GetCoverage(), impeller::FilterContents::GetEntity(), impeller::Entity::kSubpassPrependSnapshotTransform, impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::FilterContents::SetEffectTransform(), impeller::FilterContents::SetInputs(), impeller::MatrixFilterContents::SetMatrix(), impeller::MatrixFilterContents::SetRenderingMode(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [404/456]

impeller::testing::TEST_P | ( | MatrixFilterContentsTest | ,
|  | RenderCoverageMatchesGetCoverageTranslate |
| ) |  |

Definition at line 126 of file matrix_filter_contents_unittests.cc.

126 {
127 std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
128 MatrixFilterContents contents;
129 contents.SetInputs({FilterInput::Make(texture)});
130 contents.SetMatrix(Matrix::MakeTranslation({50, 100, 0}));
131 contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
132
133 Entity entity;
134 entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
135
136 std::shared_ptr<ContentContext> renderer = GetContentContext();
137 std::optional<Entity> result =
138 contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
139 expectRenderCoverageEqual(result, contents.GetCoverage(entity),
140 Rect::MakeXYWH(150, 300, 100, 100));
141 }

References impeller::FilterContents::GetCoverage(), impeller::FilterContents::GetEntity(), impeller::FilterInput::Make(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), impeller::TRect< Scalar >::MakeXYWH(), impeller::FilterContents::SetEffectTransform(), impeller::FilterContents::SetInputs(), impeller::MatrixFilterContents::SetMatrix(), and impeller::Entity::SetTransform().

## ◆ TEST_P() [405/456]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanCreateRenderPassAndSubmit |
| ) |  |

Definition at line 302 of file renderer_dart_unittests.cc.

302 {
303 ASSERT_TRUE(RenderDartToPlayground("canCreateRenderPassAndSubmit"));
304 }

## ◆ TEST_P() [406/456]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanCreateShaderLibrary |
| ) |  |

Definition at line 290 of file renderer_dart_unittests.cc.

290 {
291 ASSERT_TRUE(RunDartFunction("canCreateShaderLibrary"));
292 }

## ◆ TEST_P() [407/456]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanInstantiateFlutterGPUContext |
| ) |  |

These test entries correspond to Dart functions located in `flutter/impeller/fixtures/dart_tests.dart`

Definition at line 286 of file renderer_dart_unittests.cc.

286 {
287 ASSERT_TRUE(RunDartFunction("instantiateDefaultContext"));
288 }

## ◆ TEST_P() [408/456]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanReflectUniformStructs |
| ) |  |

Definition at line 294 of file renderer_dart_unittests.cc.

294 {
295 ASSERT_TRUE(RunDartFunction("canReflectUniformStructs"));
296 }

## ◆ TEST_P() [409/456]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | CanRunDartInPlaygroundFrame |
| ) |  |

Definition at line 271 of file renderer_dart_unittests.cc.

271 {
272 SinglePassCallback callback = [&](RenderPass& pass) {
273 ImGui::Begin("Dart test", nullptr);
274 ImGui::Text(
275 "This test executes Dart code during the playground frame callback.");
276 ImGui::End();
277
278 return RunDartFunction("sayHi");
279 };
280 ASSERT_TRUE(OpenPlaygroundHere(callback));
281 }

## ◆ TEST_P() [410/456]

impeller::testing::TEST_P | ( | RendererDartTest | ,
|  | UniformBindFailsForInvalidHostBufferOffset |
| ) |  |

Definition at line 298 of file renderer_dart_unittests.cc.

298 {
299 ASSERT_TRUE(RunDartFunction("uniformBindFailsForInvalidHostBufferOffset"));
300 }

## ◆ TEST_P() [411/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | ArrayUniforms |
| ) |  |

Definition at line 997 of file renderer_unittests.cc.

997 {
998 using VS = ArrayVertexShader;
999 using FS = ArrayFragmentShader;
1000
1001 auto context = GetContext();
1002 auto pipeline_descriptor =
1003 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
1004 ASSERT_TRUE(pipeline_descriptor.has_value());
1005 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
1006 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1007 auto pipeline =
1008 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1009 ASSERT_TRUE(pipeline && pipeline->IsValid());
1010
1011 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
1012 SinglePassCallback callback = [&](RenderPass& pass) {
1013 auto size = pass.GetRenderTargetSize();
1014
1015 pass.SetPipeline(pipeline);
1016 pass.SetCommandLabel("Google Dots");
1017 VertexBufferBuilder<VS::PerVertexData> builder;
1018 builder.AddVertices({{Point()},
1019 {Point(0, size.height)},
1020 {Point(size.width, 0)},
1021 {Point(size.width, 0)},
1022 {Point(0, size.height)},
1023 {Point(size.width, size.height)}});
1024 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
1025
1026 VS::FrameInfo frame_info;
1027 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
1028 frame_info.mvp =
1029 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
1030 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
1031
1032 auto time = GetSecondsElapsed();
1033 auto y_pos = [&time](float x) {
1034 return 400 + 10 * std::cos(time * 5 + x / 6);
1035 };
1036
1037 FS::FragInfo fs_uniform = {
1038 .circle_positions = {Point(430, y_pos(0)), Point(480, y_pos(1)),
1039 Point(530, y_pos(2)), Point(580, y_pos(3))},
1040 .colors = {Color::MakeRGBA8(66, 133, 244, 255),
1041 Color::MakeRGBA8(219, 68, 55, 255),
1042 Color::MakeRGBA8(244, 180, 0, 255),
1043 Color::MakeRGBA8(15, 157, 88, 255)},
1044 };
1045 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1046
1047 pass.Draw();
1048 host_buffer->Reset();
1049 return true;
1050 };
1051 OpenPlaygroundHere(callback);
1052 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::kCount4, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Color::MakeRGBA8(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [412/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | BabysFirstTriangle |
| ) |  |

Definition at line 123 of file renderer_unittests.cc.

123 {
124 auto context = GetContext();
125 ASSERT_TRUE(context);
126
127 // Declare a shorthand for the shaders we are going to use.
128 using VS = BabyVertexShader;
129 using FS = BabyFragmentShader;
130
131 // Create a pipeline descriptor that uses the shaders together and default
132 // initializes the fixed function state.
133 //
134 // If the vertex shader outputs disagree with the fragment shader inputs, this
135 // will be a compile time error.
136 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
137 ASSERT_TRUE(desc.has_value());
138
139 // Modify the descriptor for our environment. This is specific to our test.
140 desc->SetSampleCount(SampleCount::kCount4);
141 desc->SetStencilAttachmentDescriptors(std::nullopt);
142
143 // Create a pipeline from our descriptor. This is expensive to do. So just do
144 // it once.
145 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
146
147 // Create a host side buffer to build the vertex and uniform information.
148 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
149
150 // Specify the vertex buffer information.
151 VertexBufferBuilder<VS::PerVertexData> vertex_buffer_builder;
152 vertex_buffer_builder.AddVertices({
153 {{-0.5, -0.5}, Color::Red(), Color::Green()},
154 {{0.0, 0.5}, Color::Green(), Color::Blue()},
155 {{0.5, -0.5}, Color::Blue(), Color::Red()},
156 });
157
158 auto vertex_buffer = vertex_buffer_builder.CreateVertexBuffer(
159 *context->GetResourceAllocator());
160
161 SinglePassCallback callback = [&](RenderPass& pass) {
162 pass.SetPipeline(pipeline);
163 pass.SetVertexBuffer(vertex_buffer);
164
165 FS::FragInfo frag_info;
166 frag_info.time = fml::TimePoint::Now().ToEpochDelta().ToSecondsF();
167
168 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
169 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(frag_info));
170
171 return pass.Draw().ok();
172 };
173 OpenPlaygroundHere(callback);
174 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::Color::Blue(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::Color::Green(), impeller::kCount4, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), and impeller::Color::Red().

## ◆ TEST_P() [413/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CachesRenderPassAndFramebuffer |
| ) |  |

Definition at line 16 of file render_pass_cache_unittests.cc.

16 {
17 if (GetBackend() != PlaygroundBackend::kVulkan) {
18 GTEST_SKIP() << "Test only applies to Vulkan";
19 }
20
21 auto allocator = std::make_shared<RenderTargetAllocator>(
22 GetContext()->GetResourceAllocator());
23
24 auto render_target =
25 allocator->CreateOffscreenMSAA(*GetContext(), {100, 100}, 1);
26 auto resolve_texture =
27 render_target.GetColorAttachments().find(0u)->second.resolve_texture;
28 auto& texture_vk = TextureVK::Cast(*resolve_texture);
29
30 EXPECT_EQ(texture_vk.GetCachedFramebuffer(), nullptr);
31 EXPECT_EQ(texture_vk.GetCachedRenderPass(), nullptr);
32
33 auto buffer = GetContext()->CreateCommandBuffer();
34 auto render_pass = buffer->CreateRenderPass(render_target);
35
36 EXPECT_NE(texture_vk.GetCachedFramebuffer(), nullptr);
37 EXPECT_NE(texture_vk.GetCachedRenderPass(), nullptr);
38
39 render_pass->EncodeCommands();
40 GetContext()->GetCommandQueue()->Submit({buffer});
41
42 // Can be reused without error.
43 auto buffer_2 = GetContext()->CreateCommandBuffer();
44 auto render_pass_2 = buffer_2->CreateRenderPass(render_target);
45
46 EXPECT_TRUE(render_pass_2->EncodeCommands());
47 EXPECT_TRUE(GetContext()->GetCommandQueue()->Submit({buffer_2}).ok());
48 }

References impeller::BackendCast< TextureVK, Texture >::Cast(), and impeller::kVulkan.

## ◆ TEST_P() [414/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanBlitTextureToBuffer |
| ) |  |

Definition at line 613 of file renderer_unittests.cc.

613 {
614 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
615 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
616 }
617 auto context = GetContext();
618 ASSERT_TRUE(context);
619
620 using VS = MipmapsVertexShader;
621 using FS = MipmapsFragmentShader;
622 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
623 ASSERT_TRUE(desc.has_value());
624 desc->SetSampleCount(SampleCount::kCount4);
625 desc->SetStencilAttachmentDescriptors(std::nullopt);
626 auto mipmaps_pipeline =
627 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
628 ASSERT_TRUE(mipmaps_pipeline);
629
630 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
631 auto boston = CreateTextureForFixture("boston.jpg");
632 ASSERT_TRUE(bridge && boston);
633 const std::unique_ptr<const Sampler>& sampler =
634 context->GetSamplerLibrary()->GetSampler({});
635 ASSERT_TRUE(sampler);
636
637 TextureDescriptor texture_desc;
638 texture_desc.storage_mode = StorageMode::kHostVisible;
639 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
640 texture_desc.size = bridge->GetTextureDescriptor().size;
641 texture_desc.mip_count = 1u;
642 texture_desc.usage = TextureUsage::kRenderTarget |
643 TextureUsage::kShaderWrite | TextureUsage::kShaderRead;
644 DeviceBufferDescriptor device_buffer_desc;
645 device_buffer_desc.storage_mode = StorageMode::kHostVisible;
646 device_buffer_desc.size =
647 bridge->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
648 auto device_buffer =
649 context->GetResourceAllocator()->CreateBuffer(device_buffer_desc);
650
651 // Vertex buffer.
652 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
653 vertex_builder.SetLabel("Box");
654 auto size = Point(boston->GetSize());
655 vertex_builder.AddVertices({
656 {{0, 0}, {0.0, 0.0}}, // 1
657 {{size.x, 0}, {1.0, 0.0}}, // 2
658 {{size.x, size.y}, {1.0, 1.0}}, // 3
659 {{0, 0}, {0.0, 0.0}}, // 1
660 {{size.x, size.y}, {1.0, 1.0}}, // 3
661 {{0, size.y}, {0.0, 1.0}}, // 4
662 });
663 auto vertex_buffer =
664 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
665 ASSERT_TRUE(vertex_buffer);
666
667 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
668 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
669 {
670 auto buffer = context->CreateCommandBuffer();
671 if (!buffer) {
672 return false;
673 }
674 buffer->SetLabel("Playground Command Buffer");
675 auto pass = buffer->CreateBlitPass();
676 if (!pass) {
677 return false;
678 }
679 pass->SetLabel("Playground Blit Pass");
680
681 if (render_target.GetColorAttachments().empty()) {
682 return false;
683 }
684
685 // Blit `bridge` to the top left corner of the texture.
686 pass->AddCopy(bridge, device_buffer);
687 pass->EncodeCommands(context->GetResourceAllocator());
688
689 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
690 return false;
691 }
692 }
693
694 {
695 auto buffer = context->CreateCommandBuffer();
696 if (!buffer) {
697 return false;
698 }
699 buffer->SetLabel("Playground Command Buffer");
700
701 auto pass = buffer->CreateRenderPass(render_target);
702 if (!pass) {
703 return false;
704 }
705 pass->SetLabel("Playground Render Pass");
706 {
707 pass->SetCommandLabel("Image");
708 pass->SetPipeline(mipmaps_pipeline);
709 pass->SetVertexBuffer(vertex_buffer);
710
711 VS::FrameInfo frame_info;
712 EXPECT_EQ(pass->GetOrthographicTransform(),
713 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
714 frame_info.mvp = pass->GetOrthographicTransform() *
715 Matrix::MakeScale(GetContentScale());
716 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
717
718 FS::FragInfo frag_info;
719 frag_info.lod = 0;
720 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
721
722 const std::unique_ptr<const Sampler>& sampler =
723 context->GetSamplerLibrary()->GetSampler({});
724 auto buffer_view = DeviceBuffer::AsBufferView(device_buffer);
725 auto texture =
726 context->GetResourceAllocator()->CreateTexture(texture_desc);
727 if (!texture->SetContents(device_buffer->OnGetContents(),
728 buffer_view.range.length)) {
729 VALIDATION_LOG << "Could not upload texture to device memory";
730 return false;
731 }
732 FS::BindTex(*pass, texture, sampler);
733
734 pass->Draw().ok();
735 }
736 pass->EncodeCommands();
737 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
738 return false;
739 }
740 }
741 host_buffer->Reset();
742 return true;
743 };
744 OpenPlaygroundHere(callback);
745 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::DeviceBuffer::AsBufferView(), buffer_view, impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::TextureDescriptor::format, impeller::kCount4, impeller::kHostVisible, impeller::kOpenGLES, impeller::kR8G8B8A8UNormInt, impeller::kRenderTarget, impeller::kShaderRead, impeller::kShaderWrite, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::TextureDescriptor::mip_count, 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() [415/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanBlitTextureToTexture |
| ) |  |

Definition at line 498 of file renderer_unittests.cc.

498 {
499 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
500 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
501 }
502 auto context = GetContext();
503 ASSERT_TRUE(context);
504
505 using VS = MipmapsVertexShader;
506 using FS = MipmapsFragmentShader;
507 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
508 ASSERT_TRUE(desc.has_value());
509 desc->SetSampleCount(SampleCount::kCount4);
510 desc->SetStencilAttachmentDescriptors(std::nullopt);
511 auto mipmaps_pipeline =
512 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
513 ASSERT_TRUE(mipmaps_pipeline);
514
515 TextureDescriptor texture_desc;
516 texture_desc.storage_mode = StorageMode::kHostVisible;
517 texture_desc.format = PixelFormat::kR8G8B8A8UNormInt;
518 texture_desc.size = {800, 600};
519 texture_desc.mip_count = 1u;
520 texture_desc.usage = TextureUsage::kRenderTarget | TextureUsage::kShaderRead;
521 auto texture = context->GetResourceAllocator()->CreateTexture(texture_desc);
522 ASSERT_TRUE(texture);
523
524 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
525 auto boston = CreateTextureForFixture("boston.jpg");
526 ASSERT_TRUE(bridge && boston);
527 const std::unique_ptr<const Sampler>& sampler =
528 context->GetSamplerLibrary()->GetSampler({});
529 ASSERT_TRUE(sampler);
530
531 // Vertex buffer.
532 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
533 vertex_builder.SetLabel("Box");
534 auto size = Point(boston->GetSize());
535 vertex_builder.AddVertices({
536 {{0, 0}, {0.0, 0.0}}, // 1
537 {{size.x, 0}, {1.0, 0.0}}, // 2
538 {{size.x, size.y}, {1.0, 1.0}}, // 3
539 {{0, 0}, {0.0, 0.0}}, // 1
540 {{size.x, size.y}, {1.0, 1.0}}, // 3
541 {{0, size.y}, {0.0, 1.0}}, // 4
542 });
543 auto vertex_buffer =
544 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
545 ASSERT_TRUE(vertex_buffer);
546
547 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
548 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
549 auto buffer = context->CreateCommandBuffer();
550 if (!buffer) {
551 return false;
552 }
553 buffer->SetLabel("Playground Command Buffer");
554
555 {
556 auto pass = buffer->CreateBlitPass();
557 if (!pass) {
558 return false;
559 }
560 pass->SetLabel("Playground Blit Pass");
561
562 if (render_target.GetColorAttachments().empty()) {
563 return false;
564 }
565
566 // Blit `bridge` to the top left corner of the texture.
567 pass->AddCopy(bridge, texture);
568
569 if (!pass->EncodeCommands(context->GetResourceAllocator())) {
570 return false;
571 }
572 }
573
574 {
575 auto pass = buffer->CreateRenderPass(render_target);
576 if (!pass) {
577 return false;
578 }
579 pass->SetLabel("Playground Render Pass");
580 {
581 pass->SetCommandLabel("Image");
582 pass->SetPipeline(mipmaps_pipeline);
583 pass->SetVertexBuffer(vertex_buffer);
584
585 VS::FrameInfo frame_info;
586 EXPECT_EQ(pass->GetOrthographicTransform(),
587 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
588 frame_info.mvp = pass->GetOrthographicTransform() *
589 Matrix::MakeScale(GetContentScale());
590 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
591
592 FS::FragInfo frag_info;
593 frag_info.lod = 0;
594 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
595
596 auto& sampler = context->GetSamplerLibrary()->GetSampler({});
597 FS::BindTex(*pass, texture, sampler);
598
599 pass->Draw();
600 }
601 pass->EncodeCommands();
602 }
603
604 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
605 return false;
606 }
607 host_buffer->Reset();
608 return true;
609 };
610 OpenPlaygroundHere(callback);
611 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::TextureDescriptor::format, impeller::kCount4, impeller::kHostVisible, impeller::kOpenGLES, impeller::kR8G8B8A8UNormInt, impeller::kRenderTarget, impeller::kShaderRead, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::TextureDescriptor::mip_count, impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, and impeller::TextureDescriptor::usage.

## ◆ TEST_P() [416/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanCreateBoxPrimitive |
| ) |  |

Definition at line 54 of file renderer_unittests.cc.

54 {
55 using VS = BoxFadeVertexShader;
56 using FS = BoxFadeFragmentShader;
57 auto context = GetContext();
58 ASSERT_TRUE(context);
59 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
60 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
61 ASSERT_TRUE(desc.has_value());
62 desc->SetSampleCount(SampleCount::kCount4);
63 desc->SetStencilAttachmentDescriptors(std::nullopt);
64
65 // Vertex buffer.
66 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
67 vertex_builder.SetLabel("Box");
68 vertex_builder.AddVertices({
69 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
70 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
71 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
72 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
73 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
74 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
75 });
76 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
77 auto boston = CreateTextureForFixture("boston.jpg");
78 ASSERT_TRUE(bridge && boston);
79 const std::unique_ptr<const Sampler>& sampler =
80 context->GetSamplerLibrary()->GetSampler({});
81 ASSERT_TRUE(sampler);
82
83 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
84 SinglePassCallback callback = [&](RenderPass& pass) {
85 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
86 static bool wireframe;
87 ImGui::Checkbox("Wireframe", &wireframe);
88 ImGui::End();
89
90 desc->SetPolygonMode(wireframe ? PolygonMode::kLine : PolygonMode::kFill);
91 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
92
93 assert(pipeline && pipeline->IsValid());
94
95 pass.SetCommandLabel("Box");
96 pass.SetPipeline(pipeline);
97 pass.SetVertexBuffer(
98 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator()));
99
100 VS::UniformBuffer uniforms;
101 EXPECT_EQ(pass.GetOrthographicTransform(),
102 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
103 uniforms.mvp =
104 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
105 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
106
107 FS::FrameInfo frame_info;
108 frame_info.current_time = GetSecondsElapsed();
109 frame_info.cursor_position = GetCursorPosition();
110 frame_info.window_size.x = GetWindowSize().width;
111 frame_info.window_size.y = GetWindowSize().height;
112
113 FS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
114 FS::BindContents1(pass, boston, sampler);
115 FS::BindContents2(pass, bridge, sampler);
116
117 host_buffer->Reset();
118 return pass.Draw().ok();
119 };
120 OpenPlaygroundHere(callback);
121 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::kCount4, impeller::kFill, impeller::kLine, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), and impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel().

## ◆ TEST_P() [417/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanGenerateMipmaps |
| ) |  |

Definition at line 747 of file renderer_unittests.cc.

747 {
748 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
749 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
750 }
751 auto context = GetContext();
752 ASSERT_TRUE(context);
753
754 using VS = MipmapsVertexShader;
755 using FS = MipmapsFragmentShader;
756 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
757 ASSERT_TRUE(desc.has_value());
758 desc->SetSampleCount(SampleCount::kCount4);
759 desc->SetStencilAttachmentDescriptors(std::nullopt);
760 auto mipmaps_pipeline =
761 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
762 ASSERT_TRUE(mipmaps_pipeline);
763
764 auto boston = CreateTextureForFixture("boston.jpg", true);
765 ASSERT_TRUE(boston);
766
767 // Vertex buffer.
768 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
769 vertex_builder.SetLabel("Box");
770 auto size = Point(boston->GetSize());
771 vertex_builder.AddVertices({
772 {{0, 0}, {0.0, 0.0}}, // 1
773 {{size.x, 0}, {1.0, 0.0}}, // 2
774 {{size.x, size.y}, {1.0, 1.0}}, // 3
775 {{0, 0}, {0.0, 0.0}}, // 1
776 {{size.x, size.y}, {1.0, 1.0}}, // 3
777 {{0, size.y}, {0.0, 1.0}}, // 4
778 });
779 auto vertex_buffer =
780 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
781 ASSERT_TRUE(vertex_buffer);
782
783 bool first_frame = true;
784 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
785 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
786 const char* mip_filter_names[] = {"Base", "Nearest", "Linear"};
787 const MipFilter mip_filters[] = {MipFilter::kBase, MipFilter::kNearest,
788 MipFilter::kLinear};
789 const char* min_filter_names[] = {"Nearest", "Linear"};
790 const MinMagFilter min_filters[] = {MinMagFilter::kNearest,
791 MinMagFilter::kLinear};
792
793 // UI state.
794 static int selected_mip_filter = 1;
795 static int selected_min_filter = 0;
796 static float lod = 4.5;
797
798 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
799 ImGui::Combo("Mip filter", &selected_mip_filter, mip_filter_names,
800 sizeof(mip_filter_names) / sizeof(char*));
801 ImGui::Combo("Min filter", &selected_min_filter, min_filter_names,
802 sizeof(min_filter_names) / sizeof(char*));
803 ImGui::SliderFloat("LOD", &lod, 0, boston->GetMipCount() - 1);
804 ImGui::End();
805
806 auto buffer = context->CreateCommandBuffer();
807 if (!buffer) {
808 return false;
809 }
810 buffer->SetLabel("Playground Command Buffer");
811
812 if (first_frame) {
813 auto pass = buffer->CreateBlitPass();
814 if (!pass) {
815 return false;
816 }
817 pass->SetLabel("Playground Blit Pass");
818
819 pass->GenerateMipmap(boston, "Boston Mipmap");
820
821 pass->EncodeCommands(context->GetResourceAllocator());
822 }
823
824 first_frame = false;
825
826 {
827 auto pass = buffer->CreateRenderPass(render_target);
828 if (!pass) {
829 return false;
830 }
831 pass->SetLabel("Playground Render Pass");
832 {
833 pass->SetCommandLabel("Image LOD");
834 pass->SetPipeline(mipmaps_pipeline);
835 pass->SetVertexBuffer(vertex_buffer);
836
837 VS::FrameInfo frame_info;
838 EXPECT_EQ(pass->GetOrthographicTransform(),
839 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
840 frame_info.mvp = pass->GetOrthographicTransform() *
841 Matrix::MakeScale(GetContentScale());
842 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
843
844 FS::FragInfo frag_info;
845 frag_info.lod = lod;
846 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
847
848 SamplerDescriptor sampler_desc;
849 sampler_desc.mip_filter = mip_filters[selected_mip_filter];
850 sampler_desc.min_filter = min_filters[selected_min_filter];
851 const std::unique_ptr<const Sampler>& sampler =
852 context->GetSamplerLibrary()->GetSampler(sampler_desc);
853 FS::BindTex(*pass, boston, sampler);
854
855 pass->Draw();
856 }
857 pass->EncodeCommands();
858 }
859
860 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
861 return false;
862 }
863 host_buffer->Reset();
864 return true;
865 };
866 OpenPlaygroundHere(callback);
867 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::kBase, impeller::kCount4, impeller::kLinear, impeller::kNearest, impeller::kOpenGLES, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::SamplerDescriptor::min_filter, impeller::SamplerDescriptor::mip_filter, and impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel().

## ◆ TEST_P() [418/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanLookupRenderTargetProperties |
| ) |  |

Definition at line 1341 of file renderer_unittests.cc.

1341 {
1342 auto context = GetContext();
1343 auto cmd_buffer = context->CreateCommandBuffer();
1344 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1345 GetContext()->GetResourceAllocator());
1346
1347 auto render_target = render_target_cache->CreateOffscreen(
1348 *context, {100, 100}, /*mip_count=*/1);
1349 auto render_pass = cmd_buffer->CreateRenderPass(render_target);
1350
1351 EXPECT_EQ(render_pass->GetSampleCount(), render_target.GetSampleCount());
1352 EXPECT_EQ(render_pass->GetRenderTargetPixelFormat(),
1353 render_target.GetRenderTargetPixelFormat());
1354 EXPECT_EQ(render_pass->HasStencilAttachment(),
1355 render_target.GetStencilAttachment().has_value());
1356 EXPECT_EQ(render_pass->GetRenderTargetSize(),
1357 render_target.GetRenderTargetSize());
1358 render_pass->EncodeCommands();
1359 }

## ◆ TEST_P() [419/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderInstanced |
| ) |  |

Definition at line 441 of file renderer_unittests.cc.

441 {
442 if (GetParam() == PlaygroundBackend::kOpenGLES) {
443 GTEST_SKIP_("Instancing is not supported on OpenGL.");
444 }
445 using VS = InstancedDrawVertexShader;
446 using FS = InstancedDrawFragmentShader;
447
448 VertexBufferBuilder<VS::PerVertexData> builder;
449 builder.AddVertices({
450 VS::PerVertexData{Point{10, 10}},
451 VS::PerVertexData{Point{10, 110}},
452 VS::PerVertexData{Point{110, 10}},
453 VS::PerVertexData{Point{10, 110}},
454 VS::PerVertexData{Point{110, 10}},
455 VS::PerVertexData{Point{110, 110}},
456 });
457
458 ASSERT_NE(GetContext(), nullptr);
459 auto pipeline =
460 GetContext()
461 ->GetPipelineLibrary()
462 ->GetPipeline(PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(
463 *GetContext())
464 ->SetSampleCount(SampleCount::kCount4)
465 .SetStencilAttachmentDescriptors(std::nullopt))
466
467 .Get();
468 ASSERT_TRUE(pipeline && pipeline->IsValid());
469
470 static constexpr size_t kInstancesCount = 5u;
471 VS::InstanceInfo<kInstancesCount> instances;
472 for (size_t i = 0; i < kInstancesCount; i++) {
473 instances.colors[i] = Color::Random();
474 }
475
476 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
477 ASSERT_TRUE(OpenPlaygroundHere([&](RenderPass& pass) -> bool {
478 pass.SetPipeline(pipeline);
479 pass.SetCommandLabel("InstancedDraw");
480
481 VS::FrameInfo frame_info;
482 EXPECT_EQ(pass.GetOrthographicTransform(),
483 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
484 frame_info.mvp =
485 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
486 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
487 VS::BindInstanceInfo(pass, host_buffer->EmplaceStorageBuffer(instances));
488 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
489
490 pass.SetInstanceCount(kInstancesCount);
491 pass.Draw();
492
493 host_buffer->Reset();
494 return true;
495 }));
496 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::RenderPass::Draw(), impeller::RenderPass::GetOrthographicTransform(), impeller::RenderPass::GetRenderTargetSize(), impeller::kCount4, impeller::kOpenGLES, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::Color::Random(), impeller::RenderPass::SetCommandLabel(), impeller::RenderPass::SetInstanceCount(), impeller::RenderPass::SetPipeline(), and impeller::RenderPass::SetVertexBuffer().

## ◆ TEST_P() [420/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderMultiplePrimitives |
| ) |  |

Definition at line 265 of file renderer_unittests.cc.

265 {
266 using VS = BoxFadeVertexShader;
267 using FS = BoxFadeFragmentShader;
268 auto context = GetContext();
269 ASSERT_TRUE(context);
270 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
271 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
272 ASSERT_TRUE(desc.has_value());
273 desc->SetSampleCount(SampleCount::kCount4);
274 desc->SetStencilAttachmentDescriptors(std::nullopt);
275 auto box_pipeline =
276 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
277 ASSERT_TRUE(box_pipeline);
278
279 // Vertex buffer.
280 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
281 vertex_builder.SetLabel("Box");
282 vertex_builder.AddVertices({
283 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
284 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
285 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
286 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
287 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
288 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
289 });
290 auto vertex_buffer =
291 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
292 ASSERT_TRUE(vertex_buffer);
293
294 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
295 auto boston = CreateTextureForFixture("boston.jpg");
296 ASSERT_TRUE(bridge && boston);
297 const std::unique_ptr<const Sampler>& sampler =
298 context->GetSamplerLibrary()->GetSampler({});
299 ASSERT_TRUE(sampler);
300
301 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
302 SinglePassCallback callback = [&](RenderPass& pass) {
303 for (size_t i = 0; i < 1; i++) {
304 for (size_t j = 0; j < 1; j++) {
305 pass.SetCommandLabel("Box");
306 pass.SetPipeline(box_pipeline);
307 pass.SetVertexBuffer(vertex_buffer);
308
309 FS::FrameInfo frame_info;
310 frame_info.current_time = GetSecondsElapsed();
311 frame_info.cursor_position = GetCursorPosition();
312 frame_info.window_size.x = GetWindowSize().width;
313 frame_info.window_size.y = GetWindowSize().height;
314
315 FS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
316 FS::BindContents1(pass, boston, sampler);
317 FS::BindContents2(pass, bridge, sampler);
318
319 VS::UniformBuffer uniforms;
320 EXPECT_EQ(pass.GetOrthographicTransform(),
321 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
322 uniforms.mvp = pass.GetOrthographicTransform() *
323 Matrix::MakeScale(GetContentScale()) *
324 Matrix::MakeTranslation({i * 50.0f, j * 50.0f, 0.0f});
325 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
326 if (!pass.Draw().ok()) {
327 return false;
328 }
329 }
330 }
331
332 host_buffer->Reset();
333 return true;
334 };
335 OpenPlaygroundHere(callback);
336 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::kCount4, impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), impeller::Matrix::MakeTranslation(), and impeller::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel().

## ◆ TEST_P() [421/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderPerspectiveCube |
| ) |  |

Definition at line 176 of file renderer_unittests.cc.

176 {
177 using VS = ColorsVertexShader;
178 using FS = ColorsFragmentShader;
179 auto context = GetContext();
180 ASSERT_TRUE(context);
181 auto desc = PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
182 ASSERT_TRUE(desc.has_value());
183 desc->SetCullMode(CullMode::kBackFace);
184 desc->SetWindingOrder(WindingOrder::kCounterClockwise);
185 desc->SetSampleCount(SampleCount::kCount4);
186 desc->SetStencilAttachmentDescriptors(std::nullopt);
187 auto pipeline =
188 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
189 ASSERT_TRUE(pipeline);
190
191 struct Cube {
192 VS::PerVertexData vertices[8] = {
193 // -Z
194 {{-1, -1, -1}, Color::Red()},
195 {{1, -1, -1}, Color::Yellow()},
196 {{1, 1, -1}, Color::Green()},
197 {{-1, 1, -1}, Color::Blue()},
198 // +Z
199 {{-1, -1, 1}, Color::Green()},
200 {{1, -1, 1}, Color::Blue()},
201 {{1, 1, 1}, Color::Red()},
202 {{-1, 1, 1}, Color::Yellow()},
203 };
204 uint16_t indices[36] = {
205 1, 5, 2, 2, 5, 6, // +X
206 4, 0, 7, 7, 0, 3, // -X
207 4, 5, 0, 0, 5, 1, // +Y
208 3, 2, 7, 7, 2, 6, // -Y
209 5, 4, 6, 6, 4, 7, // +Z
210 0, 1, 3, 3, 1, 2, // -Z
211 };
212 } cube;
213
214 VertexBuffer vertex_buffer;
215 {
216 auto device_buffer = context->GetResourceAllocator()->CreateBufferWithCopy(
217 reinterpret_cast<uint8_t*>(&cube), sizeof(cube));
218 vertex_buffer.vertex_buffer = {
219 .buffer = device_buffer,
220 .range = Range(offsetof(Cube, vertices), sizeof(Cube::vertices))};
221 vertex_buffer.index_buffer = {
222 .buffer = device_buffer,
223 .range = Range(offsetof(Cube, indices), sizeof(Cube::indices))};
224 vertex_buffer.vertex_count = 36;
225 vertex_buffer.index_type = IndexType::k16bit;
226 }
227
228 const std::unique_ptr<const Sampler>& sampler =
229 context->GetSamplerLibrary()->GetSampler({});
230 ASSERT_TRUE(sampler);
231
232 Vector3 euler_angles;
233 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
234 SinglePassCallback callback = [&](RenderPass& pass) {
235 static Degrees fov_y(60);
236 static Scalar distance = 10;
237
238 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
239 ImGui::SliderFloat("Field of view", &fov_y.degrees, 0, 180);
240 ImGui::SliderFloat("Camera distance", &distance, 0, 30);
241 ImGui::End();
242
243 pass.SetCommandLabel("Perspective Cube");
244 pass.SetPipeline(pipeline);
245 pass.SetVertexBuffer(vertex_buffer);
246
247 VS::UniformBuffer uniforms;
248 Scalar time = GetSecondsElapsed();
249 euler_angles = Vector3(0.19 * time, 0.7 * time, 0.43 * time);
250
251 uniforms.mvp =
252 Matrix::MakePerspective(fov_y, pass.GetRenderTargetSize(), 0, 10) *
253 Matrix::MakeTranslation({0, 0, distance}) *
254 Matrix::MakeRotationX(Radians(euler_angles.x)) *
255 Matrix::MakeRotationY(Radians(euler_angles.y)) *
256 Matrix::MakeRotationZ(Radians(euler_angles.z));
257 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
258
259 host_buffer->Reset();
260 return pass.Draw().ok();
261 };
262 OpenPlaygroundHere(callback);
263 }

References impeller::Color::Blue(), impeller::BufferView::buffer, impeller::HostBuffer::Create(), impeller::Degrees::degrees, impeller::saturated::distance, 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::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() [422/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanRenderToTexture |
| ) |  |

Definition at line 338 of file renderer_unittests.cc.

338 {
339 using VS = BoxFadeVertexShader;
340 using FS = BoxFadeFragmentShader;
341 auto context = GetContext();
342 ASSERT_TRUE(context);
343 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
344 auto pipeline_desc =
345 BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
346 pipeline_desc->SetSampleCount(SampleCount::kCount1);
347 pipeline_desc->ClearDepthAttachment();
348 pipeline_desc->SetStencilPixelFormat(PixelFormat::kS8UInt);
349
350 ASSERT_TRUE(pipeline_desc.has_value());
351 auto box_pipeline =
352 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
353 ASSERT_TRUE(box_pipeline);
354 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
355
356 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
357 vertex_builder.SetLabel("Box");
358 vertex_builder.AddVertices({
359 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
360 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
361 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
362 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
363 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
364 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
365 });
366 auto vertex_buffer =
367 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
368 ASSERT_TRUE(vertex_buffer);
369
370 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
371 auto boston = CreateTextureForFixture("boston.jpg");
372 ASSERT_TRUE(bridge && boston);
373 const std::unique_ptr<const Sampler>& sampler =
374 context->GetSamplerLibrary()->GetSampler({});
375 ASSERT_TRUE(sampler);
376
377 std::shared_ptr<RenderPass> r2t_pass;
378 auto cmd_buffer = context->CreateCommandBuffer();
379 ASSERT_TRUE(cmd_buffer);
380 {
381 ColorAttachment color0;
382 color0.load_action = LoadAction::kClear;
383 color0.store_action = StoreAction::kStore;
384
385 TextureDescriptor texture_descriptor;
386 ASSERT_NE(pipeline_desc->GetColorAttachmentDescriptor(0u), nullptr);
387 texture_descriptor.format =
388 pipeline_desc->GetColorAttachmentDescriptor(0u)->format;
389 texture_descriptor.storage_mode = StorageMode::kHostVisible;
390 texture_descriptor.size = {400, 400};
391 texture_descriptor.mip_count = 1u;
392 texture_descriptor.usage = TextureUsage::kRenderTarget;
393
394 color0.texture =
395 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
396
397 ASSERT_TRUE(color0.IsValid());
398
399 color0.texture->SetLabel("r2t_target");
400
401 StencilAttachment stencil0;
402 stencil0.load_action = LoadAction::kClear;
403 stencil0.store_action = StoreAction::kDontCare;
404 TextureDescriptor stencil_texture_desc;
405 stencil_texture_desc.storage_mode = StorageMode::kDeviceTransient;
406 stencil_texture_desc.size = texture_descriptor.size;
407 stencil_texture_desc.format = PixelFormat::kS8UInt;
408 stencil_texture_desc.usage = TextureUsage::kRenderTarget;
409 stencil0.texture =
410 context->GetResourceAllocator()->CreateTexture(stencil_texture_desc);
411
412 RenderTarget r2t_desc;
413 r2t_desc.SetColorAttachment(color0, 0u);
414 r2t_desc.SetStencilAttachment(stencil0);
415 r2t_pass = cmd_buffer->CreateRenderPass(r2t_desc);
416 ASSERT_TRUE(r2t_pass && r2t_pass->IsValid());
417 }
418
419 r2t_pass->SetCommandLabel("Box");
420 r2t_pass->SetPipeline(box_pipeline);
421 r2t_pass->SetVertexBuffer(vertex_buffer);
422
423 FS::FrameInfo frame_info;
424 frame_info.current_time = GetSecondsElapsed();
425 frame_info.cursor_position = GetCursorPosition();
426 frame_info.window_size.x = GetWindowSize().width;
427 frame_info.window_size.y = GetWindowSize().height;
428
429 FS::BindFrameInfo(*r2t_pass, host_buffer->EmplaceUniform(frame_info));
430 FS::BindContents1(*r2t_pass, boston, sampler);
431 FS::BindContents2(*r2t_pass, bridge, sampler);
432
433 VS::UniformBuffer uniforms;
434 uniforms.mvp = Matrix::MakeOrthographic(ISize{1024, 768}) *
435 Matrix::MakeTranslation({50.0f, 50.0f, 0.0f});
436 VS::BindUniformBuffer(*r2t_pass, host_buffer->EmplaceUniform(uniforms));
437 ASSERT_TRUE(r2t_pass->Draw().ok());
438 ASSERT_TRUE(r2t_pass->EncodeCommands());
439 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), 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::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() [423/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanSepiaToneThenSwizzleWithSubpasses |
| ) |  |

Definition at line 1489 of file renderer_unittests.cc.

1489 {
1490 // The GLES framebuffer fetch implementation currently does not support this.
1491 // TODO(chinmaygarde): revisit after the GLES framebuffer fetch capabilities
1492 // are clarified.
1493 if (GetParam() == PlaygroundBackend::kOpenGLES) {
1494 GTEST_SKIP_("Not supported on GLES.");
1495 }
1496
1497 // Define shader types
1498 using TextureVS = TextureVertexShader;
1499 using TextureFS = TextureFragmentShader;
1500
1501 using SwizzleVS = SepiaVertexShader;
1502 using SwizzleFS = SwizzleFragmentShader;
1503
1504 using SepiaVS = SepiaVertexShader;
1505 using SepiaFS = SepiaFragmentShader;
1506
1507 auto context = GetContext();
1508 ASSERT_TRUE(context);
1509
1510 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1511 GTEST_SKIP_(
1512 "This test uses framebuffer fetch and the backend doesn't support it.");
1513 return;
1514 }
1515
1516 // Create pipelines.
1517 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1518 auto swizzle_pipeline = CreateDefaultPipeline<SwizzleVS, SwizzleFS>(context);
1519 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1520
1521 ASSERT_TRUE(texture_pipeline);
1522 ASSERT_TRUE(swizzle_pipeline);
1523 ASSERT_TRUE(sepia_pipeline);
1524
1525 // Vertex buffer builders.
1526 VertexBufferBuilder<TextureVS::PerVertexData> texture_vtx_builder;
1527 texture_vtx_builder.AddVertices({
1528 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1529 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1530 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1531 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1532 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1533 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1534 });
1535
1536 VertexBufferBuilder<SepiaVS::PerVertexData> sepia_vtx_builder;
1537 sepia_vtx_builder.AddVertices({
1538 {{100, 100, 0.0}}, // 1
1539 {{800, 100, 0.0}}, // 2
1540 {{800, 800, 0.0}}, // 3
1541 {{100, 100, 0.0}}, // 1
1542 {{800, 800, 0.0}}, // 3
1543 {{100, 800, 0.0}}, // 4
1544 });
1545
1546 auto boston = CreateTextureForFixture("boston.jpg");
1547 ASSERT_TRUE(boston);
1548
1549 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1550 ASSERT_TRUE(sampler);
1551
1552 SinglePassCallback callback = [&](RenderPass& pass) {
1553 auto buffer = HostBuffer::Create(context->GetResourceAllocator());
1554
1555 // Draw the texture.
1556 {
1557 pass.SetPipeline(texture_pipeline);
1558 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1559 *context->GetResourceAllocator()));
1560 TextureVS::UniformBuffer uniforms;
1561 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1562 Matrix::MakeScale(GetContentScale());
1563 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1564 TextureFS::BindTextureContents(pass, boston, sampler);
1565 if (!pass.Draw().ok()) {
1566 return false;
1567 }
1568 }
1569
1570 // Draw the sepia toner.
1571 {
1572 pass.SetPipeline(sepia_pipeline);
1573 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1574 *context->GetResourceAllocator()));
1575 SepiaVS::UniformBuffer uniforms;
1576 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1577 Matrix::MakeScale(GetContentScale());
1578 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1579 if (!pass.Draw().ok()) {
1580 return false;
1581 }
1582 }
1583
1584 // Draw the swizzle.
1585 {
1586 pass.SetPipeline(swizzle_pipeline);
1587 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1588 *context->GetResourceAllocator()));
1589 SwizzleVS::UniformBuffer uniforms;
1590 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1591 Matrix::MakeScale(GetContentScale());
1592 SwizzleVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1593 if (!pass.Draw().ok()) {
1594 return false;
1595 }
1596 }
1597
1598 return true;
1599 };
1600 OpenPlaygroundHere(callback);
1601 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::kOpenGLES, impeller::Matrix::MakeOrthographic(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [424/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | CanSepiaToneWithSubpasses |
| ) |  |

Definition at line 1394 of file renderer_unittests.cc.

1394 {
1395 // The GLES framebuffer fetch implementation currently does not support this.
1396 // TODO(chinmaygarde): revisit after the GLES framebuffer fetch capabilities
1397 // are clarified.
1398 if (GetParam() == PlaygroundBackend::kOpenGLES) {
1399 GTEST_SKIP_("Not supported on GLES.");
1400 }
1401
1402 // Define shader types
1403 using TextureVS = TextureVertexShader;
1404 using TextureFS = TextureFragmentShader;
1405
1406 using SepiaVS = SepiaVertexShader;
1407 using SepiaFS = SepiaFragmentShader;
1408
1409 auto context = GetContext();
1410 ASSERT_TRUE(context);
1411
1412 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1413 GTEST_SKIP_(
1414 "This test uses framebuffer fetch and the backend doesn't support it.");
1415 return;
1416 }
1417
1418 // Create pipelines.
1419 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1420 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1421
1422 ASSERT_TRUE(texture_pipeline);
1423 ASSERT_TRUE(sepia_pipeline);
1424
1425 // Vertex buffer builders.
1426 VertexBufferBuilder<TextureVS::PerVertexData> texture_vtx_builder;
1427 texture_vtx_builder.AddVertices({
1428 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1429 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1430 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1431 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1432 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1433 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1434 });
1435
1436 VertexBufferBuilder<SepiaVS::PerVertexData> sepia_vtx_builder;
1437 sepia_vtx_builder.AddVertices({
1438 {{100, 100, 0.0}}, // 1
1439 {{800, 100, 0.0}}, // 2
1440 {{800, 800, 0.0}}, // 3
1441 {{100, 100, 0.0}}, // 1
1442 {{800, 800, 0.0}}, // 3
1443 {{100, 800, 0.0}}, // 4
1444 });
1445
1446 auto boston = CreateTextureForFixture("boston.jpg");
1447 ASSERT_TRUE(boston);
1448
1449 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1450 ASSERT_TRUE(sampler);
1451
1452 SinglePassCallback callback = [&](RenderPass& pass) {
1453 auto buffer = HostBuffer::Create(context->GetResourceAllocator());
1454
1455 // Draw the texture.
1456 {
1457 pass.SetPipeline(texture_pipeline);
1458 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1459 *context->GetResourceAllocator()));
1460 TextureVS::UniformBuffer uniforms;
1461 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1462 Matrix::MakeScale(GetContentScale());
1463 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1464 TextureFS::BindTextureContents(pass, boston, sampler);
1465 if (!pass.Draw().ok()) {
1466 return false;
1467 }
1468 }
1469
1470 // Draw the sepia toner.
1471 {
1472 pass.SetPipeline(sepia_pipeline);
1473 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1474 *context->GetResourceAllocator()));
1475 SepiaVS::UniformBuffer uniforms;
1476 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1477 Matrix::MakeScale(GetContentScale());
1478 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1479 if (!pass.Draw().ok()) {
1480 return false;
1481 }
1482 }
1483
1484 return true;
1485 };
1486 OpenPlaygroundHere(callback);
1487 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::kOpenGLES, impeller::Matrix::MakeOrthographic(), and impeller::Matrix::MakeScale().

## ◆ TEST_P() [425/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | DefaultIndexBehavior |
| ) |  |

Definition at line 1111 of file renderer_unittests.cc.

1111 {
1112 using VS = BoxFadeVertexShader;
1113
1114 // Do not create any index buffer if no indices were provided.
1115 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1116 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::kNone);
1117 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetIndexType(), and impeller::kNone.

## ◆ TEST_P() [426/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | DefaultIndexSize |
| ) |  |

Definition at line 1101 of file renderer_unittests.cc.

1101 {
1102 using VS = BoxFadeVertexShader;
1103
1104 // Default to 16bit index buffer size, as this is a reasonable default and
1105 // supported on all backends without extensions.
1106 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1107 vertex_builder.AppendIndex(0u);
1108 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::k16bit);
1109 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AppendIndex(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::GetIndexType(), and impeller::k16bit.

## ◆ TEST_P() [427/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | InactiveUniforms |
| ) |  |

Definition at line 1054 of file renderer_unittests.cc.

1054 {
1055 using VS = InactiveUniformsVertexShader;
1056 using FS = InactiveUniformsFragmentShader;
1057
1058 auto context = GetContext();
1059 auto pipeline_descriptor =
1060 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
1061 ASSERT_TRUE(pipeline_descriptor.has_value());
1062 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
1063 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1064 auto pipeline =
1065 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1066 ASSERT_TRUE(pipeline && pipeline->IsValid());
1067
1068 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
1069 SinglePassCallback callback = [&](RenderPass& pass) {
1070 auto size = pass.GetRenderTargetSize();
1071
1072 pass.SetPipeline(pipeline);
1073 pass.SetCommandLabel("Inactive Uniform");
1074
1075 VertexBufferBuilder<VS::PerVertexData> builder;
1076 builder.AddVertices({{Point()},
1077 {Point(0, size.height)},
1078 {Point(size.width, 0)},
1079 {Point(size.width, 0)},
1080 {Point(0, size.height)},
1081 {Point(size.width, size.height)}});
1082 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
1083
1084 VS::FrameInfo frame_info;
1085 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
1086 frame_info.mvp =
1087 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
1088 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
1089
1090 FS::FragInfo fs_uniform = {.unused_color = Color::Red(),
1091 .color = Color::Green()};
1092 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1093
1094 pass.Draw().ok();
1095 host_buffer->Reset();
1096 return true;
1097 };
1098 OpenPlaygroundHere(callback);
1099 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::Color::Green(), impeller::kCount4, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), impeller::Matrix::MakeScale(), and impeller::Color::Red().

## ◆ TEST_P() [428/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | Planet |
| ) |  |

Definition at line 931 of file renderer_unittests.cc.

931 {
932 using VS = PlanetVertexShader;
933 using FS = PlanetFragmentShader;
934
935 auto context = GetContext();
936 auto pipeline_descriptor =
937 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
938 ASSERT_TRUE(pipeline_descriptor.has_value());
939 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
940 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
941 auto pipeline =
942 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
943 ASSERT_TRUE(pipeline && pipeline->IsValid());
944
945 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
946
947 SinglePassCallback callback = [&](RenderPass& pass) {
948 static Scalar speed = 0.1;
949 static Scalar planet_size = 550.0;
950 static bool show_normals = false;
951 static bool show_noise = false;
952 static Scalar seed_value = 42.0;
953
954 auto size = pass.GetRenderTargetSize();
955
956 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
957 ImGui::SliderFloat("Speed", &speed, 0.0, 10.0);
958 ImGui::SliderFloat("Planet Size", &planet_size, 0.1, 1000);
959 ImGui::Checkbox("Show Normals", &show_normals);
960 ImGui::Checkbox("Show Noise", &show_noise);
961 ImGui::InputFloat("Seed Value", &seed_value);
962 ImGui::End();
963
964 pass.SetPipeline(pipeline);
965 pass.SetCommandLabel("Planet scene");
966 VertexBufferBuilder<VS::PerVertexData> builder;
967 builder.AddVertices({{Point()},
968 {Point(0, size.height)},
969 {Point(size.width, 0)},
970 {Point(size.width, 0)},
971 {Point(0, size.height)},
972 {Point(size.width, size.height)}});
973 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
974
975 VS::FrameInfo frame_info;
976 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
977 frame_info.mvp = pass.GetOrthographicTransform();
978 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
979
980 FS::FragInfo fs_uniform;
981 fs_uniform.resolution = Point(size);
982 fs_uniform.time = GetSecondsElapsed();
983 fs_uniform.speed = speed;
984 fs_uniform.planet_size = planet_size;
985 fs_uniform.show_normals = show_normals ? 1.0 : 0.0;
986 fs_uniform.show_noise = show_noise ? 1.0 : 0.0;
987 fs_uniform.seed_value = seed_value;
988 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
989
990 pass.Draw().ok();
991 host_buffer->Reset();
992 return true;
993 };
994 OpenPlaygroundHere(callback);
995 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::kCount4, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), and impeller::Matrix::MakeOrthographic().

## ◆ TEST_P() [429/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | RenderTargetCreateOffscreenMSAASetsDefaultDepthStencilFormat |
| ) |  |

Definition at line 1361 of file renderer_unittests.cc.

1362 {
1363 auto context = GetContext();
1364 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1365 GetContext()->GetResourceAllocator());
1366
1367 RenderTarget render_target = render_target_cache->CreateOffscreenMSAA(
1368 *context, {100, 100}, /*mip_count=*/1);
1369 EXPECT_EQ(render_target.GetDepthAttachment()
1370 ->texture->GetTextureDescriptor()
1371 .format,
1372 GetContext()->GetCapabilities()->GetDefaultDepthStencilFormat());
1373 }

References impeller::RenderTarget::GetDepthAttachment().

## ◆ TEST_P() [430/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | StencilMask |
| ) |  |

Definition at line 1189 of file renderer_unittests.cc.

1189 {
1190 using VS = BoxFadeVertexShader;
1191 using FS = BoxFadeFragmentShader;
1192 auto context = GetContext();
1193 ASSERT_TRUE(context);
1194 using BoxFadePipelineBuilder = PipelineBuilder<VS, FS>;
1195 auto desc = BoxFadePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1196 ASSERT_TRUE(desc.has_value());
1197
1198 // Vertex buffer.
1199 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1200 vertex_builder.SetLabel("Box");
1201 vertex_builder.AddVertices({
1202 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1203 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1204 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1205 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1206 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1207 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1208 });
1209 auto vertex_buffer =
1210 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
1211 ASSERT_TRUE(vertex_buffer);
1212
1213 desc->SetSampleCount(SampleCount::kCount4);
1214 desc->SetStencilAttachmentDescriptors(std::nullopt);
1215
1216 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
1217 auto boston = CreateTextureForFixture("boston.jpg");
1218 ASSERT_TRUE(bridge && boston);
1219 const std::unique_ptr<const Sampler>& sampler =
1220 context->GetSamplerLibrary()->GetSampler({});
1221 ASSERT_TRUE(sampler);
1222
1223 static bool mirror = false;
1224 static int stencil_reference_write = 0xFF;
1225 static int stencil_reference_read = 0x1;
1226 std::vector<uint8_t> stencil_contents;
1227 static int last_stencil_contents_reference_value = 0;
1228 static int current_front_compare =
1229 CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
1230 static int current_back_compare =
1231 CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
1232
1233 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
1234 Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
1235 auto buffer = context->CreateCommandBuffer();
1236 if (!buffer) {
1237 return false;
1238 }
1239 buffer->SetLabel("Playground Command Buffer");
1240
1241 {
1242 // Configure the stencil attachment for the test.
1243 RenderTarget::AttachmentConfig stencil_config;
1244 stencil_config.load_action = LoadAction::kLoad;
1245 stencil_config.store_action = StoreAction::kDontCare;
1246 stencil_config.storage_mode = StorageMode::kHostVisible;
1247 render_target.SetupDepthStencilAttachments(
1248 *context, *context->GetResourceAllocator(),
1249 render_target.GetRenderTargetSize(), true, "stencil", stencil_config);
1250 // Fill the stencil buffer with an checkerboard pattern.
1251 const auto target_width = render_target.GetRenderTargetSize().width;
1252 const auto target_height = render_target.GetRenderTargetSize().height;
1253 const size_t target_size = target_width * target_height;
1254 if (stencil_contents.size() != target_size ||
1255 last_stencil_contents_reference_value != stencil_reference_write) {
1256 stencil_contents.resize(target_size);
1257 last_stencil_contents_reference_value = stencil_reference_write;
1258 for (int y = 0; y < target_height; y++) {
1259 for (int x = 0; x < target_width; x++) {
1260 const auto index = y * target_width + x;
1261 const auto kCheckSize = 64;
1262 const auto value =
1263 (((y / kCheckSize) + (x / kCheckSize)) % 2 == 0) *
1264 stencil_reference_write;
1265 stencil_contents[index] = value;
1266 }
1267 }
1268 }
1269 if (!render_target.GetStencilAttachment()->texture->SetContents(
1270 stencil_contents.data(), stencil_contents.size(), 0, false)) {
1271 VALIDATION_LOG << "Could not upload stencil contents to device memory";
1272 return false;
1273 }
1274 auto pass = buffer->CreateRenderPass(render_target);
1275 if (!pass) {
1276 return false;
1277 }
1278 pass->SetLabel("Stencil Buffer");
1279 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1280 ImGui::SliderInt("Stencil Write Value", &stencil_reference_write, 0,
1281 0xFF);
1282 ImGui::SliderInt("Stencil Compare Value", &stencil_reference_read, 0,
1283 0xFF);
1284 ImGui::Checkbox("Back face mode", &mirror);
1285 ImGui::ListBox("Front face compare function", &current_front_compare,
1286 CompareFunctionUI().labels(), CompareFunctionUI().size());
1287 ImGui::ListBox("Back face compare function", &current_back_compare,
1288 CompareFunctionUI().labels(), CompareFunctionUI().size());
1289 ImGui::End();
1290
1291 StencilAttachmentDescriptor front;
1292 front.stencil_compare =
1293 CompareFunctionUI().FunctionOf(current_front_compare);
1294 StencilAttachmentDescriptor back;
1295 back.stencil_compare =
1296 CompareFunctionUI().FunctionOf(current_back_compare);
1297 desc->SetStencilAttachmentDescriptors(front, back);
1298 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
1299
1300 assert(pipeline && pipeline->IsValid());
1301
1302 pass->SetCommandLabel("Box");
1303 pass->SetPipeline(pipeline);
1304 pass->SetStencilReference(stencil_reference_read);
1305 pass->SetVertexBuffer(vertex_buffer);
1306
1307 VS::UniformBuffer uniforms;
1308 EXPECT_EQ(pass->GetOrthographicTransform(),
1309 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
1310 uniforms.mvp = pass->GetOrthographicTransform() *
1311 Matrix::MakeScale(GetContentScale());
1312 if (mirror) {
1313 uniforms.mvp = Matrix::MakeScale(Vector2(-1, 1)) * uniforms.mvp;
1314 }
1315 VS::BindUniformBuffer(*pass, host_buffer->EmplaceUniform(uniforms));
1316
1317 FS::FrameInfo frame_info;
1318 frame_info.current_time = GetSecondsElapsed();
1319 frame_info.cursor_position = GetCursorPosition();
1320 frame_info.window_size.x = GetWindowSize().width;
1321 frame_info.window_size.y = GetWindowSize().height;
1322
1323 FS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
1324 FS::BindContents1(*pass, boston, sampler);
1325 FS::BindContents2(*pass, bridge, sampler);
1326 if (!pass->Draw().ok()) {
1327 return false;
1328 }
1329 pass->EncodeCommands();
1330 }
1331
1332 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
1333 return false;
1334 }
1335 host_buffer->Reset();
1336 return true;
1337 };
1338 OpenPlaygroundHere(callback);
1339 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), CompareFunctionUI(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), 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::VertexBufferBuilder< VertexType_, IndexType_ >::SetLabel(), impeller::StencilAttachmentDescriptor::stencil_compare, impeller::RenderTarget::AttachmentConfig::storage_mode, impeller::RenderTarget::AttachmentConfig::store_action, and VALIDATION_LOG.

## ◆ TEST_P() [431/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | TheImpeller |
| ) |  |

Definition at line 869 of file renderer_unittests.cc.

869 {
870 using VS = ImpellerVertexShader;
871 using FS = ImpellerFragmentShader;
872
873 auto context = GetContext();
874 auto pipeline_descriptor =
875 PipelineBuilder<VS, FS>::MakeDefaultPipelineDescriptor(*context);
876 ASSERT_TRUE(pipeline_descriptor.has_value());
877 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
878 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
879 auto pipeline =
880 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
881 ASSERT_TRUE(pipeline && pipeline->IsValid());
882
883 auto blue_noise = CreateTextureForFixture("blue_noise.png");
884 SamplerDescriptor noise_sampler_desc;
885 noise_sampler_desc.width_address_mode = SamplerAddressMode::kRepeat;
886 noise_sampler_desc.height_address_mode = SamplerAddressMode::kRepeat;
887 const std::unique_ptr<const Sampler>& noise_sampler =
888 context->GetSamplerLibrary()->GetSampler(noise_sampler_desc);
889
890 auto cube_map = CreateTextureCubeForFixture(
891 {"table_mountain_px.png", "table_mountain_nx.png",
892 "table_mountain_py.png", "table_mountain_ny.png",
893 "table_mountain_pz.png", "table_mountain_nz.png"});
894 const std::unique_ptr<const Sampler>& cube_map_sampler =
895 context->GetSamplerLibrary()->GetSampler({});
896 auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
897
898 SinglePassCallback callback = [&](RenderPass& pass) {
899 auto size = pass.GetRenderTargetSize();
900
901 pass.SetPipeline(pipeline);
902 pass.SetCommandLabel("Impeller SDF scene");
903 VertexBufferBuilder<VS::PerVertexData> builder;
904 builder.AddVertices({{Point()},
905 {Point(0, size.height)},
906 {Point(size.width, 0)},
907 {Point(size.width, 0)},
908 {Point(0, size.height)},
909 {Point(size.width, size.height)}});
910 pass.SetVertexBuffer(builder.CreateVertexBuffer(*host_buffer));
911
912 VS::FrameInfo frame_info;
913 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
914 frame_info.mvp = pass.GetOrthographicTransform();
915 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
916
917 FS::FragInfo fs_uniform;
918 fs_uniform.texture_size = Point(size);
919 fs_uniform.time = GetSecondsElapsed();
920 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
921 FS::BindBlueNoise(pass, blue_noise, noise_sampler);
922 FS::BindCubeMap(pass, cube_map, cube_map_sampler);
923
924 pass.Draw().ok();
925 host_buffer->Reset();
926 return true;
927 };
928 OpenPlaygroundHere(callback);
929 }

References impeller::VertexBufferBuilder< VertexType_, IndexType_ >::AddVertices(), impeller::HostBuffer::Create(), impeller::VertexBufferBuilder< VertexType_, IndexType_ >::CreateVertexBuffer(), impeller::SamplerDescriptor::height_address_mode, impeller::kCount4, impeller::kRepeat, impeller::PipelineBuilder< VertexShader_, FragmentShader_ >::MakeDefaultPipelineDescriptor(), impeller::Matrix::MakeOrthographic(), and impeller::SamplerDescriptor::width_address_mode.

## ◆ TEST_P() [432/456]

impeller::testing::TEST_P | ( | RendererTest | ,
|  | VertexBufferBuilder |
| ) |  |

Definition at line 1119 of file renderer_unittests.cc.

1119 {
1120 // Does not create index buffer if one is provided.
1121 using VS = BoxFadeVertexShader;
1122 VertexBufferBuilder<VS::PerVertexData> vertex_builder;
1123 vertex_builder.SetLabel("Box");
1124 vertex_builder.AddVertices({
1125 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1126 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1127 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1128 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1129 });
1130 vertex_builder.AppendIndex(0);
1131 vertex_builder.AppendIndex(1);
1132 vertex_builder.AppendIndex(2);
1133 vertex_builder.AppendIndex(1);
1134 vertex_builder.AppendIndex(2);
1135 vertex_builder.AppendIndex(3);
1136
1137 ASSERT_EQ(vertex_builder.GetIndexCount(), 6u);
1138 ASSERT_EQ(vertex_builder.GetVertexCount(), 4u);
1139 }

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() [433/456]

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | CachedTextureGetsNewAttachmentConfig |
| ) |  |

Definition at line 90 of file render_target_cache_unittests.cc.

90 {
91 auto render_target_cache =
92 RenderTargetCache(GetContext()->GetResourceAllocator());
93
94 render_target_cache.Start();
95 RenderTarget::AttachmentConfig color_attachment_config =
96 RenderTarget::kDefaultColorAttachmentConfig;
97 RenderTarget target1 = render_target_cache.CreateOffscreen(
98 *GetContext(), {100, 100}, 1, "Offscreen1", color_attachment_config);
99 render_target_cache.End();
100
101 render_target_cache.Start();
102 color_attachment_config.clear_color = Color::Red();
103 RenderTarget target2 = render_target_cache.CreateOffscreen(
104 *GetContext(), {100, 100}, 1, "Offscreen2", color_attachment_config);
105 render_target_cache.End();
106
107 auto color1 = target1.GetColorAttachments().find(0)->second;
108 auto color2 = target2.GetColorAttachments().find(0)->second;
109 // The second color attachment should reuse the first attachment's texture
110 // but with attributes from the second AttachmentConfig.
111 EXPECT_EQ(color2.texture, color1.texture);
112 EXPECT_EQ(color2.clear_color, Color::Red());
113 }

References impeller::RenderTarget::AttachmentConfig::clear_color, impeller::RenderTarget::GetColorAttachments(), impeller::RenderTarget::kDefaultColorAttachmentConfig, and impeller::Color::Red().

## ◆ TEST_P() [434/456]

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

Definition at line 51 of file render_target_cache_unittests.cc.

51 {
52 auto render_target_cache =
53 RenderTargetCache(GetContext()->GetResourceAllocator());
54
55 render_target_cache.Start();
56 // Create two render targets of the same exact size/shape. Both should be
57 // marked as used this frame, so the cached data set will contain two.
58 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
59 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
60
61 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
62
63 render_target_cache.End();
64 render_target_cache.Start();
65
66 // Next frame, only create one texture. The set will still contain two,
67 // but one will be removed at the end of the frame.
68 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
69 EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
70
71 render_target_cache.End();
72 EXPECT_EQ(render_target_cache.CachedTextureCount(), 1u);
73 }

## ◆ TEST_P() [435/456]

impeller::testing::TEST_P | ( | RenderTargetCacheTest | ,
|  | CreateWithEmptySize |
| ) |  |

Definition at line 115 of file render_target_cache_unittests.cc.

115 {
116 auto render_target_cache =
117 RenderTargetCache(GetContext()->GetResourceAllocator());
118
119 render_target_cache.Start();
120 RenderTarget empty_target =
121 render_target_cache.CreateOffscreen(*GetContext(), {100, 0}, 1);
122 RenderTarget empty_target_msaa =
123 render_target_cache.CreateOffscreenMSAA(*GetContext(), {0, 0}, 1);
124 render_target_cache.End();
125
126 {
127 ScopedValidationDisable disable_validation;
128 EXPECT_FALSE(empty_target.IsValid());
129 EXPECT_FALSE(empty_target_msaa.IsValid());
130 }
131 }

References impeller::RenderTarget::IsValid().

## ◆ TEST_P() [436/456]

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

Definition at line 75 of file render_target_cache_unittests.cc.

75 {
76 ScopedValidationDisable disable;
77 auto allocator = std::make_shared<TestAllocator>();
78 auto render_target_cache = RenderTargetCache(allocator);
79
80 render_target_cache.Start();
81 allocator->should_fail = true;
82
83 auto render_target =
84 render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
85
86 EXPECT_FALSE(render_target.IsValid());
87 EXPECT_EQ(render_target_cache.CachedTextureCount(), 0u);
88 }

## ◆ TEST_P() [437/456]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanCreatePipelineFromRuntimeStage |
| ) |  |

Definition at line 314 of file runtime_stage_unittests.cc.

314 {
315 auto stages = OpenAssetAsRuntimeStage("ink_sparkle.frag.iplr");
316 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
317
318 ASSERT_TRUE(stage);
319 ASSERT_NE(stage, nullptr);
320 ASSERT_TRUE(RegisterStage(*stage));
321 auto library = GetContext()->GetShaderLibrary();
322 using VS = RuntimeEffectVertexShader;
323 PipelineDescriptor desc;
324 desc.SetLabel("Runtime Stage InkSparkle");
325 desc.AddStageEntrypoint(
326 library->GetFunction(VS::kEntrypointName, ShaderStage::kVertex));
327 desc.AddStageEntrypoint(
328 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment));
329 auto vertex_descriptor = std::make_shared<VertexDescriptor>();
330 vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs,
331 VS::kInterleavedBufferLayout);
332
333 std::array<DescriptorSetLayout, 2> descriptor_set_layouts = {
334 VS::kDescriptorSetLayouts[0],
335 DescriptorSetLayout{
336 .binding = 64u,
337 .descriptor_type = DescriptorType::kUniformBuffer,
338 .shader_stage = ShaderStage::kFragment,
339 },
340 };
341 vertex_descriptor->RegisterDescriptorSetLayouts(descriptor_set_layouts);
342
343 desc.SetVertexDescriptor(std::move(vertex_descriptor));
344 ColorAttachmentDescriptor color0;
345 color0.format = GetContext()->GetCapabilities()->GetDefaultColorFormat();
346 StencilAttachmentDescriptor stencil0;
347 stencil0.stencil_compare = CompareFunction::kEqual;
348 desc.SetColorAttachmentDescriptor(0u, color0);
349 desc.SetStencilAttachmentDescriptors(stencil0);
350 const auto stencil_fmt =
351 GetContext()->GetCapabilities()->GetDefaultStencilFormat();
352 desc.SetStencilPixelFormat(stencil_fmt);
353 auto pipeline = GetContext()->GetPipelineLibrary()->GetPipeline(desc).Get();
354 ASSERT_NE(pipeline, nullptr);
355 }

References impeller::PipelineDescriptor::AddStageEntrypoint(), impeller::DescriptorSetLayout::binding, impeller::ColorAttachmentDescriptor::format, impeller::kEqual, impeller::kFragment, impeller::kUniformBuffer, impeller::kVertex, impeller::PlaygroundBackendToRuntimeStageBackend(), impeller::PipelineDescriptor::SetColorAttachmentDescriptor(), impeller::PipelineDescriptor::SetLabel(), impeller::PipelineDescriptor::SetStencilAttachmentDescriptors(), impeller::PipelineDescriptor::SetStencilPixelFormat(), impeller::PipelineDescriptor::SetVertexDescriptor(), and impeller::StencilAttachmentDescriptor::stencil_compare.

## ◆ TEST_P() [438/456]

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

Definition at line 55 of file runtime_stage_unittests.cc.

55 {
56 const std::shared_ptr<fml::Mapping> fixture =
57 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
58 ASSERT_TRUE(fixture);
59 ASSERT_GT(fixture->GetSize(), 0u);
60 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
61 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
62
63 ASSERT_TRUE(stage->IsValid());
64 switch (GetBackend()) {
65 case PlaygroundBackend::kMetal:
66 [[fallthrough]];
67 case PlaygroundBackend::kOpenGLES: {
68 ASSERT_EQ(stage->GetUniforms().size(), 17u);
69 {
70 auto uni = stage->GetUniform("u_color");
71 ASSERT_NE(uni, nullptr);
72 EXPECT_EQ(uni->dimensions.rows, 4u);
73 EXPECT_EQ(uni->dimensions.cols, 1u);
74 EXPECT_EQ(uni->location, 0u);
75 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
76 }
77 {
78 auto uni = stage->GetUniform("u_alpha");
79 ASSERT_NE(uni, nullptr);
80 EXPECT_EQ(uni->dimensions.rows, 1u);
81 EXPECT_EQ(uni->dimensions.cols, 1u);
82 EXPECT_EQ(uni->location, 1u);
83 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
84 }
85 {
86 auto uni = stage->GetUniform("u_sparkle_color");
87 ASSERT_NE(uni, nullptr);
88 EXPECT_EQ(uni->dimensions.rows, 4u);
89 EXPECT_EQ(uni->dimensions.cols, 1u);
90 EXPECT_EQ(uni->location, 2u);
91 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
92 }
93 {
94 auto uni = stage->GetUniform("u_sparkle_alpha");
95 ASSERT_NE(uni, nullptr);
96 EXPECT_EQ(uni->dimensions.rows, 1u);
97 EXPECT_EQ(uni->dimensions.cols, 1u);
98 EXPECT_EQ(uni->location, 3u);
99 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
100 }
101 {
102 auto uni = stage->GetUniform("u_blur");
103 ASSERT_NE(uni, nullptr);
104 EXPECT_EQ(uni->dimensions.rows, 1u);
105 EXPECT_EQ(uni->dimensions.cols, 1u);
106 EXPECT_EQ(uni->location, 4u);
107 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
108 }
109 {
110 auto uni = stage->GetUniform("u_radius_scale");
111 ASSERT_NE(uni, nullptr);
112 EXPECT_EQ(uni->dimensions.rows, 1u);
113 EXPECT_EQ(uni->dimensions.cols, 1u);
114 EXPECT_EQ(uni->location, 6u);
115 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
116 }
117 {
118 auto uni = stage->GetUniform("u_max_radius");
119 ASSERT_NE(uni, nullptr);
120 EXPECT_EQ(uni->dimensions.rows, 1u);
121 EXPECT_EQ(uni->dimensions.cols, 1u);
122 EXPECT_EQ(uni->location, 7u);
123 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
124 }
125 {
126 auto uni = stage->GetUniform("u_resolution_scale");
127 ASSERT_NE(uni, nullptr);
128 EXPECT_EQ(uni->dimensions.rows, 2u);
129 EXPECT_EQ(uni->dimensions.cols, 1u);
130 EXPECT_EQ(uni->location, 8u);
131 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
132 }
133 {
134 auto uni = stage->GetUniform("u_noise_scale");
135 ASSERT_NE(uni, nullptr);
136 EXPECT_EQ(uni->dimensions.rows, 2u);
137 EXPECT_EQ(uni->dimensions.cols, 1u);
138 EXPECT_EQ(uni->location, 9u);
139 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
140 }
141 {
142 auto uni = stage->GetUniform("u_noise_phase");
143 ASSERT_NE(uni, nullptr);
144 EXPECT_EQ(uni->dimensions.rows, 1u);
145 EXPECT_EQ(uni->dimensions.cols, 1u);
146 EXPECT_EQ(uni->location, 10u);
147 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
148 }
149
150 {
151 auto uni = stage->GetUniform("u_circle1");
152 ASSERT_NE(uni, nullptr);
153 EXPECT_EQ(uni->dimensions.rows, 2u);
154 EXPECT_EQ(uni->dimensions.cols, 1u);
155 EXPECT_EQ(uni->location, 11u);
156 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
157 }
158 {
159 auto uni = stage->GetUniform("u_circle2");
160 ASSERT_NE(uni, nullptr);
161 EXPECT_EQ(uni->dimensions.rows, 2u);
162 EXPECT_EQ(uni->dimensions.cols, 1u);
163 EXPECT_EQ(uni->location, 12u);
164 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
165 }
166 {
167 auto uni = stage->GetUniform("u_circle3");
168 ASSERT_NE(uni, nullptr);
169 EXPECT_EQ(uni->dimensions.rows, 2u);
170 EXPECT_EQ(uni->dimensions.cols, 1u);
171 EXPECT_EQ(uni->location, 13u);
172 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
173 }
174 {
175 auto uni = stage->GetUniform("u_rotation1");
176 ASSERT_NE(uni, nullptr);
177 EXPECT_EQ(uni->dimensions.rows, 2u);
178 EXPECT_EQ(uni->dimensions.cols, 1u);
179 EXPECT_EQ(uni->location, 14u);
180 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
181 }
182 {
183 auto uni = stage->GetUniform("u_rotation2");
184 ASSERT_NE(uni, nullptr);
185 EXPECT_EQ(uni->dimensions.rows, 2u);
186 EXPECT_EQ(uni->dimensions.cols, 1u);
187 EXPECT_EQ(uni->location, 15u);
188 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
189 }
190 {
191 auto uni = stage->GetUniform("u_rotation3");
192 ASSERT_NE(uni, nullptr);
193 EXPECT_EQ(uni->dimensions.rows, 2u);
194 EXPECT_EQ(uni->dimensions.cols, 1u);
195 EXPECT_EQ(uni->location, 16u);
196 EXPECT_EQ(uni->type, RuntimeUniformType::kFloat);
197 }
198 break;
199 }
200 case PlaygroundBackend::kVulkan: {
201 EXPECT_EQ(stage->GetUniforms().size(), 1u);
202 auto uni = stage->GetUniform(RuntimeStage::kVulkanUBOName);
203 ASSERT_TRUE(uni);
204 EXPECT_EQ(uni->type, RuntimeUniformType::kStruct);
205 EXPECT_EQ(uni->struct_float_count, 32u);
206
207 // There are 36 4 byte chunks in the UBO: 32 for the 32 floats, and 4 for
208 // padding. Initialize a vector as if they'll all be floats, then manually
209 // set the few padding bytes. If the shader changes, the padding locations
210 // will change as well. For example, if `u_alpha` was moved to the end,
211 // three bytes of padding could potentially be dropped - or if some of the
212 // scalar floats were changed to vec2 or vec4s, or if any vec3s are
213 // introduced.
214 // This means 36 * 4 = 144 bytes total.
215
216 EXPECT_EQ(uni->GetSize(), 144u);
217 std::vector<uint8_t> layout(uni->GetSize() / sizeof(float), 1);
218 layout[5] = 0;
219 layout[6] = 0;
220 layout[7] = 0;
221 layout[23] = 0;
222
223 EXPECT_THAT(uni->struct_layout, ::testing::ElementsAreArray(layout));
224 break;
225 }
226 }
227 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kFloat, impeller::kMetal, impeller::kOpenGLES, impeller::kStruct, impeller::kVulkan, impeller::RuntimeStage::kVulkanUBOName, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [439/456]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanReadUniformsSamplerAfterUBO |
| ) |  |

Definition at line 254 of file runtime_stage_unittests.cc.

254 {
255 if (GetBackend() != PlaygroundBackend::kVulkan) {
256 GTEST_SKIP() << "Test only relevant for Vulkan";
257 }
258 const std::shared_ptr<fml::Mapping> fixture =
259 flutter::testing::OpenFixtureAsMapping(
260 "uniforms_and_sampler_2.frag.iplr");
261 ASSERT_TRUE(fixture);
262 ASSERT_GT(fixture->GetSize(), 0u);
263 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
264 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
265
266 EXPECT_EQ(stage->GetUniforms().size(), 2u);
267 auto uni = stage->GetUniform(RuntimeStage::kVulkanUBOName);
268 ASSERT_TRUE(uni);
269 // Struct must be offset at 45.
270 EXPECT_EQ(uni->type, RuntimeUniformType::kStruct);
271 EXPECT_EQ(uni->binding, 64u);
272 // Sampler should be offset at 64 but due to current bug
273 // has offset of 0, the correct offset is computed at runtime.
274 auto sampler_uniform = stage->GetUniform("u_texture");
275 EXPECT_EQ(sampler_uniform->type, RuntimeUniformType::kSampledImage);
276 EXPECT_EQ(sampler_uniform->binding, 65u);
277 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kSampledImage, impeller::kStruct, impeller::kVulkan, impeller::RuntimeStage::kVulkanUBOName, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [440/456]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanReadUniformsSamplerBeforeUBO |
| ) |  |

Definition at line 229 of file runtime_stage_unittests.cc.

229 {
230 if (GetBackend() != PlaygroundBackend::kVulkan) {
231 GTEST_SKIP() << "Test only relevant for Vulkan";
232 }
233 const std::shared_ptr<fml::Mapping> fixture =
234 flutter::testing::OpenFixtureAsMapping(
235 "uniforms_and_sampler_1.frag.iplr");
236 ASSERT_TRUE(fixture);
237 ASSERT_GT(fixture->GetSize(), 0u);
238 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
239 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
240
241 EXPECT_EQ(stage->GetUniforms().size(), 2u);
242 auto uni = stage->GetUniform(RuntimeStage::kVulkanUBOName);
243 ASSERT_TRUE(uni);
244 // Struct must be offset at 65.
245 EXPECT_EQ(uni->type, RuntimeUniformType::kStruct);
246 EXPECT_EQ(uni->binding, 65u);
247 // Sampler should be offset at 64 but due to current bug
248 // has offset of 0, the correct offset is computed at runtime.
249 auto sampler_uniform = stage->GetUniform("u_texture");
250 EXPECT_EQ(sampler_uniform->type, RuntimeUniformType::kSampledImage);
251 EXPECT_EQ(sampler_uniform->binding, 64u);
252 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kSampledImage, impeller::kStruct, impeller::kVulkan, impeller::RuntimeStage::kVulkanUBOName, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [441/456]

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

Definition at line 29 of file runtime_stage_unittests.cc.

29 {
30 const std::shared_ptr<fml::Mapping> fixture =
31 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
32 ASSERT_TRUE(fixture);
33 ASSERT_GT(fixture->GetSize(), 0u);
34 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
35 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
36 ASSERT_TRUE(stage->IsValid());
37 ASSERT_EQ(stage->GetShaderStage(), RuntimeShaderStage::kFragment);
38 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kFragment, and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [442/456]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | CanRegisterStage |
| ) |  |

Definition at line 279 of file runtime_stage_unittests.cc.

279 {
280 const std::shared_ptr<fml::Mapping> fixture =
281 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
282 ASSERT_TRUE(fixture);
283 ASSERT_GT(fixture->GetSize(), 0u);
284 auto stages = RuntimeStage::DecodeRuntimeStages(fixture);
285 auto stage = stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())];
286 ASSERT_TRUE(stage->IsValid());
287 std::promise<bool> registration;
288 auto future = registration.get_future();
289 auto library = GetContext()->GetShaderLibrary();
290 library->RegisterFunction(
291 stage->GetEntrypoint(), //
292 ToShaderStage(stage->GetShaderStage()), //
293 stage->GetCodeMapping(), //
294 fml::MakeCopyable([reg = std::move(registration)](bool result) mutable {
295 reg.set_value(result);
296 }));
297 ASSERT_TRUE(future.get());
298 {
299 auto function =
300 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
301 ASSERT_NE(function, nullptr);
302 }
303
304 // Check if unregistering works.
305
306 library->UnregisterFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
307 {
308 auto function =
309 library->GetFunction(stage->GetEntrypoint(), ShaderStage::kFragment);
310 ASSERT_EQ(function, nullptr);
311 }
312 }

References impeller::RuntimeStage::DecodeRuntimeStages(), impeller::kFragment, impeller::PlaygroundBackendToRuntimeStageBackend(), and impeller::ToShaderStage().

## ◆ TEST_P() [443/456]

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

Definition at line 40 of file runtime_stage_unittests.cc.

40 {
41 ScopedValidationDisable disable_validation;
42 const std::shared_ptr<fml::Mapping> fixture =
43 flutter::testing::OpenFixtureAsMapping("ink_sparkle.frag.iplr");
44 ASSERT_TRUE(fixture);
45 auto junk_allocation = std::make_shared<Allocation>();
46 ASSERT_TRUE(junk_allocation->Truncate(fixture->GetSize(), false));
47 // Not meant to be secure. Just reject obviously bad blobs using magic
48 // numbers.
49 ::memset(junk_allocation->GetBuffer(), 127, junk_allocation->GetLength());
50 auto stages = RuntimeStage::DecodeRuntimeStages(
51 CreateMappingFromAllocation(junk_allocation));
52 ASSERT_FALSE(stages[PlaygroundBackendToRuntimeStageBackend(GetBackend())]);
53 }

References impeller::CreateMappingFromAllocation(), impeller::RuntimeStage::DecodeRuntimeStages(), and impeller::PlaygroundBackendToRuntimeStageBackend().

## ◆ TEST_P() [444/456]

impeller::testing::TEST_P | ( | RuntimeStageTest | ,
|  | ContainsExpectedShaderTypes |
| ) |  |

Definition at line 357 of file runtime_stage_unittests.cc.

357 {
358 auto stages = OpenAssetAsRuntimeStage("ink_sparkle.frag.iplr");
359 // Right now, SkSL gets implicitly bundled regardless of what the build rule
360 // for this test requested. After
361 // https://github.com/flutter/flutter/issues/138919, this may require a build
362 // rule change or a new test.
363 EXPECT_TRUE(stages[RuntimeStageBackend::kSkSL]);
364
365 EXPECT_TRUE(stages[RuntimeStageBackend::kOpenGLES]);
366 EXPECT_TRUE(stages[RuntimeStageBackend::kMetal]);
367 EXPECT_TRUE(stages[RuntimeStageBackend::kVulkan]);
368 }

References impeller::kMetal, impeller::kOpenGLES, impeller::kSkSL, and impeller::kVulkan.

## ◆ TEST_P() [445/456]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | CanConvertTextBlob |
| ) |  |

Definition at line 65 of file typographer_unittests.cc.

65 {
66 SkFont font = flutter::testing::CreateTestFontOfSize(12);
67 auto blob = SkTextBlob::MakeFromString(
68 "the quick brown fox jumped over the lazy dog.", font);
69 ASSERT_TRUE(blob);
70 auto frame = MakeTextFrameFromTextBlobSkia(blob);
71 ASSERT_EQ(frame->GetRunCount(), 1u);
72 for (const auto& run : frame->GetRuns()) {
73 ASSERT_TRUE(run.IsValid());
74 ASSERT_EQ(run.GetGlyphCount(), 45u);
75 }
76 }

References impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [446/456]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | CanCreateGlyphAtlas |
| ) |  |

Definition at line 83 of file typographer_unittests.cc.

83 {
84 auto context = TypographerContextSkia::Make();
85 auto atlas_context =
86 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
87 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
88 ASSERT_TRUE(context && context->IsValid());
89 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
90 auto blob = SkTextBlob::MakeFromString("hello", sk_font);
91 ASSERT_TRUE(blob);
92 auto atlas =
93 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
94 GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
95 *MakeTextFrameFromTextBlobSkia(blob));
96 ASSERT_NE(atlas, nullptr);
97 ASSERT_NE(atlas->GetTexture(), nullptr);
98 ASSERT_EQ(atlas->GetType(), GlyphAtlas::Type::kAlphaBitmap);
99 ASSERT_EQ(atlas->GetGlyphCount(), 4llu);
100
101 std::optional<impeller::ScaledFont> first_scaled_font;
102 std::optional<impeller::SubpixelGlyph> first_glyph;
103 Rect first_rect;
104 atlas->IterateGlyphs([&](const ScaledFont& scaled_font,
105 const SubpixelGlyph& glyph,
106 const Rect& rect) -> bool {
107 first_scaled_font = scaled_font;
108 first_glyph = glyph;
109 first_rect = rect;
110 return false;
111 });
112
113 ASSERT_TRUE(first_scaled_font.has_value());
114 ASSERT_TRUE(atlas
115 ->FindFontGlyphBounds(
116 {first_scaled_font.value(), first_glyph.value()})
117 .has_value());
118 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [447/456]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | CanCreateRenderContext |
| ) |  |

Definition at line 78 of file typographer_unittests.cc.

78 {
79 auto context = TypographerContextSkia::Make();
80 ASSERT_TRUE(context && context->IsValid());
81 }

References impeller::TypographerContextSkia::Make().

## ◆ TEST_P() [448/456]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasIsRecycledIfUnchanged |
| ) |  |

Definition at line 179 of file typographer_unittests.cc.

179 {
180 auto context = TypographerContextSkia::Make();
181 auto atlas_context =
182 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
183 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
184 ASSERT_TRUE(context && context->IsValid());
185 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
186 auto blob = SkTextBlob::MakeFromString("spooky skellingtons", sk_font);
187 ASSERT_TRUE(blob);
188 auto atlas =
189 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
190 GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
191 *MakeTextFrameFromTextBlobSkia(blob));
192 ASSERT_NE(atlas, nullptr);
193 ASSERT_NE(atlas->GetTexture(), nullptr);
194 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
195
196 // now attempt to re-create an atlas with the same text blob.
197
198 auto next_atlas =
199 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
200 GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
201 *MakeTextFrameFromTextBlobSkia(blob));
202 ASSERT_EQ(atlas, next_atlas);
203 ASSERT_EQ(atlas_context->GetGlyphAtlas(), atlas);
204 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [449/456]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasTextureIsRecycledIfUnchanged |
| ) |  |

Definition at line 253 of file typographer_unittests.cc.

253 {
254 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
255 auto context = TypographerContextSkia::Make();
256 auto atlas_context =
257 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
258 ASSERT_TRUE(context && context->IsValid());
259 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
260 auto blob = SkTextBlob::MakeFromString("spooky 1", sk_font);
261 ASSERT_TRUE(blob);
262 auto atlas =
263 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
264 GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
265 *MakeTextFrameFromTextBlobSkia(blob));
266 auto old_packer = atlas_context->GetRectPacker();
267
268 ASSERT_NE(atlas, nullptr);
269 ASSERT_NE(atlas->GetTexture(), nullptr);
270 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
271
272 auto* first_texture = atlas->GetTexture().get();
273
274 // Now create a new glyph atlas with a nearly identical blob.
275
276 auto blob2 = SkTextBlob::MakeFromString("spooky 2", sk_font);
277 auto next_atlas =
278 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
279 GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
280 *MakeTextFrameFromTextBlobSkia(blob2));
281 ASSERT_EQ(atlas, next_atlas);
282 auto* second_texture = next_atlas->GetTexture().get();
283
284 auto new_packer = atlas_context->GetRectPacker();
285
286 ASSERT_EQ(second_texture, first_texture);
287 ASSERT_EQ(old_packer, new_packer);
288 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [450/456]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasTextureWillGrowTilMaxTextureSize |
| ) |  |

Definition at line 419 of file typographer_unittests.cc.

419 {
420 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
421 GTEST_SKIP() << "Atlas growth isn't supported for OpenGLES currently.";
422 }
423
424 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
425 auto context = TypographerContextSkia::Make();
426 auto atlas_context =
427 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
428 ASSERT_TRUE(context && context->IsValid());
429 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
430 auto blob = SkTextBlob::MakeFromString("A", sk_font);
431 ASSERT_TRUE(blob);
432 auto atlas =
433 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
434 GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
435 *MakeTextFrameFromTextBlobSkia(blob));
436 // Continually append new glyphs until the glyph size grows to the maximum.
437 // Note that the sizes here are more or less experimentally determined, but
438 // the important expectation is that the atlas size will shrink again after
439 // growing to the maximum size.
440 constexpr ISize expected_sizes[13] = {
441 {4096, 4096}, //
442 {4096, 4096}, //
443 {4096, 8192}, //
444 {4096, 8192}, //
445 {4096, 8192}, //
446 {4096, 8192}, //
447 {4096, 16384}, //
448 {4096, 16384}, //
449 {4096, 16384}, //
450 {4096, 16384}, //
451 {4096, 16384}, //
452 {4096, 16384}, //
453 {4096, 4096} // Shrinks!
454 };
455
456 for (int i = 0; i < 13; i++) {
457 SkFont sk_font = flutter::testing::CreateTestFontOfSize(50 + i);
458 auto blob = SkTextBlob::MakeFromString("A", sk_font);
459
460 atlas =
461 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
462 GlyphAtlas::Type::kAlphaBitmap, 50 + i, atlas_context,
463 *MakeTextFrameFromTextBlobSkia(blob));
464 ASSERT_TRUE(!!atlas);
465 EXPECT_EQ(atlas->GetTexture()->GetTextureDescriptor().size,
466 expected_sizes[i]);
467 }
468 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::kOpenGLES, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [451/456]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasWithLotsOfdUniqueGlyphSize |
| ) |  |

Definition at line 206 of file typographer_unittests.cc.

206 {
207 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
208 auto context = TypographerContextSkia::Make();
209 auto atlas_context =
210 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
211 ASSERT_TRUE(context && context->IsValid());
212
213 const char* test_string =
214 "QWERTYUIOPASDFGHJKLZXCVBNMqewrtyuiopasdfghjklzxcvbnm,.<>[]{};':"
215 "2134567890-=!@#$%^&*()_+"
216 "œ∑´®†¥¨ˆøπ““‘‘åß∂ƒ©˙∆˚¬…æ≈ç√∫˜µ≤≥≥≥≥÷¡™£¢∞§¶•ªº–≠⁄€‹›ﬁﬂ‡°·‚—±Œ„´‰Á¨Ø∏”’/"
217 "* Í˝ */¸˛Ç◊ı˜Â¯˘¿";
218
219 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
220 auto blob = SkTextBlob::MakeFromString(test_string, sk_font);
221 ASSERT_TRUE(blob);
222
223 FontGlyphMap font_glyph_map;
224 size_t size_count = 8;
225 for (size_t index = 0; index < size_count; index += 1) {
226 MakeTextFrameFromTextBlobSkia(blob)->CollectUniqueFontGlyphPairs(
227 font_glyph_map, 0.6 * index, {0, 0}, {});
228 };
229 auto atlas =
230 context->CreateGlyphAtlas(*GetContext(), GlyphAtlas::Type::kAlphaBitmap,
231 *host_buffer, atlas_context, font_glyph_map);
232 ASSERT_NE(atlas, nullptr);
233 ASSERT_NE(atlas->GetTexture(), nullptr);
234
235 std::set<uint16_t> unique_glyphs;
236 std::vector<uint16_t> total_glyphs;
237 atlas->IterateGlyphs([&](const ScaledFont& scaled_font,
238 const SubpixelGlyph& glyph, const Rect& rect) {
239 unique_glyphs.insert(glyph.glyph.index);
240 total_glyphs.push_back(glyph.glyph.index);
241 return true;
242 });
243
244 // These numbers may be different due to subpixel positions.
245 EXPECT_LE(unique_glyphs.size() * size_count, atlas->GetGlyphCount());
246 EXPECT_EQ(total_glyphs.size(), atlas->GetGlyphCount());
247
248 EXPECT_TRUE(atlas->GetGlyphCount() > 0);
249 EXPECT_TRUE(atlas->GetTexture()->GetSize().width > 0);
250 EXPECT_TRUE(atlas->GetTexture()->GetSize().height > 0);
251 }

References impeller::HostBuffer::Create(), impeller::SubpixelGlyph::glyph, impeller::Glyph::index, impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [452/456]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphAtlasWithOddUniqueGlyphSize |
| ) |  |

Definition at line 159 of file typographer_unittests.cc.

159 {
160 auto context = TypographerContextSkia::Make();
161 auto atlas_context =
162 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
163 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
164 ASSERT_TRUE(context && context->IsValid());
165 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
166 auto blob = SkTextBlob::MakeFromString("AGH", sk_font);
167 ASSERT_TRUE(blob);
168 auto atlas =
169 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
170 GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
171 *MakeTextFrameFromTextBlobSkia(blob));
172 ASSERT_NE(atlas, nullptr);
173 ASSERT_NE(atlas->GetTexture(), nullptr);
174
175 EXPECT_EQ(atlas->GetTexture()->GetSize().width, 4096u);
176 EXPECT_EQ(atlas->GetTexture()->GetSize().height, 1024u);
177 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [453/456]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphColorIsIgnoredForNonEmojiFonts |
| ) |  |

Definition at line 324 of file typographer_unittests.cc.

324 {
325 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
326 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
327 sk_sp<SkTypeface> typeface =
328 font_mgr->matchFamilyStyle("Arial", SkFontStyle::Normal());
329 SkFont sk_font(typeface, 0.5f);
330
331 auto context = TypographerContextSkia::Make();
332 auto atlas_context =
333 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kColorBitmap);
334
335 // Create two frames with the same character and a different color, but as a
336 // non-emoji font the text frame constructor will ignore it.
337 auto frame =
338 MakeTextFrameFromTextBlobSkia(SkTextBlob::MakeFromString("A", sk_font));
339 auto frame_2 =
340 MakeTextFrameFromTextBlobSkia(SkTextBlob::MakeFromString("A", sk_font));
341 auto properties = {
342 GlyphProperties{},
343 GlyphProperties{},
344 };
345
346 auto next_atlas =
347 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
348 GlyphAtlas::Type::kColorBitmap, 1.0f, atlas_context,
349 {frame, frame_2}, properties);
350
351 EXPECT_EQ(next_atlas->GetGlyphCount(), 1u);
352 }

References impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kColorBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [454/456]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | GlyphColorIsPartOfCacheKey |
| ) |  |

Definition at line 290 of file typographer_unittests.cc.

290 {
291 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
292 #if FML_OS_MACOSX
293 auto mapping = flutter::testing::OpenFixtureAsSkData("Apple Color Emoji.ttc");
294 #else
295 auto mapping = flutter::testing::OpenFixtureAsSkData("NotoColorEmoji.ttf");
296 #endif
297 ASSERT_TRUE(mapping);
298 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
299 SkFont emoji_font(font_mgr->makeFromData(mapping), 50.0);
300
301 auto context = TypographerContextSkia::Make();
302 auto atlas_context =
303 context->CreateGlyphAtlasContext(GlyphAtlas::Type::kColorBitmap);
304
305 // Create two frames with the same character and a different color, expect
306 // that it adds a character.
307 auto frame = MakeTextFrameFromTextBlobSkia(
308 SkTextBlob::MakeFromString("😂", emoji_font));
309 auto frame_2 = MakeTextFrameFromTextBlobSkia(
310 SkTextBlob::MakeFromString("😂", emoji_font));
311 auto properties = {
312 GlyphProperties{.color = Color::Red()},
313 GlyphProperties{.color = Color::Blue()},
314 };
315
316 auto next_atlas =
317 CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
318 GlyphAtlas::Type::kColorBitmap, 1.0f, atlas_context,
319 {frame, frame_2}, properties);
320
321 EXPECT_EQ(next_atlas->GetGlyphCount(), 2u);
322 }

References impeller::Color::Blue(), impeller::GlyphProperties::color, impeller::HostBuffer::Create(), CreateGlyphAtlas(), impeller::GlyphAtlas::kColorBitmap, impeller::TypographerContextSkia::Make(), impeller::MakeTextFrameFromTextBlobSkia(), and impeller::Color::Red().

## ◆ TEST_P() [455/456]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | LazyAtlasTracksColor |
| ) |  |

Definition at line 120 of file typographer_unittests.cc.

120 {
121 auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
122 #if FML_OS_MACOSX
123 auto mapping = flutter::testing::OpenFixtureAsSkData("Apple Color Emoji.ttc");
124 #else
125 auto mapping = flutter::testing::OpenFixtureAsSkData("NotoColorEmoji.ttf");
126 #endif
127 ASSERT_TRUE(mapping);
128 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
129 SkFont emoji_font(font_mgr->makeFromData(mapping), 50.0);
130 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
131
132 auto blob = SkTextBlob::MakeFromString("hello", sk_font);
133 ASSERT_TRUE(blob);
134 auto frame = MakeTextFrameFromTextBlobSkia(blob);
135
136 ASSERT_FALSE(frame->GetAtlasType() == GlyphAtlas::Type::kColorBitmap);
137
138 LazyGlyphAtlas lazy_atlas(TypographerContextSkia::Make());
139
140 lazy_atlas.AddTextFrame(*frame, 1.0f, {0, 0}, {});
141
142 frame = MakeTextFrameFromTextBlobSkia(
143 SkTextBlob::MakeFromString("😀 ", emoji_font));
144
145 ASSERT_TRUE(frame->GetAtlasType() == GlyphAtlas::Type::kColorBitmap);
146
147 lazy_atlas.AddTextFrame(*frame, 1.0f, {0, 0}, {});
148
149 // Creates different atlases for color and red bitmap.
150 auto color_atlas = lazy_atlas.CreateOrGetGlyphAtlas(
151 *GetContext(), *host_buffer, GlyphAtlas::Type::kColorBitmap);
152
153 auto bitmap_atlas = lazy_atlas.CreateOrGetGlyphAtlas(
154 *GetContext(), *host_buffer, GlyphAtlas::Type::kAlphaBitmap);
155
156 ASSERT_FALSE(color_atlas == bitmap_atlas);
157 }

References impeller::LazyGlyphAtlas::AddTextFrame(), impeller::HostBuffer::Create(), impeller::LazyGlyphAtlas::CreateOrGetGlyphAtlas(), impeller::GlyphAtlas::kAlphaBitmap, impeller::GlyphAtlas::kColorBitmap, impeller::TypographerContextSkia::Make(), and impeller::MakeTextFrameFromTextBlobSkia().

## ◆ TEST_P() [456/456]

impeller::testing::TEST_P | ( | TypographerTest | ,
|  | RectanglePackerAddsNonoverlapingRectangles |
| ) |  |

Definition at line 354 of file typographer_unittests.cc.

354 {
355 auto packer = RectanglePacker::Factory(200, 100);
356 ASSERT_NE(packer, nullptr);
357 ASSERT_EQ(packer->PercentFull(), 0);
358
359 const SkIRect packer_area = SkIRect::MakeXYWH(0, 0, 200, 100);
360
361 IPoint16 first_output = {-1, -1}; // Fill with sentinel values
362 ASSERT_TRUE(packer->AddRect(20, 20, &first_output));
363 // Make sure the rectangle is placed such that it is inside the bounds of
364 // the packer's area.
365 const SkIRect first_rect =
366 SkIRect::MakeXYWH(first_output.x(), first_output.y(), 20, 20);
367 ASSERT_TRUE(SkIRect::Intersects(packer_area, first_rect));
368
369 // Initial area was 200 x 100 = 20_000
370 // We added 20x20 = 400. 400 / 20_000 == 0.02 == 2%
371 ASSERT_TRUE(flutter::testing::NumberNear(packer->PercentFull(), 0.02));
372
373 IPoint16 second_output = {-1, -1};
374 ASSERT_TRUE(packer->AddRect(140, 90, &second_output));
375 const SkIRect second_rect =
376 SkIRect::MakeXYWH(second_output.x(), second_output.y(), 140, 90);
377 // Make sure the rectangle is placed such that it is inside the bounds of
378 // the packer's area but not in the are of the first rectangle.
379 ASSERT_TRUE(SkIRect::Intersects(packer_area, second_rect));
380 ASSERT_FALSE(SkIRect::Intersects(first_rect, second_rect));
381
382 // We added another 90 x 140 = 12_600 units, now taking us to 13_000
383 // 13_000 / 20_000 == 0.65 == 65%
384 ASSERT_TRUE(flutter::testing::NumberNear(packer->PercentFull(), 0.65));
385
386 // There's enough area to add this rectangle, but no space big enough for
387 // the 50 units of width.
388 IPoint16 output;
389 ASSERT_FALSE(packer->AddRect(50, 50, &output));
390 // Should be unchanged.
391 ASSERT_TRUE(flutter::testing::NumberNear(packer->PercentFull(), 0.65));
392
393 packer->Reset();
394 // Should be empty now.
395 ASSERT_EQ(packer->PercentFull(), 0);
396 }

References impeller::RectanglePacker::Factory(), NumberNear(), impeller::IPoint16::x(), and impeller::IPoint16::y().

## ◆ toColor()

flutter::DlColor impeller::testing::toColor | ( | const float * | components | ) |

Definition at line 41 of file dl_unittests.cc.

41 {
42 return flutter::DlColor(Color::ToIColor(
43 Color(components[0], components[1], components[2], components[3])));
44 }

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 16 of file golden_paths.h.

## ◆ kFontFixture

constexpr std::string_view impeller::testing::kFontFixture
| static constexpr

Initial value:
=
"NotoColorEmoji.ttf"

Definition at line 740 of file aiks_unittests.cc.

Referenced by TEST_P().

## ◆ kPaintVariations

const std::map<std::string, MaskBlurTestConfig> impeller::testing::kPaintVariations
| static

Definition at line 378 of file aiks_blur_unittests.cc.

impeller::ISize
ISize64 ISize
Definition: size.h:140
_BLEND_MODE_RESULT_CHECK
#define _BLEND_MODE_RESULT_CHECK(blend_mode)
Definition: geometry_unittests.cc:1655
NumberNear
bool NumberNear(double a, double b)
Definition: geometry_asserts.h:18
ASSERT_COLOR_NEAR
#define ASSERT_COLOR_NEAR(a, b)
Definition: geometry_asserts.h:192
impeller::kFloat
@ kFloat
Definition: runtime_types.h:23
impeller::OptionsFromPass
ContentContextOptions OptionsFromPass(const RenderPass &pass)
Definition: contents.cc:19
impeller::k1OverSqrt2
constexpr float k1OverSqrt2
Definition: constants.h:50
impeller::testing::CompareFunctionUI
static const CompareFunctionUIData & CompareFunctionUI()
Definition: renderer_unittests.cc:1184
impeller::MyMask
Mask< MyMaskBits > MyMask
Definition: base_unittests.cc:20
impeller::BlendModeToString
const char * BlendModeToString(BlendMode blend_mode)
Definition: color.cc:47
polyline
const Path::Polyline & polyline
Definition: stroke_path_geometry.cc:303
impeller::TPoint::y
Type y
Definition: point.h:31
impeller::PixelFormatToString
constexpr const char * PixelFormatToString(PixelFormat format)
Definition: formats.h:140
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::skia_conversions::IsNearlySimpleRRect
bool IsNearlySimpleRRect(const SkRRect &rr)
Like SkRRect.isSimple, but allows the corners to differ by kEhCloseEnough.
Definition: skia_conversions.cc:12
impeller::TPoint::Ceil
constexpr TPoint Ceil() const
Definition: point.h:196
impeller::testing::CompareFunctionUIData::IndexOf
int IndexOf(CompareFunction func) const
Definition: renderer_unittests.cc:1167
uvs
Quad uvs
Definition: gaussian_blur_filter_contents.cc:222
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:212
impeller::testing::swap_nan
static constexpr Point swap_nan(const Point &point, int index)
Definition: rect_unittests.cc:1305
impeller::skia_conversions::ToSize
Size ToSize(const SkPoint &point)
Definition: skia_conversions.cc:158
impeller::BlendMode
BlendMode
Definition: color.h:59
impeller::testing::CreateMappingFromString
static std::shared_ptr< fml::Mapping > CreateMappingFromString(std::string p_string)
Definition: shader_archive_unittests.cc:15
impeller::TPoint::Lerp
constexpr TPoint Lerp(const TPoint &p, Scalar t) const
Definition: point.h:236
impeller::kEhCloseEnough
constexpr float kEhCloseEnough
Definition: constants.h:56
data
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
font_size
SkScalar font_size
Definition: dl_golden_blur_unittests.cc:22
impeller::TextureDescriptor::format
PixelFormat format
Definition: texture_descriptor.h:41
impeller::TPoint::Min
constexpr TPoint Min(const TPoint &p) const
Definition: point.h:186
impeller::TPoint::Round
static constexpr TPoint Round(const TPoint< U > &other)
Definition: point.h:49
impeller::Vector2
Point Vector2
Definition: point.h:326
EXPECT_POINT_NEAR
#define EXPECT_POINT_NEAR(a, b)
Definition: geometry_asserts.h:205
MatrixNear
inline ::testing::AssertionResult MatrixNear(impeller::Matrix a, impeller::Matrix b)
Definition: geometry_asserts.h:56
impeller::kPi
constexpr float kPi
Definition: constants.h:26
impeller::testing::CanRenderRadialGradientWithDithering
static void CanRenderRadialGradientWithDithering(AiksTest *aiks_test)
Definition: aiks_dl_gradient_unittests.cc:124
impeller::testing::flip_lrtb
static constexpr R flip_lrtb(R rect)
Definition: rect_unittests.cc:1291
impeller::CreateTextureFromDrawableFuture
std::shared_ptr< TextureMTL > CreateTextureFromDrawableFuture(TextureDescriptor desc, const std::shared_future< id< CAMetalDrawable >> &drawble_future)
Create a TextureMTL from a deferred drawable.
Definition: lazy_drawable_holder.mm:41
impeller::kSampledImage
@ kSampledImage
Definition: runtime_types.h:24
impeller::skia_conversions::ToColor
Color ToColor(const flutter::DlColor &color)
Definition: skia_conversions.cc:162
impeller::UintPoint32
TPoint< uint32_t > UintPoint32
Definition: point.h:325
padding
Vector2 padding
The halo padding in source space.
Definition: gaussian_blur_filter_contents.cc:91
buffer_view
BufferView buffer_view
Definition: blit_command_gles.cc:127
impeller::Size
TSize< Scalar > Size
Definition: size.h:137
impeller::StorageMode::kHostVisible
@ kHostVisible
ASSERT_POINT_NEAR
#define ASSERT_POINT_NEAR(a, b)
Definition: geometry_asserts.h:193
impeller::kGaussianBlurMaxKernelSize
static constexpr int32_t kGaussianBlurMaxKernelSize
Definition: gaussian_blur_filter_contents.h:16
impeller::CreateMappingFromAllocation
std::shared_ptr< fml::Mapping > CreateMappingFromAllocation(const std::shared_ptr< Allocation > &allocation)
Definition: allocation.cc:99
ASSERT_VECTOR4_NEAR
#define ASSERT_VECTOR4_NEAR(a, b)
Definition: geometry_asserts.h:195
impeller::PlaygroundBackendToRuntimeStageBackend
constexpr RuntimeStageBackend PlaygroundBackendToRuntimeStageBackend(PlaygroundBackend backend)
Definition: playground.h:33
stroke_width
const Scalar stroke_width
Definition: stroke_path_geometry.cc:304
offset
SeparatedVector2 offset
Definition: stroke_path_geometry.cc:311
impeller::MoveTo
void MoveTo(PathBuilder *builder, Scalar x, Scalar y)
Definition: tessellator.cc:20
EXPECT_RECT_NEAR
#define EXPECT_RECT_NEAR(a, b)
Definition: geometry_asserts.h:203
impeller::GetDrawableDeferred
std::shared_future< id< CAMetalDrawable > > GetDrawableDeferred(CAMetalLayer *layer)
Create a deferred drawable from a CAMetalLayer.
Definition: lazy_drawable_holder.mm:23
impeller::TPoint::Floor
constexpr TPoint Floor() const
Definition: point.h:194
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:590
impeller::kPiOver2
constexpr float kPiOver2
Definition: constants.h:32
impeller::PixelFormat
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:99
ASSERT_RECT_NEAR
#define ASSERT_RECT_NEAR(a, b)
Definition: geometry_asserts.h:191
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::ToMatrix
static Matrix ToMatrix(const SkMatrix &m)
Definition: dl_dispatcher.cc:161
impeller::kPhi
constexpr float kPhi
Definition: constants.h:53
impeller::VS
SolidFillVertexShader VS
Definition: stroke_path_geometry.cc:16
impeller::saturated::distance
SI distance
Definition: saturated_math.h:57
impeller::testing::toColor
flutter::DlColor toColor(const float *components)
Definition: dl_unittests.cc:41
impeller::Point
TPoint< Scalar > Point
Definition: point.h:322
impeller::k2Pi
constexpr float k2Pi
Definition: constants.h:29
impeller::Quad
std::array< Point, 4 > Quad
Definition: point.h:327
impeller::testing::CompareFunctionUIData::FunctionOf
CompareFunction FunctionOf(int index) const
Definition: renderer_unittests.cc:1177
BLEND_MODE_TUPLE
#define BLEND_MODE_TUPLE(blend_mode)
Definition: aiks_blend_unittests.cc:181
impeller::testing::RGBToYUV
static Vector3 RGBToYUV(Vector3 rgb, YUVColorSpace yuv_color_space)
Definition: entity_unittests.cc:1838
impeller::MipFilter
MipFilter
Options for selecting and filtering between mipmap levels.
Definition: formats.h:419
impeller::testing::flip_lr
static constexpr R flip_lr(R rect)
Definition: rect_unittests.cc:1279
impeller::SPrintF
std::string SPrintF(const char *format,...)
Definition: strings.cc:12
EXPECT_VECTOR3_NEAR
#define EXPECT_VECTOR3_NEAR(a, b)
Definition: geometry_asserts.h:206
transform
Matrix transform
Definition: gaussian_blur_filter_contents.cc:231
impeller::testing::GetBlendModeSelection
static BlendModeSelection GetBlendModeSelection()
Definition: aiks_blend_unittests.cc:188
impeller::IPoint32
TPoint< int32_t > IPoint32
Definition: point.h:324
impeller::ScalarToHalf
constexpr InternalHalf ScalarToHalf(Scalar f)
Convert a scalar to a half precision float.
Definition: half.h:32
impeller::TPoint::Max
constexpr TPoint Max(const TPoint &p) const
Definition: point.h:190
impeller::FontGlyphMap
std::unordered_map< ScaledFont, std::unordered_set< SubpixelGlyph > > FontGlyphMap
Definition: font_glyph_pair.h:54
impeller::testing::CreatePassWithRectPath
auto CreatePassWithRectPath(Rect rect, std::optional< Rect > bounds_hint, ContentBoundsPromise bounds_promise=ContentBoundsPromise::kUnknown, bool collapse=false)
Definition: entity_unittests.cc:110
type
GLenum type
Definition: blit_command_gles.cc:126
impeller::Matrix::MakeColumn
static constexpr Matrix MakeColumn(Scalar m0, Scalar m1, Scalar m2, Scalar m3, Scalar m4, Scalar m5, Scalar m6, Scalar m7, Scalar m8, Scalar m9, Scalar m10, Scalar m11, Scalar m12, Scalar m13, Scalar m14, Scalar m15)
Definition: matrix.h:69
impeller::MinMagFilter
MinMagFilter
Describes how the texture should be sampled when the texture is being shrunk (minified) or expanded (...
Definition: formats.h:409
impeller::testing::CreateTestYUVTextures
static std::vector< std::shared_ptr< Texture > > CreateTestYUVTextures(Context *context, YUVColorSpace yuv_color_space)
Definition: entity_unittests.cc:1855
_BLEND_MODE_NAME_CHECK
#define _BLEND_MODE_NAME_CHECK(blend_mode)
Definition: geometry_unittests.cc:1673
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:769
ASSERT_MATRIX_NEAR
#define ASSERT_MATRIX_NEAR(a, b)
Definition: geometry_asserts.h:189
impeller::testing::CreateStringFromMapping
const std::string CreateStringFromMapping(const fml::Mapping &mapping)
Definition: shader_archive_unittests.cc:23
impeller::TextureUsageMask
Mask< TextureUsage > TextureUsageMask
Definition: formats.h:308
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::kStruct
@ kStruct
Definition: runtime_types.h:25
impeller::skia_conversions::ToPoint
Point ToPoint(const SkPoint &point)
Definition: skia_conversions.cc:154
impeller::testing::CanRenderConicalGradientWithDithering
static void CanRenderConicalGradientWithDithering(AiksTest *aiks_test)
Definition: aiks_dl_gradient_unittests.cc:167
IMPELLER_FOR_EACH_BLEND_MODE
#define IMPELLER_FOR_EACH_BLEND_MODE(V)
Definition: color.h:19
IMPELLER_RAND
#define IMPELLER_RAND
Definition: gaussian_blur_filter_contents_unittests.cc:18
impeller::MakeTextFrameFromTextBlobSkia
std::shared_ptr< TextFrame > MakeTextFrameFromTextBlobSkia(const sk_sp< SkTextBlob > &blob)
Definition: text_frame_skia.cc:61
impeller::ToMTLPixelFormat
constexpr MTLPixelFormat ToMTLPixelFormat(PixelFormat format)
Definition: formats_mtl.h:76
ASSERT_QUATERNION_NEAR
#define ASSERT_QUATERNION_NEAR(a, b)
Definition: geometry_asserts.h:190
impeller::GenerateBlurInfo
KernelSamples GenerateBlurInfo(BlurParameters parameters)
Definition: gaussian_blur_filter_contents.cc:817
impeller::Close
void Close(PathBuilder *builder)
Definition: tessellator.cc:38
impeller::TextureDescriptor::size
ISize size
Definition: texture_descriptor.h:42
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:73
impeller::testing::RenderTextInCanvasSkia
bool RenderTextInCanvasSkia(const std::shared_ptr< Context > &context, Canvas &canvas, const std::string &text, const std::string_view &font_fixture, TextRenderOptions options={})
Definition: aiks_unittests.cc:550
impeller::LineTo
void LineTo(PathBuilder *builder, Scalar x, Scalar y)
Definition: tessellator.cc:24
impeller::Join
Join
Definition: path.h:24
RectNear
inline ::testing::AssertionResult RectNear(impeller::Rect a, impeller::Rect b)
Definition: geometry_asserts.h:89
impeller::DrawPlaygroundPoint
Point DrawPlaygroundPoint(PlaygroundPoint &point)
Definition: widgets.cc:9
impeller::testing::CanRenderLinearGradientWithDithering
static void CanRenderLinearGradientWithDithering(AiksTest *aiks_test)
Definition: aiks_dl_gradient_unittests.cc:104
impeller::IPoint
TPoint< int64_t > IPoint
Definition: point.h:323
impeller::MyMaskBits
MyMaskBits
Definition: base_unittests.cc:13
ASSERT_VECTOR3_NEAR
#define ASSERT_VECTOR3_NEAR(a, b)
Definition: geometry_asserts.h:194
FLT_FORWARD
#define FLT_FORWARD(mock, real, method)
Definition: aiks_blur_unittests.cc:499
impeller::saturated::b
SI b
Definition: saturated_math.h:87
impeller::testing::kFontFixture
static constexpr std::string_view kFontFixture
Definition: aiks_unittests.cc:740
scale
const Scalar scale
Definition: stroke_path_geometry.cc:308
blur_radius
Vector2 blur_radius
Blur radius in source pixels based on scaled_sigma.
Definition: gaussian_blur_filter_contents.cc:89
paint
const Paint & paint
Definition: color_source.cc:38
impeller::ScalarNearlyEqual
constexpr bool ScalarNearlyEqual(Scalar x, Scalar y, Scalar tolerance=kEhCloseEnough)
Definition: scalar.h:30
impeller::YUVColorSpace
YUVColorSpace
Definition: color.h:55
impeller::LerpHackKernelSamples
GaussianBlurPipeline::FragmentShader::KernelSamples LerpHackKernelSamples(KernelSamples parameters)
Definition: gaussian_blur_filter_contents.cc:864
impeller::testing::CreateGlyphAtlas
static std::shared_ptr< GlyphAtlas > CreateGlyphAtlas(Context &context, const TypographerContext *typographer_context, HostBuffer &host_buffer, GlyphAtlas::Type type, Scalar scale, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const std::vector< std::shared_ptr< TextFrame >> &frames, const std::vector< GlyphProperties > &properties)
Definition: typographer_unittests.cc:46
impeller::TPoint::Rotate
constexpr TPoint Rotate(const Radians &angle) const
Definition: point.h:226
impeller::SampleCount::kCount1
@ kCount1
impeller::IRect
IRect64 IRect
Definition: rect.h:772
color
DlColor color
Definition: dl_golden_blur_unittests.cc:23
impeller::TextureDescriptor::storage_mode
StorageMode storage_mode
Definition: texture_descriptor.h:39
impeller::TPoint::GetDistance
constexpr Type GetDistance(const TPoint &p) const
Definition: point.h:200
impeller::TextureDescriptor
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
Definition: texture_descriptor.h:38
impeller::TSize::MipCount
constexpr size_t MipCount() const
Definition: size.h:115
impeller::TPoint::Normalize
constexpr TPoint Normalize() const
Definition: point.h:208
impeller::testing::flip_tb
static constexpr R flip_tb(R rect)
Definition: rect_unittests.cc:1285
ASSERT_COLOR_BUFFER_NEAR
#define ASSERT_COLOR_BUFFER_NEAR(a, b)
Definition: geometry_asserts.h:198
impeller::testing::CanRenderSweepGradientWithDithering
static void CanRenderSweepGradientWithDithering(AiksTest *aiks_test)
Definition: aiks_dl_gradient_unittests.cc:144
impeller::kPiOver4
constexpr float kPiOver4
Definition: constants.h:35
impeller::MakeVertices
std::shared_ptr< impeller::VerticesGeometry > MakeVertices(const std::shared_ptr< const flutter::DlVertices > &vertices)
Definition: dl_vertices_geometry.cc:31
impeller::Cap
Cap
Definition: path.h:18
ASSERT_ARRAY_4_NEAR
#define ASSERT_ARRAY_4_NEAR(a, b)
Definition: geometry_asserts.h:197
IPLR_REQUIRES
#define IPLR_REQUIRES(...)
Definition: thread_safety.h:30
impeller::DrawPlaygroundLine
std::tuple< Point, Point > DrawPlaygroundLine(PlaygroundPoint &point_a, PlaygroundPoint &point_b)
Definition: widgets.cc:50